persistProcessor->process($data, $operation, $uriVariables, $context); } $period = $data->getContractPeriod(); if (!$period instanceof EmployeeContractPeriod && null !== $data->getContractPeriodId()) { $period = $this->entityManager->find(EmployeeContractPeriod::class, $data->getContractPeriodId()); if ($period instanceof EmployeeContractPeriod) { $data->setContractPeriod($period); } } if (!$period instanceof EmployeeContractPeriod) { throw new UnprocessableEntityHttpException('contractPeriodId is required.'); } $this->validate($data, $period); return $this->persistProcessor->process($data, $operation, $uriVariables, $context); } private function validate(ContractSuspension $suspension, EmployeeContractPeriod $period): void { // Compare as Y-m-d strings to avoid timezone issues between Doctrine and API Platform DateTimeImmutable $startDate = $suspension->getStartDate()->format('Y-m-d'); $endDate = $suspension->getEndDate()?->format('Y-m-d'); $periodStart = $period->getStartDate()->format('Y-m-d'); $periodEnd = $period->getEndDate()?->format('Y-m-d'); if (null !== $periodEnd && $periodEnd < new DateTimeImmutable('today')->format('Y-m-d')) { throw new UnprocessableEntityHttpException('Impossible de suspendre une période de contrat clôturée.'); } if (null !== $endDate && $endDate < $startDate) { throw new UnprocessableEntityHttpException('La date de fin doit être postérieure à la date de début.'); } if ($startDate < $periodStart) { throw new UnprocessableEntityHttpException('La suspension ne peut pas commencer avant le début du contrat.'); } if (null !== $periodEnd) { if ($startDate > $periodEnd) { throw new UnprocessableEntityHttpException('La suspension ne peut pas commencer après la fin du contrat.'); } if (null !== $endDate && $endDate > $periodEnd) { throw new UnprocessableEntityHttpException('La suspension ne peut pas se terminer après la fin du contrat.'); } } $this->validateNoOverlap($suspension, $period); } private function validateNoOverlap(ContractSuspension $suspension, EmployeeContractPeriod $period): void { $start = $suspension->getStartDate()->format('Y-m-d'); $end = $suspension->getEndDate()?->format('Y-m-d'); foreach ($period->getSuspensions() as $existing) { if ($existing->getId() === $suspension->getId() && null !== $suspension->getId()) { continue; } $existingStart = $existing->getStartDate()->format('Y-m-d'); $existingEnd = $existing->getEndDate()?->format('Y-m-d'); if (null === $end && null === $existingEnd) { throw new UnprocessableEntityHttpException('Les suspensions ne peuvent pas se chevaucher.'); } if (null === $end) { if ($start <= $existingEnd) { throw new UnprocessableEntityHttpException('Les suspensions ne peuvent pas se chevaucher.'); } continue; } if (null === $existingEnd) { if ($existingStart <= $end) { throw new UnprocessableEntityHttpException('Les suspensions ne peuvent pas se chevaucher.'); } continue; } if ($start <= $existingEnd && $end >= $existingStart) { throw new UnprocessableEntityHttpException('Les suspensions ne peuvent pas se chevaucher.'); } } } }