fix : correction calcule prorata congés avec un arrêt maladie long
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
This commit is contained in:
@@ -24,6 +24,7 @@ final readonly class LeaveBalanceComputationService
|
||||
private const float STANDARD_SATURDAY_ACCRUAL_PER_MONTH = self::STANDARD_ANNUAL_SATURDAYS / 12.0;
|
||||
private const float FOUR_HOUR_ANNUAL_DAYS = 10.0;
|
||||
private const float FOUR_HOUR_ACCRUAL_PER_MONTH = 0.83;
|
||||
private const float LONG_MALADIE_MONTHLY_ACCRUAL = 2.0;
|
||||
|
||||
public function __construct(
|
||||
private AbsenceRepository $absenceRepository,
|
||||
@@ -31,6 +32,7 @@ final readonly class LeaveBalanceComputationService
|
||||
private EmployeeLeaveBalanceRepository $leaveBalanceRepository,
|
||||
private PublicHolidayServiceInterface $publicHolidayService,
|
||||
private SuspensionDaysCalculator $suspensionDaysCalculator,
|
||||
private LongMaladieService $longMaladieService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -83,19 +85,34 @@ final readonly class LeaveBalanceComputationService
|
||||
$suspensions = $this->suspensionDaysCalculator->applyFirstMonthGrace(
|
||||
$this->resolveSuspensionsForEmployeePeriod($employee, $from, $to)
|
||||
);
|
||||
|
||||
$longMaladiePeriods = [];
|
||||
$longMaladieReductionFactor = 1.0;
|
||||
if (4 !== $employee->getContract()?->getWeeklyHours()) {
|
||||
$longMaladiePeriods = $this->longMaladieService->findReducedRatePeriods($employee, $effectiveFrom, $to);
|
||||
if ([] !== $longMaladiePeriods) {
|
||||
$totalNormalAccrual = $this->resolveDaysAccrualPerMonth($employee) + $this->resolveSaturdayAccrualPerMonth($employee);
|
||||
$longMaladieReductionFactor = self::LONG_MALADIE_MONTHLY_ACCRUAL / $totalNormalAccrual;
|
||||
}
|
||||
}
|
||||
|
||||
$generatedDays = $this->computeAccruedDays(
|
||||
$this->resolveAnnualDays($employee),
|
||||
$this->resolveDaysAccrualPerMonth($employee),
|
||||
$effectiveFrom,
|
||||
$to,
|
||||
$suspensions
|
||||
$suspensions,
|
||||
$longMaladiePeriods,
|
||||
$longMaladieReductionFactor
|
||||
);
|
||||
$generatedSaturdays = $this->computeAccruedDays(
|
||||
$this->resolveAnnualSaturdays($employee),
|
||||
$this->resolveSaturdayAccrualPerMonth($employee),
|
||||
$effectiveFrom,
|
||||
$to,
|
||||
$suspensions
|
||||
$suspensions,
|
||||
$longMaladiePeriods,
|
||||
$longMaladieReductionFactor
|
||||
);
|
||||
|
||||
$absences = $this->absenceRepository->findByEmployeeAndOverlappingDateRange($employee, $effectiveFrom, $to);
|
||||
@@ -267,12 +284,18 @@ final readonly class LeaveBalanceComputationService
|
||||
: self::STANDARD_SATURDAY_ACCRUAL_PER_MONTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<ContractSuspension> $suspensions
|
||||
* @param list<array{start: DateTimeImmutable, end: DateTimeImmutable}> $longMaladiePeriods
|
||||
*/
|
||||
private function computeAccruedDays(
|
||||
float $annualCap,
|
||||
float $accrualPerMonth,
|
||||
DateTimeImmutable $periodStart,
|
||||
DateTimeImmutable $periodEnd,
|
||||
array $suspensions = []
|
||||
array $suspensions = [],
|
||||
array $longMaladiePeriods = [],
|
||||
float $longMaladieReductionFactor = 1.0
|
||||
): float {
|
||||
if ($accrualPerMonth <= 0.0 || $periodEnd < $periodStart) {
|
||||
return 0.0;
|
||||
@@ -281,7 +304,8 @@ final readonly class LeaveBalanceComputationService
|
||||
$periodStart = $this->normalizeDate($periodStart);
|
||||
$periodEnd = $this->normalizeDate($periodEnd);
|
||||
$publicHolidays = [] !== $suspensions ? $this->buildPublicHolidayMap($periodStart, $periodEnd) : [];
|
||||
$coveredMonths = 0.0;
|
||||
$normalMonths = 0.0;
|
||||
$reducedMonths = 0.0;
|
||||
$cursor = $periodStart->modify('first day of this month')->setTime(0, 0);
|
||||
while ($cursor <= $periodEnd) {
|
||||
$monthStart = $cursor > $periodStart ? $cursor : $periodStart;
|
||||
@@ -295,7 +319,7 @@ final readonly class LeaveBalanceComputationService
|
||||
if ($suspendedDays > 0) {
|
||||
$businessDays = $this->countBusinessDaysInRange($monthStart, $monthEnd, $publicHolidays);
|
||||
$suspendedBusinessDays = $this->suspensionDaysCalculator->countSuspendedBusinessDays($monthStart, $monthEnd, $suspensions, $publicHolidays);
|
||||
$coveredMonths += max(0, $businessDays - $suspendedBusinessDays) / 22.0;
|
||||
$normalMonths += max(0, $businessDays - $suspendedBusinessDays) / 22.0;
|
||||
$cursor = $cursor->modify('first day of next month');
|
||||
|
||||
continue;
|
||||
@@ -304,12 +328,25 @@ final readonly class LeaveBalanceComputationService
|
||||
|
||||
$coveredDays = ((int) $monthEnd->diff($monthStart)->format('%a')) + 1;
|
||||
$daysInMonth = (int) $cursor->format('t');
|
||||
$coveredMonths += $coveredDays / $daysInMonth;
|
||||
|
||||
if ([] !== $longMaladiePeriods) {
|
||||
$reducedDays = $this->longMaladieService->countReducedDaysInMonth($monthStart, $monthEnd, $longMaladiePeriods);
|
||||
if ($reducedDays > 0) {
|
||||
$normalDays = max(0, $coveredDays - $reducedDays);
|
||||
$normalMonths += $normalDays / $daysInMonth;
|
||||
$reducedMonths += min($coveredDays, $reducedDays) / $daysInMonth;
|
||||
$cursor = $cursor->modify('first day of next month');
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$normalMonths += $coveredDays / $daysInMonth;
|
||||
|
||||
$cursor = $cursor->modify('first day of next month');
|
||||
}
|
||||
|
||||
return min($annualCap, $coveredMonths * $accrualPerMonth);
|
||||
return min($annualCap, ($normalMonths + $reducedMonths * $longMaladieReductionFactor) * $accrualPerMonth);
|
||||
}
|
||||
|
||||
private function parseYmdDate(string $value): ?DateTimeImmutable
|
||||
|
||||
Reference in New Issue
Block a user