Commit Graph

5 Commits

Author SHA1 Message Date
matthieu 3f356f0679 feat(commercial) : referentiel pays (country) en base + branchement front (ERP-116) (#79)
Auto Tag Develop / tag (push) Successful in 9s
## Objectif (ERP-116, 1re iteration minimale)

Sortir la liste des pays du **code en dur** cote front et la poser en base comme **referentiel `country`**, source unique du select pays. **Perimetre volontairement minimal** : code ISO + libelle + ordre uniquement — **aucune longueur bancaire/fiscale** (numero de compte, IBAN, TVA, BIC, SIREN) a ce stade.

## Backend
- Entite `Country` (`code` ISO 3166-1 alpha-2 unique, `name`, `position`), calquee sur `Bank` : referentiel statique **lecture seule** (`GetCollection` + `Get`), gating `commercial.clients.view OR commercial.suppliers.view`.
- Migration `Version20260609100000` : table `country` + `COMMENT ON COLUMN` + seed des **6 pays** (France, Allemagne, Belgique, Espagne, Italie, Royaume-Uni), `ON CONFLICT DO NOTHING`.
- `CommercialReferentialFixtures` : re-seed des pays en dev/test.
- Garde-fous : ajout au `ColumnCommentsCatalog` + whitelist `EntitiesAreTimestampableBlamableTest`.

## Frontend
- `useClientReferentials` charge `/countries` (value = **nom** du pays : l'adresse stocke `country` en chaine libre, **pas de FK ni migration de donnees**).
- Les 3 listes `countryOptions` en dur (clients new / edit / consultation) sont supprimees ; la consultation derive ses options de l'embed.

## Hors-scope (iterations suivantes du ticket)
- Longueurs bancaires/fiscales par pays + validation associee.
- FK `country_id` sur les adresses + migration de donnees.

## Tests
- Back : suite complete verte (583), tests API dedies countries (200/seed/405/403/401).
- Front : Vitest vert (256), spec `useClientReferentials` mise a jour.
- Migration appliquee en dev + test.

---------

Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #79
2026-06-11 08:09:38 +00:00
tristan c594a76d47 feat(front) : page Modification fournisseur (/suppliers/{id}/edit) (ERP-96) (#85)
Auto Tag Develop / tag (push) Successful in 7s
## ERP-96 — Modification fournisseur

Étape 7/7 (front). Dépend de #94 (Ajouter) + #95 (Consultation).

> ⚠️ MR **stackée sur `feature/ERP-95-suppliers-show`** (95 → 94, pas encore mergées dans develop) pour limiter le diff aux 3 fichiers d'ERP-96. À recibler sur `develop` une fois 94 puis 95 mergées. Squash au merge.

### Périmètre
- Route `/suppliers/{id}/edit` : champs **pré-remplis** depuis GET /suppliers/{id}, **PATCH partiel indépendant par onglet**. Bloc principal conservé (éditable via son propre PATCH `supplier:write:main`), pas de contact inline (ERP-106).
- **Mode strict (RG-2.16)** : chaque onglet n'envoie QUE les champs de son groupe de sérialisation (jamais de mélange → sinon 403). Builders de payload scopés (`supplierEdit`).
- Éditabilité par rôle (`resolveTabEditability`) : métier readonly sans `manage` ; Comptabilité visible/éditable selon `accounting.view`/`accounting.manage` ; placeholders non éditables.
- Collections contacts/adresses/RIB : POST/PATCH par ligne + DELETE différé des retraits ; 422 mappées **inline par champ** (`propertyPath` → `useSupplierFormErrors`/`extractApiViolations`), jamais un toast fourre-tout (ERP-101).

### Tests
- Vitest : `supplierEdit.spec.ts` enrichi (mappers d'hydratation `mapMainDraft`/`mapInformationDraft` avec `volumeForecast`/`mapAccountingFormDraft` + `resolveTabEditability` matrice § 2.7). `make nuxt-test` → 375/375 . ESLint .
- `nuxi typecheck` non lancé sur l'hôte (casse le conteneur dev-nuxt).

Miroir de l'écran Modification client (M1), adapté M2 (enum `addressType`, `bennes`/`triageProvider`/`volumeForecast`, pas de relation Distributeur/Courtier).

Reviewed-on: #85
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 07:26:32 +00:00
tristan 477f77a6b5 feat(front) : page Consultation fournisseur (/suppliers/{id}) lecture seule (ERP-95) (#84)
Auto Tag Develop / tag (push) Successful in 7s
## ERP-95 — Consultation fournisseur (lecture seule)

Étape 6/7 (front). Dépend de #92 (contrat JSON figé) et #94 (blocs/types fournisseur). Bloque #96.

> ⚠️ MR **stackée sur `feature/ERP-94-suppliers-new`** (ERP-94 pas encore mergée dans develop) pour garder le diff limité aux 5 fichiers d'ERP-95. À recibler sur `develop` une fois la 94 mergée. Squash au merge.

### Périmètre
- `useSupplier(id)` : GET /api/suppliers/{id} en Hydra (embed contacts/adresses/ribs + scalaires compta si `accounting.view`), `archive()`/`restore()` via PATCH `isArchived` seul + rechargement complet.
- `supplierConsultation` : mappers purs de l'embed (enum `addressType`, `bennes`/`triageProvider`, `volumeForecast`, gating compta par **omission de clé** → null) + helpers de permissions.
- Page `[id]/index.vue` lecture seule : bloc principal + onglets Information / Contacts / Adresses / Comptabilité (si permission) / 4 coquilles « À venir » ; boutons Modifier (`manage`), Archiver/Restaurer (`archive`) ; flèche retour → répertoire. Miroir de l'écran Consultation client (M1).

### Tests
- Vitest : `supplierConsultation.spec.ts` (mappers + permissions, gating compta) + `useSupplier.spec.ts` (GET/PATCH + propagation 403/409). `make nuxt-test` → 365/365 . ESLint .
- `nuxi typecheck` non lancé sur l'hôte (régénère .nuxt/tailwind en chemins hôte et casse le conteneur dev-nuxt).

Reviewed-on: #84
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 07:15:28 +00:00
tristan d6790dd37d feat(front) : page Ajouter un fournisseur (/suppliers/new) + workflow par onglets (ERP-94) (#83)
Auto Tag Develop / tag (push) Successful in 7s
ERP-94 (etape front 7/7 du M2). **Stack sur #97** (base = `feature/ERP-97-suppliers-i18n-sidebar`, elle-meme sur #93) pour un diff isole. A recibler sur `develop` une fois #93 (MR #81) et #97 (MR #82) mergees.

Page « Ajouter un fournisseur » — **replique a l'identique le fonctionnement de l'ecran Client** (workflow inline par onglets, blocs reutilisables, validation 422 inline ERP-101), avec les specificites M2.

## Architecture (miroir Client)
- Workflow par onglets **inline dans `suppliers/new.vue`** (comme `clients/new.vue` — il n'existe pas de `useClientForm` monolithique). Helpers paralleles : `useSupplierReferentials`, `useSupplierFormErrors`, `supplierFormRules`, `supplierEdit` (payloads), `types/supplierForm`.
- Blocs `SupplierContactBlock` / `SupplierAddressBlock` (miroir des blocs Client).
- POST `/suppliers` puis PATCH partiels par onglet (mode strict, groupes de serialisation). Sous-ressources : `/suppliers/{id}/contacts|addresses|ribs`.
- Validation ERP-101 : 422 `violations[].propertyPath` mappees inline par champ (`useFormErrors` / `mapViolationsToRecord`), `{ toast: false }`, bouton Valider toujours actif.

## Specificites M2 (vs M1)
- Formulaire principal **sans contact inline** (ERP-106) : Entreprise + Categorie (type FOURNISSEUR, `?typeCode=FOURNISSEUR`).
- Adresse : **radio exclusif** Prospect/Depart/Rendu (`addressType` enum, RG-2.09), champs **Bennes** (stepper) + **Prestation de triage**, **pas d'email de facturation**.
- Information : champ **Volume previsionnel** (8e champ).
- Compta (Admin+Compta) : banque si VIREMENT (RG-2.07), RIB si LCR (RG-2.08) ; RIB sous-ressource gardee par `accounting.manage`.

## Tests (mirroir strategie Client)
- `make nuxt-test` : 338 passed (specs ajoutees : supplierFormRules, supplierEdit, useSupplierReferentials, SupplierContactBlock, SupplierAddressBlock).
- ESLint propre ; `nuxi typecheck` (lance en container) : **0 erreur**.
- Golden path navigateur valide end-to-end : POST /suppliers OK, companyName normalise UPPERCASE (RG-2.12), gating des onglets (Information actif, Contacts deverrouille).

## Note de revue
~30 `WARN Duplicated imports` au typecheck : les helpers Supplier exportent les memes noms generiques que leurs equivalents Client (`buildMainPayload`, `omitEmptyRequired`, `RefOption`...), tous deux auto-importes par Nuxt. **Sans impact runtime** : tous les consommateurs utilisent des imports explicites (qui priment). Consequence directe du miroir 1:1 ; une factorisation des generiques dans `shared/` pourrait etre un suivi.

Reviewed-on: #83
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 07:14:51 +00:00
tristan d72f67d374 feat(front) : page Répertoire fournisseurs (/suppliers) + datatable + filtres + export (ERP-93) (#81)
Auto Tag Develop / tag (push) Successful in 7s
Page liste `/suppliers` (ERP-93, étape front 6/7 du M2).

## Périmètre
Répertoire fournisseurs uniquement (datatable + filtres + export). Les écrans new/consultation/edit sont d'autres tickets.

- `MalioDataTable` branché sur `usePaginatedList<Supplier>({url:'/suppliers'})`
- Colonnes : Nom, Catégories (`categories[].name`), Site (`sites[].name`, badges colorés), Dernière activité (`updatedAt`) ; clic ligne → `/suppliers/{id}`
- Boutons : « + Ajouter » (manage), « Filtrer » (drawer : search / categoryCode / siteId / includeArchived + badge + Réinitialiser), « Exporter » (XLSX)
- État filtres/pagination 100 % local (règle n°6) ; pagination 10/25/50 ; `useApi()` + composants `Malio*` only

## Différences vs Répertoire clients
- filtre `includeArchived` (au lieu de `archivedOnly`)
- colonne Catégories = `name` (clients affiche `code`)
- catégories du filtre = `?typeCode=FOURNISSEUR` ; export `/suppliers/export.xlsx`

## Tests
- `make nuxt-test` : 284 passed (11 nouveaux : useSuppliersRepository ×3, page index ×8)
- ESLint propre ; typecheck sans erreur sur les fichiers suppliers
- Golden path navigateur OK (page + drawer)

Aucun mirror RBAC à toucher (sidebar + permissions posés par #90/#92).

Reviewed-on: #81
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 07:00:55 +00:00