feat(directory) : type prestataire, validateurs front, autocomplete adresse BAN #23

Merged
matthieu merged 2 commits from feat/directory-prestataire into develop 2026-06-24 16:07:43 +00:00
Owner

Résumé

Annuaire (répertoire) — 6 volets :

  1. Type prestataire (entité séparée, mirror Client) : ressource API Platform CRUD avec RBAC directory.providers.*, ownership prestataire sur contacts/adresses/comptes-rendus (CHECK XOR à 3), DTO/service/drawer/fiche détail + onglet dédié.
  2. Prospect = société uniquement : suppression du champ name, company requis (migration de backfill), conversion prospect→client et tools MCP adaptés.
  3. Champ site web sur client/prospect/prestataire (onglet Information).
  4. Validateurs front email / téléphone FR (0549200910) / URL — enregistrement bloqué si invalide.
  5. Autocomplete adresse branché sur la Base Adresse Nationale (api-adresse.data.gouv.fr) avec mode dégradé en saisie libre.
  6. Administration : retrait de l'onglet Clients.

Migration & déploiement

  • Version20260624153709 : table prestataire, colonnes website, FK prestataire + CHECK XOR à 3, backfill/drop prospect.name.
  • Penser à app:sync-permissions au déploiement (ajoute directory.providers.view/manage).

Vérifications

  • Suite PHPUnit complète : 179 tests verts (hook pre-commit).
  • doctrine:schema:validate OK, routes /api/prestataires enregistrées.
  • Build Nuxt OK (exit 0).
## Résumé Annuaire (répertoire) — 6 volets : 1. **Type prestataire** (entité séparée, mirror Client) : ressource API Platform CRUD avec RBAC `directory.providers.*`, ownership prestataire sur contacts/adresses/comptes-rendus (CHECK XOR à 3), DTO/service/drawer/fiche détail + onglet dédié. 2. **Prospect = société uniquement** : suppression du champ `name`, `company` requis (migration de backfill), conversion prospect→client et tools MCP adaptés. 3. **Champ site web** sur client/prospect/prestataire (onglet Information). 4. **Validateurs front** email / téléphone FR (`0549200910`) / URL — enregistrement bloqué si invalide. 5. **Autocomplete adresse** branché sur la Base Adresse Nationale (api-adresse.data.gouv.fr) avec mode dégradé en saisie libre. 6. **Administration** : retrait de l'onglet Clients. ## Migration & déploiement - `Version20260624153709` : table prestataire, colonnes website, FK prestataire + CHECK XOR à 3, backfill/drop prospect.name. - Penser à `app:sync-permissions` au déploiement (ajoute `directory.providers.view/manage`). ## Vérifications - Suite PHPUnit complète : 179 tests verts (hook pre-commit). - `doctrine:schema:validate` OK, routes `/api/prestataires` enregistrées. - Build Nuxt OK (exit 0).
matthieu added 1 commit 2026-06-24 15:56:42 +00:00
feat(directory) : type prestataire, validateurs front, autocomplete adresse BAN
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m20s
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 1m26s
5764d8f472
- Prestataire : entité/repo + ressource API Platform (RBAC directory.providers.*),
  ownership prestataire sur contacts/adresses/comptes-rendus (CHECK XOR à 3),
  DTO/service/drawer/fiche détail + onglet dédié dans le répertoire.
- Prospect : société uniquement (suppression du champ name, company requis) ;
  migration de backfill, conversion prospect→client et MCP adaptés.
- Champ site web sur client/prospect/prestataire (entités, DTO, onglet Information, MCP).
- Validateurs front email / téléphone FR (0549200910) / URL sur Information et Contacts,
  enregistrement bloqué tant qu'un champ est invalide.
- Autocomplete adresse branché sur la Base Adresse Nationale (api-adresse.data.gouv.fr)
  avec mode dégradé en saisie libre.
- Administration : retrait de l'onglet Clients.
matthieu added 1 commit 2026-06-24 16:06:33 +00:00
fix(directory) : ville absente du select corrigée (option courante conservée) + matching suggestion BAN par libellé
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 38s
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m23s
435c7fcfc2
Author
Owner

Revue — objections

Revue du diff complet (entités, services owner, composables, migration, composants lib MalioInputAutocomplete/MalioSelect). Le cœur de la MR est propre (mécanisme owner générique, RBAC directory.providers.* cohérent, migration réversible, MCP/Serializer/tests alignés). Restent les points suivants.

🟠 Bloquant (corrigé dans 435c7fc)

Champ Ville affiché vide pour toute adresse existante / pré-remplieDirectoryAddressBlock.vue. La ville est passée d'un MalioInputText à un MalioSelect dont les options ne sont alimentées qu'à la frappe d'un code postal. Or Select.vue n'affiche que les valeurs présentes dans ses options (options.find(...)?.label ?? '') : au chargement d'une fiche (et après remplissage par l'autocomplétion d'adresse), la ville enregistrée ne s'affichait pas. Régression sur toutes les fiches Client/Prospect existantes, pas seulement les prestataires.
→ Fix poussé : cityOptions devient un computed qui réinjecte toujours la ville courante dans les options. Idem matching de suggestion BAN par label (unique) plutôt que par rue.

🟡 Objections ouvertes (non bloquantes)

  • Édition d'une rue existante : MalioInputAutocomplete émet update:modelValue(null) dès le 1ᵉʳ caractère (pas de selectedOption car options vides), vidant la rue dans le modèle jusqu'au commit (blur/clic-dehors/Entrée). Mitigé par le clic « Enregistrer » qui déclenche le commit, mais fragile si une sauvegarde est lancée sans blur. Comportement interne de la lib — non corrigeable depuis le projet.
  • Recherche ville sans debounce : onPostalCodeInput appelle la BAN directement à chaque frappe ≥ 5 chiffres (la recherche rue est debouncée par le composant, pas celle-ci). Coût faible, mode dégradé géré.
  • Migration : DROP CONSTRAINT chk_*_owner sans IF EXISTS → échoue durement si une contrainte d'ownership manque sur la cible. OK en prod (créées par la migration directory antérieure), mais IF EXISTS serait plus défensif.

⚠️ À confirmer avant déploiement (produit, pas un bug)

La migration supprime définitivement prospect.name (nom de la personne), sauf quand company était vide (recopie). Si des prospects en prod ont un name distinct de company qui compte, l'info est perdue. Confirmer que c'est l'intention (le contact passe par l'entité Contact).

Rappel déploiement : app:sync-permissions enregistrera directory.providers.view/manage (déjà dans deploy.sh).

## Revue — objections Revue du diff complet (entités, services `owner`, composables, migration, composants lib `MalioInputAutocomplete`/`MalioSelect`). Le cœur de la MR est propre (mécanisme `owner` générique, RBAC `directory.providers.*` cohérent, migration réversible, MCP/Serializer/tests alignés). Restent les points suivants. ### 🟠 Bloquant (corrigé dans `435c7fc`) **Champ Ville affiché vide pour toute adresse existante / pré-remplie** — `DirectoryAddressBlock.vue`. La ville est passée d'un `MalioInputText` à un `MalioSelect` dont les options ne sont alimentées qu'à la frappe d'un code postal. Or `Select.vue` n'affiche que les valeurs présentes dans ses `options` (`options.find(...)?.label ?? ''`) : au chargement d'une fiche (et après remplissage par l'autocomplétion d'adresse), la ville enregistrée ne s'affichait pas. Régression sur **toutes** les fiches Client/Prospect existantes, pas seulement les prestataires. → Fix poussé : `cityOptions` devient un `computed` qui réinjecte toujours la ville courante dans les options. Idem matching de suggestion BAN par `label` (unique) plutôt que par rue. ### 🟡 Objections ouvertes (non bloquantes) - **Édition d'une rue existante** : `MalioInputAutocomplete` émet `update:modelValue(null)` dès le 1ᵉʳ caractère (pas de `selectedOption` car options vides), vidant la rue dans le modèle jusqu'au commit (blur/clic-dehors/Entrée). Mitigé par le clic « Enregistrer » qui déclenche le commit, mais fragile si une sauvegarde est lancée sans blur. Comportement interne de la lib — non corrigeable depuis le projet. - **Recherche ville sans debounce** : `onPostalCodeInput` appelle la BAN directement à chaque frappe ≥ 5 chiffres (la recherche *rue* est debouncée par le composant, pas celle-ci). Coût faible, mode dégradé géré. - **Migration** : `DROP CONSTRAINT chk_*_owner` sans `IF EXISTS` → échoue durement si une contrainte d'ownership manque sur la cible. OK en prod (créées par la migration directory antérieure), mais `IF EXISTS` serait plus défensif. ### ⚠️ À confirmer avant déploiement (produit, pas un bug) La migration **supprime définitivement** `prospect.name` (nom de la personne), sauf quand `company` était vide (recopie). Si des prospects en prod ont un `name` distinct de `company` qui compte, l'info est perdue. Confirmer que c'est l'intention (le contact passe par l'entité `Contact`). Rappel déploiement : `app:sync-permissions` enregistrera `directory.providers.view/manage` (déjà dans `deploy.sh`).
matthieu merged commit 04be081ffd into develop 2026-06-24 16:07:43 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MALIO-DEV/Lesstime#23