Compare commits

..

7 Commits

Author SHA1 Message Date
Matthieu 8c3c0b58ed test(catalog) : cover RG-1.01 to RG-1.17 with 9 test classes (63 tests)
PHPUnit suite for the M0 Catalog module covering the 17 business rules of
the spec :
- CategoryPermissionsTest (RG-1.01) — 4 personas + admin + anonymous on GET / POST / PATCH / DELETE
- CategoryValidationTest (RG-1.02 to RG-1.06) — name NotBlank + trim + length + categoryType required / must exist
- CategoryUniqueTest (RG-1.07) — 409 case-insensitive, multi-type allowed, recreate after soft delete
- CategoryListTest (RG-1.08 to RG-1.10) — soft-delete filter, includeDeleted flag, name ASC sort
- CategoryGetTest (RG-1.11) — 404 on soft-deleted, 200 with flag, 404 on not found
- CategoryDeleteTest (RG-1.12 / RG-1.13) — soft delete, deletedAt unwriteable via PATCH, 404 on already deleted
- CategoryAuditTest — audit_log written on create / update / soft delete with correct performed_by
- CategoryTimestampableBlamableTest (RG-1.15 / RG-1.16) — blame admin on POST, null in console context, frozen createdBy on PATCH, updated_* on soft delete
- EntitiesAreTimestampableBlamableTest (RG-1.17) — stays green (already shipped in ERP-52)

Side fixes uncovered by the suite :
- Category.php : add normalizer 'trim' to NotBlank + Length so a whitespace-only
  name returns 422 (RG-1.02 + RG-1.03 alignment, the Processor trim was running
  after validation).
- makefile : recreate the partial index uq_category_name_type_active in
  test-db-setup. doctrine:schema:update drops the unexpressable index after
  migrations, which made RG-1.07 silently pass (duplicate POST -> 201 instead
  of 409). The DDL is now restored after schema:update via dbal:run-sql.

Tests : 311 total (248 + 63 new), 1071 assertions, 0 failure, 0 risky.
2026-05-28 11:40:40 +02:00
Matthieu 04336cc682 feat(catalog) : declare CatalogModule with RBAC permissions and sync 3 RBAC sources
- CatalogModule.php (REQUIRED=true) expose 2 permissions : catalog.categories.view + catalog.categories.manage
- modules.php : wire CatalogModule
- sidebar.php : item "Gestion des categories" dans la section Administration (gate sur catalog.categories.view)
- fr.json : cle sidebar.catalog.categories
- personas.ts : user-full recoit les 2 permissions, super-admin + ALL_ADMIN_LINKS etendus avec 'categories'
- SeedE2ECommand.php : miroir back, user-full recoit les 2 permissions

RG-1.01 verifiee manuellement (admin 200, bob 403, anonyme 401) sur /api/categories et /api/category_types.
2026-05-28 11:40:40 +02:00
Matthieu bc4e47d5ad feat(catalog) : expose CategoryType as read-only ApiResource with default label ASC sort 2026-05-28 11:40:40 +02:00
Matthieu ae70e90db2 feat(catalog) : implement CategoryProvider and CategoryProcessor with soft delete and 409 mapping
- CategoryProvider applique le filtre soft-delete par defaut (RG-1.08), respecte ?includeDeleted=true (RG-1.09), trie par name ASC (RG-1.10) et renvoie 404 sur Get d'une soft-deleted hors flag (RG-1.11). Cable aussi sur Patch+Delete pour fermer la fuite sur PATCH.
- CategoryProcessor : trim du name au POST/PATCH (RG-1.03), conversion DELETE en UPDATE avec deletedAt=now() via persist_processor (RG-1.12), mapping UniqueConstraintViolationException -> HTTP 409 avec le message attendu (RG-1.07).
- Cablage des Provider/Processor dans #[ApiResource] de Category.
- DoctrineCategoryRepository expose createListQueryBuilder($includeDeleted) pour le Provider.
2026-05-28 11:40:40 +02:00
Matthieu e0575de646 feat(catalog) : add Category and CategoryType entities with Timestampable+Blamable pattern
- Category : ApiResource (5 ops), #[Auditable], TimestampableBlamableTrait +
  interfaces, asserts (NotBlank/Length sur name, NotNull sur categoryType),
  soft delete via deletedAt, groupes category:read/category:write + default:read
- CategoryType : referentiel statique en lecture seule (GetCollection + Get),
  embarque dans Category via le groupe category:read
- Repositories : interfaces Domain + impl Doctrine pour les deux entites
- doctrine.yaml : mapping ORM Catalog inconditionnel (miroir Sites) pour que
  l'ORM reconnaisse les entites ; declaration du module = ticket 0.5
- EntitiesAreTimestampableBlamableTest : CategoryType ajoute a EXCLUDED (RG-1.17)
- Index nommes declares sur les entites (match migration) ; index unique partiel
  uq_category_name_type_active possede par la migration seule
2026-05-28 11:40:40 +02:00
Matthieu 44d8c77718 ci : retire tout le caching (backend de cache runner injoignable, timeout 4m30)
Les logs montrent que chaque operation actions/cache attend ~4m30 avant
ETIMEDOUT sur le serveur de cache du runner Gitea (51.91.78.99:39531) :
- cache: npm de setup-node = tout le 'Setup Node 22' (271s)
- cache node_modules et cache .nuxt : timeouts additionnels
- cache Composer cote backend : meme risque

Node 22 est deja dans le tool-cache (install instantane), npm ci a froid
~30s, build ~20s : le caching n'apportait rien ici. A re-activer si le
serveur de cache du runner est repare.
2026-05-28 11:40:40 +02:00
Matthieu 670c58e02e ci(frontend) : accelere le job PR (nuxt build + cache node_modules & build Nuxt/Vite)
- remplace build:dist (nuxt generate + prerender inutile en SPA) par nuxt build
- cache node_modules sur hash du lockfile, npm ci uniquement en cache miss
- regenere les types Nuxt (postinstall) en cache hit
- cache des artefacts .nuxt / Vite avec restore-keys pour eviter le build a froid
2026-05-28 11:40:40 +02:00
+1 -1
View File
@@ -1,2 +1,2 @@
parameters: parameters:
app.version: '0.1.48' app.version: '0.1.42'