- migration : Asset.underContract + WorkOrder.periodKey avec unicité
[assetId, periodKey] — l'idempotence de la génération est EN BASE
(deux appels concurrents ne doublent jamais une grille)
- génération : une grille par appareil sous contrat, périodicités ancrées
sur la mise en service (mensuelles toujours dues), premier contrôle
(toutes les tâches) pour un appareil sans historique, échéance fin de
mois, événement GENERATED ; déclenchement manuel (cron au durcissement)
- gabarits administrables (désactivé = exclu des générations suivantes) ;
GET /preventive/status (générées, terminées, en retard, premiers contrôles)
- compteurs : GET meters (2 compteurs, récents d'abord) ; relevé
strictement croissant, refus motivé sinon
- contrat +7 opérations (48) ; 50 tests verts (94,7 % / 78 %) ; smoke test
prod : juillet généré (9 grilles, 8 premiers contrôles), 2e appel à zéro
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- migration r2_exploitation (10 tables) : WorkOrder (référence séquentielle,
horodatages), WorkOrderEvent, Request (1-1, motif de rejet), ReferenceValue,
InterventionReport (6 FK), TaskTemplate/ChecklistItem, Meter/MeterReading
- contrat : 15 opérations (41 total) ; la table des transitions et les champs
requis du bilan vivent dans @siop/shared ; la fiche OT expose
allowedTransitions + closureBlockers (messages métier)
- API : machine à états stricte ; garde de clôture (bilan 3 champs requis +
checklist sans tâche en attente) ; approbation → OT lié 1-1 (409 si déjà
traitée) ; rejet à motif obligatoire ; scoping « voir autre » sur listes et
accès directs (404 sans fuite) ; validation des valeurs de bilan par champ ;
« personne bloquée » triée en tête côté API
- seed : 31 valeurs de référentiels, 8 gabarits (parachute réglementaire),
OT/demandes/compteurs de la maquette — idempotent
- 45 tests verts (95 % stmts / 79 % branches) dont la recette officielle
rejouée de bout en bout ; smoke test sur build de prod
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>