8fae987e15
Auto Tag Develop / tag (push) Successful in 6s
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>
332 lines
22 KiB
Markdown
332 lines
22 KiB
Markdown
---
|
||
# === IDENTITÉ ===
|
||
module: M2
|
||
nom: "Répertoire fournisseurs"
|
||
ecran: repertoire-fournisseurs
|
||
owner_spec: Matthieu
|
||
backup_spec: Tristan
|
||
version: V0.2
|
||
date_redaction: 2026-06-02
|
||
# Historique : V0.2 (2026-06-03) — Refonte contact : suppression du bloc contact principal inline
|
||
# du formulaire Supplier (Nom/Prénom/Téléphone/Téléphone 2/Email). Saisie via l'onglet Contacts.
|
||
# Aligné sur M1. Cf. docs/specs/M1-clients/refonte-contact/README.md
|
||
|
||
# === LIENS ===
|
||
maquette_figma: "https://www.figma.com/design/jRYgT0T9c03VsEbjGhCwwS/Composants---Design-System?node-id=1132-36987&p=f&m=dev"
|
||
regles_metier: [RG-2.01, RG-2.02, RG-2.03, RG-2.04, RG-2.05, RG-2.06, RG-2.07, RG-2.08, RG-2.09, RG-2.10, RG-2.11, RG-2.12, RG-2.13, RG-2.14, RG-2.15, RG-2.16, RG-2.17]
|
||
roles: [Admin, Bureau, Compta, Commerciale, Usine]
|
||
lien_spec_back: ./spec-back.md
|
||
|
||
# === VALIDATION CLIENT ===
|
||
client_validation_1:
|
||
statut: validee
|
||
date: 2026-05-22
|
||
version: V0
|
||
valide_par: "Matthieu (CP MALIO)"
|
||
client_validation_2:
|
||
statut: validee
|
||
date: 2026-06-01
|
||
version: V0.1
|
||
valide_par: "Matthieu (CP MALIO)"
|
||
resume: "Module 2 — Répertoire fournisseurs. Page d'entrée Commercial. Datatable + 3 écrans (Ajouter / Consulter / Modifier). Création par onglets : Information / Contact / Adresse / Comptabilité (Transport, Statistiques, Rapports, Échanges = placeholders 'À venir')."
|
||
trace_archivee: "uploads/M2-reportoire-fournisseurs.docx (V0.1) + M2-reportoire-fournisseurs-V01.pdf"
|
||
|
||
# === LIEN LESSTIME ===
|
||
lesstime_taskgroup_id: 26
|
||
lesstime_project_id: 6
|
||
statut_global: a_dev
|
||
---
|
||
|
||
# Module 2 — Répertoire fournisseurs (V0.1 front)
|
||
|
||
> **Origine** : spec front livrée le 22/05/2026 (V0), amendée le 01/06/2026 (V0.1) — `M2-reportoire-fournisseurs.docx`. Restitution Markdown pour intégration au workflow MALIO. Le contenu fonctionnel original n'est pas modifié ; toute décision technique (back) vit dans [`spec-back.md`](./spec-back.md). Le M2 réutilise massivement le pattern et les composants posés au [M1 clients](../M1-clients/spec-front.md).
|
||
|
||
## But
|
||
|
||
Permettre aux utilisateurs Starseed (selon rôle) de gérer le **répertoire des fournisseurs** de l'organisation : consultation, création, modification, archivage. C'est la **deuxième porte d'entrée du module Commercial** (aux côtés des Clients).
|
||
|
||
## Accès
|
||
|
||
- **Depuis** : menu principal → section **Commercial** → entrée « Répertoire fournisseurs » (route `/suppliers`).
|
||
- **Rôles autorisés** :
|
||
|
||
| Rôle | Consultation | Création / Modification | Archivage |
|
||
|---|---|---|---|
|
||
| **Admin** | ✅ Tout | ✅ Tout | ✅ |
|
||
| **Bureau** | ✅ Tout | ✅ Tout sauf onglet Comptabilité | ❌ |
|
||
| **Compta** | ✅ Tout | ✅ Onglet Comptabilité uniquement | ❌ |
|
||
| **Commerciale** | ✅ Tout sauf Comptabilité | ✅ Tout sauf Comptabilité | ❌ |
|
||
| **Usine** | ❌ (pas d'accès) | ❌ | ❌ |
|
||
|
||
> **Note** : RBAC identique au M1, transposée sur `commercial.suppliers.*`. Compta édite uniquement l'onglet Comptabilité (SIREN / N° compte / TVA / Délai / Type de règlement / Banque / RIBs) d'un fournisseur existant ; Compta ne peut pas **créer** un fournisseur. **L'archivage est réservé à Admin** (cf. tableau du docx).
|
||
|
||
## Navigation
|
||
|
||
Page d'entrée du module **Commercial** (route `/suppliers`). Titre : « **Répertoire fournisseurs** ».
|
||
|
||
- Affichage principal : un **datatable** listant tous les fournisseurs **actifs** (les archivés sont masqués par défaut — toggle UI dédié).
|
||
- **Clic sur une ligne** → écran **Consultation fournisseur** (page dédiée).
|
||
- **Bouton « + Ajouter »** (haut droite) → écran **Ajouter un fournisseur**.
|
||
- **Bouton « Filtrer »** (haut droite, **à côté de « + Ajouter »**) → ouvre le **panneau de filtres** (cf. ci-dessous). Un badge/compteur indique le nombre de filtres actifs ; un bouton « Réinitialiser » les vide.
|
||
- **Bouton « Exporter »** (haut droite) → télécharge un **XLSX** des fournisseurs **affichés** (cf. filtres actifs). Format dans [`spec-back.md § 4.6`](./spec-back.md).
|
||
|
||
### Panneau de filtres (bouton « Filtrer »)
|
||
|
||
Ouvre un drawer/popover (composant à confirmer côté équipe front — réutiliser le pattern M1 s'il existe). Filtres proposés, branchés sur les query params de `GET /api/suppliers` (cf. [`spec-back.md § 4.1`](./spec-back.md)) :
|
||
|
||
| Filtre | Composant | Query param back |
|
||
|---|---|---|
|
||
| **Recherche** (nom entreprise / contact / email — recherche contact via `supplier_contact`, décision D1) | `<MalioInputText>` | `?search=` |
|
||
| **Catégorie** | `<MalioSelectCheckbox>` (multi, type FOURNISSEUR) | `?categoryCode=` |
|
||
| **Site** | `<MalioSelectCheckbox>` (86 / 17 / 82) | `?siteId=` |
|
||
| **Inclure les archivés** | `<MalioCheckbox>` | `?includeArchived=true` |
|
||
|
||
- À l'application des filtres → `setFilters(...)` de `usePaginatedList` (retombe en **page 1**), qui relance `GET /api/suppliers` avec les params.
|
||
- **État 100 % local** (jamais dans l'URL — règle ABSOLUE n°6). Le bouton « Filtrer » + son panneau remplacent/regroupent l'ancien toggle « archivés » isolé.
|
||
|
||
## Datatable du Répertoire
|
||
|
||
Composant : `<MalioDataTable>` branché sur `usePaginatedList<Supplier>({ url: '/suppliers' })` (règle frontend obligatoire — pagination Hydra, état 100 % local). Colonnes **conformes à la maquette Figma** (4 colonnes) :
|
||
|
||
| Colonne | Source | Tri |
|
||
|---|---|---|
|
||
| **Nom** | `supplier.companyName` | ASC par défaut |
|
||
| **Catégories** | `supplier.categories[].name` (embarquées en liste — cohérence M1/ERP-62 ; libellé = `name`, pas `label`) | Non |
|
||
| **Site** | `supplier.sites[].name` (agrégat des adresses via `getSites()` ; `Site` n'a pas de `code`) | Non |
|
||
| **Dernière activité** | `supplier.updatedAt` (format `JJ-MM-AAAA`) — exposé dans `supplier:read` | Oui |
|
||
|
||
> **Clic sur une ligne** (texte en bleu lien) → écran Consultation.
|
||
> **Filtres** : regroupés dans le panneau du bouton « Filtrer » (cf. section précédente), dont l'inclusion des archivés (désactivée par défaut). **État local** (jamais dans l'URL — règle ABSOLUE n°6).
|
||
> **Pagination** : `<MalioDataTable>` + `usePaginatedList`, options **standard Starseed 10 / 25 / 50 (défaut 10)** — on **n'applique pas** le « Ligne : 20 » de la maquette (décision Matthieu : on reste sur le standard). Tri serveur `companyName ASC` par défaut.
|
||
|
||
## Écran « Ajouter un fournisseur »
|
||
|
||
Création par **onglets successifs avec validation incrémentale** : pour passer à l'onglet suivant, il faut avoir validé l'onglet en cours. **Une fois un onglet validé, on passe automatiquement au suivant** ; les champs validés passent en lecture seule + bouton « Valider » désactivé (disabled). Cf. [`spec-back.md § 2.10`](./spec-back.md) (PATCH partiels par groupe de sérialisation).
|
||
|
||
**Barre d'onglets en création (5 onglets, conforme maquette)** : `Information` · `Contacts` · `Adresses` · `Transport` · `Comptabilité`. L'onglet `Information` est actif par défaut juste après validation du formulaire principal. Les onglets `Statistiques`, `Rapports` et `Échanges` **n'apparaissent PAS dans le flux de création** — ils ne sont présents qu'en Consultation / Modification.
|
||
|
||
### Formulaire principal (pré-onglets)
|
||
|
||
1er bloc à remplir. Sans validation, les onglets ne sont pas accessibles. Une fois validé → POST `/api/suppliers`, puis bascule sur l'onglet Information ; les champs passent en readonly.
|
||
|
||
> **V0.2 — refonte-contact** : le contact principal (Nom / Prénom / Téléphone / Téléphone 2 / Email) a été **retiré** du formulaire principal. Les coordonnées se saisissent dans l'onglet **Contacts** (RG-2.04 / RG-2.13). Le formulaire principal ne contient plus que Entreprise + Catégorie.
|
||
|
||
| Champ | Type composant | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **Nom du fournisseur (Entreprise)** | `<MalioInputText>` | Oui | RG-2.12 (UPPERCASE serveur) |
|
||
| **Catégorie** | `<MalioSelectCheckbox>` (multi) | Oui | `Category` de **type FOURNISSEUR** via `GET /api/categories?typeCode=FOURNISSEUR` (RG-2.10). Libellé affiché = `category.name`. ⚠️ Le type + le filtre `?typeCode=` sont **à créer** côté back (n'existent pas en prod — cf. spec-back § 2.4). |
|
||
|
||
**Action** : « Valider » (`<MalioButton>`) → POST `/api/suppliers` ([`spec-back.md § 4.3`](./spec-back.md)). Succès → onglet « Information ».
|
||
|
||
### Onglet « Information »
|
||
|
||
Saisir les informations du fournisseur.
|
||
|
||
| Champ | Type | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **Description** | `<MalioInputTextArea>` | Conditionnel | RG-2.03 (obligatoire rôle Commerciale) |
|
||
| **Concurrent** | `<MalioInputText>` | Conditionnel | RG-2.03 |
|
||
| **Date création** (entreprise) | `<input type="date">` (exception Malio — `// TODO migrer`) | Conditionnel | RG-2.03 |
|
||
| **Nombre de salariés** | `<MalioInputNumber>` | Conditionnel | RG-2.03 |
|
||
| **CA €** | `<MalioInputAmount>` | Conditionnel | RG-2.03 |
|
||
| **Dirigeant** | `<MalioInputText>` | Conditionnel | RG-2.03 |
|
||
| **Résultat €** | `<MalioInputAmount>` | Conditionnel | RG-2.03 |
|
||
| **Volume Prévisionnel** | `<MalioInputNumber>` | Conditionnel | RG-2.03 (champ spécifique fournisseur) |
|
||
|
||
> **Disposition maquette** : 3 colonnes — ligne 1 (Description / Concurrent / Date création), ligne 2 (Nombre de salariés / CA / Dirigeant), ligne 3 (Résultat / Volume Prévisionnel).
|
||
|
||
**Action** : « Valider » → PATCH `/api/suppliers/{id}` (groupe `supplier:write:information`).
|
||
|
||
### Onglet « Contact »
|
||
|
||
Saisir un ou plusieurs contacts. **(V0.2 — refonte-contact : plus de pré-remplissage depuis le formulaire principal ; les coordonnées du contact se saisissent directement ici.)** Au moins un bloc Contact valide est requis (RG-2.13).
|
||
|
||
**Bloc Contact** :
|
||
|
||
| Champ | Type | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **Nom** | `<MalioInputText>` | Conditionnel | RG-2.04 + RG-2.12 (Capitalize) |
|
||
| **Prénom** | `<MalioInputText>` | Conditionnel | RG-2.04 + RG-2.12 (Capitalize) |
|
||
| **Fonction** | `<MalioInputText>` | Non | — |
|
||
| **Téléphone** (x1, +1 possible) | `<MalioInputText>` | Non | RG-2.12 (format) |
|
||
| **Email** | `<MalioInputText>` type email | Non | RG-2.12 (lowercase) |
|
||
|
||
**RG-2.04 / RG-2.13** : au moins 1 bloc Contact valide (Nom OU Prénom rempli) pour valider l'onglet — l'onglet Contact ne peut pas être finalisé vide.
|
||
|
||
**Actions** :
|
||
- « + Nouveau contact » : ajoute un bloc. **Désactivé tant que le bloc précédent n'a pas Prénom OU Nom** (RG-2.04).
|
||
- « Supprimer » (icône) : modal de confirmation, puis suppression du bloc.
|
||
- « Valider » → PATCH `/api/suppliers/{id}/contacts`.
|
||
|
||
### Onglet « Adresse »
|
||
|
||
Saisir une ou plusieurs adresses, rattachées à un ou plusieurs sites (86 / 17 / 82) et à des contacts.
|
||
|
||
**Bloc Adresse** :
|
||
|
||
| Champ | Type | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **Type d'adresse** | `<MalioRadioButton>` — `Prospect` / `Départ` / `Rendu` | Oui | RG-2.09 (exclusif, enum `PROSPECT`/`DEPART`/`RENDU`) |
|
||
| **Pays** | `<MalioSelect>` (saisie assistée — préremplie « France ») | Oui | — |
|
||
| **Code postal** | `<MalioInputText>` (saisie assistée) | Oui | RG-2.05 — déclenche autocomplete ville (BAN) |
|
||
| **Ville** | `<MalioSelect>` (saisie assistée) | Oui | RG-2.05 — alimentée par api-adresse.data.gouv.fr suivant le CP |
|
||
| **Adresse** | `<MalioInputText>` (saisie assistée) | Oui | RG-2.05 — autocomplete BAN |
|
||
| **Adresse complémentaire** | `<MalioInputText>` | Non | — |
|
||
| **Sélecteur de site** | `<MalioSelectCheckbox>` (86 / 17 / 82) | Oui | RG-2.06 — ≥ 1 site. Les 3 cases = les 3 `Site` fixes ; libellés « 86/17/82 » = **préfixe du `postalCode`** (86100/17400/82400), pas un `Site.code` (qui n'existe pas). La sélection stocke des **IDs de Site** (M2M). |
|
||
| **Catégories** | `<MalioSelectCheckbox>` (multi) | Oui | Catégories de type FOURNISSEUR (RG-2.10), liées aux catégories du fournisseur |
|
||
| **Contact** | `<MalioSelectCheckbox>` (multi) | Non | Liste = blocs Contact saisis dans l'onglet Contact |
|
||
| **Benne(s)** | `<MalioInputNumber>` (stepper −/+ , défaut 0) | Non | Champ spécifique fournisseur |
|
||
| **Prestation de triage** | `<MalioCheckbox>` | Non | Champ spécifique fournisseur (porté par l'adresse — colonne back `triage_provider`) |
|
||
|
||
> **Disposition maquette par bloc** : ligne 1 = radio (Prospect / Départ / Rendu) + Pays + Code postal ; ligne 2 = Ville + Adresse + Adresse complémentaire ; ligne 3 = sites (86 / 17 / 82) + Catégories + Contact ; ligne 4 = Benne(s) + Prestation de triage. Icône corbeille en haut à droite de chaque bloc pour le supprimer.
|
||
|
||
**Actions** :
|
||
- « + Nouvelle Adresse » : ajoute un bloc identique au premier.
|
||
- « Supprimer » : modal de confirmation puis suppression.
|
||
- « Valider » → PATCH `/api/suppliers/{id}/addresses`.
|
||
|
||
### Onglet « Transport »
|
||
|
||
🚧 **Onglet placeholder minimal au M2.** Conforme à la maquette : la frame est **vide** (aucun champ, aucun bouton de validation, aucune API back). L'onglet reste navigable. Un libellé discret « À venir » est toléré mais non requis (la maquette ne l'affiche pas). Cet onglet **fait partie de la barre de création** (entre Adresses et Comptabilité).
|
||
|
||
### Onglet « Comptabilité »
|
||
|
||
⚠ **Accessible aux rôles avec `commercial.suppliers.accounting.view`** (Admin + Compta au M2). Bureau et Commerciale ne voient pas l'onglet. **Compta peut éditer** cet onglet (`accounting.manage`). Compta ne peut pas créer un fournisseur (pas de `manage` global).
|
||
|
||
**Champs comptables** :
|
||
|
||
| Champ | Type | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **SIREN** | `<MalioInputText>` (masque 9 chiffres) | Oui | 9 chiffres. **Pas d'unicité** (cf. § 2.6) |
|
||
| **Numéro de compte** | `<MalioInputText>` | Oui | — |
|
||
| **Mode de TVA** | `<MalioSelect>` | Oui | Liste depuis `/api/tva_modes` (référentiel M1) |
|
||
| **N° de TVA** | `<MalioInputText>` | Oui | — |
|
||
| **Délai de règlement** | `<MalioSelect>` | Oui | Liste depuis `/api/payment_delays` |
|
||
| **Type de règlement** | `<MalioSelect>` | Oui | Liste depuis `/api/payment_types` |
|
||
| **Banque** | `<MalioSelect>` | Conditionnel | RG-2.07 — visible et obligatoire **si** Type de règlement = `VIREMENT`. Liste depuis `/api/banks` (SG / CIC / CA). |
|
||
|
||
**Bloc RIB** (0..n, présence obligatoire conditionnée par RG-2.08) :
|
||
|
||
| Champ | Type | Obligatoire | Règle |
|
||
|---|---|---|---|
|
||
| **Libellé** | `<MalioInputText>` | Oui (si LCR) | RG-2.08 |
|
||
| **BIC** | `<MalioInputText>` | Oui (si LCR) | RG-2.08 |
|
||
| **IBAN** | `<MalioInputText>` | Oui (si LCR) | RG-2.08 |
|
||
|
||
**Actions** :
|
||
- « + RIB » : ajoute un bloc.
|
||
- « Supprimer » (icône) : modal de confirmation.
|
||
- « Valider » → PATCH `/api/suppliers/{id}` (groupe `supplier:write:accounting`) + sous-ressource RIBs.
|
||
|
||
### Onglets « Statistiques » / « Rapports » / « Échanges »
|
||
|
||
🚧 **Placeholders minimaux au M2 — uniquement en Consultation / Modification** (ils n'apparaissent **pas** dans le flux de création, cf. maquette). Frames vides, pas de validation, pas d'API.
|
||
|
||
## Écran « Consultation fournisseur »
|
||
|
||
Tous les champs en **lecture seule**. Layout identique à l'écran Ajouter mais sans bouton « Valider », sans `+` pour ajouter des blocs.
|
||
|
||
- **Flèche retour** (gauche) → revient au Répertoire.
|
||
- **Bouton « Modifier »** (droite, visible si `commercial.suppliers.manage`) → écran Modification.
|
||
- **Bouton « Archiver »** (droite, visible **uniquement Admin** via `commercial.suppliers.archive`) → modal de confirmation, puis PATCH `/api/suppliers/{id}` `{ "isArchived": true }`.
|
||
|
||
> Un fournisseur archivé peut être restauré (`isArchived: false`) — bouton « Restaurer » remplace « Archiver » dans la consultation d'un archivé.
|
||
|
||
### Onglets affichés en consultation
|
||
|
||
Information / Contacts / Adresses / Transport / Statistiques / Rapports / Échanges / Comptabilité (les 4 derniers métiers en placeholder « À venir », Comptabilité selon permission). L'utilisateur navigue **librement** entre les onglets (pas de séquence forcée en consultation).
|
||
|
||
## Écran « Modification fournisseur »
|
||
|
||
Comportement identique à l'écran Ajouter sauf :
|
||
- **Pas de formulaire principal** réaffiché (champs principaux édités via les onglets correspondants).
|
||
- Les champs sont **pré-remplis** avec les valeurs actuelles.
|
||
- **Validation par onglet** : on peut modifier UN onglet sans toucher aux autres (PATCH partiel).
|
||
- Les onglets pour lesquels l'utilisateur n'a **pas** la permission `manage` (ou `accounting.manage`) restent en **lecture seule** (pas de bouton Valider, pas d'icône suppression).
|
||
- Les onglets placeholders « À venir » restent non éditables.
|
||
|
||
## Composants UI à utiliser (`@malio/layer-ui`)
|
||
|
||
- **Datatable** : `<MalioDataTable>` (+ `usePaginatedList`)
|
||
- **Input texte** : `<MalioInputText>`
|
||
- **Input numérique** : `<MalioInputNumber>` (Nombre de salariés, Volume prévisionnel, Bennes)
|
||
- **Input montant** : `<MalioInputAmount>` (CA, Résultat)
|
||
- **TextArea** : `<MalioInputTextArea>` (Description)
|
||
- **Select simple** : `<MalioSelect>` (Pays, Ville, référentiels comptables)
|
||
- **Select multi (cases à cocher)** : `<MalioSelectCheckbox>` (Catégorie, Sites, Contacts rattachés)
|
||
- **Radio** : `<MalioRadioButton>` (Type d'adresse Prospect / Départ / Rendu — RG-2.09)
|
||
- **Checkbox** : `<MalioCheckbox>` (Prestataire de triage)
|
||
- **Bouton** : `<MalioButton>`, `<MalioButtonIcon>`
|
||
- **Toasts** : standards via `useApi()`
|
||
|
||
**Exceptions autorisées** (commenter `// TODO migrer quand Malio couvre`) :
|
||
- `<input type="date">` pour « Date Création » (`MalioDate` non couvert).
|
||
- Modal de confirmation : `<MalioModal>` ou wrapper partagé dans `frontend/shared/` (réutiliser celui du M1 si présent).
|
||
|
||
## Composables & appels API
|
||
|
||
- `usePaginatedList<Supplier>({ url: '/suppliers' })` — liste paginée (obligatoire, règle frontend). La liste consomme `categories[]` (libellé = `name`) et `sites[]` (libellé = `name`, pas de `code`) **embarqués** + `updatedAt` (cohérence M1/ERP-62, cf. [`spec-back.md § 2.12 / § 4.0`](./spec-back.md)). Côté back, fetch-joins anti-N+1.
|
||
- `useSupplier(id)` — charge le détail via `GET /api/suppliers/{id}`, qui **embarque** `contacts`, `addresses` (avec `sites` / `categories` / `contacts` imbriqués) et, si permission, `ribs` + scalaires compta. Les écrans Consultation et Modification se peuplent depuis cette seule réponse (RETEX M1 §2 : embed borné, pas de N+1 d'appels). **DoD avant intégration** : vérifier que le JSON réel contient bien ces blocs (cf. [`spec-back.md § 4.0.bis`](./spec-back.md)).
|
||
- `useSupplierForm()` — workflow par onglet (POST principal + PATCH partiels par groupe), miroir de `useClientForm()`.
|
||
- `useAddressAutocomplete()` — **réutilisé du M1** (BAN), pas de réécriture.
|
||
- `usePermissions()` — masque l'onglet Comptabilité et le bouton Archiver.
|
||
- Tous les appels passent par `useApi()` (jamais `$fetch` direct — règle ABSOLUE n°4).
|
||
- Filter `formatPhoneFR()` — **réutilisé du M1** pour l'affichage `XX XX XX XX XX`.
|
||
|
||
## Règles de formatage et normalisation
|
||
|
||
Le serveur normalise systématiquement (RG-2.12 — cf. [`spec-back.md`](./spec-back.md)) :
|
||
|
||
| Champ | Normalisation serveur | Affichage front |
|
||
|---|---|---|
|
||
| Nom fournisseur (`companyName`) | UPPERCASE intégral | UPPERCASE |
|
||
| Nom + Prénom contact | Capitalize | identique |
|
||
| Téléphones (blocs `SupplierContact`) | Chiffres uniquement en BDD | Formaté `XX XX XX XX XX` (filter Vue) |
|
||
| Email | lowercase intégral | identique |
|
||
|
||
> Le front **ne normalise pas** : il envoie la valeur saisie, le serveur normalise et renvoie la valeur normalisée que l'UI affiche. Cohérent avec `useApi()`.
|
||
|
||
## API adresse postale
|
||
|
||
Code postal + Ville + Adresse branchés sur **api-adresse.data.gouv.fr** (BAN) via le composable `useAddressAutocomplete()` **déjà créé au M1** (réutilisé tel quel) :
|
||
- À la saisie du CP (5 chiffres) : `GET https://api-adresse.data.gouv.fr/search/?q={cp}&type=municipality` → alimente le select Ville.
|
||
- À la saisie d'adresse : `?q={addr}&postcode={cp}&type=housenumber` → suggestions.
|
||
- Cas dégradé (timeout / offline) : Ville en `<MalioInputText>` libre + toast d'avertissement.
|
||
|
||
## Différences notables avec le M1 (clients)
|
||
|
||
| Zone | M1 clients | M2 fournisseurs |
|
||
|---|---|---|
|
||
| Distributeur / Courtier | Auto-référence Client (RG-1.03) | **Absent** |
|
||
| Prestation de triage | Booléen sur le client (formulaire principal) | **Booléen sur l'adresse** (`triage_provider`) |
|
||
| Type d'adresse | 3 checkboxes Prospect / Livraison / Facturation | **Radio exclusif** Prospect / Départ / Rendu (RG-2.09) |
|
||
| Email facturation sur adresse | Oui (conditionnel) | **Absent** |
|
||
| Champ adresse « Bennes » | — | **Présent** (nombre) |
|
||
| Onglet Information | 7 champs | **8 champs** (ajout « Volume prévisionnel ») |
|
||
| Catégories | type unique `CLIENT` (codes ERP-78) | **nouveau type `FOURNISSEUR`** |
|
||
| Archivage | Admin | **Admin uniquement** (idem) |
|
||
| Onglets « À venir » | frames blanches | **placeholder « À venir »** (minimal) |
|
||
|
||
## Points résolus côté back
|
||
|
||
| # | Zone d'ombre | Résolution (cf. `spec-back.md`) |
|
||
|---|---|---|
|
||
| 1 | Catégorie multi-select | M2M `supplier_category`, `Category` de type **FOURNISSEUR** (RG-2.10) |
|
||
| 2 | Type d'adresse Prospect/Départ/Rendu | Enum exclusif `address_type` (RG-2.09) |
|
||
| 3 | Onglet Comptabilité : qui édite ? | Admin + Compta (`accounting.manage`) ; Bureau/Commerciale ne le voient pas |
|
||
| 4 | Workflow par onglet | Sauvegarde incrémentale (POST principal + PATCH partiels) — pas d'état « draft » |
|
||
| 5 | Onglets « À venir » | Placeholder minimal « À venir » (Transport / Stats / Rapports / Échanges) |
|
||
| 6 | Archive vs delete | Flag `is_archived` séparé de `deleted_at` ; archivage Admin seul ; soft delete = HP |
|
||
| 7 | Unicité métier | Nom de fournisseur uniquement (à valider — § 2.6). SIREN/email non uniques |
|
||
| 8 | Référentiels comptables | Réutilisés du M1 (zéro duplication) |
|
||
| 9 | API code postal | BAN via `useAddressAutocomplete()` du M1 |
|
||
| 10 | Format export | XLSX uniquement (CSV = HP) |
|
||
|
||
---
|
||
|
||
## 📦 Tickets Lesstime
|
||
|
||
**TaskGroup Lesstime** : à créer — `M2 — Répertoire fournisseurs` (projet `ERP / Starseed`, projectId=6).
|
||
|
||
> Détail complet et action manuelle → voir [`spec-back.md § Tickets Lesstime`](./spec-back.md#-tickets-lesstime-à-découper).
|