Commit Graph

2 Commits

Author SHA1 Message Date
matthieu 96ddd15c86 refactor(commercial) : suppression du contact principal inline du Client (M1 · back 1/3) (#55)
Auto Tag Develop / tag (push) Successful in 9s
## Contexte

M1 · Ticket 1/3 (Backend) de la refonte contact. Le contact principal inline du `Client` (firstName, lastName, phonePrimary, phoneSecondary, email) faisait doublon avec la sous-entité `ClientContact` (onglet Contact). Il est supprimé : les contacts vivent désormais **uniquement** dans `client_contact`.

RG-1.01 (firstName OU lastName sur Client) et RG-1.02 (max 2 téléphones sur Client) sont **supprimées** du Client — leur équivalent vit déjà sur `ClientContact` (RG-1.05 / RG-1.14).

## Changements

- **Migration** `Version20260603120000` (namespace racine `DoctrineMigrations` — tri par timestamp, cf. AlphabeticalComparator) : **backfill** des clients sans contact vers `client_contact` (position 0) **avant** le `DROP` des 5 colonnes. `down()` best-effort documenté.
- **Entité `Client`** : retrait des 5 propriétés + getters/setters + groupes de sérialisation.
- **`ClientProcessor`** : `MAIN_FIELDS` / `changedBusinessFields()` / `normalize()` allégés ; `validateMainContact()` (RG-1.01) supprimée.
- **Recherche répertoire (D1)** : sur `companyName` seul (les anciens critères lastName/email vivaient sur les colonnes supprimées).
- **Export XLSX (D2)** : colonnes de contact retirées (Nom entreprise / Catégories / Sites / [SIREN] / Date).
- **Fixtures** + **catalogue de commentaires SQL** (`ColumnCommentsCatalog`) alignés.
- **Tests** fonctionnels et unitaires mis à jour.

## Décisions actées

- **Migration** au namespace racine (et non modulaire Commercial) : une migration `App\Module\Commercial\…` trierait avant le `CREATE TABLE client` sur base fraîche → casse. Conforme à la règle ABSOLUE n°11.
- **D1** = recherche `companyName` seul. **D2** = retrait des colonnes contact de l'export.

## Vérifications

-  `make db-reset && make migration-migrate` : migration rejouable sur base fraîche (backfill no-op si contacts déjà présents).
-  `make test` : 466 tests verts.
-  `make php-cs-fixer-allow-risky` : clean.
-  Contrat réel `GET /api/clients/{id}` : les 5 champs ont disparu de la racine, `contacts[]` porte l'info.

---------

Co-authored-by: admin malio <malio@yuno.malio.fr>
Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #55
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
2026-06-03 13:52:25 +00:00
matthieu 1ff335b3fe fix(commercial) : corrige le contrat de sérialisation du répertoire clients (ERP-80/81/82/83) (#45)
Auto Tag Develop / tag (push) Successful in 7s
## Contexte

Correctifs des 4 bugs de contrat de sérialisation du répertoire clients M1, révélés par la capture du JSON réel le 02/06/2026 (cf. `docs/specs/M2-suppliers/spec-back.md` § 4.0.ter). Tous étaient des oublis **silencieux** (aucune erreur levée).

## Changements

- **ERP-80 — Fuite RIB (sécurité)** : `Client::getRibs()` et les propriétés de `ClientRib` passent sous le groupe gaté `client:read:accounting` (ajouté au contexte par `ClientReadGroupContextBuilder` uniquement si `accounting.view`). La clé `ribs` est désormais **absente** du détail pour la Commerciale. La sous-ressource autonome `/api/client_ribs/{id}` conserve `client_rib:read` (écriture/PATCH intacts).
- **ERP-81 — Booléens d'adresse** : `#[Groups]` + `#[SerializedName]` portés sur les **getters** `isProspect()/isDelivery()/isBilling()` (le getter booléen strippait le préfixe `is` et droppait la clé — même pattern que `Client::isArchived`).
- **ERP-82 — Embed Category/Site** : `category:read` + `site:read` ajoutés au `normalizationContext` du `Get` Client → `categories[].code/.name` et `addresses[].sites[].name` embarqués.
- **ERP-83 — Tests anti-régression** : nouveau `ClientSerializationContractTest` (7 tests, 64 assertions) assertant sur le **corps JSON réel**.

## Dépendance signalée

⚠️ L'entité **`Site` n'a pas de champ `code`** (ni `SiteInterface`) — son libellé est `name`. Les « codes 86/17/82 » de la spec M2 sont en réalité le préfixe du code postal des sites fixtures. À planifier côté module Sites si un `Site.code` est requis (notamment pour `getSiteCodes()` au M2).

## Vérifications

- `make test` : **460 tests, 1535 assertions, exit 0** 
- `make php-cs-fixer-allow-risky` : 0 fix 
- Capture JSON réelle AVANT/APRÈS (client 6 TRANSPORTS RAPIDES) :
  - **Admin** : `ribs` présents, `siren`/`accountNumber`/`nTva` présents, `categories[].code/.name` + `addresses[].sites[].name` embarqués, booléens d'adresse présents.
  - **Commerciale** : `ribs` **absent**, scalaires comptables **absents** (omission), embed Category/Site + booléens visibles.

Tickets : ERP-80, ERP-81, ERP-82, ERP-83 (passés « En review »).
---------

Co-authored-by: admin malio <malio@yuno.malio.fr>
Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #45
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
2026-06-02 09:51:36 +00:00