Compare commits

..

9 Commits

Author SHA1 Message Date
gitea-actions
f7dc9b6988 chore: bump version to v0.1.26
All checks were successful
Auto Tag Develop / tag (push) Successful in 4s
Build Release Artefact / build (push) Successful in 1m11s
2026-03-11 16:34:29 +00:00
b0de877b27 Merge remote-tracking branch 'origin/develop' into develop
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
2026-03-11 17:34:15 +01:00
59f05717bf fix : prise en compte des congés au provisionnel sauf pour les en cours d'acquisition 2026-03-11 17:34:07 +01:00
gitea-actions
f96fd64767 chore: bump version to v0.1.25
All checks were successful
Auto Tag Develop / tag (push) Successful in 4s
Build Release Artefact / build (push) Successful in 1m12s
2026-03-11 16:27:05 +00:00
523d4f296b fix : prise en compte des congés au provisionnel
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
2026-03-11 17:26:48 +01:00
gitea-actions
3994be6556 chore: bump version to v0.1.24
All checks were successful
Auto Tag Develop / tag (push) Successful in 4s
Build Release Artefact / build (push) Successful in 1m8s
2026-03-11 12:53:39 +00:00
f46eeaa893 fix : prise en compte des jours de congés sur l'année N-1 même si on a pas d'historique de contrat sur l'année N-1
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
2026-03-11 13:53:29 +01:00
gitea-actions
eb703272c7 chore: bump version to v0.1.23
All checks were successful
Auto Tag Develop / tag (push) Successful in 4s
Build Release Artefact / build (push) Successful in 1m11s
2026-03-11 10:41:38 +00:00
6629eb98cb fix : on ne prend plus en compte les jour de congé du samedi et dimanche pour les forfaits dans le calcule des RTT
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
2026-03-11 11:41:26 +01:00
4 changed files with 60 additions and 14 deletions

View File

@@ -1,2 +1,2 @@
parameters:
app.version: '0.1.22'
app.version: '0.1.26'

View File

@@ -198,13 +198,16 @@ Tous les filtres checkbox sont cochés par défaut à l'ouverture du drawer.
- lecture des compteurs:
- `acquis` = droits reportés de l'exercice N-1 (après application des règles de soldé)
- `en cours d'acquisition` = total droits générés sur l'exercice N (jours + samedis en cours), sans detail séparé en UI
- `en cours d'acquisition` est arrêté au dernier jour du mois précédent
- règle de consommation:
- les absences s'imputent d'abord sur `acquis`, puis sur `en cours d'acquisition`
- la prise sur `en cours d'acquisition` est autorisée (usage anticipé)
- `en cours d'acquisition` peut devenir négatif si la prise dépasse le généré (ex: `2.08 - 3 = -0.92`), puis se reconstitue avec les acquisitions suivantes
- date d'arret de calcul:
- les compteurs sont calculés jusqu'au dernier jour du mois précédent (le mois en cours est exclu)
- exemple: au `04/03/2026`, l'arret de calcul est le `28/02/2026` (ou `29/02` en année bissextile)
- `reste à prendre` est calculé en prévisionnel jusqu'à la fin de l'exercice
- les absences futures déjà posées sur l'exercice sont déduites du `reste à prendre`
- `en cours d'acquisition` reste calculé jusqu'au dernier jour du mois précédent
- exemple: au `11/03/2026`, l'exercice `2026` déduit les absences posées jusqu'au `31/05/2026`, mais l'acquisition reste arrêtée au `28/02/2026`
- hors périmètre phase 1: `INTERIM` (retour non supporté)
- onglet `RTT`:
- endpoint de synthèse: `GET /api/employees/{id}/rtt-summary?year=YYYY`

View File

@@ -349,14 +349,25 @@ final readonly class LeaveBalanceComputationService
}
for ($cursor = $rangeStart; $cursor <= $rangeEnd; $cursor = $cursor->modify('+1 day')) {
$dayOfWeek = (int) $cursor->format('N');
if ($splitSaturdays) {
if (7 === $dayOfWeek) {
continue;
}
} else {
if ($dayOfWeek >= 6) {
continue;
}
}
[$am, $pm] = $this->resolveSegmentsForDate($absence, $cursor->format('Y-m-d'));
$dayAmount = ($am ? 0.5 : 0.0) + ($pm ? 0.5 : 0.0);
if ($dayAmount <= 0.0) {
continue;
}
$isSaturday = $splitSaturdays && '6' === $cursor->format('N');
if ($isSaturday) {
if ($splitSaturdays && 6 === $dayOfWeek) {
$takenSaturdays += $dayAmount;
} else {
$takenDays += $dayAmount;

View File

@@ -163,18 +163,19 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
$effectiveFrom = $this->resolveEffectivePeriodStart($employee, $from, $to);
$hasShiftedStart = $effectiveFrom > $from;
if ($hasShiftedStart) {
if ($hasShiftedStart && null === $openingBalance) {
$carryDays = 0.0;
$carrySaturdays = 0.0;
}
$calculationEnd = $this->resolveCalculationEndDate($leavePolicy['ruleCode'], $year, $to, $employee);
$generatedDays = $leavePolicy['accrualPerMonth'] > 0.0
$accrualCalculationEnd = $this->resolveAccrualCalculationEndDate($leavePolicy['ruleCode'], $year, $to, $employee);
$takenCalculationEnd = $this->resolveTakenCalculationEndDate($to, $employee);
$generatedDays = $leavePolicy['accrualPerMonth'] > 0.0
? $this->computeAccruedDaysFromStart(
$leavePolicy['acquiredDays'],
$leavePolicy['accrualPerMonth'],
$effectiveFrom,
$calculationEnd
$accrualCalculationEnd
)
: 0.0;
$generatedSaturdays = $leavePolicy['saturdayAccrualPerMonth'] > 0.0
@@ -182,14 +183,14 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
$leavePolicy['acquiredSaturdays'],
$leavePolicy['saturdayAccrualPerMonth'],
$effectiveFrom,
$calculationEnd
$accrualCalculationEnd
)
: 0.0;
$absences = $this->absenceRepository->findByEmployeeAndOverlappingDateRange($employee, $from, $to);
[$takenDays, $takenSaturdays] = $this->computeTakenAbsences(
$absences,
$effectiveFrom,
$calculationEnd,
$takenCalculationEnd,
$leavePolicy['countOnlyCp'],
$leavePolicy['splitSaturdays']
);
@@ -353,7 +354,7 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
return min($acquiredDays, $monthsElapsed * $accrualPerMonth);
}
private function resolveCalculationEndDate(
private function resolveAccrualCalculationEndDate(
string $ruleCode,
int $year,
DateTimeImmutable $periodEnd,
@@ -388,6 +389,24 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
return $end;
}
private function resolveTakenCalculationEndDate(
DateTimeImmutable $periodEnd,
Employee $employee
): ?DateTimeImmutable {
$end = $periodEnd;
// Cap at contract end date if the employee has left.
$contractEndRaw = $employee->getCurrentContractEndDate();
if (null !== $end && null !== $contractEndRaw && '' !== trim($contractEndRaw)) {
$contractEnd = DateTimeImmutable::createFromFormat('Y-m-d', $contractEndRaw);
if ($contractEnd instanceof DateTimeImmutable && $contractEnd < $end) {
$end = $contractEnd;
}
}
return $end;
}
/**
* @return null|array{
* ruleCode: string,
@@ -632,14 +651,27 @@ final readonly class EmployeeLeaveSummaryProvider implements ProviderInterface
}
for ($cursor = $rangeStart; $cursor <= $rangeEnd; $cursor = $cursor->modify('+1 day')) {
$dayOfWeek = (int) $cursor->format('N');
if ($splitSaturdays) {
// Mode CDI/CDD : dimanche ignoré, samedi compté séparément.
if (7 === $dayOfWeek) {
continue;
}
} else {
// Mode forfait : seuls les jours ouvrés (lun-ven) comptent.
if ($dayOfWeek >= 6) {
continue;
}
}
[$am, $pm] = $this->resolveSegmentsForDate($absence, $cursor->format('Y-m-d'));
$dayAmount = ($am ? 0.5 : 0.0) + ($pm ? 0.5 : 0.0);
if ($dayAmount <= 0.0) {
continue;
}
$isSaturday = $splitSaturdays && '6' === $cursor->format('N');
if ($isSaturday && $splitSaturdays) {
if ($splitSaturdays && 6 === $dayOfWeek) {
$takenSaturdays += $dayAmount;
} else {
$takenDays += $dayAmount;