normalizeProduct() had customFields hardcoded to [] and was missing
customFieldValues entirely, unlike normalizeComposant and normalizePiece.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getStructure() was returning hardcoded empty customFields arrays after
the JSON-to-tables migration. Now reads from the relational CustomField
entities via serializeCustomFields() for all three categories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Composant.structure property, getter/setter
- Remove Piece.productIds property, setProductIds()
- Update fixtures to remove dropped columns
- Add migrations to drop both columns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ModelType.setStructure() now stores data in pendingStructure instead of
writing to JSON columns. A new ModelTypeProcessor intercepts API Platform
POST/PUT/PATCH operations and delegates skeleton writes to
SkeletonStructureService, which persists to relation tables.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- normalizeComposant : inclure structure du composant dans la réponse
- enrichStructureWithPieceData : résoudre selectedPieceId vers les
données complètes de la pièce catalogue (nom, référence, prix, etc.)
- Update submodule : affichage pièces incluses + quantité machine
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API Platform silently ignored the constructeurs field on PATCH because
Machine was missing the add/remove methods (unlike Composant, Piece, Product).
Also fixes the read-only fournisseur display overflow in MachineInfoCard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add color VARCHAR(7) column to sites entity
- Migration with IF NOT EXISTS for idempotence
- Update reference config
- Frontend: site color picker, dark mode, card styling improvements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove orphaned PUBLIC_ACCESS rule for deleted /api/test route
- Remove JWT login firewall (app is session-based only)
- Set APP_SECRET placeholder (real value must be in .env.local)
- Remove JWT env vars from .env
- Add session regeneration on login (prevent session fixation)
- Remove Document.path from API serialization groups (prevent path leak)
- Restrict health check details to ROLE_ADMIN (anonymes get status only)
- Add path traversal guard in DocumentStorageService
- Convert CreateProfileCommand password to interactive hidden prompt
- Restrict Profile Get endpoint to ROLE_ADMIN
- Change api firewall to stateless: false (matches session-based auth)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared ID generation + timestamps into CuidEntityTrait used by all entities
- Create AbstractAuditSubscriber to deduplicate audit logic across 7 subscribers
- Merge per-entity history controllers into single EntityHistoryController
- Delete redundant ComposantHistory/MachineHistory/PieceHistory/ProductHistoryController
- Add OpenApiDecorator for API documentation customization
- Disable failOnDeprecation in PHPUnit (vendor API Platform deprecation)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add nullable TEXT description column to both pieces and composants
tables with corresponding Doctrine entity mappings, getters/setters
and serialization groups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Patch operation to Site entity (was only Put, causing 405 errors).
Fix migration to use ALTER TABLE DROP CONSTRAINT instead of DROP INDEX
for the piece name unique constraint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create Comment entity with API Platform annotations (GET, PATCH, DELETE).
Add CommentController with POST (create), PATCH (resolve) and GET
(unresolved count) endpoints. Add migration for comments table and
piece reference unique index.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add UniqueEntity validation on Constructeur.name and Piece.reference.
Move unique DB constraint from piece name to piece reference column.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- Add role hierarchy (ADMIN > GESTIONNAIRE > VIEWER > USER) in security.yaml
- Add password authentication on profile activation (SessionProfileController)
- Add SessionProfileAuthenticator with stateless API firewall
- Add ProfilePasswordHasher state processor for API Platform
- Add security annotations on all 18 API Platform entities
- Add denyAccessUnlessGranted on all 13 custom controllers
- Add AdminProfileController for profile/role management (/api/admin/profiles)
- Add InitProfilePasswordsCommand for initial admin setup
- Simplify SessionProfilesController to list-only (removed create/delete)
Frontend (submodule update):
- Add usePermissions composable (isAdmin, canEdit, canView, isGranted)
- Add password login modal on profiles page
- Add admin backoffice page for profile management
- Disable all form fields for ROLE_VIEWER across all edit/create pages
- Show navigation buttons for all roles, hide destructive actions for viewers
- Add readonly mode to ModelTypeForm and site/constructeur modals
- Guard /admin routes in middleware
- Configure Vite proxy for API requests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend service and controller for converting piece categories to component
categories (and vice-versa). Uses raw SQL in a transaction to preserve IDs
and transfer all related data (documents, custom fields, constructeurs).
Includes php-cs-fixer formatting pass on existing controllers/entities.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The path field (base64 data URIs) is now excluded from GetCollection
via document:list group. Individual GET returns path via document:detail
group. Related entities expose id+name in document:list for attachment
display. Frontend lazy-loads path on download/preview click.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update setName() to use mb_strtoupper on the first character so that
category and component names always start with an uppercase letter.
Also update frontend submodule with URL state preservation and back
button improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New GET /api/activity-logs endpoint with pagination and filters
(entityType, action) for the global activity log page
- Add findAllPaginated() to AuditLogRepository
- normalizeCollection() now stores {id, name} objects instead of
bare IDs so constructeur changes display readable names
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Inject Security service into all 3 audit subscribers to resolve
actor profile from authenticated user (fixes "Par Inconnu" issue)
- Add CustomFieldValue tracking: insertions, updates, and deletions
on custom field values now produce audit log entries on the parent
entity (composant, piece, product) with field name prefix
"customField:{name}"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expose customField definitions (id, name, type, required, options, orderIndex)
inline in entity responses, eliminating separate API calls for custom field data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add PdfCompressorService for lossless compression with qpdf
- Add DocumentPdfCompressorListener for automatic compression on persist/update
- Add app:compress-pdf command for batch compression of existing PDFs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Fix Groups sur TypeMachine*Requirement: exposer typePiece/typeComposant/typeProduct
- Fix Groups sur Document, Piece, Product, Composant pour sérialisation
- Add addConstructeur/removeConstructeur sur Piece et Product
Scripts:
- Fix normalize-dump.py: gérer les schémas quotés ("public"."table")
Frontend (sous-module):
- Corrections formulaires et sérialisation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>