EmployeeContractPhaseResolver now accepts the data-start date and filters
out phases whose endDate is strictly before it. No work-hour or absence
data exists before the application launch date, so legacy contract
periods that ended before that date would surface meaningless RTT/CP
figures in the phase picker.
For employees who joined long before the software (typical legacy 35h
contracts, in production since 2014), only the current phase remains
visible — which also collapses the picker (threshold ≥ 2 phases).
The Employee entity reads RTT_START_DATE from $_SERVER/$_ENV directly
since it has no DI. The resolver service is wired via services.yaml.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pull the "date -> leave/RTT exercise year" formula out of
EmployeeRttPaymentProcessor, EmployeeRttSummaryProvider and
EmployeeLeaveSummaryProvider into a single
App\Service\Exercise\ExerciseYearResolver. Forfait flag is parameterised
so the leave (calendar year) and RTT (Juin N-1 -> Mai N) variants share
the same implementation. Pure refactor, no behavioural change.
- Extract private helper `exerciseYearForDate(date, isForfait)` to dedupe
the date->leave-exercise-year expression duplicated across `clampYearToPhase`
and `resolveFirstComputationYear` (4 copies collapsed into 1 helper + 4
call sites).
- Remove the unused `ContractPhase $phase` parameter from
`resolveLeavePeriodBounds`: the body never reads it (the phase cap is
applied later by `resolvePeriodBounds`).
- Add `ContractNature $contractNature` to `ContractPhase` DTO, populated
from the first period of the group by `EmployeeContractPhaseResolver`.
Drop the `resolveNatureForPhase` lookup in `EmployeeLeaveSummaryProvider`
in favor of `$phase->contractNature`. Expose `contractNature` in
`Employee::getContractPhases()` array shape for frontend use.
- Fix regression for terminated employees calling `computeYearSummary`
without an explicit phase (LeaveRecapRowBuilder,
DumpVerificationSnapshotCommand). Before the refactor the period bounds,
accrual end and taken end were NOT capped at the contract end for
terminated employees, because `Employee::getCurrentContractEndDate()`
returns null when no period covers "today". The new fallback phase
(`isCurrent=false`, real `endDate`) was silently capping `to`. Add an
internal `applyPhaseEndCap` flag, true when phase is explicit, false
for legacy callers, threaded through `resolvePeriodBounds`,
`resolveAccrualCalculationEndDate` and `resolveTakenCalculationEndDate`.
- Add regression test
`testTerminatedEmployeeWithoutExplicitPhaseSkipsPhaseEndCap` proving
that legacy callers keep the natural exercise upper bound while explicit
phase callers get the cap.
- Add `contractNature` assertion in `EmployeeContractPhaseResolverTest`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
| #339 | Ajout d'une page listant les règles de calcules |
## Description de la PR
[#339] Ajout d'une page listant les règles de calcules
## Modification du .env
## Check list
- [ ] Pas de régression
- [x] TU/TI/TF rédigée
- [x] TU/TI/TF OK
- [ ] CHANGELOG modifié
Reviewed-on: #5
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>