# Suivi - Caisses internes, accueil ponctuel, RH (2026-08-10 →)

*Document de suivi pour reprendre ce chantier après une déconnexion -
statut de chaque point, ce qui reste à valider avant de coder. Le détail
fonctionnel complet est dans `documentation/cahier-des-charges-creche-v4.1.md`
(§14 à §19, ajoutés le 2026-08-10). Origine : retour client brut dans
`documentation/retour_clients` (à ne pas modifier, propriété de
l'utilisateur).

**Phase actuelle : implémentation terminée** - les 8 modules validés le
2026-08-10 sont tous codés, testés et vérifiés en E2E (démarrage
autorisé le 2026-08-11 : "on garde l'ordre que tu as defini, tu peux
demarrer le codage"). Reste seulement les micro-ajustements non
bloquants listés en bas de ce document.

## Statut par sujet

| Sujet | Statut | Détail |
| --- | --- | --- |
| Caisses - concept extensible | ✅ Validé | §14 |
| Accès caisses | ✅ Validé | §14.1 - Direction : création + consultation ; Comptabilité : saisie de mouvements dans une caisse existante, pas de création |
| Facture libre (sans contrat) | ✅ Validé | §14.2.b, §16.1.a |
| Accueil ponctuel / garderie - réutiliser Enfant | ✅ Validé | §15.1 |
| Accueil ponctuel - restitution du suivi | ✅ Validé | §15.2 - email si adresse renseignée, sinon impression sur place |
| Scolarité en tranches | ✅ Validé (à construire) | §16.1.b |
| Dépenses fixes + marge réelle | ✅ Validé | §16.1.c |
| Cantine - catalogue saisonnier informatif | ✅ Validé | §17 |
| Produits vendus - avec stock | ✅ Validé | §18 |
| RH - contrats de travail (accès Direction seule) | ✅ Validé | §19.2.a - liste de champs proposée, à ajuster (cf. ci-dessous) |
| RH - congés (déclaratif + solde estimé auto) | ✅ Validé | §19.2.b - droit ivoirien vérifié (2,2j/mois, 24j/an) comme taux par défaut, **paramétrable par établissement** (écran `/administration/rh`) ; solde = mois travaillés (depuis le 1er contrat) × taux − congés payés pris + corrections manuelles ; rappel légal + invitation à vérification juriste toujours affiché |
| RH - jours posés exceptionnels | ✅ Validé | §19.2.c - type de congé sans solde |
| RH - salaires (montant + confirmation virement) | ✅ Validé | §19.2.d - réutilise le mécanisme des dépenses fixes |
| RH - accès (contrat = Direction, salaire = Compta+Direction) | ✅ Validé | §19.2.e |

**Tout est validé à ce stade.** Il ne reste que des micro-ajustements
(pas des points bloquants) - voir ci-dessous.

## Ce qui reste à affiner (non bloquant, à confirmer en cours de route)

1. **Liste exacte des champs du contrat de travail** - proposition dans
   §19.2.a (type de contrat, poste, dates, salaire de base, régime
   horaire, numéro CNPS) à valider ou ajuster avec la direction, mais
   ne bloque pas le démarrage du codage sur les autres modules.

**Calcul automatique du solde de congés - fait le 2026-08-12.** Décision
client : le taux de base (2,2j/mois par défaut, droit ivoirien) est
maintenant calculé automatiquement, mais reste **paramétrable par la
Direction** (`Etablissement::joursCongesAcquisParMois`, écran
`/administration/rh`, valeur par défaut si non renseigné) - les
majorations (ancienneté, enfants à charge) ne sont volontairement pas
automatisées, seul le taux de base l'est. Le solde peut aussi être
**corrigé manuellement** (report d'une année antérieure, régularisation)
via une correction cumulative (`AjustementSoldeConge`, append-only) qui
**n'est jamais écrasée par le recalcul automatique** - le recalcul est
purement dérivé des congés déclarés et du taux paramétré, les
corrections manuelles vivent à part et s'additionnent toujours au
résultat. Le rappel légal + l'invitation à vérification par une juriste
restent affichés sur l'écran de déclaration (l'estimation ne remplace
pas un avis professionnel).

## Ordre d'implémentation (suivi)

*Logique : d'abord ce qui débloque le concept transverse (caisses +
facture libre), ensuite ce qui en dépend directement.*

1. ✅ **Facture libre** (lever la contrainte `Contrat` obligatoire sur
   `Facture`) - prérequis technique de presque tout le reste. Fait le
   2026-08-11 : `Facture::contrat` nullable (entité + migration
   `Version20260811112306`), nouveau
   `ModeFacturation::LIBRE`, nouvelle méthode
   `FactureService::genererLibre(Enfant, montant, libellé, période,
   généréePar)` (pas encore de paramètre `Caisse` - sera étendu à
   l'étape 2). Aucun appelant pour l'instant (attendu : caisses,
   garderie, produits vendus). Suite complète verte (395 tests),
   `doctrine:schema:validate` confirme la colonne `facture.contrat_id`
   synchronisée (seul écart restant : dérive préexistante et non liée sur
   `theme_activite`, migration antérieure).
2. ✅ **Caisses** (entité + écrans Direction/Comptabilité) - cœur du
   chantier, réutilisé par la garderie et les produits vendus. Fait le
   2026-08-11 : entité `Caisse` (nom, mode, migration
   `Version20260811113128`), `Facture.caisse`/`Depense.caisse` nullables
   (facture libre et dépense rattachables à une caisse),
   `CaisseService::creer()/lister()/solde()`, écran
   `/comptabilite/caisses` (liste + création, formulaire de création
   masqué hors Direction, contrôleur gardé par
   `denyAccessUnlessGranted('ROLE_DIRECTION')`) et
   `/comptabilite/caisses/{id}` (détail : solde, nouvelle facture libre,
   nouvelle dépense, historique). Vérifié en E2E manuel (serveur PHP
   local, comptes recette fondateur/comptabilité) : création de caisse
   refusée en 403 pour Comptabilité, formulaire masqué côté template,
   dépense en attente n'affecte pas le solde tant qu'elle n'est pas
   validée par un autre compte (double validation §7.2.j réutilisée telle
   quelle), solde recalculé correctement après validation. Suite complète
   verte (400 tests), DB remise aux fixtures après le test manuel.
3. ✅ **Dépenses fixes** - indépendant du reste, relativement isolé, vient
   enrichir l'écran Trésorerie existant. Les salaires (RH, point 8) en
   dépendront directement - vaut le coup de le poser tôt. Fait le
   2026-08-11 : entités `DepenseFixe` (liste permanente, actif/inactif,
   même patron que `CategorieDepense`) et `EcheanceDepenseFixe`
   (occurrence datée, pointage manuel payée/non payée - jamais de
   `Depense` générée automatiquement), migration
   `Version20260811114110`. `TresorerieService::calculerVueDEnsemble()`
   étendu avec `depensesFixesDues` (somme des échéances non payées dues
   sur le mois calendaire en cours) et `margeReelle` (solde − dépenses
   fixes dues) - les caisses (§14) n'ont pas besoin d'être rajoutées
   séparément, leurs paiements/dépenses sont déjà dans `solde`. Écran
   `/comptabilite/depenses-fixes` (création dépense fixe,
   activer/désactiver, création + pointage d'échéance) + indicateur
   ajouté sur `/comptabilite/tresorerie`. Vérifié en E2E manuel : création
   d'une dépense fixe "Loyer", échéance du mois en cours, indicateur
   "argent réellement disponible" passe à -250000, repasse à 0 une fois
   l'échéance marquée payée. Suite complète verte (409 tests), DB remise
   aux fixtures après le test manuel.
4. ✅ **Cantine saisonnière** - le plus petit morceau (catalogue simple,
   patron déjà éprouvé avec `ThemeActivite`), bon "quick win" une fois
   les caisses posées. Fait le 2026-08-11 : entité `ProduitSaisonnier`
   (libellé, prix indicatif, dateDebut/dateFin obligatoires - contrairement
   à `ThemeActivite` où elles restent facultatives -, actif/inactif, même
   patron "jamais supprimé"), migration `Version20260811114659`. Gestion
   Direction sur `/administration/produits-saisonniers` (créer,
   activer/désactiver). Consultation en lecture seule ajoutée en haut de
   l'écran Cantine (`/cantine`, `ProduitSaisonnierService::listerEnCours()`
   - produits actifs dont la période couvre la date du jour). Vérifié en
   E2E manuel : produit créé par Direction visible immédiatement côté
   Cantine, `/administration/produits-saisonniers` refusé en 403 pour le
   compte Cantine. Suite complète verte (415 tests), DB remise aux
   fixtures après le test manuel.
5. ✅ **Produits vendus & stock** - dépend des caisses (point 2) et de la
   facture libre (point 1). Fait le 2026-08-11 : entité `ProduitVendu`
   (nom, prix, quantiteStock, seuilAlerte configurable par produit - le
   seuil numérique n'a volontairement pas été tranché côté client, cf.
   "reste à affiner" ci-dessous), migration `Version20260811115128`.
   `ProduitVenduService::vendre()`/`reapprovisionner()` délèguent à
   `FactureService::genererLibre()`/`DepenseService::saisir()` plutôt que
   dupliquer la mécanique - mêmes primitives que les caisses (§14) et,
   plus tard, la garderie (§15). Écran `/comptabilite/produits-vendus` :
   gestion du catalogue (créer, activer/désactiver) réservée Direction
   (§11), vente et réapprovisionnement accessibles Comptabilité+Direction
   - caisse de rattachement laissée au choix dans le formulaire plutôt que
   figée en dur sur une caisse "Produits vendus" nommée précisément, pour
   rester cohérent avec le principe "aucune liste figée" déjà posé pour
   les caisses. Vérifié en E2E manuel : création produit par Direction,
   apparition immédiate dans les listes vente/réappro, réapprovisionnement
   incrémente le stock (10 → 15) et génère une dépense en attente, vente
   décrémente correctement en cas de succès et ne touche pas au stock en
   cas d'échec (`AucunPayeurDefiniException`, atomicité confirmée), 403
   pour Comptabilité sur la création de produit. Suite complète verte
   (420 tests), DB remise aux fixtures après le test manuel.
6. ✅ **Accueil ponctuel / garderie** - dépend des caisses et de la
   facture libre ; touche aussi le suivi quotidien existant (Module 2)
   et l'envoi d'email, donc plus délicat - à faire une fois le socle
   "caisses" stable. Fait le 2026-08-11 : `Enfant.typeInscription`
   (enum `TypeInscriptionEnfant`, migration backfill 3 étapes - ajout
   nullable, `UPDATE ... = 'reguliere'`, `MODIFY NOT NULL`, même patron
   que la migration `Sondage.dateCloture`) ; entité `AccueilPonctuel`
   (période, tarifs, statut, canal de restitution), migration
   `Version20260811120056`. `AccueilPonctuelService::enregistrer()`
   réutilise exactement le schéma d'admission existant
   (`InscriptionService::admettre()`) : `Enfant` +
   `ResponsableLegal` (jamais de `compteUtilisateur` - pas de compte
   parent) + `EnfantResponsableLegal` (payeur + contact urgence), plus
   une `AlerteEnfant` (`TypeAlerte::CONSIGNE_MEDICALE`) si des infos de
   sécurité sont fournies. `cloturer()` marque l'enfant sorti (mêmes
   champs `actif`/`dateSortie` que la fin de présence régulière, §6.2.f),
   appelle `SuiviParentService::filDuJour()` (déjà construit pour
   l'espace parent - aucune nouvelle agrégation) et envoie un email
   (Symfony Mailer + Sweego, texte via nouveau template
   `accueil_ponctuel_recapitulatif_email.txt.twig`) si un contact a une
   adresse, sinon redirige vers un écran imprimable
   (`window.print()` + CSS `@media print` masquant sidebar/header).
   Écran `/administration/accueil-ponctuel`, Direction exclusivement
   (§11) - la facturation réutilise telle quelle l'écran "facture libre"
   d'une caisse (§14), aucune mécanique de facturation dupliquée.
   **Correctif trouvé en E2E** : le sélecteur d'enfant de l'écran caisse
   (`CaisseController::detail()`) ne listait que les enfants actifs -
   un accueil ponctuel clôturé devient `actif = false`, donc invisible
   pour la facturation après récupération. Corrigé (actif OU
   `ACCUEIL_PONCTUEL`, quel que soit le statut). Vérifié en E2E manuel
   de bout en bout : enregistrement → suivi quotidien réutilisé →
   clôture avec email (contact avec adresse) → clôture avec redirection
   impression (contact sans adresse) → facturation via la caisse pour
   les deux enfants après récupération → 403 pour Comptabilité sur tout
   l'écran. Suite complète verte (425 tests), DB remise aux fixtures
   après le test manuel.
7. ✅ **Échéancier de paiement en tranches** - indépendant des caisses,
   mais touche `Contrat`/`Facture`, entités déjà sensibles ; à faire
   posément. Fait le 2026-08-11 : entité `EcheanceContrat` (dateEcheance,
   montant, `facture` nullable rattachée une fois générée - pas
   d'entité conteneur séparée, plusieurs lignes pour un même `Contrat`
   forment l'échéancier, même principe qu'`EcheanceDepenseFixe`),
   migration `Version20260811121119`. Nouvelle
   `FactureService::genererPourEcheance()` : montant fourni par
   l'appelant (le montant de la tranche) plutôt que recalculé par
   `calculerMontant()` - c'est la différence clé avec
   `genererPourContrat()`, qui facture toujours le tarif intégral.
   `EcheanceContratService::genererFacture()` refuse une échéance déjà
   facturée (double-facturation impossible). UI intégrée directement à
   l'écran facture existant (`/comptabilite/enfant/{id}/facture`),
   nouvelle carte "Échéancier de paiement en plusieurs tranches" -
   ajout d'échéances + génération de facture par échéance, statut
   dû/payé réutilisant `PaiementService::statut()` (aucun état de
   paiement dupliqué). Vérifié en E2E manuel de bout en bout : contrat
   maternelle 550 000/an créé, 4 échéances de 137 500 ajoutées,
   génération de facture pour la 1ère échéance → facture bien à
   137 500 (pas 550 000, la scénario exact du besoin client), bouton
   "Générer" disparaît une fois facturée, les 3 autres restent "Non
   facturée". Suite complète verte (430 tests), DB remise aux fixtures
   après le test manuel.
8. ✅ **RH du personnel** - dernier, le plus gros morceau. Les salaires
   (§19.2.d) réutilisent le mécanisme des dépenses fixes (point 3) donc
   viennent naturellement après ; contrats/congés sont indépendants du
   reste et peuvent être développés à part. Fait le 2026-08-11 :
   `personnel` = `User` directement, aucune entité séparée (cf.
   `UserRepository::findPersonnel()`, déjà utilisé par l'écran "Places &
   personnel"). Entités `ContratTravail` (Direction exclusivement,
   §19.2.a, champs proposés implémentés tels quels - type/poste/dates/
   salaire de base/régime horaire/CNPS ; un seul contrat actif à la fois
   par personne, le nouveau désactive automatiquement l'ancien) et
   `Conge` (§19.2.b/c, déclaratif simple, `JOUR_EXCEPTIONNEL` = un type
   de congé sans solde - aucune différence de traitement dans ce premier
   incrément, juste une distinction d'affichage). Migration
   `Version20260811132429`. **Salaires (§19.2.d/e) : pas de nouvelle
   entité** - `DepenseFixe.personnel` (User nullable) rattache une
   dépense fixe à un salarié ("un salaire apparaît dans la même liste de
   dépenses fixes, catégorisé 'Salaire - [nom]'", décision client
   explicite) ; le pointage payé/non payé réutilise tel quel
   `EcheanceDepenseFixe`/l'écran `/comptabilite/depenses-fixes` déjà
   construit (point 3), désormais avec un sélecteur "Salarié" dans le
   formulaire de création. Écran `/administration/rh` (Direction
   exclusivement, contrats + congés + calendrier d'équipe simplifié +
   résumé des salaires en lecture seule renvoyant vers l'écran
   Comptabilité) - respecte la distinction d'accès exacte du §19.2.e :
   contrat de travail = Direction seule, salaire = Comptabilité +
   Direction avec visibilité individuelle (pas seulement agrégée). Le
   rappel légal (Code du travail, seuils + invitation à vérification par
   une juriste) est affiché sur le formulaire de déclaration de congé,
   sans jamais bloquer la saisie. Vérifié en E2E manuel de bout en bout :
   contrat CDI créé pour un membre du personnel, congé payé déclaré et
   visible sur le calendrier d'équipe, salaire créé depuis l'écran
   Dépenses fixes et visible en lecture seule sur la fiche RH, 403 pour
   Comptabilité sur tout `/administration/rh`, 200 + sélecteur "Salarié"
   fonctionnel pour Comptabilité sur `/comptabilite/depenses-fixes`.
   Suite complète verte (439 tests), DB remise aux fixtures après le
   test manuel.

**Les 8 modules du retour client 2026-08-10 sont maintenant tous
implémentés, testés et vérifiés en E2E.** Chantier clos, sous réserve
des micro-ajustements non bloquants listés plus haut (liste exacte des
champs de contrat de travail, calcul automatique du solde de congés -
à reprendre plus tard si le besoin se confirme, avec avis juridique
préalable).

## Journal

- **2026-08-10** : retour client reçu (`documentation/retour_clients`),
  discussion de conception, validations recueillies, cahier des charges
  complété (§14-§19), ce document créé.
- **2026-08-10 (suite 1)** : accès caisses précisé (Comptabilité peut
  saisir des mouvements mais pas créer de caisse) - point clos.
- **2026-08-10 (suite 2)** : tous les points RH tranchés (contrats,
  congés - avec vérification du droit ivoirien par recherche web,
  jours exceptionnels, salaires, accès) ; restitution du suivi garderie
  tranchée (email si disponible, sinon impression). Spécification
  complète - plus aucun point bloquant avant de démarrer le codage.
- **2026-08-11** : relecture complète du cahier des charges (correction
  d'une note de bas de tableau restée en doublon, de références `§16.a/
  b/c` obsolètes). Feu vert client pour démarrer le codage dans l'ordre
  défini.
- **2026-08-11 (suite)** : les 8 étapes codées, testées (439 tests) et
  vérifiées en E2E manuel dans l'ordre défini - voir "Ordre
  d'implémentation" ci-dessus pour le détail de chaque étape. Commit
  intermédiaire après l'étape 7 (`5bf391b`), puis étape 8 (RH du
  personnel) terminée à la suite. Chantier retour client 2026-08-10
  clos.
