Critical fixes:
- Make MigrateConstructeurLinks migration no-op (legacy tables already dropped)
- Add explicit ON CONFLICT (id) target in RestoreConstructeurLinks migration
- Replace N+1 queries with 4 bulk GROUP BY in ConstructeurStatsController
- Declare missing versionListRef template ref in machine detail page
- Add missing await on removeMachineDocument, cast activeTab as string
Important fixes:
- Add lang="ts" to ToastContainer and constructeurs page
- Type entityType as union in UsedInSection/useUsedIn
- Remove dead duration param from showError
- Update back-link props to new /catalogues/* URLs (3 pages)
- Replace raw error blocks with EmptyState in component/piece detail pages
- Type handleFillEntity params and machineInfoCardRef
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ComponentItem/PieceItem: DaisyUI divider, emit context-field-update for batch save
- CustomFieldDisplay: support editable/emit-blur/title/show-header props
- MachineComponentsCard/MachinePiecesCard: propagate custom-field-update events
- useMachineDetailCustomFields: pendingContextFieldUpdates + saveAllContextCustomFields
- useMachineDetailData: wire context field save into submitEdition
- useMachineDetailUpdates: only PATCH changed machine fields
- useMachineHierarchy: propagate contextCustomFields/Values from link to nodes
- componentStructure: include machineContextOnly in normalizeStructureForEditor
- Machine entity: convert empty reference to null, ignoreNull on UniqueEntity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The GET response for ModelType structure was missing machineContextOnly,
so on page reload the flag was always read as false by the frontend.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SkeletonStructureService: read and write machineContextOnly on create/update
- normalizeCustomFieldData: pass machineContextOnly through both payload formats
- cloneCustomFields: copy machineContextOnly flag on machine clone
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable adding a component, piece, or product to a machine by selecting
only the category (ModelType) without a specific entity. The link
displays a red "À remplir" badge; clicking it reopens the modal
pre-filled with the category so the user can associate an item later.
Backend: entity FKs made nullable on the 3 link tables, modelType FK
added, controller/audit/version/MCP normalization adapted for null
entities.
Frontend: modal accepts category-only confirm, page handles fill mode,
hierarchy builder creates pending nodes, display components show
clickable badge with event propagation through the full hierarchy.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Empty component slots (pieces, products, subcomponents) now display
the category/type name with red styling instead of generic labels
- Machine view: empty structure pieces show type name + "manquant" in red
- Backend: include typePiece in structure slot data for name resolution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Backend: MaintenanceModeListener blocks non-admin API requests when
var/maintenance flag file exists. MaintenanceController provides
toggle (PUT /api/admin/maintenance) and public check endpoint
(GET /api/maintenance/check).
- Frontend: Toggle button in admin page, maintenance.vue page for
blocked users, middleware redirects non-admins to /maintenance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ModelType defines a formula with placeholders ({serie}{diametre}{type}).
ReferenceAutoGenerator resolves it from CustomFieldValues with trim+uppercase normalisation.
ReferenceAutoSubscriber (onFlush) recalculates on Piece/CFV insert/update/delete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Remove DB unique index on composants.name and add Symfony UniqueEntity
validation on reference field with explicit error message.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All findBy(['machine' => ...]) queries now sort by createdAt ASC.
Without explicit ORDER BY, PostgreSQL returned rows in heap order which
changed on every INSERT, causing the displayed order to shuffle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comments can now have documents attached via multipart/form-data upload.
New endpoint GET /api/documents/comment/{id} to list a comment's files.
Document entity gains a comment relation with cascade remove.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a ModelType's custom field was renamed without sending the field ID,
the service would create a new CustomField instead of reusing the existing
one, orphaning all CustomFieldValues. Now matches by orderIndex as fallback
before name, preserving the link to existing values.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests cover:
- Clone: CustomFieldValue references cloned definitions, not source
- Clone: values are preserved after cloning
- Slots: 404 on non-existent piece, 422 on wrong type, success on correct type
- Conversion: blocked when slots have filled data, allowed when empty
- CustomField: rejects orphan creation, accepts existing field by ID
Also removes legacy JSON structure check (column no longer exists
after normalization) — replaced by slot table checks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Frontend: always include constructeurs key in PATCH payload even when
empty, so merge-patch+json actually clears the relation
- Backend: add setConstructeurs() on Piece and Product entities (Composant
already had it) so API Platform can replace the ManyToMany collection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ComposantProcessor now reads the structure payload from the frontend
and applies selectedPieceId/selectedProductId/selectedComponentId to the
scaffolded slots, so user selections are actually saved to the database.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add ComposantProcessor: initializes piece/product/subcomponent slots
from ModelType skeleton requirements when a composant is created
- UniqueConstraintSubscriber: priority 256, French error messages,
constraint name detection for specific feedback
- Migration: scaffold missing slots for existing composants in prod
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: match existing CustomField by name as fallback when ID is not provided,
preventing deletion and recreation of field definitions (which cascade-deletes values).
Includes restoration/migration scripts for prod:
- restore-custom-field-values.php: restores piece values from audit logs
- migrate-orphaned-custom-fields.php: migrates values from orphaned CFs
- fix-prod-all.php: combined fix (migrate + restore + cleanup)
- fix-prod-recreate-and-migrate.php: full fix (recreate missing CFs + migrate + restore)
- check-prod-*.php: diagnostic scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tools now return CallToolResult directly instead of Content arrays,
preventing the MCP SDK from auto-generating structuredContent as a
JSON array (which Claude Code rejects — expects a JSON object/record).
Also adds Accept header to test helpers and SSE response parsing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 3 MCP resources: schema, roles, stats
- docs/mcp/README.md with full user guide (config, tools catalogue, workflows)
- .mcp.json for Claude Code stdio transport
- Design spec and implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- list_slots + update_slots for composant/piece slots
- list/add/update/remove machine links (component, piece, product)
- get_machine_structure with full hierarchy
- clone_machine with all links and custom fields
- 52 MCP tests pass total
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 5 tools each: list, get, create, update, delete
- Piece: includes typePiece, constructeurs, prix (string)
- Composant: includes typeComposant, constructeurs, prix (string)
- Machine: includes site (required), constructeurs
- 40 MCP tests pass total
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>