This commit is contained in:
Matthieu
2026-03-31 17:57:59 +02:00
parent 1b1dab65b6
commit 476060cf7d
45 changed files with 8547 additions and 648 deletions

View File

@@ -20,7 +20,8 @@ Permettre de consulter l'historique des versions numerotees (v1, v2, v3...) des
### Restauration
- La restauration cree une **nouvelle version** (v+1) — on ne supprime jamais d'historique
- L'AuditLog de la restauration a `action = "restore"` et le diff contient `restoredFromVersion: N`
- Le service `EntityVersionService::restore()` cree **manuellement** un AuditLog avec `action = "restore"` et le diff contient `restoredFromVersion: N`
- Important : le flush du restore declenche les AuditSubscribers, qui produiraient un `update` duplique. Pour eviter cela, l'entite porte un flag transitoire `$skipAudit = true` que les subscribers verifient
### Controle de squelette (Composant, Piece, Produit uniquement)
- Avant restauration, on compare le ModelType actuel avec celui du snapshot
@@ -35,10 +36,13 @@ Permettre de consulter l'historique des versions numerotees (v1, v2, v3...) des
- **Machine** : site, liens composants/pieces/produits (MachineComponentLink, MachinePieceLink, MachineProductLink)
- Les entites manquantes generent des **warnings** affiches a l'utilisateur
- Les slots avec des entites supprimees sont restaures **vides** (sans selection)
- Pour les custom field values : restauration par `fieldId` + entite parente (pas par ID de la CustomFieldValue elle-meme, car un sync ModelType peut recreer les CFV avec des IDs differents)
- Les controles d'integrite utilisent des requetes batch (`findBy(['id' => $ids])`) plutot que des requetes individuelles par slot
### Machines
- Pas de controle de squelette (pas de ModelType) : restauration toujours complete
- Controle d'integrite sur le site et les liens machine
- Machine n'a pas de champ `description` (contrairement aux autres entites)
### Permissions
- Consulter les versions : `ROLE_VIEWER`
@@ -78,7 +82,7 @@ Les Audit Subscribers doivent inclure dans le `snapshot` :
"prix": 100.00,
"typeComposant": { "id": "cl...", "name": "...", "code": "..." },
"product": { "id": "cl...", "name": "..." },
"constructeurs": [{ "id": "cl...", "name": "..." }],
"constructeurIds": [{ "id": "cl...", "name": "..." }],
"customFieldValues": [{ "id": "cl...", "fieldName": "...", "value": "..." }],
"pieceSlots": [
{ "id": "cl...", "typePieceId": "cl...", "selectedPieceId": "cl...", "quantity": 1, "position": 0 }
@@ -103,7 +107,7 @@ Les Audit Subscribers doivent inclure dans le `snapshot` :
"prix": 50.00,
"typePiece": { "id": "cl...", "name": "...", "code": "..." },
"product": { "id": "cl...", "name": "..." },
"constructeurs": [{ "id": "cl...", "name": "..." }],
"constructeurIds": [{ "id": "cl...", "name": "..." }],
"customFieldValues": [{ "id": "cl...", "fieldName": "...", "value": "..." }],
"productSlots": [
{ "id": "cl...", "typeProductId": "cl...", "selectedProductId": "cl...", "familyCode": "...", "position": 0 }
@@ -120,7 +124,7 @@ Les Audit Subscribers doivent inclure dans le `snapshot` :
"reference": "...",
"supplierPrice": 25.00,
"typeProduct": { "id": "cl...", "name": "...", "code": "..." },
"constructeurs": [{ "id": "cl...", "name": "..." }],
"constructeurIds": [{ "id": "cl...", "name": "..." }],
"customFieldValues": [{ "id": "cl...", "fieldName": "...", "value": "..." }],
"version": 1
}
@@ -132,8 +136,9 @@ Les Audit Subscribers doivent inclure dans le `snapshot` :
"id": "cl...",
"name": "...",
"reference": "...",
"description": "...",
"prix": 1500.00,
"site": { "id": "cl...", "name": "..." },
"constructeurIds": [{ "id": "cl...", "name": "..." }],
"customFieldValues": [{ "id": "cl...", "fieldName": "...", "value": "..." }],
"version": 4
}
@@ -295,6 +300,10 @@ CREATE INDEX IF NOT EXISTS idx_audit_entity_version ON audit_logs (entity_type,
---
## Ce qui change (breaking)
- **Piece snapshot** : le champ legacy `productIds` (ancien JSON) est remplace par `productSlots` (tables normalisees). Les anciens AuditLogs conservent `productIds` dans leur snapshot mais les nouveaux ne l'auront plus. Le restore utilise `productSlots` exclusivement.
## Ce qui ne change PAS
- L'onglet/page d'historique existant (`EntityHistoryController`) reste inchange