feat(leave) : forfait mid-year entry credits prorated repos + carried CP

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 16:17:07 +02:00
parent b43f854528
commit 37c718c839

View File

@@ -763,6 +763,33 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
{
$type = $phase->contractType;
if (ContractType::FORFAIT === $type) {
$year = (int) $from->format('Y'); // période forfait = année civile
// Entrée en FORFAIT en cours d'année : repos proratisés + CP nets reportés de
// la phase précédente, au lieu de max(0, businessDays 218) qui donnerait 0.
if ($this->isForfaitEntryYear($phase, $year)) {
$yearStart = new DateTimeImmutable(sprintf('%d-01-01 00:00:00', $year));
$yearEnd = new DateTimeImmutable(sprintf('%d-12-31 00:00:00', $year));
$rawYearHolidays = $this->buildRawPublicHolidayMap($yearStart, $yearEnd);
$businessDaysYear = $this->countBusinessDays($yearStart, $yearEnd, $rawYearHolidays);
$businessDaysPeriod = $this->countBusinessDays($from, $to, $rawYearHolidays);
$repoDays = $this->computeProratedForfaitRepoDays($businessDaysYear, $businessDaysPeriod);
$carriedCp = $this->resolveCarriedCpFromPriorPhase($employee, $phase);
return [
'ruleCode' => LeaveRuleCode::FORFAIT_218->value,
'acquiredDays' => $repoDays + $carriedCp,
'acquiredSaturdays' => 0.0,
'accrualPerMonth' => 0.0,
'saturdayAccrualPerMonth' => 0.0,
'countOnlyCp' => false,
'splitSaturdays' => false,
];
}
// Année pleine : calcul 218 existant (INCHANGÉ).
// Business days for forfait must use the RAW holiday list (excluded holidays like
// "Lundi de Pentecôte" / journée de solidarité still count as non-working days for
// the 218-day legal target).