Files
Starseed/docs/specs/M1-clients/refonte-contact/M1-ticket-01-back.prompt.md
T
matthieu 8fae987e15
Auto Tag Develop / tag (push) Successful in 6s
docs(commercial) : refonte contact — suppression du contact inline (specs M1 + M2) (#54)
Acte la décision refonte-contact dans les specs : le contact principal inline (firstName/lastName/phonePrimary/phoneSecondary/email) est retiré des entités tiers (Client, Supplier). Les contacts vivent uniquement dans ClientContact / SupplierContact (onglet Contacts). Garantie « >=1 contact nommé » préservée par RG-1.05/1.14 (M1) et RG-2.04/2.13 (M2).

- M1 (spec-back/spec-front/cahier) : modèle Client sans contact inline ; RG-1.01/1.02 supprimées ; D1 (recherche) / D2 (export) décrites ; version V1.
- M2 (spec-back/spec-front) : FICHIERS NOUVEAUX (non versionnés sur develop), introduits déjà corrigés (Supplier sans contact inline, RG-2.01/2.02 supprimées) ; version V0.2.
- docs/specs/M1-clients/refonte-contact/ : décision (README) + tickets (M1 back/front/specs, M2 specs) + prompts + amendement des tickets M2.

Lesstime : tâches #103 (M1 back), #104 (M1 front), #105 (M1 specs), #106 (M2 specs) ; tickets M2 #85-#97 amendés.
---------

Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #54
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
2026-06-03 13:16:11 +00:00

3.2 KiB

Prompt d'implémentation — M1 · Ticket 1/3 (Backend)

Tu travailles sur le projet Starseed (Symfony 8 / API Platform 4 / Doctrine / PostgreSQL). Lis CLAUDE.md et .claude/rules/backend.md avant de coder. Commentaires en français, code en anglais, declare(strict_types=1); partout.

Mission

Supprimer le contact principal inline de l'entité Client : les 5 champs firstName, lastName, phonePrimary, phoneSecondary, email. Les contacts sont gérés uniquement via la sous-entité ClientContact (onglet Contacts), déjà en place. Le code est déjà en prod → migration avec backfill avant DROP.

La spec détaillée du ticket est dans docs/specs/M1-clients/refonte-contact/M1-ticket-01-back.md. Lis-la en entier, ainsi que le README.md du même dossier (décision + RG impactées + D1/D2).

Étapes

  1. Explorer : Client.php, ClientProcessor.php, DoctrineClientRepository.php, ClientExportController.php, ClientFixtures.php, et ClientContact.php (pour confirmer que la cible porte bien les mêmes champs).
  2. Demander la validation des décisions D1 (recherche) et D2 (export) avant de coder — défauts recommandés : D1 = LEFT JOIN sur client_contact, D2 = colonnes export depuis le contact position minimal. Ne pas inventer un autre comportement.
  3. Migration (src/Module/Commercial/Infrastructure/Doctrine/Migrations/) : backfill INSERT INTO client_contact ... WHERE NOT EXISTS(...) puis ALTER TABLE client DROP COLUMN ... (les 5). down() best-effort documenté. Voir le SQL exact dans la spec § 4.
  4. Entité : retirer les 5 props + getters/setters + #[ORM\Column] + #[Assert\*] + #[Groups(['client:read','client:write:main'])].
  5. Processor : retirer de MAIN_FIELDS, changedBusinessFields(), normalize() ; supprimer validateMainContact() et son appel.
  6. Repository : applySearch() selon D1.
  7. Export : buildHeaders() / buildRows() selon D2.
  8. Fixtures : alléger ensureClient() ; garder addContact().
  9. Tests : mettre à jour ClientApiTest, ClientFormulaireMainTest, ClientExportControllerTest, ClientMigrationTest, ClientFieldNormalizerTest (cf. spec § 5). Ajouter une assertion que le backfill crée bien un contact pour un client qui n'en avait pas.

Garde-fous

  • Ne touche pas ClientContact, ClientContactProcessor, ClientFieldNormalizer.
  • Respecte les règles ABSOLUES : pagination, #[Auditable], COMMENT ON COLUMN (ici on supprime → pas de commentaire à poser, mais ne pas casser le garde-fou).
  • Les RG-1.01 et RG-1.02 disparaissent du Client : leur équivalent (RG-1.05 / RG-1.14) vit déjà sur ClientContact, ne le duplique pas.

Vérification finale (obligatoire avant de dire « fini »)

make db-reset && make migration-migrate     # migration rejouable sur base fraîche
make test                                    # PHPUnit vert
make php-cs-fixer-allow-risky                # lint

Puis capture le JSON réel de GET /api/clients/{id} (avec un JWT) et confirme que les 5 champs ont disparu de la réponse et que contacts[] porte bien l'info (réflexe RETEX M1 : on valide sur le contrat réel, pas sur les annotations).