From 8ce1dc21deba52e29b5861e9d84a2f30128a6c70 Mon Sep 17 00:00:00 2001 From: Corentin JOGUET Date: Tue, 16 Jun 2026 14:21:27 +0200 Subject: [PATCH] docs(catalogue): contrat exact des FK a la suppression produit (#27) --- src/app/Catalogue/ProductRepository.php | 16 ++++++++++++---- src/app/Controllers/ProductController.php | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/Catalogue/ProductRepository.php b/src/app/Catalogue/ProductRepository.php index 790bf2c..3a93f3a 100644 --- a/src/app/Catalogue/ProductRepository.php +++ b/src/app/Catalogue/ProductRepository.php @@ -8,10 +8,18 @@ use App\Core\DatabaseInterface; /** * Acces aux donnees de la table product (sous-domaine Catalogue). Suit le pattern - * etabli par CategoryRepository. La suppression dure peut etre bloquee par des FK - * RESTRICT (order_item, menu.burger_product_id, menu_slot_option, - * order_item_selection) : le controleur attrape la violation (SQLSTATE 23000) -> - * 422, plutot que de pre-tester chaque reference. + * etabli par CategoryRepository. + * + * Topologie des FK entrantes sur product(id) (db/migrations/0001) et effet sur la + * suppression dure : + * - RESTRICT (bloquent la suppression) : order_item, menu.burger_product_id, + * menu_slot_option, order_item_selection. Le controleur attrape la violation + * (SQLSTATE 23000) -> 422, plutot que de pre-tester chaque reference. + * - CASCADE : product_ingredient (la recette appartient au produit ; la + * supprimer avec le produit est voulu). La suppression n'est donc PAS bloquee + * par une recette existante. TODO (phase stock/recettes, table aujourd'hui + * vide) : tracer le nombre de lignes product_ingredient cascade-supprimees + * dans l'audit_log pour ne laisser aucune perte hors-trace. */ final class ProductRepository { diff --git a/src/app/Controllers/ProductController.php b/src/app/Controllers/ProductController.php index 6a487f4..9a82d40 100644 --- a/src/app/Controllers/ProductController.php +++ b/src/app/Controllers/ProductController.php @@ -240,6 +240,10 @@ class ProductController extends AdminController $name = (string) ($product['name'] ?? ''); + // FK RESTRICT (order_item / menu / menu_slot_option / order_item_selection) + // -> PDOException 23000 -> 422 (catch ci-dessous). product_ingredient est + // CASCADE (recette possedee par le produit) : supprimee avec lui, jamais + // bloquante (cf. docblock ProductRepository). try { $this->db()->transaction(function (DatabaseInterface $db) use ($id, $actor, $name): void { $deleted = (new ProductRepository($db))->delete($id);