feat(admin): CRUD menus composes avec slots (P3, mlt 8.4-8.6) #32

Merged
Corentin merged 1 commit from feat/p3-menus-crud into dev 2026-06-16 15:39:10 +02:00
Owner

P3 — CRUD Menus composes (suite P3, mlt 8.4-8.6)

4e CRUD back-office, cas le plus riche : un menu = burger de base + N slots (menu_slot) chacun proposant M options (menu_slot_option), tarification Normal/Maxi.

Conception (FD : brainstorm -> prune -> dispatch -> build -> validate)

  • Slots en vanilla JS dynamique (decision user) : builder ajout/retrait + cases d'options. CSP 'self' -> donnees via data-*, etat serialise dans un champ cache slots_json (Request::formBody ne garde que les scalaires).
  • PIN selon la spec (decision user) : create/update sans PIN (un menu n'a pas de vat_rate) ; delete avec PIN equipier + audit (RG-T13/T14, mlt 8.6).

Contenu

  • MenuRepository : create/update transactionnels (RG-T08) ; update = delete-and-reinsert des slots (mlt 8.5 RG-2) ; delete FK-safe (order_item.menu_id RESTRICT, CASCADE vers slots/options).
  • MenuController : guard menu.* (RG-T03), CSRF (RG-T01), validation bornee + allowlist (RG-T16/T18), throttle PIN RG-T22 (gate-before-verify, echec PIN trace+compte dans une transaction).
  • Vues admin/menus/{index,form,delete} + menu-form.js ; routes + lien nav Menus reactive (celui retire en #23).

Verification

  • 201 tests verts (597 assertions avec WAKDO_DB_TESTS=1), PHPStan L6 propre.
  • MenuControllerTest (12 cas) + MenuRepositoryDbTest (integration vraie DB : create+slots, slotsWithOptions, update delete-and-reinsert, delete+cascade).
  • Smoke live : routes /admin/menus* resolvent + gardent.

Pas de label auto-merge : relecture manuelle.

## P3 — CRUD Menus composes (suite P3, mlt 8.4-8.6) 4e CRUD back-office, cas le plus riche : un menu = **burger de base + N slots** (`menu_slot`) chacun proposant **M options** (`menu_slot_option`), tarification **Normal/Maxi**. ### Conception (FD : brainstorm -> prune -> dispatch -> build -> validate) - **Slots en vanilla JS dynamique** (decision user) : builder ajout/retrait + cases d'options. CSP `'self'` -> donnees via `data-*`, etat serialise dans un champ cache `slots_json` (`Request::formBody` ne garde que les scalaires). - **PIN selon la spec** (decision user) : create/update **sans** PIN (un menu n'a pas de `vat_rate`) ; **delete avec PIN equipier + audit** (RG-T13/T14, mlt 8.6). ### Contenu - `MenuRepository` : create/update transactionnels (RG-T08) ; update = **delete-and-reinsert** des slots (mlt 8.5 RG-2) ; delete **FK-safe** (`order_item.menu_id` RESTRICT, CASCADE vers slots/options). - `MenuController` : guard `menu.*` (RG-T03), CSRF (RG-T01), validation bornee + allowlist (RG-T16/T18), throttle PIN RG-T22 (gate-before-verify, echec PIN trace+compte dans une transaction). - Vues `admin/menus/{index,form,delete}` + `menu-form.js` ; routes + **lien nav Menus reactive** (celui retire en #23). ### Verification - **201 tests verts** (597 assertions avec `WAKDO_DB_TESTS=1`), PHPStan L6 propre. - `MenuControllerTest` (12 cas) + `MenuRepositoryDbTest` (integration vraie DB : create+slots, slotsWithOptions, update delete-and-reinsert, delete+cascade). - Smoke live : routes `/admin/menus*` resolvent + gardent. Pas de label `auto-merge` : relecture manuelle.
Corentin added 1 commit 2026-06-16 15:17:32 +02:00
feat(admin): CRUD menus composes avec slots (P3, mlt 8.4-8.6)
All checks were successful
CI / secret-scan (pull_request) Successful in 9s
CI / php-lint (pull_request) Successful in 21s
CI / static-tests (pull_request) Successful in 46s
CI / secret-scan (push) Successful in 9s
CI / php-lint (push) Successful in 21s
CI / static-tests (push) Successful in 52s
CI / auto-merge (pull_request) Successful in 6s
CI / auto-merge (push) Has been skipped
26672b1467
Quatrieme CRUD back-office, cas le plus riche du catalogue : un menu = burger de
base + N slots de composition (menu_slot) chacun proposant M options eligibles
(menu_slot_option), avec tarification Normal/Maxi.

- App\Catalogue\MenuRepository : all/find, slotsWithOptions (LEFT JOIN regroupe),
  create + update dans UNE transaction (RG-T08) ; update reconstruit les slots en
  delete-and-reinsert (mlt 8.5 RG-2) ; delete FK-safe (order_item.menu_id RESTRICT,
  CASCADE vers slots/options) ; setActive ; categoryExists/productExists/isReferencedByOrders.
- App\Controllers\MenuController : index/create/store/edit/update/toggle/confirmDelete/
  destroy ; guard menu.read/create/update/delete (RG-T03) ; CSRF sur les mutations
  (RG-T01) ; validation bornee + allowlist (RG-T16/T18). PIN equipier + audit_log
  UNIQUEMENT a la suppression (mlt 8.6, RG-T13/T14) ; create/update sans PIN (un
  menu n'a pas de vat_rate). Throttle PIN RG-T22 (gate-before-verify, echec PIN
  trace + compte dans UNE transaction).
- Vues admin/menus/{index,form,delete} + assets/js/menu-form.js : builder de slots
  vanilla JS (CSP 'self' : donnees via data-*, etat serialise en champ cache
  slots_json car Request::formBody ne garde que les scalaires).
- Routes /admin/menus dans le front controller ; lien nav Menus reactive (menu.read).
- Tests : MenuControllerTest (12 cas : guard, slots, CSRF, toggle, flux PIN+audit
  atomique sur delete, 422 FK) ; MenuRepositoryDbTest (integration, vraie DB :
  create+slots, slotsWithOptions, update delete-and-reinsert, delete+cascade) ;
  FakeDatabase etendu (menu).

Suite : 201 tests verts (597 assertions avec WAKDO_DB_TESTS=1), PHPStan L6 propre.
Corentin merged commit c2a4854083 into dev 2026-06-16 15:39:10 +02:00
Corentin deleted branch feat/p3-menus-crud 2026-06-16 15:39:10 +02:00
Sign in to join this conversation.
No reviewers
No labels
auto-merge
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: AcadeNice/corentin_wakdo#32
No description provided.