# 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 »)

```bash
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).
