Aller au contenu

Story AB-016 : Déclaration de Maternité (Backend + Frontend)

Module : absence-management Tranche : VS-AB-009 de l'architecture Contexte de marque : [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité : 16 Dépend de : AB-012 Peut se développer en parallèle avec : AB-014, AB-015 Ordre de fusion : Après AB-012 Complexité estimée : M PRD User Stories : US-ABS-004


Objectif

Permettre aux responsables RH et aux DG de créer des déclarations de maternité qui génèrent automatiquement un bloc de congé de 14 semaines : 6 semaines prénatales + 8 semaines postnatales (Art. 25.8 Code du Travail, 98 jours calendaires au total). Le congé est AUTO_APPROVED — aucune étape d'approbation manager n'est requise. Les congés annuels qui se chevauchent sont détectés et recrédités automatiquement via BalanceMutationService.


Périmètre Backend

Entités et Enregistrements

MaternityDeclaration (depuis AB-002) :

public class MaternityDeclaration {
    private UUID id;
    private UUID tenantId;
    private UUID employeeId;
    private LocalDate expectedDeliveryDate;
    private LocalDate actualDeliveryDate;       // nullable — renseigné via PATCH
    private LocalDate startDate;                 // calculé : expectedDeliveryDate - 42 jours
    private LocalDate endDate;                   // calculé : expectedDeliveryDate + 56 jours (ou actualDeliveryDate + 56 jours après mise à jour)
    private UUID leaveRequestId;                 // FK vers le LeaveRequest créé automatiquement
    private UUID supportingDocumentId;           // attestation médicale — obligatoire
    private Instant createdAt;
    private Instant updatedAt;
}

LeaveRequest (status=AUTO_APPROVED, type=MATERNITY) — utilise l'entité existante d'AB-002.

Enregistrements de requête :

public record CreateMaternityDeclarationRequest(
    @NotNull UUID employeeId,
    @NotNull LocalDate expectedDeliveryDate,
    @NotNull UUID supportingDocumentId          // attestation médicale — blocage dur
) {}

public record UpdateMaternityDeclarationRequest(
    @NotNull LocalDate actualDeliveryDate
) {}

Couche Repository

MaternityDeclarationRepository.java : - save(MaternityDeclaration declaration) — insertion ou mise à jour - findById(UUID id) — recherche d'une déclaration unique - findByTenantIdAndEmployeeId(UUID tenantId, UUID employeeId) — toutes les déclarations d'un employé - existsOverlapping(UUID tenantId, UUID employeeId, LocalDate startDate, LocalDate endDate) — vérifie le chevauchement avec des déclarations de maternité existantes

Couche Service

MaternityService.java :

  • createDeclaration(UUID employeeId, LocalDate expectedDeliveryDate, UUID supportingDocumentId) :
  • Calculer la période : startDate = expectedDeliveryDate - 42 jours, endDate = expectedDeliveryDate + 56 jours
  • Valider qu'il n'existe aucune déclaration de maternité chevauchante pour l'employé
  • Créer un LeaveRequest avec status=AUTO_APPROVED, type=MATERNITY
  • Détecter les congés annuels APPROVED qui se chevauchent avec la période de maternité
  • Pour chaque chevauchement : recréditer les jours de congé annuel chevauchants via une entrée de grand livre OVERLAP_CREDIT en utilisant BalanceMutationService
  • Notifier l'employé + le manager (publier un événement de notification)
  • Publier LeaveApproved avec { leaveType=MATERNITY, isPaid=true, payRate=100 }
  • Persister MaternityDeclaration et retourner la réponse

  • updateActualDeliveryDate(UUID declarationId, LocalDate actualDate) :

  • Charger la déclaration existante
  • Définir actualDeliveryDate
  • Recalculer la période post-accouchement : newEndDate = actualDate + 56 jours
  • La période pré-accouchement reste telle qu'initialement prise (FR-ABS-093)
  • Mettre à jour la date de fin du LeaveRequest associé
  • Réévaluer les crédits de chevauchement si la date de fin est étendue
  • Publier un LeaveApproved mis à jour

Points de terminaison API

Méthode Chemin Corps de la requête Réponse Auth
POST /api/v1/absence/maternity-declarations CreateMaternityDeclarationRequest ApiResponse<MaternityDeclarationResponse> (201) HR_MANAGER, DG
PATCH /api/v1/absence/maternity-declarations/:id UpdateMaternityDeclarationRequest ApiResponse<MaternityDeclarationResponse> HR_MANAGER, DG

Règles de validation

  • L'employé doit être ACTIVE (validé via la recherche dans le service employé)
  • expectedDeliveryDate doit être dans le futur — 422 "La date presumee d'accouchement doit etre dans le futur."
  • supportingDocumentId (attestation médicale) est obligatoire — 422 "L'attestation medicale est obligatoire."
  • Impossible de créer des déclarations de maternité chevauchantes pour le même employé — 409 "Une declaration de maternite existe deja pour cette periode."
  • actualDeliveryDate sur PATCH doit être une date valide (passée ou aujourd'hui) — 422 "La date d'accouchement doit etre dans le passe ou aujourd'hui."
  • La vérification du genre n'est PAS appliquée par le système (conception inclusive)

Considérations Multi-Tenant

  • Toutes les requêtes incluent tenantId depuis ScopedValue<TenantContext>
  • La table MaternityDeclaration possède une colonne tenant_id
  • La détection de chevauchement est limitée au tenant + employé
  • Fonctionne avec les 4 profils de base de données (conçu pour BYO-DB en priorité)

Périmètre Frontend

RAPPEL SYNCHRONISATION HORS LIGNE (Papillon — CRITIQUE) : La déclaration de maternité est une action en ligne uniquement — elle nécessite un accès RH/DG et le téléversement d'un document. Le formulaire est bloqué hors connexion avec un message clair.

Pages et Routes

Route Page Description
/absences/maternite/nouvelle MaternityDeclarationPage Formulaire de déclaration de maternité réservé aux RH/DG

Composants

  • InfoBanner — Bandeau d'information (bg=info-light) expliquant les droits à la maternité
  • FormField + Select (recherchable) — Recherche d'employé
  • FormField + DatePicker — Date présumée d'accouchement (DPA)
  • MaternityPeriodSummary — Carte de résumé auto-calculé (bg=primary-subtle) affichant le début, la fin et la durée
  • OverlapNotice — Texte d'information orange pour le recrédit de congé annuel chevauchant
  • FileUpload — Zone de téléversement de l'attestation médicale (obligatoire)
  • Button — Bouton d'envoi (primary, lg, fullWidth)
  • HelperText — Texte d'aide sous le bouton d'envoi

États UI (TOUS REQUIS)

État Comportement Copie Française
Chargement Squelette pour le select employé
Vide N/A (formulaire toujours disponible)
Erreur (validation) Erreurs inline sur les champs Divers messages de validation
Erreur (API) Toast "Impossible d'enregistrer la declaration."
Hors ligne Formulaire bloqué (action en ligne uniquement) "Cette action necessite une connexion internet"
Succès Animation confetti + Toast + navigation retour "Declaration enregistree — conge cree automatiquement"

Comportement Responsive

Mobile (360px — Papillon en priorité) : - Mise en page formulaire plein écran, colonne unique - Bandeau d'information en haut (bg=info-light) : "La maternite est un droit legal. Ce formulaire cree automatiquement un conge de 14 semaines." - FormField + Select (recherchable) pour l'employé : placeholder "Rechercher une employee..." - FormField + DatePicker pour la DPA : label "Date presumee d'accouchement" - Carte de résumé auto-calculé (bg=primary-subtle) : "Debut : {date} (DPA - 42 jours) / Fin : {date} (DPA + 56 jours) / Duree : 14 semaines (98 jours)" - Si chevauchement détecté : texte d'information orange : "{n} jours de conge annuel approuve seront recredites automatiquement." - Zone FileUpload : label "Attestation medicale" (obligatoire) - Bouton d'envoi : "Enregistrer la declaration" (primary, lg, fullWidth) - Aide : "L'employee et son manager seront notifies automatiquement." - Toutes les cibles tactiles >= 48px

Desktop (1024px+ — Enterprise en priorité) : - Modal ou panneau latéral, même flux de formulaire, max-width 600px - Espacement plus compact, même ordre de composants

Interactions

  • Recherche d'employé : recherche prédictive avec debounce (300ms), affiche le nom + matricule de l'employé
  • Sélection de la DPA : quand la date est sélectionnée, MaternityPeriodSummary calcule et s'affiche automatiquement
  • Détection de chevauchement : le client vérifie si un avertissement de chevauchement est nécessaire (l'API fournit le nombre de chevauchements lors du changement de DPA)
  • FileUpload : appuyer pour ouvrir le sélecteur de fichiers (mobile), glisser-déposer également supporté (desktop)
  • Envoi : valide tous les champs obligatoires côté client, puis POST vers l'API
  • Succès : animation confetti (200ms), toast, navigation vers /absences

Micro-Copie Française

  • maternity.info: "La maternite est un droit legal. Ce formulaire cree automatiquement un conge de 14 semaines."
  • maternity.employee: "Employee"
  • maternity.search: "Rechercher une employee..."
  • maternity.dpa: "Date presumee d'accouchement"
  • maternity.summary: "Resume du conge"
  • maternity.start: "Debut : {date} (DPA - 42 jours)"
  • maternity.end: "Fin : {date} (DPA + 56 jours)"
  • maternity.duration: "Duree : 14 semaines (98 jours)"
  • maternity.overlap: "{n} jours de conge annuel approuve seront recredites automatiquement."
  • maternity.attestation: "Attestation medicale"
  • maternity.submit: "Enregistrer la declaration"
  • maternity.notify: "L'employee et son manager seront notifies automatiquement."
  • maternity.error.future_date: "La date presumee d'accouchement doit etre dans le futur."
  • maternity.error.attestation_required: "L'attestation medicale est obligatoire."
  • maternity.error.overlap: "Une declaration de maternite existe deja pour cette periode."
  • maternity.error.save: "Impossible d'enregistrer la declaration."
  • maternity.offline: "Cette action necessite une connexion internet"
  • maternity.success: "Declaration enregistree — conge cree automatiquement"

Critères d'Acceptation

AC-051 : La maternité crée automatiquement un bloc de congé de 14 semaines
Étant donné que je saisis une date présumée d'accouchement
Quand j'enregistre la déclaration de maternité
Alors le système crée un bloc de congé de 14 semaines (6 semaines avant l'accouchement prévu + 8 semaines après)

AC-052 : Le congé maternité est auto-approuvé
Étant donné qu'un congé maternité est créé
Quand je le consulte
Alors il affiche le statut AUTO_APPROVED — aucune étape d'approbation manager n'est requise

AC-053 : Les jours de congé annuel chevauchants sont recrédités
Étant donné que l'employée a d'autres congés approuvés qui chevauchent la période de maternité
Quand la maternité est créée
Alors les jours de congé annuel chevauchants sont recrédités sur le solde de l'employée

Règles OHADA et Réglementaires

  • FR-ABS-090 : Maternité = 14 semaines (6 avant + 8 après l'accouchement)
  • FR-ABS-091 : Le RH saisit la date présumée d'accouchement ; le système calcule automatiquement la période de congé
  • FR-ABS-092 : Calcul automatique et création automatique avec résolution des chevauchements
  • FR-ABS-093 : La mise à jour de la date d'accouchement réelle recalcule uniquement la période post-accouchement — la période pré-accouchement reste telle qu'initialement prise
  • FR-ABS-094 : L'employeur paie 100%, demande le remboursement CNPS (TV-ABS-01)
  • FR-ABS-095 : L'employée est protégée contre le licenciement pendant toute la période de maternité

Standards et Conventions

  • docs/standards/java-spring-guidelines.md — §Patterns REST controller, §Application Events, §Patterns couche service
  • docs/standards/database-guidelines.md — §Pattern repository multi-tenant, §Isolation tenant dans chaque requête
  • docs/standards/api-guidelines.md — §Patterns endpoints POST/PATCH, §Enveloppe ApiResponse, §201 Created, §Erreurs de validation 422
  • docs/standards/react-typescript-guidelines.md — §Patterns de composants, §CSS Modules, §i18n, §Patterns de formulaires
  • docs/standards/design-system.md — §Select (recherchable), §DatePicker, §FileUpload, §Button, §Card, §InfoBanner
  • docs/standards/offline-sync-guidelines.md — §Actions en ligne uniquement, §Pattern de blocage hors ligne
  • docs/standards/multi-datasource-patterns.md — §Requêtes repository limitées au tenant

Exigences de Test

Tests Unitaires

  • MaternityService.createDeclaration() : entrée valide → crée un LeaveRequest avec AUTO_APPROVED + MaternityDeclaration
  • MaternityService.createDeclaration() : calcule start = DPA - 42 jours, end = DPA + 56 jours
  • MaternityService.createDeclaration() : congé annuel approuvé chevauchant (5 jours) → 5 entrées de grand livre OVERLAP_CREDIT
  • MaternityService.createDeclaration() : aucun congé annuel chevauchant → aucune entrée de recrédit
  • MaternityService.createDeclaration() : une déclaration de maternité chevauchante existe → 409
  • MaternityService.createDeclaration() : expectedDeliveryDate dans le passé → 422
  • MaternityService.createDeclaration() : supportingDocumentId manquant → 422
  • MaternityService.updateActualDeliveryDate() : recalcule end = actualDate + 56 jours, start inchangé
  • MaternityService.updateActualDeliveryDate() : date de fin étendue déclenche la réévaluation des crédits de chevauchement

Tests d'Intégration

  • POST déclaration de maternité valide → 201, LeaveRequest créé avec AUTO_APPROVED
  • POST avec expectedDeliveryDate dans le passé → 422
  • POST sans supportingDocumentId → 422
  • POST avec une déclaration chevauchante existante → 409
  • PATCH avec actualDeliveryDate → 200, date de fin recalculée
  • Multi-tenant : la déclaration du tenant A n'affecte pas le tenant B

Ce que QA Validera

  • Le formulaire s'affiche à 360px avec le bandeau d'information, la recherche d'employé, le sélecteur de date, le téléversement de fichier
  • La sélection de la DPA déclenche le calcul automatique du résumé de période
  • L'avis de chevauchement apparaît le cas échéant
  • Envoi avec données valides → confetti + toast + navigation
  • Envoi sans attestation → erreur inline
  • Hors ligne → formulaire bloqué avec "Cette action necessite une connexion internet"
  • Desktop : mise en page modal/panneau, max-width 600px

Hors Périmètre

  • Suivi du remboursement CNPS (processus comptable)
  • Application de la protection contre le licenciement (module Gestion des Employés)
  • Flux de congé paternité (utilise le flux de demande standard avec pré-remplissage de 2 jours via AB-010)
  • Extension de maternité pour complications médicales (V2)
  • Suivi de la réduction d'heures pour allaitement (V2)

Définition de Done

  • [ ] Tous les endpoints backend implémentés et retournant les réponses correctes
  • [ ] Toutes les pages frontend s'affichent correctement à 360px, 768px, 1024px
  • [ ] Les 5 états UI implémentés (chargement, vide, erreur, hors ligne, succès)
  • [ ] La micro-copie française correspond exactement à la spécification design
  • [ ] Tous les critères d'acceptation passent manuellement
  • [ ] Tests unitaires écrits et passants
  • [ ] Tests d'intégration écrits et passants
  • [ ] Isolation multi-tenant vérifiée — déclarations limitées au tenant, vérification des chevauchements par tenant+employé
  • [ ] Comportement hors ligne vérifié — formulaire bloqué avec message (Papillon) / N/A (Enterprise)
  • [ ] Pas de any TypeScript
  • [ ] Pas de types bruts Java — tous les génériques explicites
  • [ ] Les réponses API suivent le format d'enveloppe standard
  • [ ] Entrées de piste d'audit pour chaque mutation de données — LeaveApproved publié avec leaveType=MATERNITY