a9c14704b7
Auto Tag Develop / tag (push) Successful in 7s
## Contexte Une `Category` ne pouvait appartenir qu'à **un seul** `CategoryType` (ManyToOne). Le besoin métier : plusieurs types par catégorie. Cette MR fait passer la relation en **ManyToMany** et ajoute le bouton **« Filtres »** à droite de la liste des catégories (modèle Répertoire Clients). Slice vertical complet (le passage M:N casse mécaniquement le contrat inter-module `CategoryInterface`, consommé par la RG-2.10 fournisseurs). ## Volet A — Relation M:N - `Category.categoryType` (ManyToOne) → `categoryTypes` (ManyToMany, jonction `category_category_type`). Au moins un type obligatoire (`Assert\\Count(min:1)`). - **Unicité du nom GLOBALE** parmi les actifs (`uq_category_name_active`, remplace `uq_category_name_type_active`). Message 409 reformulé. - Migration : table de jonction + backfill + drop colonne `category_type_id` + nouvel index. Validée **rejouable sur base fraîche**. - Contrat Shared : `getCategoryTypeCode()` → `getCategoryTypeCodes(): array`. `Supplier`/`SupplierAddress`/`SupplierFixtures` revalident « contient FOURNISSEUR » (RG-2.10). - Provider/Repository : filtre type via sous-requête `EXISTS` (ne tronque pas la collection embarquée), eager-load anti-N+1. ## Volet B — Bouton « Filtres » - Drawer recherche par nom + types multi (OR). Compteur de filtres actifs. État local, jamais persisté en URL. - Back : filtres `?name=` et `?typeId[]=` sur la collection. ## Front - Multi-select `MalioSelectCheckbox`, `useCategoryForm` en `categoryTypeIds[]`, colonne « Types », clés i18n. ## Tests / vérifs - `make test` : **582 tests, 2474 assertions, 0 échec** ✅ - `make nuxt-test` : **236 tests** ✅ - `make php-cs-fixer-allow-risky` ✅ - Migration rejouée sur base fraîche (`make db-reset`) ✅ - Nouveau `CategoryFilterTest` (name partiel + typeId[] OR + multi-type non dupliqué) --------- Co-authored-by: Matthieu <contact@malio.fr> Reviewed-on: #75 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
49 lines
1.9 KiB
PHP
49 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Shared\Domain\Contract;
|
|
|
|
/**
|
|
* Interface minimale exposant ce qu'un module tiers (Commercial...) doit
|
|
* connaitre d'une Category, sans creer de couplage direct vers le module
|
|
* Catalog (regle ABSOLUE n°1 : pas d'import inter-modules).
|
|
*
|
|
* Implementee par App\Module\Catalog\Domain\Entity\Category.
|
|
* Utilisee comme cible des ManyToMany Client.categories et
|
|
* ClientAddress.categories via resolve_target_entities (cf. doctrine.yaml),
|
|
* sur le meme modele que SiteInterface / UserInterface.
|
|
*/
|
|
interface CategoryInterface
|
|
{
|
|
public function getId(): ?int;
|
|
|
|
public function getName(): ?string;
|
|
|
|
/**
|
|
* Code technique stable de la categorie (Category::code), ou null si non
|
|
* encore renseigne. Slug MAJUSCULE derive du nom a la creation, fige ensuite.
|
|
* Expose pour permettre a un module tiers de filtrer/valider par categorie
|
|
* metier sans dependre du libelle (`name`) ni de l'`id` (non deterministe
|
|
* entre environnements) ni importer la classe concrete Category (regle
|
|
* ABSOLUE n°1). Pilote, cote M1 Commercial :
|
|
* - RG-1.03 : un distributor doit referencer un client portant la categorie
|
|
* de code DISTRIBUTEUR (resp. COURTIER pour broker) ;
|
|
* - RG-1.29 : une adresse interdit les categories de code DISTRIBUTEUR /
|
|
* COURTIER (relations entre clients, pas des attributs d'adresse).
|
|
*/
|
|
public function getCode(): ?string;
|
|
|
|
/**
|
|
* Codes des types de categorie rattaches (CategoryType::code), tableau vide
|
|
* si aucun. Depuis le passage en ManyToMany, une categorie peut porter
|
|
* plusieurs types : un module tiers teste l'appartenance via
|
|
* `in_array($code, $category->getCategoryTypeCodes(), true)`. Pilote, cote
|
|
* M2 Commercial, la RG-2.10 (une categorie de fournisseur doit etre de type
|
|
* FOURNISSEUR).
|
|
*
|
|
* @return list<string>
|
|
*/
|
|
public function getCategoryTypeCodes(): array;
|
|
}
|