diff --git a/src/State/EmployeeLeaveSummaryProvider.php b/src/State/EmployeeLeaveSummaryProvider.php index ea92f04..0292a1a 100644 --- a/src/State/EmployeeLeaveSummaryProvider.php +++ b/src/State/EmployeeLeaveSummaryProvider.php @@ -786,6 +786,20 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface return $repoDaysYear * $businessDaysPeriod / $businessDaysYear; } + /** + * Vrai si la phase FORFAIT démarre en cours de l'année civile consultée + * (donc avec une période partielle), faux pour une année pleine ou un démarrage le 1er janvier. + */ + private function isForfaitEntryYear(ContractPhase $phase, int $year): bool + { + if (ContractType::FORFAIT !== $phase->contractType) { + return false; + } + + return (int) $phase->startDate->format('Y') === $year + && '01-01' !== $phase->startDate->format('m-d'); + } + /** * @param null|array $publicHolidays pre-built map (built if null) */ diff --git a/tests/State/EmployeeLeaveSummaryProviderTest.php b/tests/State/EmployeeLeaveSummaryProviderTest.php index 69007ee..8a2347f 100644 --- a/tests/State/EmployeeLeaveSummaryProviderTest.php +++ b/tests/State/EmployeeLeaveSummaryProviderTest.php @@ -210,6 +210,43 @@ final class EmployeeLeaveSummaryProviderTest extends TestCase self::assertEqualsWithDelta(22.92, $acquired, 0.1); } + public function testIsForfaitEntryYearTrueOnStartYear(): void + { + $employee = $this->buildEmployeeWithTransition('2020-06-01', '2026-04-30', '2026-05-01'); + $forfaitPhase = new EmployeeContractPhaseResolver()->resolvePhases($employee)[0]; + $provider = $this->buildProvider(); + + self::assertTrue($this->invokePrivate($provider, 'isForfaitEntryYear', $forfaitPhase, 2026)); + } + + public function testIsForfaitEntryYearFalseOnSubsequentFullYear(): void + { + $employee = $this->buildEmployeeWithTransition('2020-06-01', '2026-04-30', '2026-05-01'); + $forfaitPhase = new EmployeeContractPhaseResolver()->resolvePhases($employee)[0]; + $provider = $this->buildProvider(); + + self::assertFalse($this->invokePrivate($provider, 'isForfaitEntryYear', $forfaitPhase, 2027)); + } + + public function testIsForfaitEntryYearFalseWhenForfaitStartsJan1(): void + { + $employee = $this->buildEmployeeWithTransition('2020-06-01', '2025-12-31', '2026-01-01'); + $forfaitPhase = new EmployeeContractPhaseResolver()->resolvePhases($employee)[0]; + $provider = $this->buildProvider(); + + // Forfait démarrant un 1er janvier = année pleine, pas une entrée en cours d'année. + self::assertFalse($this->invokePrivate($provider, 'isForfaitEntryYear', $forfaitPhase, 2026)); + } + + public function testIsForfaitEntryYearFalseForNonForfaitPhase(): void + { + $employee = $this->buildEmployeeWithTransition('2020-06-01', '2026-04-30', '2026-05-01'); + $h39Phase = new EmployeeContractPhaseResolver()->resolvePhases($employee)[1]; + $provider = $this->buildProvider(); + + self::assertFalse($this->invokePrivate($provider, 'isForfaitEntryYear', $h39Phase, 2026)); + } + public function testNonForfaitPhaseStartingMidExerciseUsesFullExerciseFromAsStart(): void { // Scenario: 35h CDI from 2014-07-01 to 2025-10-31, then 39h CDI from 2025-11-01.