Commit Graph

108 Commits

Author SHA1 Message Date
aec33e7911 feat(custom-fields) : clone context field values on machine clone
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:52:50 +02:00
2edb748bd4 feat(custom-fields) : support link-based upsert in CustomFieldValueController
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:52:18 +02:00
da12955b52 feat(custom-fields) : expose context custom fields in machine structure response
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:51:40 +02:00
4f1f643436 feat(custom-fields) : add machineContextOnly flag and link FKs for machine context
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:49:01 +02:00
1c3b566923 feat(machines) : allow category-only links on machine structure
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>
2026-04-03 10:15:47 +02:00
Matthieu
d6441bef06 feat(ui) : highlight empty slots with category name in red
- 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>
2026-04-03 09:21:25 +02:00
Matthieu
5e7a744151 feat : add maintenance mode toggle in admin panel
All checks were successful
Auto Tag Develop / tag (push) Successful in 8s
- 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>
2026-04-01 16:18:32 +02:00
Matthieu
476060cf7d WIP 2026-03-31 17:57:59 +02:00
Matthieu
1b1dab65b6 feat(constructeur) : add SearchFilter on ConstructeurLink entities
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:31:54 +02:00
Matthieu
5fff226f84 fix(constructeur) : fix remaining references after ConstructeurLink migration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:50:05 +02:00
Matthieu
691f632be0 refactor(mcp) : update MCP tools to use ConstructeurLinks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:29:10 +02:00
Matthieu
43fafc2251 refactor(conversion) : update category conversion to use ConstructeurLink tables
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:26:30 +02:00
Matthieu
0ad5815659 refactor(versioning) : update EntityVersionService to use ConstructeurLinks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:25:20 +02:00
Matthieu
a249a5b785 refactor(audit) : update audit subscribers to use ConstructeurLinks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:23:35 +02:00
Matthieu
d85272208a refactor(machines) : update structure controller to use ConstructeurLinks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:19:03 +02:00
Matthieu
26be0b655d refactor(constructeur) : replace ManyToMany with OneToMany to ConstructeurLink entities
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:12:17 +02:00
Matthieu
2d33c97449 feat(constructeur) : add 4 ConstructeurLink pivot entities with supplierReference
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:09:07 +02:00
Matthieu
03c2451990 feat(reference-auto) : extend auto-reference to composants + formula builder UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:59:42 +02:00
Matthieu
3f6ce153bb feat(reference-auto) : add automatic reference generation for pieces
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>
2026-03-26 17:58:53 +01:00
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
Matthieu
9299a46c8b feat(versioning) : add entity versioning with numbered versions and restore
Backend:
- Migration: version column on audit_logs and machines
- AuditLog, Machine, Composant, Piece, Product: version + skipAudit properties
- AbstractAuditSubscriber: auto-increment version, skip on restore, fix decimal diff
- Enriched snapshots with slots, custom fields and version number
- AuditLogRepository: findVersionHistory, findByVersion
- EntityVersionService: list, preview, restore with skeleton/integrity checks
- EntityVersionController: REST endpoints for all 4 entity types
- 11 tests covering list, preview, restore, auth

Frontend: update submodule pointer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:01:56 +01:00
3a75269323 fix(composant) : replace unique constraint from name to reference validation
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>
2026-03-25 22:12:19 +01:00
Matthieu
d70b9086d5 feat(search) : add MultiSearchFilter for OR search on name + reference
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:57:30 +01:00
Matthieu
3b35598b07 fix(structure) : stabilize piece/component/product ordering in machines
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>
2026-03-24 09:02:36 +01:00
Matthieu
8851f22e4e feat(ops) : add custom field audit and restore commands
- app:check-missing-custom-field-values — diagnostic des valeurs perdues
- app:restore-piece-custom-field-values — restauration générale
- app:restore-recoverable-piece-custom-field-values — restauration ciblée
  depuis l'audit log (dry-run par défaut, --apply pour exécuter)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 08:49:53 +01:00
Matthieu
330b9376f6 feat(comments) : add file attachments on comments
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>
2026-03-24 08:49:46 +01:00
Matthieu
4468fd7cdf fix(custom-fields) : match by orderIndex to prevent value loss on rename
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>
2026-03-24 08:36:59 +01:00
Matthieu
509c4d2247 test(data-integrity) : add 10 tests for data loss prevention
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>
2026-03-23 17:33:18 +01:00
Matthieu
043f6b1ce6 fix(data-integrity) : prevent data loss in clone, slots, conversion and custom fields
- Clone: CustomFieldValue now references cloned CustomField, not source
- Slots: validate piece type matches slot requirement + 404 on missing piece
- Conversion: check slot tables before allowing category conversion + clean orphan skeleton requirements
- CustomFieldValue: prevent creation of orphan CustomField without target entity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 17:15:05 +01:00
Matthieu
5ec6e49af2 feat(documents) : accept type on upload + expose in query controller + PATCH tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:20:39 +01:00
Matthieu
8d920d5f65 feat(documents) : add migration for type column with data classification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:14:33 +01:00
Matthieu
342b0afdbb feat(documents) : add DocumentType enum and type column on entity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:09:49 +01:00
Matthieu
2043e5b643 fix(constructeurs) : persist supplier removal on Piece, Composant and Product
- 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>
2026-03-23 13:54:08 +01:00
Matthieu
53b6abc9a8 fix(composant) : persist piece/product/subcomponent selections on creation
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>
2026-03-23 12:04:19 +01:00
Matthieu
826dae7712 fix(composant) : scaffold skeleton slots on creation + explicit unique constraint errors
- 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>
2026-03-23 11:48:23 +01:00
Matthieu
38777b7de0 fix(custom-fields) : prevent data loss on ModelType save + restoration scripts
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>
2026-03-17 20:24:37 +01:00
Matthieu
add3a9a21f fix(mcp) : return CallToolResult to prevent structuredContent serialization issue
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>
2026-03-16 17:24:04 +01:00
Matthieu
f965affc94 feat(mcp) : add MCP resources, documentation, and .mcp.json config
- 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>
2026-03-16 15:49:00 +01:00
Matthieu
4340a0e13e feat(mcp) : add business tools — search, history, comments, custom fields, documents, model types
- search_inventory: global search across all 6 entity types
- get_entity_history + get_activity_log: audit trail access
- 4 comment tools: list, create, resolve, unresolved count
- 3 custom field tools: list values, upsert, delete
- 2 document tools: list, delete (upload via REST only)
- 6 model type tools: list, get, create, update, delete, sync
- 69 MCP tests pass total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:00:37 +01:00
Matthieu
bd7259ed05 feat(mcp) : add Slots, Machine Links, Structure, and Clone tools
- 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>
2026-03-16 14:49:55 +01:00
Matthieu
2f173e766d feat(mcp) : add CRUD tools for Pieces, Composants, Machines
- 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>
2026-03-16 14:38:55 +01:00
Matthieu
4f1e136dc5 feat(mcp) : add CRUD tools for Sites, Constructeurs, Products
- 5 tools each: list, get, create, update, delete
- McpToolHelper extracted to AbstractApiTestCase for reuse
- DashboardStatsToolTest simplified to use base helpers
- 22 MCP tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:31:15 +01:00
Matthieu
e335f4c24c feat(mcp) : add stdio auth, dashboard stats PoC tool, and helper trait
- McpStdioAuthSubscriber for console transport auth via env vars
- DashboardStatsTool as PoC (validates MCP protocol flow)
- McpToolHelper trait for shared pagination/error utilities
- Key learning: #[McpTool] must be on CLASS, not method for __invoke

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:18:09 +01:00
Matthieu
98caaa148d feat(mcp) : add McpHeaderAuthenticator with rate limiting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:07:32 +01:00
Matthieu
43bec07bb8 fix(sync) : preserve slot selections when modifying ModelType structure
SkeletonStructureService was deleting all skeleton requirements and
recreating them on every ModelType update. Combined with position-based
matching in sync strategies, any reordering or insertion caused all
existing slots to be orphaned and recreated empty, losing selections.

- SkeletonStructureService: update requirements in-place by matching
  on typeId instead of delete-all/recreate-all
- ComposantSyncStrategy & PieceSyncStrategy: two-pass smart matching
  algorithm (exact typeId+position first, then typeId-only fallback)
  to preserve selectedPiece/selectedComposant/selectedProduct on
  reorder/insertion
- Frontend: check patch result.success before updating local state

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:32:14 +01:00
Matthieu
b2aff0e414 feat(sync) : add slot selection controllers, custom field sync, and position fallbacks
- Add selectedPieceId support to ComposantPieceSlotController
- Create ComposantProductSlotController and ComposantSubcomponentSlotController
- Add updateCustomFields() to SkeletonStructureService for managing CustomField entities
- Fix position/orderIndex fallback to array index in all 3 sync strategies
- Fix type comparison in ProductSyncStrategy for dual format support
- Update CLAUDE.md with new entities, controllers, and fixtures documentation
- Update frontend submodule with interactive slot selectors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:40:44 +01:00
Matthieu
4072abf7ba feat(sync) : add ModelTypeSyncService orchestrator and controller with tests
Implement the sync orchestrator that delegates to tagged strategies via
AutowireIterator, and the HTTP controller exposing sync-preview and sync
endpoints with transaction wrapping and role-based access control.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:17:57 +01:00
Matthieu
089ca43404 feat(sync) : implement PieceSyncStrategy with tests 2026-03-13 14:07:04 +01:00
Matthieu
f09c7e4782 feat(sync) : implement ComposantSyncStrategy with tests 2026-03-13 14:00:59 +01:00
Matthieu
6a20dcce54 feat(sync) : implement ProductSyncStrategy with tests 2026-03-13 13:54:47 +01:00