diff --git a/app/ApiModule/Services/ScheduleService.php b/app/ApiModule/Services/ScheduleService.php index e6cff2961..72131bf17 100644 --- a/app/ApiModule/Services/ScheduleService.php +++ b/app/ApiModule/Services/ScheduleService.php @@ -218,10 +218,20 @@ public function saveProgram(ProgramSaveDto $programSaveDto) : ResponseDto $start = $programSaveDto->getStart(); $end = $start->add(new DateInterval('PT' . $block->getDuration() . 'M')); + $overlappingLecturersProgram = false; + foreach ($block->getLectors() as $lector) { + if ($this->userRepository->hasOverlappingLecturersProgram($lector, $programId, $start, $end)) { + $overlappingLecturersProgram = true; + break; + } + } + if (! $this->user->isAllowed(SrsResource::PROGRAM, Permission::MANAGE_SCHEDULE)) { $responseDto->setMessage($this->translator->translate('common.api.schedule_user_not_allowed_manage')); } elseif (! $this->settingsService->getBoolValue(Settings::IS_ALLOWED_MODIFY_SCHEDULE)) { $responseDto->setMessage($this->translator->translate('common.api.schedule_not_allowed_modfify')); + } elseif ($overlappingLecturersProgram) { + $responseDto->setMessage($this->translator->translate('common.api.schedule_lector_has_another_program')); } elseif ($room && $this->roomRepository->hasOverlappingProgram($room, $programId, $start, $end)) { $responseDto->setMessage($this->translator->translate('common.api.schedule_room_occupied', null, ['name' => $room->getName()])); } elseif ($block->getMandatory() === ProgramMandatoryType::AUTO_REGISTERED && $this->programRepository->hasOverlappingProgram($programId, $start, $end)) { diff --git a/app/Model/User/UserRepository.php b/app/Model/User/UserRepository.php index ad77903d6..074786e38 100644 --- a/app/Model/User/UserRepository.php +++ b/app/Model/User/UserRepository.php @@ -8,6 +8,7 @@ use App\Model\Acl\Role; use App\Model\Enums\ApplicationState; use App\Model\Program\Block; +use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; @@ -278,6 +279,29 @@ public function getLectorsOptions() : array return $options; } + /** + * Má lektor jiný program ve stejný čas? + */ + public function hasOverlappingLecturersProgram(User $lector, ?int $programId, DateTimeImmutable $start, DateTimeImmutable $end) : bool + { + $qb = $this->createQueryBuilder('u') + ->select('u.id') + ->join('u.lecturersBlocks', 'b') + ->join('b.programs', 'p') + ->where($this->createQueryBuilder('u')->expr()->orX( + "(p.start < :end) AND (DATE_ADD(p.start, (b.duration * 60), 'second') > :start)", + "(p.start < :end) AND (:start < (DATE_ADD(p.start, (b.duration * 60), 'second')))" + )) + ->andWhere('u.id = :uid') + ->andWhere('(p.id != :pid) or (:pid IS NULL)') + ->setParameter('start', $start) + ->setParameter('end', $end) + ->setParameter('uid', $lector->getId()) + ->setParameter('pid', $programId); + + return ! empty($qb->getQuery()->getResult()); + } + /** * Uloží uživatele. * diff --git a/app/lang/common.cs_CZ.neon b/app/lang/common.cs_CZ.neon index 5b05bc83a..1644dd733 100644 --- a/app/lang/common.cs_CZ.neon +++ b/app/lang/common.cs_CZ.neon @@ -151,6 +151,7 @@ api: program_registered: "Program byl úspěšně přihlášen." schedule_program_not_registered: "Na tento program jste nebyli přihlášeni." program_unregistered: "Program byl úspěšně odhlášen." + schedule_lector_has_another_program: "Lektor má v tuto dobu již jiný program." schedule_room_occupied: "Místnost \"%name%\" je v tuto dobu již obsazena." schedule_auto_registered_not_allowed: "Automaticky přihlašovaný program nesmí být ve stejnou dobu jako jiný program."