diff --git a/docs/merise/_diagrams/mcd-catalogue.drawio b/docs/merise/_diagrams/mcd-catalogue.drawio deleted file mode 100644 index c9cf3e8..0000000 --- a/docs/merise/_diagrams/mcd-catalogue.drawio +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-catalogue.mmd b/docs/merise/_diagrams/mcd-catalogue.mmd new file mode 100644 index 0000000..698a179 --- /dev/null +++ b/docs/merise/_diagrams/mcd-catalogue.mmd @@ -0,0 +1,51 @@ +erDiagram + category { + int id PK + varchar name + varchar slug + varchar image_path + smallint display_order + tinyint is_active + } + product { + int id PK + int category_id FK + varchar name + text description + int price_cents + smallint vat_rate + varchar image_path + tinyint is_available + smallint display_order + } + menu { + int id PK + int category_id FK + int burger_product_id FK + varchar name + text description + int price_normal_cents + int price_maxi_cents + varchar image_path + tinyint is_available + smallint display_order + } + menu_slot { + int id PK + int menu_id FK + varchar name + enum slot_type + tinyint is_required + smallint display_order + } + menu_slot_option { + int menu_slot_id FK + int product_id FK + } + + category ||--o{ product : "groups" + category ||--o{ menu : "groups" + menu ||--|| product : "anchors (burger_product_id)" + menu ||--o{ menu_slot : "defines_slot" + menu_slot ||--o{ menu_slot_option : "lists" + product ||--o{ menu_slot_option : "is_eligible_for" diff --git a/docs/merise/_diagrams/mcd-catalogue.svg b/docs/merise/_diagrams/mcd-catalogue.svg index c3a2016..38c2764 100644 --- a/docs/merise/_diagrams/mcd-catalogue.svg +++ b/docs/merise/_diagrams/mcd-catalogue.svg @@ -1,4 +1 @@ - - - -CATEGORIEid : INT (PK)libelle : VARCHAR (UNIQUE)slug : VARCHAR (UNIQUE)image_path : VARCHARordre : SMALLINTest_actif : BOOLEANCATEGORIEid : INT (PK)...PRODUITid : INT (PK)categorie_id : INT (FK)libelle : VARCHARdescription : TEXTprix_ttc_cents : INTimage_path : VARCHARest_disponible : BOOLEANordre : SMALLINTPRODUITid : INT (PK)...MENUid : INT (PK)categorie_id : INT (FK)libelle : VARCHARdescription : TEXTprix_ttc_cents : INTimage_path : VARCHARest_disponible : BOOLEANordre : SMALLINTMENUid : INT (PK)...MENU_PRODUIT (associative)menu_id : INT (PK, FK)produit_id : INT (PK, FK)role : ENUMposition : SMALLINTMENU_PRODUIT (associative)menu_id : INT (PK,...regrouperegroupe(0,N)(0,N)(1,1)(1,1)regrouperegroupe(0,N)(0,N)(1,1)(1,1)fait_partie_defait_partie_de(0,N)(0,N)(1,1)(1,1)composecompose(1,N)(1,N)(1,1)(1,1)Text is not SVG - cannot display \ No newline at end of file +groupsgroupsanchors (burger_product_id)defines_slotlistsis_eligible_forcategoryintidPKvarcharnamevarcharslugvarcharimage_pathsmallintdisplay_ordertinyintis_activeproductintidPKintcategory_idFKvarcharnametextdescriptionintprice_centssmallintvat_ratevarcharimage_pathtinyintis_availablesmallintdisplay_ordermenuintidPKintcategory_idFKintburger_product_idFKvarcharnametextdescriptionintprice_normal_centsintprice_maxi_centsvarcharimage_pathtinyintis_availablesmallintdisplay_ordermenu_slotintidPKintmenu_idFKvarcharnameenumslot_typetinyintis_requiredsmallintdisplay_ordermenu_slot_optionintmenu_slot_idFKintproduct_idFK \ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-commande.drawio b/docs/merise/_diagrams/mcd-commande.drawio deleted file mode 100644 index a6ef277..0000000 --- a/docs/merise/_diagrams/mcd-commande.drawio +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-commande.svg b/docs/merise/_diagrams/mcd-commande.svg deleted file mode 100644 index 2d4be3b..0000000 --- a/docs/merise/_diagrams/mcd-commande.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -COMMANDEid : INT (PK)numero : VARCHAR (UNIQUE)source : ENUM (kiosk|comptoir|drive)mode_consommation : ENUM (sur_place|a_emporter|drive)statut : ENUMtotal_ht_cents : INTtotal_tva_cents : INTtotal_ttc_cents : INTtva_taux_pourmille : SMALLINTpaye_a : DATETIMEUSERid : INT (PK)(detail dans RBAC)COMMANDE_EVENTid : INT (PK)commande_id : INT (FK)event_type : ENUMfrom_statut : ENUM (NULL)to_statut : ENUMuser_id : INT (FK, NULL)payload : JSON (NULL)created_at : DATETIMELIGNE_COMMANDEid : INT (PK)commande_id : INT (FK)type_item : ENUM (produit|menu)produit_id : INT (FK, NULL)menu_id : INT (FK, NULL)libelle_snapshot : VARCHARprix_unitaire_ttc_cents_snapshot : INTquantite : SMALLINTPRODUITid : INT (PK)(detail dans Catalogue)MENUid : INT (PK)(detail dans Catalogue)contient(1,N)(1,1)refere_si_type_produit(0,1)(0,N)refere_si_type_menu(0,N)PolymorphismeExactement UNE des deux references est non-nulle.Discriminateur : type_item ∈ {produit, menu}.Contrainte CHECK SQL au MLD.journalise(1,N)(1,1)declenche(0,N)(0,1)(0,1)Journal d'audit (event sourcing)Append-only : aucun UPDATE / DELETE applicatif.user_id NULL si auto-validation kiosk.ON DELETE CASCADE cote commande_id.ON DELETE SET NULL cote user_id. \ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-global.drawio b/docs/merise/_diagrams/mcd-global.drawio deleted file mode 100644 index 962f01b..0000000 --- a/docs/merise/_diagrams/mcd-global.drawio +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-global.svg b/docs/merise/_diagrams/mcd-global.svg deleted file mode 100644 index 1d26537..0000000 --- a/docs/merise/_diagrams/mcd-global.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -CATEGORIEPRODUITMENU_PRODUITMENULIGNE_COMMANDECOMMANDECOMMANDE_EVENTUSERROLEROLE_PERMISSIONPERMISSIONregroupe(0,N)(1,1)regroupe(0,N)(1,1)fait_partie_de(0,N)(1,1)compose(1,N)(1,1)contient(1,N)(1,1)refere_si_type_produit(0,1)(0,N)refere_si_type_menu(0,1)(0,N)a_pour_role(1,1)(0,N)possede(0,N)(1,1)assignee_a(0,N)(1,1)journalise(1,N)(1,1)declenche(0,N)(0,1) \ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-ingredients-stock.mmd b/docs/merise/_diagrams/mcd-ingredients-stock.mmd new file mode 100644 index 0000000..dff0eee --- /dev/null +++ b/docs/merise/_diagrams/mcd-ingredients-stock.mmd @@ -0,0 +1,61 @@ +erDiagram + product { + int id PK + varchar name + } + ingredient { + int id PK + varchar name + varchar unit + int stock_quantity + int stock_capacity + smallint pack_size + varchar pack_label + smallint low_stock_pct + smallint critical_stock_pct + tinyint is_active + } + product_ingredient { + int product_id FK + int ingredient_id FK + smallint quantity_normal + smallint quantity_maxi + tinyint is_removable + tinyint is_addable + int extra_price_cents + } + allergen { + int id PK + varchar code + varchar name + text description + } + ingredient_allergen { + int ingredient_id FK + int allergen_id FK + } + customer_order { + int id PK + varchar order_number + } + user { + int id PK + varchar email + } + stock_movement { + int id PK + int ingredient_id FK + enum movement_type + int delta + int order_id FK + int user_id FK + varchar note + } + + product ||--o{ product_ingredient : "is_composed_of" + ingredient ||--o{ product_ingredient : "appears_in" + ingredient ||--o{ ingredient_allergen : "contains" + allergen ||--o{ ingredient_allergen : "is_present_in" + ingredient ||--o{ stock_movement : "decrements" + customer_order |o--o{ stock_movement : "triggers" + user |o--o{ stock_movement : "logs" diff --git a/docs/merise/_diagrams/mcd-ingredients-stock.svg b/docs/merise/_diagrams/mcd-ingredients-stock.svg new file mode 100644 index 0000000..615a975 --- /dev/null +++ b/docs/merise/_diagrams/mcd-ingredients-stock.svg @@ -0,0 +1 @@ +is_composed_ofappears_incontainsis_present_indecrementstriggerslogsproductintidPKvarcharnameingredientintidPKvarcharnamevarcharunitintstock_quantityintstock_capacitysmallintpack_sizevarcharpack_labelsmallintlow_stock_pctsmallintcritical_stock_pcttinyintis_activeproduct_ingredientintproduct_idFKintingredient_idFKsmallintquantity_normalsmallintquantity_maxitinyintis_removabletinyintis_addableintextra_price_centsallergenintidPKvarcharcodevarcharnametextdescriptioningredient_allergenintingredient_idFKintallergen_idFKcustomer_orderintidPKvarcharorder_numberuserintidPKvarcharemailstock_movementintidPKintingredient_idFKenummovement_typeintdeltaintorder_idFKintuser_idFKvarcharnote \ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-order.mmd b/docs/merise/_diagrams/mcd-order.mmd new file mode 100644 index 0000000..be06a07 --- /dev/null +++ b/docs/merise/_diagrams/mcd-order.mmd @@ -0,0 +1,67 @@ +erDiagram + customer_order { + int id PK + varchar order_number + varchar idempotency_key + enum source + int acting_user_id FK + enum service_mode + enum status + int total_ht_cents + int total_vat_cents + int total_ttc_cents + datetime paid_at + datetime delivered_at + datetime cancelled_at + } + order_item { + int id PK + int order_id FK + enum item_type + int product_id FK + int menu_id FK + enum format + varchar label_snapshot + int unit_price_cents_snapshot + smallint vat_rate_snapshot + smallint quantity + } + order_item_selection { + int id PK + int order_item_id FK + int menu_slot_id FK + int product_id FK + varchar label_snapshot + } + order_item_modifier { + int id PK + int order_item_id FK + int ingredient_id FK + enum action + int extra_price_cents + } + product { + int id PK + varchar name + } + menu { + int id PK + varchar name + } + menu_slot { + int id PK + varchar name + } + ingredient { + int id PK + varchar name + } + + customer_order ||--o{ order_item : "contains" + order_item }o--o| product : "references_product" + order_item }o--o| menu : "references_menu" + order_item ||--o{ order_item_selection : "fills_slot" + order_item ||--o{ order_item_modifier : "modifies_ingredient" + menu_slot ||--o{ order_item_selection : "slot_filled_by" + product ||--o{ order_item_selection : "chosen_for_slot" + ingredient ||--o{ order_item_modifier : "modified_by" diff --git a/docs/merise/_diagrams/mcd-order.svg b/docs/merise/_diagrams/mcd-order.svg new file mode 100644 index 0000000..aeb5ac7 --- /dev/null +++ b/docs/merise/_diagrams/mcd-order.svg @@ -0,0 +1 @@ +containsreferences_productreferences_menufills_slotmodifies_ingredientslot_filled_bychosen_for_slotmodified_bycustomer_orderintidPKvarcharorder_numbervarcharidempotency_keyenumsourceintacting_user_idFKenumservice_modeenumstatusinttotal_ht_centsinttotal_vat_centsinttotal_ttc_centsdatetimepaid_atdatetimedelivered_atdatetimecancelled_atorder_itemintidPKintorder_idFKenumitem_typeintproduct_idFKintmenu_idFKenumformatvarcharlabel_snapshotintunit_price_cents_snapshotsmallintvat_rate_snapshotsmallintquantityorder_item_selectionintidPKintorder_item_idFKintmenu_slot_idFKintproduct_idFKvarcharlabel_snapshotorder_item_modifierintidPKintorder_item_idFKintingredient_idFKenumactionintextra_price_centsproductintidPKvarcharnamemenuintidPKvarcharnamemenu_slotintidPKvarcharnameingredientintidPKvarcharname \ No newline at end of file diff --git a/docs/merise/_diagrams/mcd-rbac.drawio b/docs/merise/_diagrams/mcd-rbac.drawio deleted file mode 100644 index 31e109d..0000000 --- a/docs/merise/_diagrams/mcd-rbac.drawio +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mcd-rbac.mmd b/docs/merise/_diagrams/mcd-rbac.mmd new file mode 100644 index 0000000..f3bb49a --- /dev/null +++ b/docs/merise/_diagrams/mcd-rbac.mmd @@ -0,0 +1,64 @@ +erDiagram + user { + int id PK + varchar email + varchar password_hash + varchar pin_hash + varchar first_name + varchar last_name + int role_id FK + tinyint is_active + datetime last_login_at + smallint failed_login_attempts + datetime lockout_until + datetime anonymized_at + } + role { + int id PK + varchar code + varchar label + text description + varchar default_route + enum order_source + tinyint is_active + } + role_visible_source { + int role_id FK + enum source + } + permission { + int id PK + varchar code + varchar label + text description + } + role_permission { + int role_id FK + int permission_id FK + } + audit_log { + int id PK + int actor_user_id FK + int actor_role_id FK + varchar action_code + varchar entity_type + int entity_id + varchar summary + json details + datetime created_at + } + login_throttle { + int id PK + varchar ip_address UK + smallint failed_attempts + datetime window_started_at + datetime lockout_until + datetime last_attempt_at + } + + user }o--|| role : "holds" + role ||--o{ role_visible_source : "sees_source" + role ||--o{ role_permission : "grants" + permission ||--o{ role_permission : "granted_to" + user |o--o{ audit_log : "performs" + role |o--o{ audit_log : "context_of" diff --git a/docs/merise/_diagrams/mcd-rbac.svg b/docs/merise/_diagrams/mcd-rbac.svg index e92d624..688b27f 100644 --- a/docs/merise/_diagrams/mcd-rbac.svg +++ b/docs/merise/_diagrams/mcd-rbac.svg @@ -1,4 +1 @@ - - - -USERid : INT (PK)email : VARCHAR (UNIQUE, RFC 5321)password_hash : VARCHAR (argon2id)nom : VARCHARprenom : VARCHARrole_id : INT (FK)est_actif : BOOLEANlast_login_at : DATETIMEROLEid : INT (PK)code : VARCHAR (UNIQUE)libelle : VARCHARdescription : TEXTest_actif : BOOLEANPERMISSIONid : INT (PK)code : VARCHAR (UNIQUE, resource.action)libelle : VARCHARdescription : TEXTROLE_PERMISSION (associative)role_id : INT (PK, FK)permission_id : INT (PK, FK)a_pour_role(1,1)(0,N)possede(0,N)(1,1)assignee_a(0,N)(1,1) \ No newline at end of file +holdssees_sourcegrantsgranted_toperformscontext_ofuserintidPKvarcharemailvarcharpassword_hashvarcharpin_hashvarcharfirst_namevarcharlast_nameintrole_idFKtinyintis_activedatetimelast_login_atsmallintfailed_login_attemptsdatetimelockout_untildatetimeanonymized_atroleintidPKvarcharcodevarcharlabeltextdescriptionvarchardefault_routeenumorder_sourcetinyintis_activerole_visible_sourceintrole_idFKenumsourcepermissionintidPKvarcharcodevarcharlabeltextdescriptionrole_permissionintrole_idFKintpermission_idFKaudit_logintidPKintactor_user_idFKintactor_role_idFKvarcharaction_codevarcharentity_typeintentity_idvarcharsummaryjsondetailsdatetimecreated_atlogin_throttleintidPKvarcharip_addressUKsmallintfailed_attemptsdatetimewindow_started_atdatetimelockout_untildatetimelast_attempt_at \ No newline at end of file diff --git a/docs/merise/_diagrams/mld-catalogue.drawio b/docs/merise/_diagrams/mld-catalogue.drawio deleted file mode 100644 index e292dbc..0000000 --- a/docs/merise/_diagrams/mld-catalogue.drawio +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mld-commande.drawio b/docs/merise/_diagrams/mld-commande.drawio deleted file mode 100644 index 1a47a5d..0000000 --- a/docs/merise/_diagrams/mld-commande.drawio +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/_diagrams/mld-rbac.drawio b/docs/merise/_diagrams/mld-rbac.drawio deleted file mode 100644 index 0922801..0000000 --- a/docs/merise/_diagrams/mld-rbac.drawio +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/merise/mcd.md b/docs/merise/mcd.md index 64a889c..e910e23 100644 --- a/docs/merise/mcd.md +++ b/docs/merise/mcd.md @@ -83,8 +83,9 @@ Merise practice for models of this size. **Note on the absence of a global diagram**: a single 21-entity ER diagram would be unreadable and unmaintainable. The sub-domain decomposition below is the intentional -structural choice. The `.drawio` source files will be regenerated from this document as the -single reference once the MCD is stabilised (regeneration tracked in `docs/notes/`). +structural choice. Each sub-domain is a Mermaid `erDiagram` (authoritative, rendered +natively) with a portable SVG render in `docs/merise/_diagrams/`; see section 11 for the +sources and regeneration command. --- @@ -600,10 +601,27 @@ audit writes, reset/lockout, anonymisation). The treatment-layer additions are t --- -## 11. Note on .drawio diagram regeneration +## 11. Diagram sources and regeneration -The `.drawio` XML sources in `docs/merise/_diagrams/` reflect the v0.1 model (11 entities, -French naming). They are scheduled for regeneration from this v0.2 MCD as a separate task. -Until regenerated, this Markdown document is the authoritative conceptual model. The Mermaid -`erDiagram` blocks in sections 4-7 render natively on GitHub and serve as the interim -graphical reference. +The authoritative graphical model is the set of Mermaid `erDiagram` blocks in sections 4-7, +one per sub-domain. They render natively on Forgejo and GitHub. The MCD is decomposed by +sub-domain on purpose: a single 21-entity diagram cannot be laid out without crossing +relationship lines (intrinsic planarity limit, and `erDiagram` offers no manual layout +control). Each sub-domain stays at 5-8 entities, which auto-layout handles cleanly. The +integrated view across sub-domains is the cross-validation table in section 8. + +Portable SVG renders live in `docs/merise/_diagrams/` (for PDF export / offline viewing): + +| Sub-domain | Source | Render | +|---|---|---| +| Catalogue | `mcd-catalogue.mmd` | `mcd-catalogue.svg` | +| Ingredients & Stock | `mcd-ingredients-stock.mmd` | `mcd-ingredients-stock.svg` | +| Order | `mcd-order.mmd` | `mcd-order.svg` | +| RBAC | `mcd-rbac.mmd` | `mcd-rbac.svg` | + +The `.mmd` files are extracted from the `erDiagram` blocks above; the `.svg` are produced by +`make docs-render` (mmdc). If a block here changes, re-extract the matching `.mmd` and re-run +`make docs-render`. The legacy v0.1 `.drawio` sources have been removed: drawio gave manual +layout control but required hand-editing and did not render in the Markdown previews, whereas +the decomposed Mermaid blocks are version-controlled, render everywhere, and stay in sync with +this document.
groups
anchors (burger_product_id)
defines_slot
lists
is_eligible_for
category
int
id
PK
varchar
name
slug
image_path
smallint
display_order
tinyint
is_active
product
category_id
FK
text
description
price_cents
vat_rate
is_available
menu
burger_product_id
price_normal_cents
price_maxi_cents
menu_slot
menu_id
enum
slot_type
is_required
menu_slot_option
menu_slot_id
product_id
is_composed_of
appears_in
contains
is_present_in
decrements
triggers
logs
ingredient
unit
stock_quantity
stock_capacity
pack_size
pack_label
low_stock_pct
critical_stock_pct
product_ingredient
ingredient_id
quantity_normal
quantity_maxi
is_removable
is_addable
extra_price_cents
allergen
code
ingredient_allergen
allergen_id
customer_order
order_number
user
email
stock_movement
movement_type
delta
order_id
user_id
note
references_product
references_menu
fills_slot
modifies_ingredient
slot_filled_by
chosen_for_slot
modified_by
idempotency_key
source
acting_user_id
service_mode
status
total_ht_cents
total_vat_cents
total_ttc_cents
datetime
paid_at
delivered_at
cancelled_at
order_item
item_type
format
label_snapshot
unit_price_cents_snapshot
vat_rate_snapshot
quantity
order_item_selection
order_item_id
order_item_modifier
action
holds
sees_source
grants
granted_to
performs
context_of
password_hash
pin_hash
first_name
last_name
role_id
last_login_at
failed_login_attempts
lockout_until
anonymized_at
role
label
default_route
order_source
role_visible_source
permission
role_permission
permission_id
audit_log
actor_user_id
actor_role_id
action_code
entity_type
entity_id
summary
json
details
created_at
login_throttle
ip_address
UK
failed_attempts
window_started_at
last_attempt_at