mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 20:51:53 +00:00
feat(r2.1): socle backend exploitation — machine à états, bilan codé, demandes 1-1
- 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>
This commit is contained in:
93
packages/shared/src/exploitation.ts
Normal file
93
packages/shared/src/exploitation.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
/** Vocabulaires de l'exploitation (R2) — partagés API / web / seed. */
|
||||
|
||||
export const WORK_ORDER_TYPES = ['CORRECTIVE', 'PREVENTIVE', 'WORKS'] as const;
|
||||
export type WorkOrderType = (typeof WORK_ORDER_TYPES)[number];
|
||||
export const WORK_ORDER_TYPE_LABELS: Record<WorkOrderType, string> = {
|
||||
CORRECTIVE: 'Dépannage',
|
||||
PREVENTIVE: 'Maintenance',
|
||||
WORKS: 'Travaux',
|
||||
};
|
||||
|
||||
export const WORK_ORDER_STATUSES = [
|
||||
'OPEN',
|
||||
'IN_PROGRESS',
|
||||
'ON_HOLD',
|
||||
'DONE',
|
||||
'CANCELLED',
|
||||
] as const;
|
||||
export type WorkOrderStatus = (typeof WORK_ORDER_STATUSES)[number];
|
||||
export const WORK_ORDER_STATUS_LABELS: Record<WorkOrderStatus, string> = {
|
||||
OPEN: 'Ouvert',
|
||||
IN_PROGRESS: 'En cours',
|
||||
ON_HOLD: 'En attente',
|
||||
DONE: 'Terminé',
|
||||
CANCELLED: 'Annulé',
|
||||
};
|
||||
|
||||
/** Machine à états STRICTE — la table est la loi, côté API comme côté UI. */
|
||||
export const WORK_ORDER_TRANSITIONS: Record<WorkOrderStatus, WorkOrderStatus[]> = {
|
||||
OPEN: ['IN_PROGRESS', 'CANCELLED'],
|
||||
IN_PROGRESS: ['ON_HOLD', 'DONE', 'CANCELLED'],
|
||||
ON_HOLD: ['IN_PROGRESS', 'CANCELLED'],
|
||||
DONE: [],
|
||||
CANCELLED: [],
|
||||
};
|
||||
|
||||
export const WORK_ORDER_PRIORITIES = [
|
||||
'NONE',
|
||||
'LOW',
|
||||
'MEDIUM',
|
||||
'HIGH',
|
||||
'PERSON_TRAPPED',
|
||||
] as const;
|
||||
export type WorkOrderPriority = (typeof WORK_ORDER_PRIORITIES)[number];
|
||||
export const WORK_ORDER_PRIORITY_LABELS: Record<WorkOrderPriority, string> = {
|
||||
NONE: 'Aucune',
|
||||
LOW: 'Basse',
|
||||
MEDIUM: 'Moyenne',
|
||||
HIGH: 'Haute',
|
||||
PERSON_TRAPPED: 'Personne bloquée',
|
||||
};
|
||||
|
||||
export const REQUEST_STATUSES = ['RECEIVED', 'APPROVED', 'REJECTED'] as const;
|
||||
export type RequestStatus = (typeof REQUEST_STATUSES)[number];
|
||||
export const REQUEST_STATUS_LABELS: Record<RequestStatus, string> = {
|
||||
RECEIVED: 'Reçue',
|
||||
APPROVED: 'Approuvée',
|
||||
REJECTED: 'Rejetée',
|
||||
};
|
||||
|
||||
export const CHECKLIST_STATES = ['PENDING', 'DONE', 'NA'] as const;
|
||||
export type ChecklistState = (typeof CHECKLIST_STATES)[number];
|
||||
|
||||
export const BILAN_FIELDS = [
|
||||
'DOOR_STATE',
|
||||
'CABIN_POSITION',
|
||||
'ANOMALY',
|
||||
'EXTERNAL_CAUSE',
|
||||
'ACTION_TAKEN',
|
||||
'COMPONENT_CONCERNED',
|
||||
] as const;
|
||||
export type BilanField = (typeof BILAN_FIELDS)[number];
|
||||
export const BILAN_FIELD_LABELS: Record<BilanField, string> = {
|
||||
DOOR_STATE: 'État des portes',
|
||||
CABIN_POSITION: 'Position cabine',
|
||||
ANOMALY: 'Anomalie constatée',
|
||||
EXTERNAL_CAUSE: 'Cause extérieure',
|
||||
ACTION_TAKEN: 'Action réalisée',
|
||||
COMPONENT_CONCERNED: 'Élément concerné',
|
||||
};
|
||||
|
||||
/** Champs du bilan REQUIS pour clôturer (maquette fiche OT validée R0). */
|
||||
export const REQUIRED_BILAN_FIELDS: readonly BilanField[] = [
|
||||
'DOOR_STATE',
|
||||
'ACTION_TAKEN',
|
||||
'COMPONENT_CONCERNED',
|
||||
];
|
||||
|
||||
export const METER_KINDS = ['RUNNING_HOURS', 'STARTS'] as const;
|
||||
export type MeterKind = (typeof METER_KINDS)[number];
|
||||
export const METER_KIND_LABELS: Record<MeterKind, string> = {
|
||||
RUNNING_HOURS: 'Heures de marche',
|
||||
STARTS: 'Démarrages',
|
||||
};
|
||||
Reference in New Issue
Block a user