mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 12:41:54 +00:00
feat(r3.1): socle backend gestion — stock dérivé, BC, coûts figés sur OT
- migration r3_gestion (7 tables) : Partner, Part (SANS colonne de quantité), StockMovement (signé, tracé, PU figé), PurchaseOrder/Line, LaborTime (taux figé), Document (R3.2) ; User.hourlyRate administrable - API (66 opérations) : tiers ; pièces (stock = Σ mouvements, alerte sous seuil) ; entrée/ajustement (motif requis, stock jamais négatif, en transaction) ; BC Brouillon→Envoyé→Reçu (la réception crée les RECEIPT et met à jour lastUnitPrice) ; consommation sur OT (stock suffisant, PRIX FIGÉ) ; main-d'œuvre (TAUX FIGÉ, refus si taux non défini) ; WorkOrderDetail.costs ; coûts verrouillés après clôture (409) - seed : tiers/pièces/BC/taux de la maquette — OT-0341 = 505 MAD (testé) - durcissement : références OT/DEM/BC/P par SÉQUENCES Postgres (nextval) — fin des courses « max+1 » (500 sporadiques sous charge parallèle) ; 3 runs Jest complets consécutifs verts - 55 tests (92 % stmts / 74,9 % branches) dont la recette officielle : consommer sous seuil → BC → réception → réappro, prix/taux figés prouvés Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -186,10 +186,63 @@ model MeterReading { id, meterId (cascade), value Int, readById? → User, creat
|
||||
| Relevé de compteur strictement croissant | service meters |
|
||||
| Génération mensuelle idempotente ; appareil sans historique ⇒ premier contrôle (toutes tâches) | service préventif (R2.2, + tests) |
|
||||
|
||||
## R3 — Gestion
|
||||
|
||||
```prisma
|
||||
enum PartnerKind { SUPPLIER CLIENT } // fournisseur / syndic
|
||||
enum PurchaseOrderStatus { DRAFT SENT RECEIVED CANCELLED }
|
||||
enum StockMovementKind { RECEIPT ENTRY CONSUMPTION ADJUSTMENT }
|
||||
enum DocumentKind { NOTICE CERTIFICATE PHOTO OTHER }
|
||||
|
||||
model Partner { id, name @unique, kind, contact…, isActive }
|
||||
|
||||
model Part { // AUCUNE colonne de quantité : le stock EST la
|
||||
id, reference @unique // somme des mouvements (décision v1 éprouvée)
|
||||
designation, threshold Int // seuil d'alerte
|
||||
lastUnitPrice Decimal? // dernier prix d'achat (mis à jour à la réception)
|
||||
supplierId? → Partner
|
||||
}
|
||||
|
||||
model StockMovement { // + entrée / − sortie, TOUJOURS tracé
|
||||
id, partId (cascade), kind, quantity Int (signé)
|
||||
unitPrice Decimal? // FIGÉ (réception : PU du BC ; consommation : lastUnitPrice)
|
||||
reason String? // ADJUSTMENT : motif REQUIS (service)
|
||||
workOrderId? → WorkOrder // consommation
|
||||
purchaseOrderId? → PurchaseOrder // réception
|
||||
byId? → User
|
||||
}
|
||||
|
||||
model PurchaseOrder { // DRAFT → SENT → RECEIVED ; annulable avant réception
|
||||
id, reference @unique, status, supplierId → Partner
|
||||
lines PurchaseOrderLine[] // partId, quantity, unitPrice Decimal
|
||||
// la RÉCEPTION crée un mouvement RECEIPT par ligne et met à jour lastUnitPrice
|
||||
}
|
||||
|
||||
model LaborTime { // heures × taux FIGÉ à la saisie
|
||||
id, workOrderId (cascade), userId → User, minutes Int, hourlyRate Decimal, note?
|
||||
}
|
||||
// User reçoit hourlyRate Decimal? (taux COURANT, administrable)
|
||||
|
||||
model Document { // MinIO derrière FileStorage — jamais d'accès direct
|
||||
id, kind, fileName, storageKey @unique, size, contentType
|
||||
assetId? / workOrderId? // rattachement REQUIS à l'un des deux (service)
|
||||
}
|
||||
```
|
||||
|
||||
**Invariants R3** :
|
||||
|
||||
| Invariant | Où il vit |
|
||||
| --- | --- |
|
||||
| Stock = Σ mouvements ; jamais de saisie directe de quantité | par construction (pas de colonne) |
|
||||
| Un ajustement exige un motif ; le stock ne devient jamais négatif | service parts (+ tests) |
|
||||
| Consommation : PU figé = `lastUnitPrice` au moment T ; stock suffisant exigé | service (transaction) |
|
||||
| Réception : BC `SENT` uniquement ; crée les RECEIPT + met à jour `lastUnitPrice` | service (transaction) |
|
||||
| Main-d'œuvre : taux figé = `User.hourlyRate` au moment T (refus si non défini) | service |
|
||||
| Coût total d'un OT = Σ consommations + Σ main-d'œuvre — IMMUABLE après coup | dérivé des lignes figées |
|
||||
| Document : rattaché à un appareil OU un OT ; types fermés ; 20 Mo max | service documents (R3.2) |
|
||||
|
||||
## À venir (référence v1 éprouvée, sera réintroduit release par release)
|
||||
|
||||
- **R3** : `Part`/`StockMovement` (stock **dérivé des mouvements**), `PurchaseOrder`,
|
||||
`Partner`, `LaborTime` (taux figé), `Document`.
|
||||
- **R4** : `WorkOrder.version` (verrou optimiste de la synchro mobile).
|
||||
- **R5** : tables d'embeddings pgvector (côté service IA).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user