# Spécificités hors cahier des charges

Fonctionnalités ajoutées à la demande du client mais absentes du
cahier des charges v4.1 (§11 notamment, qui liste les rôles
applicatifs de façon fermée). Documentées séparément pour ne pas
laisser croire que le cahier des charges les prévoyait.

## Profil Cantine (2026-08-06)

**Besoin exprimé** : la personne en charge des achats de la cantine
envoyait jusqu'ici sa liste de courses par WhatsApp (texte tapé ou
photo du reçu/produits) à la comptabilité, qui ressaisissait
manuellement. Demande : un profil dédié, simple, pensé pour un usage
au téléphone (« non fastidieux »).

**Décision** : nouveau rôle `ROLE_CANTINE` (hérité par
`ROLE_DIRECTION` comme les autres rôles métier). Pas de nouvelle
entité : chaque achat est composé en une `Depense` existante
(catégorie `Cantine`), en réutilisant tel quel le circuit de
validation §7.2.j (une personne différente de la saisissante -
Comptabilité ou Direction - valide ou refuse depuis l'écran Dépenses
existant, où les achats cantine apparaissent mêlés aux autres
dépenses avec leur catégorie). Photo justificative optionnelle
(réutilise le stockage/format déjà validé pour les pièces
justificatives de dépense).

Écran unique `/cantine` (`CantineController`, `CantineService`) :
liste de lignes « article + prix » à remplir (total calculé
automatiquement côté client, recalculé côté serveur pour la valeur
qui fait foi), champ photo, historique des achats déjà saisis par ce
compte avec leur statut.

**Hors scope de cet ajout** : la création de compte personnel reste
manuelle (aucun écran de création de compte n'existait encore pour
aucun rôle, cf. docblock `PersonnelController`) - le compte
`cantine@creche-test.local` n'existe que dans les fixtures de
développement. Cf. « Écran de création de compte » ci-dessous, qui
comble ce manque.

**Traité (2026-08-06)** : la cantine facturée aux parents (§7.2.g) est
passée d'une facturation réactive au repas consommé à une enveloppe
prépayée - cf. section « Cantine parent : enveloppe prépayée »
ci-dessous. Les achats d'ingrédients (ce module) n'étaient de toute
façon pas affectés (dépense commune, non liée à un enfant).

## Écran de création de compte (2026-08-06)

*Note : contrairement au reste de ce document, ce point n'est pas hors
cahier des charges - il est consigné ici uniquement parce qu'il a été
demandé dans la même conversation que le profil Cantine ci-dessus.*

**Besoin exprimé** : un écran de création de compte, réservé aux
« admins », au même endroit que la liste des utilisateurs.

**Constat** : c'est le §11
(matrice des rôles) qui l'exigeait déjà : *« Comptes, rôles,
configuration, supervision technique »* est une ligne à laquelle
**seul** Admin technique a accès (✅), tous les autres rôles y compris
Direction sont à ❌. La zone `/admin-technique` existait déjà dans
`security.yaml` (rôle `ROLE_ADMIN_TECHNIQUE` réservé dès le Lot 0) mais
n'avait encore aucun écran - c'est le premier.

**Implémentation** : `AdminTechniqueController` (`/admin-technique/utilisateurs`),
`CompteUtilisateurService`. Liste de tous les comptes (tous rôles,
tous établissements) + formulaire de création (prénom, nom, email,
rôle(s) parmi Éducateur/Comptabilité/Direction/Admin technique/Cantine,
établissement optionnel, mot de passe temporaire saisi par l'Admin
technique et communiqué hors système - même principe V1 que
`CompteParentService`, pas d'email automatique).

**Décision volontaire** : `ROLE_PARENT` est exclu des rôles
attribuables par cet écran. Un compte Parent doit toujours être
rattaché à un `ResponsableLegal` existant (`CompteParentService`,
flux déjà en place sous Direction → Messagerie) ; l'écran générique
Admin technique n'a pas ce rattachement et créerait un compte Parent
orphelin s'il l'autorisait.

## Cantine parent : enveloppe prépayée (2026-08-06)

*Note : comme pour l'écran de création de compte, ceci n'est pas hors
cahier des charges - le §4.2.a et le §11 prévoyaient déjà « souscription/
résiliation du service cantine à tout moment » et « Souscrire/gérer la
cantine de son enfant » (✅ Parent, ✅ Direction). Rien de tout cela
n'était construit ; seule la facturation réactive au repas consommé
(§7.2.g) existait. Noté ici parce que la clarification du mécanisme est
venue de la même conversation que le profil Cantine ci-dessus.*

**Besoin exprimé** : la cantine payée par les parents fonctionne comme
une enveloppe versée à l'avance (pas tous les enfants n'y vont), pas
comme un décompte de repas facturé après coup. Le prix reste défini à
l'avance (tarif "par repas" existant), mais sert à calculer une somme
globale au moment de la souscription plutôt qu'à multiplier un
comptage réalisé a posteriori.

**Décisions actées avec le client (deux séries de questions)** :
accès illimité à la cantine une fois l'enveloppe payée (pas un
compteur de repas) ; le carnet quotidien de repas (quantité mangée,
visible par les parents) reste inchangé, seul le lien avec la
facturation disparaît ; période libre à chaque souscription, pas de
cadence fixe imposée par le logiciel.

**Implémentation** : nouvelle entité `AbonnementCantine`
(`AbonnementCantineService`), montant = jours calendaires couverts ×
tarif de la ligne "par repas" existante (`GrilleTarifaireRepository::findLigneCantineActive()`,
inchangée). Souscription = facture générée immédiatement
(`FactureService::genererPourAbonnementCantine()`), même circuit que
les autres factures (visible dans l'historique parent, téléchargeable).
Écrans : `/parents/enfant/{id}/cantine` (Parent, sur ses enfants) et
la fiche enfant Direction (`/administration/enfant/{id}`, section
Cantine) - même service, deux points d'entrée, conforme à la matrice
des rôles. Résiliation : ne gère aucun remboursement elle-même - si la
facture est déjà payée, la comptabilité utilise le mécanisme d'avoir
déjà existant (`AvoirFactureService`) sur la facture liée.

**Retiré** : l'ancienne facturation réactive au repas consommé
(`FactureService::genererPourCantine()`, le bouton "Facturation
cantine" côté comptabilité, `Repas::$statutConsommationCantine` et son
écran de correction côté équipe). Le carnet de repas lui-même
(`Repas`, `OrigineRepas`, `quantiteMangee`) n'a pas bougé.
