Files
Inventory/docs/superpowers/specs/2026-03-26-machine-single-save-design.md
Matthieu d568961eb3 feat(machine) : single save button + link versioning with restore
Backend:
- Enrich machine snapshot with componentLinks/pieceLinks/productLinks
- Detect link add/remove in MachineAuditSubscriber onFlush
- Add link diff comparison in restore preview
- Add link restoration in applyRestore for machines
- Add integrity warnings for missing linked entities

Frontend (submodule update):
- Single save button replacing auto-save-on-blur
- Link versioning display in version list and restore modal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 16:51:58 +01:00

5.0 KiB

Machine : Bouton Save Unique + Versioning des Liens

Date : 2026-03-26 Statut : Approuvé

Contexte

La page machine utilise actuellement un auto-save au blur pour chaque champ (info, custom fields, constructeurs). Les pages composant/pièce/produit utilisent un bouton unique "Enregistrer les modifications" en bas du formulaire. L'objectif est d'aligner la page machine sur ce pattern.

De plus, les ajouts/suppressions de liens composant/pièce/produit sur une machine ne sont pas tracés dans le versioning. Ils doivent l'être.

Volet 1 : Bouton Save Unique

Comportement cible

  • En mode édition, tous les champs (info machine, custom field values, custom field definitions, constructeurs) sont modifiés localement sans appel API.
  • Un bouton "Enregistrer les modifications" en bas du formulaire sauvegarde tout d'un coup.
  • Un bouton "Annuler" réinitialise l'état local et sort du mode édition.
  • Les documents restent en upload/suppression immédiate (inchangé).
  • Les ajouts/suppressions de liens composant/pièce/produit restent immédiats via modales (inchangé).

Changements frontend

MachineInfoCard.vue

  • Supprimer les @blur$emit('blur-field') sur les inputs (nom, référence)
  • Supprimer le @change qui émet blur-field sur le select site
  • Supprimer les @blur$emit('update-custom-field', field) sur tous les champs custom
  • Conserver @input / @update:* / set-custom-field-value pour la mise à jour de l'état local
  • Le MachineCustomFieldDefEditor perd son bouton save propre : l'état est collecté au submit global

machine/[id].vue

  • Supprimer le handler @blur-field
  • Supprimer le handler @update-custom-field
  • @update:constructeur-ids met à jour l'état local sans save
  • Ajouter le bloc boutons en bas (pattern identique à component/[id]/index.vue) :
    • "Annuler" (btn-ghost) → cancelEdition() : réinitialise depuis machine.value + sort du mode édition
    • "Enregistrer les modifications" (btn-primary, disabled si !canSubmit) → submitEdition()

useMachineDetailData.ts

  • Exposer saving ref
  • Exposer submitEdition() :
    1. updateMachineInfo() — PATCH machine (nom, ref, site, constructeurs)
    2. Batch save custom field values (tous les visibleMachineCustomFields avec valeur)
    3. Save custom field definitions si modifiées (fieldDefs.saveDefinitions())
    4. loadMachineData() pour recharger
    5. Sortie du mode édition + toast succès
  • Exposer cancelEdition() :
    1. initMachineFields() — réinitialise nom, ref, site, constructeurs depuis machine.value
    2. syncMachineCustomFields() — réinitialise les custom fields
    3. Sort du mode édition

useMachineDetailUpdates.ts

  • handleMachineConstructeurChange ne déclenche plus updateMachineInfo(), met juste à jour le ref local

useMachineDetailCustomFields.ts

  • updateMachineCustomField n'est plus appelé au blur — sera appelé en batch par submitEdition()
  • Ajouter méthode saveAllMachineCustomFields() qui itère sur les champs visibles et sauvegarde ceux avec valeur

Validation (canSubmit)

  • Machine existe
  • Nom non vide
  • Pas en cours de sauvegarde (!saving.value)
  • canEdit est true

Volet 2 : Versioning des Liens Machine

Comportement cible

Quand un composant, pièce ou produit est ajouté ou supprimé d'une machine, cela doit :

  1. Incrémenter la version de la Machine
  2. Créer une entrée AuditLog avec diff et snapshot

Changements backend

MachineAuditSubscriber — enrichir le snapshot

Ajouter au snapshot machine les liens :

'componentLinks' => array_map(fn($link) => [
    'id' => $link->getId(),
    'composantId' => $link->getComposant()->getId(),
    'composantName' => $link->getComposant()->getName(),
], $entity->getComponentLinks()->toArray()),
'pieceLinks' => [...],
'productLinks' => [...],

Nouveau subscriber ou service : MachineLinkAuditService

Écouter les événements Doctrine postPersist et postRemove sur les 3 entités link. Quand un lien est créé/supprimé :

  1. Récupérer la Machine parente
  2. Incrémenter $machine->incrementVersion()
  3. Créer un AuditLog :
    • entityType: 'machine'
    • entityId: $machine->getId()
    • action: 'update'
    • diff: { addedComponent: {id, name} } ou { removedPiece: {id, name} }
    • snapshot: snapshot complet de la machine (avec liens mis à jour)
    • version: nouvelle version

Labels pour le diff (frontend)

Ajouter au historyFieldLabels de la page machine :

addedComponent: 'Composant ajouté',
removedComponent: 'Composant supprimé',
addedPiece: 'Pièce ajoutée',
removedPiece: 'Pièce supprimée',
addedProduct: 'Produit ajouté',
removedProduct: 'Produit supprimé',

Ce qui ne change PAS

  • Upload/suppression de documents (immédiat)
  • Pattern read/edit toggle dans le header
  • L'affichage des sections composants/pièces/produits
  • Les modales d'ajout/suppression de liens (restent immédiates)
  • Le versioning des autres entités (composant, pièce, produit)