LST-66 (2.3) backend. Behaviour-preserving move of the absences domain into
src/Module/Absence/. API operations, securities, routes and the 10 MCP tool
names are unchanged.
- 3 entities + 3 enums moved to Domain/{Entity,Enum}; user relations stay on
UserInterface. 3 repositories split into Domain/Repository interfaces +
Doctrine impls (bound in services.yaml); find() kept off interfaces
(findById instead).
- Pure services (AbsenceDayCalculator, PublicHolidayProvider) -> Domain/Service;
AbsenceBalanceService -> Application/Service; State (5), controllers (5),
10 MCP tools and AccrueLeaveCommand -> Infrastructure/.
- New LeaveProfileInterface contract (Shared) exposes the HR getters used by
AbsenceBalanceService/AccrueLeaveCommand; User implements it -> Absence no
longer imports the concrete Core User. MCP tools/command inject
UserRepositoryInterface (findById) instead of the concrete repository.
- Timestampable/Blamable added to AbsenceBalance and AbsencePolicy (additive
migration: created_at/updated_at + created_by/updated_by FK ON DELETE SET
NULL + COMMENT). AbsenceRequest untouched (already has createdAt/reviewedAt).
- AbsenceModule registered (id absence, 4 RBAC perms, not re-wired); doctrine
mapping added; team-absences sidebar item gated by the module.
161 tests green, mapping valid, no API route regression, cs-fixer clean.
Sur une demande d'un seul jour, le formulaire recopie la demi-journée de
début sur la fin (même date), si bien que les deux bornes portaient une
demi-journée et 0,5 était soustrait deux fois (1 - 0,5 - 0,5 = 0).
Quand start et end tombent le même jour, les deux bornes se confondent :
on ne soustrait désormais 0,5 qu'une seule fois. Comparaison par
getTimestamp() pour rester compatible strict_comparison (=== sur deux
DateTimeImmutable distincts teste l'identité d'instance, pas la valeur).
Couverture complétée : mono-jour plein, week-end, férié, inversion de
dates, demi-journée de fin seule, demi sur samedi en mode ouvrables.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Périmètre 1-6 du design 2026-05-22-absence-legal-compliance-fixes (points
lourds — ancienneté, CP pendant maladie, rétention — reportés en backlog).
- Événements familiaux sans solde : AbsenceType::decrementsBalance() ne vaut
true que pour les CP. Mariage/PACS, naissance, décès = droits par événement ;
congé parental = suspension ; maladie = Sécu. Plus de solde fantôme.
- Décès : daysPerEvent = null (selon lien de parenté) + motif obligatoire à la
création (REST + MCP), les minimums légaux étant rappelés dans l'aide.
- Ajout du congé naissance (type, policy 3 j, justificatif, libellés/couleur front).
- Garde-fou demi-journée : -0,5 appliqué uniquement si le jour-borne est
réellement décompté (corrige un sous-décompte week-end/férié) — TDD.
- CCN documentée : paramètre app.absence.convention = "Syntec (IDCC 1486)",
rappelée en sous-titre admin et dans l'aide /help.
Tests : AbsenceDayCalculatorTest (garde-fou demi-journée), AbsenceRequestLifecycle
(motif décès obligatoire + aucun solde touché). make test 52/52, build Nuxt OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>