corentin_wakdo/docs/merise/mct.md
Imugiii 6057ef990f docs(merise): rewrite MCT to prod-like v0.2 (4-state machine)
Drop MARK_IN_PREPARATION / MARK_READY; DELIVER_ORDER as single counter/drive gesture.
Add stock operations (sale decrement, restock, inventory_correction) and RBAC operations.
Actors: 5 seed roles + customer.
2026-06-04 15:17:33 +00:00

34 KiB

Model of Conceptual Treatments (MCT) — Wakdo

Merise phase : P1 - Conception, step 3 (after MCD) Version : v0.2 — prod-like, 4-state machine Date : 2026-06-04 Branch : feat/p1-conception Status : prod-like — all D1-D8 + stock decisions applied (see docs/notes/revue-alignement-p1.md §7) Author : BYAN (methodology layer)


1. Purpose

The MCT (Model of Conceptual Treatments) describes the business operations of the Wakdo domain in the canonical Merise form: triggering event -> operation -> emitted result.

It answers the question: what happens in the domain, and when? It does not answer: who does what, on which workstation, in which organisational order (the MOT level is intentionally skipped — agile shortcut, consistent with the solo RNCP framework).

The MCT covers:

  • The order lifecycle end-to-end (kiosk, counter, drive)
  • Catalogue management (manager / admin)
  • User and role management (admin)
  • Back-office authentication (all back-office actors)

Identified actors:

Actor Code Interface
Customer (kiosk) CUSTOMER Touch kiosk (public, unauthenticated)
Counter staff COUNTER Back-office, role counter
Drive staff DRIVE Back-office, role drive
Kitchen staff KITCHEN Back-office, role kitchen (read-only on orders)
Manager MANAGER Back-office, role manager
Administrator ADMIN Back-office, role admin
System SYS Internal API / PHP logic

MCD cross-reference: each operation references entities from the MCD (section 14). The MCT is consistent with the customer_order.status state machine:

pending_payment -> paid -> delivered
      |              |
      +--------------+-----------> cancelled (from any non-terminal state)

Dropped states (compared to v0.1): preparing and ready are removed. Rationale: in a fast-food context the kitchen display (KDS) is a visual system; staff read the ticket and act. The single staff gesture is "deliver". KPI is total time delivered_at - paid_at (SLA approx. 10 min). KDS colour coding is computed from now - paid_at; no additional stored state is required.

Dropped operations (compared to v0.1): MARK_IN_PREPARATION (MARQUER_EN_PREPARATION) and MARK_READY (MARQUER_PRETE) are removed because their intermediate states no longer exist. DELIVER_ORDER becomes the sole status-advancing action for counter/drive staff.


2. Representation conventions

Operation format

[TRIGGERING EVENT(S)]
        |
        | [SYNCHRONISATION RULE / CONDITION]
        v
   ( OPERATION )
        |
        v
[EMITTED RESULT(S)]

Synchronisations:

  • AND: all events must be present simultaneously to trigger the operation.
  • OR: any one of the events is sufficient.

Conditions: expressed in square brackets [condition] on the incoming arc.

Textual notation

For each operation the document provides:

  • Triggering event(s): what occurs and causes the operation.
  • Actor(s): who initiates (or validates).
  • Synchronisation: AND / OR if multiple events, plus condition.
  • Operation: name and description of what it does.
  • MCD entities touched: read (R) or write (W).
  • Result(s): what is emitted or produced.

3. Domain 1 — Order lifecycle (kiosk)

3.1 LOAD_CATALOGUE

Field Value
Triggering event Customer opens the kiosk (connection to the kiosk endpoint)
Actor CUSTOMER
Synchronisation None (single event)
Condition The kiosk is in service (within business hours 10:00-01:00)
Operation LOAD_CATALOGUE
Description Retrieval of active categories, available products, and available menus (with their slots and eligible options) for display on the kiosk screen.
MCD entities R: category (is_active=1), product (is_available=1), menu (is_available=1), menu_slot, menu_slot_option, ingredient (is_active=1), allergen, ingredient_allergen
Result Catalogue loaded; kiosk displays the home screen

3.2 COMPOSE_CART

Field Value
Triggering event Customer selects a product or a menu on the kiosk
Actor CUSTOMER
Synchronisation Repeatable event (OR: add product, add menu, change quantity, remove item, choose menu slot, choose format Normal/Maxi, add/remove ingredient modifier)
Condition The selected product or menu has is_available=1
Operation COMPOSE_CART
Description In-memory cart construction: add an item (standalone product or menu), select slot products (order_item_selection), optionally modify ingredients (order_item_modifier), choose Normal or Maxi format for menus, recalculate TTC total. The cart is a volatile client-side structure; no database write at this stage.
MCD entities R: product, menu, menu_slot, menu_slot_option, ingredient, product_ingredient — W: none (volatile front-end state)
Result Cart updated, total recalculated, summary displayed

3.3 CREATE_ORDER

Field Value
Triggering events 1. Customer confirms cart (presses "Validate") AND 2. Customer enters their order number (RNCP payment substitute)
Actor CUSTOMER
Synchronisation AND (both actions required)
Condition Cart contains at least 1 item. The order number entered is non-empty.
Operation CREATE_ORDER
Description Atomic order creation: INSERT customer_order with status pending_payment, source kiosk, snapshot of HT/VAT/TTC totals (computed line by line using vat_rate snapshotted per item). INSERT order_item lines with label_snapshot, unit_price_cents_snapshot, vat_rate_snapshot. INSERT order_item_selection for each slot filled in a menu item. INSERT order_item_modifier for each ingredient modification. Decrement ingredient.stock_quantity for each ingredient consumed (adjusted by modifiers: remove => no decrement; add => extra decrement); INSERT one stock_movement row of type sale per affected ingredient unit. Stock decrements and order insert are within the same transaction. After the customer enters their order number, the status transitions pending_payment -> paid within the same transaction; paid_at is set. The system generates the order number in format K-YYYY-MM-DD-NNN.
MCD entities R: product, menu, ingredient, product_ingredient (snapshot) — W: customer_order (INSERT status pending_payment then UPDATE status paid, paid_at), order_item (INSERT N lines), order_item_selection (INSERT per menu slot chosen), order_item_modifier (INSERT per modification), ingredient (UPDATE stock_quantity), stock_movement (INSERT type sale per unit)
Result Order created (status paid at end of operation), order number displayed to customer, logical event ORDER_CREATED emitted toward the preparation domain

3.4 DISPLAY_CONFIRMATION

Field Value
Triggering event ORDER_CREATED (API response 201 after CREATE_ORDER)
Actor SYS
Synchronisation None
Condition API response contains an id, an order_number and status paid
Operation DISPLAY_CONFIRMATION
Description Display of the confirmation screen on the kiosk with the order number. The kiosk then resets for the next customer.
MCD entities R: none (data is in the API response)
Result Confirmation screen displayed; kiosk available for next order

4. Domain 2 — Order lifecycle (counter and drive)

4.1 CREATE_COUNTER_ORDER

Field Value
Triggering event A counter or drive staff member initiates a new order from the back-office
Actor COUNTER or DRIVE
Synchronisation None
Condition The actor is authenticated and holds permission order.create. The source is counter or drive (auto-tagged from role.order_source).
Operation CREATE_COUNTER_ORDER
Description Manual order composition via the back-office: select products and menus, choose service mode (dine_in/takeaway/drive), fill menu slots, add ingredient modifiers. Identical creation logic to CREATE_ORDER (snapshot, stock decrement in same transaction, atomic pending_payment -> paid transition). The source is auto-tagged from role.order_source (counter -> counter, drive -> drive). Order number format: C-YYYY-MM-DD-NNN (counter) or D-YYYY-MM-DD-NNN (drive). Cross-constraint: if source = 'drive' then service_mode = 'drive' (verified at creation).
MCD entities R: product, menu, menu_slot, menu_slot_option, ingredient, product_ingredient — W: customer_order (INSERT status pending_payment then UPDATE status paid, paid_at), order_item, order_item_selection, order_item_modifier, ingredient (stock decrement), stock_movement (INSERT type sale)
Result Order created (status paid), order number communicated to customer

5. Domain 3 — Preparation display (kitchen)

5.1 LIST_ORDERS_DISPLAY

Field Value
Triggering event Kitchen staff accesses or refreshes the preparation display
Actor KITCHEN (or COUNTER, DRIVE, ADMIN)
Synchronisation None
Condition The actor is authenticated and holds permission order.read.
Operation LIST_ORDERS_DISPLAY
Description Read customer_order rows with status paid, filtered by sources visible to the actor's role (from role_visible_source): kitchen sees all sources; counter sees kiosk+counter; drive sees drive. Orders are sorted by paid_at ascending (oldest first). For each order, display: order number, source, content (order_item with label_snapshot, quantity, format, slot selections, ingredient modifiers). KDS colour is computed from now - paid_at against the SLA threshold (approx. 10 min), not stored. Kitchen staff performs no status transition — this is a read-only operation.
MCD entities R: customer_order (status=paid), order_item, order_item_selection, order_item_modifier, role_visible_source
Result Preparation display list shown, sorted by payment time ascending

6. Domain 4 — Delivery to customer

6.1 DELIVER_ORDER

Field Value
Triggering events 1. The order is at status paid AND 2. Counter or drive staff clicks "Delivered"
Actor COUNTER or DRIVE
Synchronisation AND
Condition The order has status paid. The actor holds permission order.deliver. The actor's role is consistent with the order source (counter staff handles kiosk+counter orders; drive staff handles drive orders — filtered by role_visible_source).
Operation DELIVER_ORDER
Description Single-gesture transition paid -> delivered. Sets delivered_at = NOW(). The order moves to history. This operation replaces the v0.1 two-step sequence (mark-ready then deliver); the kitchen's visual confirmation (KDS) is sufficient before this action.
MCD entities W: customer_order (UPDATE status paid -> delivered, delivered_at = NOW())
Result Order at status delivered, lifecycle complete

7. Domain 5 — Cancellation

7.1 CANCEL_ORDER

Field Value
Triggering event An authorised actor requests cancellation of an order
Actor COUNTER, DRIVE, or ADMIN
Synchronisation None
Condition The order exists. customer_order.status is in ['pending_payment', 'paid']. Terminal statuses delivered and cancelled cannot transition to cancelled. The actor holds permission order.cancel.
Operation CANCEL_ORDER
Description Transition from current status to cancelled. Sets cancelled_at = NOW(). The order is retained in the database for history and stats (no physical deletion). If the current status is paid, stock is re-credited: for each ingredient consumed by the order (accounting for modifiers), ingredient.stock_quantity is incremented; one stock_movement row of type cancellation is inserted per affected ingredient unit. Stock re-credit and status update are within the same transaction.
MCD entities R: order_item, order_item_modifier, ingredient, product_ingredient — W: customer_order (UPDATE status -> cancelled, cancelled_at = NOW()), ingredient (UPDATE stock_quantity, conditional on status paid), stock_movement (INSERT type cancellation, conditional on status paid)
Result Order at status cancelled, visible in admin history

8. Domain 6 — Catalogue management

8.1 CREATE_PRODUCT

Field Value
Triggering event Admin or manager submits the product creation form
Actor ADMIN or MANAGER
Synchronisation None
Condition Actor holds permission product.create. Target category exists and is_active=1. name is non-empty. price_cents > 0.
Operation CREATE_PRODUCT
Description INSERT a new product with its category, name, price in cents, VAT rate in per-mille (vat_rate: 100=10%, 55=5.5%, default 100), optional image path. is_available=1 by default.
MCD entities R: category (FK validation) — W: product (INSERT)
Result Product created, redirect to product list

8.2 UPDATE_PRODUCT

Field Value
Triggering event Admin or manager submits the product update form
Actor ADMIN or MANAGER
Synchronisation None
Condition Actor holds permission product.update. Product exists. New values respect constraints (price_cents > 0, non-empty name).
Operation UPDATE_PRODUCT
Description UPDATE modifiable columns (name, description, price_cents, vat_rate, image_path, is_available, display_order, category_id). Snapshots already stored in order_item are not affected (historical integrity guaranteed by design).
MCD entities W: product (UPDATE)
Result Product updated, product list refreshed

8.3 DELETE_PRODUCT

Field Value
Triggering event Admin confirms deletion of a product
Actor ADMIN
Synchronisation None
Condition Actor holds permission product.delete. Product is not a slot option in any menu_slot_option (FK ON DELETE RESTRICT). Product is not referenced in any order_item historical line (FK ON DELETE RESTRICT). Preliminary check required.
Operation DELETE_PRODUCT
Description Physical deletion of the product if no FK constraint blocks. If the product is referenced in a menu slot or historical order line, deletion is blocked. The recommended alternative is to deactivate (is_available=0). Also blocks if the product is the burger_product_id of any menu.
MCD entities W: product (DELETE — blocked if referenced in menu_slot_option, order_item, or menu.burger_product_id)
Result Product deleted OR error "product in use"

8.4 CREATE_MENU

Field Value
Triggering event Admin or manager submits the menu creation form with its slot configuration
Actor ADMIN or MANAGER
Synchronisation None
Condition Actor holds permission menu.create. name is non-empty. price_normal_cents > 0, price_maxi_cents > 0. burger_product_id references an existing product. At least one slot is defined with at least one option.
Operation CREATE_MENU
Description Transaction: INSERT menu (with burger_product_id, price_normal_cents, price_maxi_cents), then INSERT menu_slot rows (one per slot: drink, side, sauce...), then INSERT menu_slot_option rows (eligible products per slot).
MCD entities R: product (burger FK validation, slot options validation), category — W: menu (INSERT), menu_slot (INSERT), menu_slot_option (INSERT)
Result Menu created with its slot configuration, visible on the kiosk

8.5 UPDATE_MENU

Field Value
Triggering event Admin or manager submits the menu update form
Actor ADMIN or MANAGER
Synchronisation None
Condition Actor holds permission menu.update. Menu exists. Updated configuration preserves at least one slot with at least one option.
Operation UPDATE_MENU
Description UPDATE menu columns. If slot configuration is modified: DELETE all menu_slot_option rows for this menu's slots, DELETE menu_slot rows, then re-INSERT (delete-and-reinsert pattern, atomic in transaction). Snapshots in order_item are not affected.
MCD entities W: menu (UPDATE), menu_slot (DELETE + INSERT), menu_slot_option (DELETE + INSERT)
Result Menu updated

8.6 DELETE_MENU

Field Value
Triggering event Admin confirms deletion of a menu
Actor ADMIN
Synchronisation None
Condition Actor holds permission menu.delete. Menu is not referenced in any order_item historical line (FK ON DELETE RESTRICT). Preliminary check required.
Operation DELETE_MENU
Description If no order_item references this menu: DELETE menu_slot_option (CASCADE from menu_slot), DELETE menu_slot (CASCADE from menu), DELETE menu. If historical references exist, propose deactivation (is_available=0) instead.
MCD entities W: menu_slot_option (DELETE CASCADE), menu_slot (DELETE CASCADE), menu (DELETE — blocked if referenced in order_item)
Result Menu deleted OR error "menu present in historical orders"

8.7 MANAGE_CATEGORY

Field Value
Triggering event Admin or manager creates, updates, or deactivates a category
Actor ADMIN or MANAGER
Synchronisation OR (create, update, deactivation)
Condition Actor holds permission category.manage. For deactivation: products and menus in the category are not auto-deactivated in DB (no CASCADE on is_active); the application layer proposes deactivating child products/menus.
Operation MANAGE_CATEGORY
Description CRUD on category. Deactivation (is_active=0) hides the category and its products from the kiosk without physical deletion. Physical deletion is blocked if products or menus reference this category (FK ON DELETE RESTRICT).
MCD entities W: category (INSERT / UPDATE / conditional DELETE)
Result Category created / updated / deactivated

8.8 MANAGE_INGREDIENT

Field Value
Triggering event Admin or manager creates, updates, or deactivates an ingredient; or manages product composition (product_ingredient) or allergen mapping (ingredient_allergen)
Actor ADMIN or MANAGER
Synchronisation OR (create ingredient, update ingredient, update composition, update allergen mapping)
Condition Actor holds permission ingredient.manage.
Operation MANAGE_INGREDIENT
Description CRUD on ingredient (name, unit, pack_size, pack_label, low_stock_threshold, is_active). Manage product_ingredient composition (quantity_normal, quantity_maxi, is_removable, is_addable, extra_price_cents) for any product. Manage ingredient_allergen mapping (14 EU regulated allergens). Deactivating an ingredient (is_active=0) hides it from the configurator without deletion. Physical deletion of ingredient is blocked if referenced in product_ingredient (FK ON DELETE RESTRICT) or stock_movement (FK ON DELETE RESTRICT).
MCD entities R: product (FK validation), allergen (FK validation) — W: ingredient (INSERT/UPDATE/DELETE conditional), product_ingredient (INSERT/UPDATE/DELETE), ingredient_allergen (INSERT/DELETE)
Result Ingredient / composition / allergen mapping updated

9. Domain 7 — Stock management

9.1 RESTOCK

Field Value
Triggering event Manager or admin records a delivery of ingredient packs
Actor MANAGER or ADMIN
Synchronisation None
Condition Actor holds permission stock.manage. Ingredient exists and is_active=1. Number of packs N >= 1.
Operation RESTOCK
Description UPDATE ingredient.stock_quantity += N * pack_size. INSERT one stock_movement row: type restock, delta += N * pack_size, user_id of the actor, optional note (e.g. delivery reference). Both writes are in the same transaction.
MCD entities R: ingredient — W: ingredient (UPDATE stock_quantity), stock_movement (INSERT type restock)
Result Stock incremented, movement logged

9.2 INVENTORY_COUNT

Field Value
Triggering event A staff member or manager records the result of a physical inventory count
Actor KITCHEN, COUNTER, DRIVE, MANAGER, or ADMIN
Synchronisation None
Condition Actor holds permission stock.count. Ingredient exists. Physical count actual_quantity >= 0.
Operation INVENTORY_COUNT
Description Compute delta = actual_quantity - ingredient.stock_quantity (may be negative or positive). UPDATE ingredient.stock_quantity = actual_quantity. INSERT one stock_movement row: type inventory_correction, delta = computed discrepancy, user_id of the actor, optional note. Both writes in the same transaction.
MCD entities R: ingredient (read current stock_quantity) — W: ingredient (UPDATE stock_quantity), stock_movement (INSERT type inventory_correction)
Result Stock reconciled to physical count, discrepancy logged

9.3 READ_STOCK

Field Value
Triggering event An authorised actor accesses the stock view
Actor KITCHEN, COUNTER, DRIVE, MANAGER, or ADMIN
Synchronisation None
Condition Actor holds permission stock.read.
Operation READ_STOCK
Description Read ingredient list with current stock_quantity, low_stock_threshold, pack_size, pack_label. Low-stock alert computed at display time: stock_quantity <= low_stock_threshold. Optional: read stock_movement history for a given ingredient, filtered by date range.
MCD entities R: ingredient, stock_movement (optional history)
Result Stock list displayed with low-stock indicators

10. Domain 8 — User and role management (admin)

10.1 CREATE_USER

Field Value
Triggering event Admin submits the user creation form
Actor ADMIN
Synchronisation None
Condition Actor holds permission user.create. Email does not already exist in user.email (UNIQUE constraint). A valid and active role_id is selected.
Operation CREATE_USER
Description INSERT user with argon2id password hash. Email is unique. role_id is mandatory (FK NOT NULL). is_active=1 by default. last_login_at=NULL at creation.
MCD entities R: role (FK validation) — W: user (INSERT)
Result User created, can log into the back-office

10.2 UPDATE_USER

Field Value
Triggering event Admin submits the user update form
Actor ADMIN
Synchronisation None
Condition Actor holds permission user.update. User exists. If a new password is provided, it is re-hashed.
Operation UPDATE_USER
Description UPDATE modifiable fields (first_name, last_name, email, role_id, is_active). If a new password is supplied, it replaces the existing hash (argon2id rehash).
MCD entities W: user (UPDATE)
Result User updated

10.3 DEACTIVATE_USER

Field Value
Triggering event Admin clicks "Deactivate" for a user
Actor ADMIN
Synchronisation None
Condition Actor holds permission user.deactivate. Admin cannot deactivate their own account (application-level protection).
Operation DEACTIVATE_USER
Description UPDATE is_active=0. The user's active session is invalidated on next access (middleware checks is_active=1 on each authenticated request). User is not deleted; history remains traceable.
MCD entities W: user (UPDATE is_active=0)
Result User deactivated, back-office access blocked

10.4 MANAGE_RBAC

Field Value
Triggering event Admin modifies permission assignments for a role, or creates / updates a custom role
Actor ADMIN
Synchronisation OR (update role permissions, create custom role, update role attributes)
Condition Actor holds permission role.manage. Selected permissions exist in the permission catalogue.
Operation MANAGE_RBAC
Description Update role_permission for a given role: DELETE existing assignments, INSERT new ones (delete-and-reinsert, atomic in transaction). Permissions themselves are static (declared in migration, not modifiable via UI). Also covers: CREATE/UPDATE custom role (code, label, description, default_route, order_source), UPDATE role_visible_source (visible dashboard sources for the role). RBAC architecture rule: application code tests permissions, not role names — adding a new role with correct permissions requires no code change.
MCD entities R: role, permission — W: role_permission (DELETE + INSERT), role (INSERT/UPDATE for custom roles), role_visible_source (INSERT/DELETE)
Result RBAC matrix updated, effective immediately for new requests of users bearing this role

11. Domain 9 — Stats and KPI

11.1 READ_STATS

Field Value
Triggering event Manager or admin accesses the stats dashboard
Actor MANAGER or ADMIN
Synchronisation None
Condition Actor holds permission stats.read.
Operation READ_STATS
Description Aggregate queries on customer_order and order_item. Key aggregations: order count and revenue (TTC) by service_day (computed with CASE WHEN HOUR(created_at) < 10 THEN DATE(created_at) - INTERVAL 1 DAY ELSE DATE(created_at) END; cutoff at 10:00); top products by label_snapshot COUNT in order_item; cancellation rate; average delivery time delivered_at - paid_at; breakdown by source and service_mode. Queries exclude cancelled orders from revenue sums but include them in volume counts. No additional stored column for service_day; computation at query time.
MCD entities R: customer_order, order_item
Result Stats dashboard displayed

12. Domain 10 — Back-office authentication

12.1 AUTHENTICATE_USER

Field Value
Triggering event An actor submits the login form
Actor COUNTER / DRIVE / KITCHEN / MANAGER / ADMIN
Synchronisation None
Condition Email exists in database. Password matches argon2id hash. User is_active=1.
Operation AUTHENTICATE_USER
Description Credential verification. If valid: session ID regeneration (protection against session fixation), storage of user_id and role_id in session, UPDATE last_login_at. Idle timeout: 4h. Absolute timeout: 10h. Redirect to role.default_route.
MCD entities R: user (verification), role (load permissions, default_route), role_permission — W: user (UPDATE last_login_at)
Result Session opened, redirect to role-specific default view

12.2 LOGOUT_USER

Field Value
Triggering event Actor clicks "Logout" OR session expires
Actor COUNTER / DRIVE / KITCHEN / MANAGER / ADMIN / SYS (expiry)
Synchronisation OR
Condition A valid session is open
Operation LOGOUT_USER
Description PHP session destruction (session_destroy()). Session deleted server-side. Session cookie invalidated.
MCD entities No database write (session management is in PHP native, outside DB for this project)
Result Session destroyed, redirect to login page

13. State machine — customer_order.status

Summary of transitions covered by MCT operations.

               [CUSTOMER / COUNTER / DRIVE]
               CREATE_ORDER
               CREATE_COUNTER_ORDER
                      |
                      v
           [ pending_payment ]  (order composed, payment pending)
                      |
    [CUSTOMER / COUNTER / DRIVE] payment confirmed
    (atomic within CREATE_ORDER / CREATE_COUNTER_ORDER)
                      |
                      v
                 [ paid ]
                      |
      [COUNTER / DRIVE] DELIVER_ORDER
                      |
                      v
               [ delivered ]  (terminal, cannot be cancelled)


  From pending_payment / paid:
  [COUNTER, DRIVE, or ADMIN] CANCEL_ORDER
                      |
                      v
               [ cancelled ]  (terminal)

Note on the pending_payment -> paid transition: in the RNCP context, payment is replaced by the customer entering their order number (kiosk) or by staff validation (counter/drive). The transition is atomic within CREATE_ORDER and CREATE_COUNTER_ORDER. The pending_payment status is not observable outside the transaction.

Dropped from v0.1: preparing and ready states; MARK_IN_PREPARATION and MARK_READY operations. Kitchen staff have a read-only view of paid orders (LIST_ORDERS_DISPLAY). The single delivery action (DELIVER_ORDER) collapses the v0.1 three-step sequence into one gesture.


14. Operations summary table

# Operation Domain Actor W Entities R Entities
1 LOAD_CATALOGUE Order kiosk CUSTOMER category, product, menu, menu_slot, menu_slot_option, ingredient, allergen, ingredient_allergen
2 COMPOSE_CART Order kiosk CUSTOMER — (volatile) product, menu, menu_slot, menu_slot_option, ingredient, product_ingredient
3 CREATE_ORDER Order kiosk CUSTOMER customer_order, order_item, order_item_selection, order_item_modifier, ingredient, stock_movement product, menu, ingredient, product_ingredient
4 DISPLAY_CONFIRMATION Order kiosk SYS
5 CREATE_COUNTER_ORDER Order counter/drive COUNTER/DRIVE customer_order, order_item, order_item_selection, order_item_modifier, ingredient, stock_movement product, menu, menu_slot, menu_slot_option, ingredient, product_ingredient
6 LIST_ORDERS_DISPLAY Preparation KITCHEN/COUNTER/DRIVE/ADMIN customer_order, order_item, order_item_selection, order_item_modifier, role_visible_source
7 DELIVER_ORDER Delivery COUNTER/DRIVE customer_order
8 CANCEL_ORDER Cancellation COUNTER/DRIVE/ADMIN customer_order, ingredient, stock_movement order_item, order_item_modifier, ingredient, product_ingredient
9 CREATE_PRODUCT Catalogue ADMIN/MANAGER product category
10 UPDATE_PRODUCT Catalogue ADMIN/MANAGER product
11 DELETE_PRODUCT Catalogue ADMIN product menu_slot_option, order_item, menu
12 CREATE_MENU Catalogue ADMIN/MANAGER menu, menu_slot, menu_slot_option product, category
13 UPDATE_MENU Catalogue ADMIN/MANAGER menu, menu_slot, menu_slot_option
14 DELETE_MENU Catalogue ADMIN menu_slot_option, menu_slot, menu order_item
15 MANAGE_CATEGORY Catalogue ADMIN/MANAGER category product, menu
16 MANAGE_INGREDIENT Catalogue ADMIN/MANAGER ingredient, product_ingredient, ingredient_allergen product, allergen
17 RESTOCK Stock MANAGER/ADMIN ingredient, stock_movement ingredient
18 INVENTORY_COUNT Stock KITCHEN/COUNTER/DRIVE/MANAGER/ADMIN ingredient, stock_movement ingredient
19 READ_STOCK Stock KITCHEN/COUNTER/DRIVE/MANAGER/ADMIN ingredient, stock_movement
20 CREATE_USER RBAC ADMIN user role
21 UPDATE_USER RBAC ADMIN user
22 DEACTIVATE_USER RBAC ADMIN user
23 MANAGE_RBAC RBAC ADMIN role_permission, role, role_visible_source role, permission
24 READ_STATS Stats MANAGER/ADMIN customer_order, order_item
25 AUTHENTICATE_USER Auth ALL BACK user user, role, role_permission
26 LOGOUT_USER Auth ALL BACK

Total: 26 operations covering the complete Wakdo business lifecycle.


15. MCT -> MCD cross-validation (mantra #34)

Verification that each MCD entity participates in at least one MCT operation.

MCD entity Operations that read Operations that write Coverage
category 1, 9, 12, 15 15 OK
product 1, 2, 3, 5, 9, 11, 12 9, 10, 11 OK
menu 1, 2, 3, 5, 12, 14 12, 13, 14 OK
menu_slot 1, 2, 5 12, 13, 14 OK
menu_slot_option 1, 2, 5, 11 12, 13, 14 OK
ingredient 1, 2, 3, 5, 8, 16, 17, 18, 19 3, 5, 8, 16, 17, 18 OK
product_ingredient 2, 3, 5, 8 16 OK
allergen 1 — (static seed) OK (*)
ingredient_allergen 1 16 OK
customer_order 6, 8, 24 3, 5, 7, 8 OK
order_item 6, 8, 14, 24 3, 5 OK
order_item_selection 6 3, 5 OK
order_item_modifier 6, 8 3, 5 OK
user 25 20, 21, 22, 25 OK
role 20, 23, 25 23 OK
role_visible_source 6 23 OK
permission 23 — (static seed) OK (*)
role_permission 25 23 OK
stock_movement 19 3, 5, 8, 17, 18 OK

(*) allergen and permission are read-only at the MCT level: their values are declared in seed migrations and are not modifiable via the UI. allergen is managed indirectly via ingredient_allergen in MANAGE_INGREDIENT.

Conclusion: 19/19 entities covered. MCT <-> MCD consistency validated.