Schéma BDD du répertoire transporteurs (M4) + entités + contrat de lecture (liste + détail), socle du front. - Migration Version20260615150000 : tables carrier / carrier_address / carrier_contact / carrier_price (FK cross-module, CHECK enum, index partiel uq_carrier_name_active, COMMENT ON COLUMN). uploaded_document et qualimat_carrier réutilisées (non recréées). - Entités Carrier* (#[Auditable], Timestampable/Blamable) + ApiResource LECTURE seule (GetCollection + Get via CarrierProvider, anti-N+1, exclusion archivés + ?includeArchived). Écriture (POST/PATCH + Processor) reportée WT4+. - QualimatCarrier : mapping ORM lecture seule sur la table référentielle existante (sortie du schema_filter, mapping aligné DDL ERP-39, schema:update no-op) + endpoint de recherche read-only (§ 4.7). - Relations cross-module des prix (Client/Supplier/adresses) via contrats Shared (ClientInterface, SupplierInterface, ClientAddressInterface, SupplierAddressInterface) + resolve_target_entities — sans import inter-module (règle n°1). Ajout du groupe supplier_address:read aux champs de SupplierAddress pour l'embed. - Garde-fous : ColumnCommentsCatalog (carrier* + qualimat_carrier), makefile test-db-setup (index partiel carrier), i18n audit (transport_carrier*), EntitiesAreTimestampableBlamableTest (QualimatCarrier whitelisté). - CarrierSerializationContractTest : contrat JSON liste + détail vérifié (embeds objet, booléens, enveloppe Hydra) ; JSON réel capturé dans spec-back § 4.0.bis. make db-reset OK, make test vert (731), make nuxt-test vert (480), php-cs-fixer OK.
23 KiB
module, nom, ecran, owner_spec, backup_spec, version, date_redaction, maquette_figma, regles_metier, roles, lien_spec_back, client_validation_1, lesstime_project_id, lesstime_taskgroup_id, statut_global
| module | nom | ecran | owner_spec | backup_spec | version | date_redaction | maquette_figma | regles_metier | roles | lien_spec_back | client_validation_1 | lesstime_project_id | lesstime_taskgroup_id | statut_global | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| M4 | Répertoire transporteurs | repertoire-transporteurs | Matthieu | Tristan | V0.1 | 2026-06-15 | https://www.figma.com/design/jRYgT0T9c03VsEbjGhCwwS/Composants---Design-System?node-id=1132-45376&p=f&m=dev |
|
|
./spec-back.md |
|
6 | 31 | pret_a_dev |
Module 4 — Répertoire transporteurs (V0.1 front)
Origine : spec fonctionnelle
M4-repertoire-transporteurs-V0(validée le 27/05/2026) + maquette Figma. Restitution Markdown pour intégration au workflow MALIO. Toute décision technique (back) vit dansspec-back.md. Le M4 réutilise le pattern et les composants posés aux M1 clients, M2 fournisseurs et M3 prestataires.
Socle déjà en place : le module back
Transportexiste (ERP-150) et porte deux référentiels synchronisés par commandes console : transporteurs QUALIMAT (qualimat_carrier, ERP-39) et codes IDTF (idtf_product, ERP-149). Le M4 ajoute le répertoire éditable (Carrier) par-dessus ces référentiels — la saisie assistée du nom interroge le référentiel QUALIMAT (RG-4.01). L'IDTF n'est pas utilisé par ces écrans.
Décisions Matthieu (15/06/2026) : (1) lien QUALIMAT = FK + copie éditable des champs (nom / certification / adresse) ; (2) pas de cloisonnement par site (référentiel global) ; (3) le champ « Décharge » s'appuie sur une infra d'upload réutilisable (
Shared), car d'autres uploads suivront. Détails :spec-back.md § 2.5 / § 2.3 / § 2.7.
But
Lister tous les transporteurs de l'organisation et accéder rapidement à leurs fiches : consultation, création, modification, archivage. Le nom est relié à QUALIMAT (saisie assistée) ; les transporteurs hors QUALIMAT (GMP+, OVOCOM, compte-propre, LIOT, autre) sont saisis manuellement.
Accès
- Depuis : menu principal → section Transport (route
/carriers). (Section « Transport » dédiée ou rattachement à une section « Logistique » — à confirmer, cf.spec-back.md § 5.3.) - Rôles autorisés (tableau « Rôles & permissions » du docx) :
| Rôle | Consultation | Ajout / Modification | Archive |
|---|---|---|---|
| Admin | ✅ Tout | ✅ Tout | ✅ |
| Bureau | ✅ Tout | ✅ Tout | ❌ |
| Compta | ❌ | ❌ | ❌ |
| Commerciale | ✅ Tout | ❌ | ❌ |
| Usine | ❌ | ❌ | ❌ |
Notes :
- RBAC transposée sur
transport.carriers.*(cf.spec-back.md § 5). Commerciale = consultation seule (pas de « + Ajouter » ni « Modifier »). Compta et Usine n'ont aucun accès au module (item sidebar masqué).- Pas de cloisonnement par site (≠ M3) : tout rôle autorisé voit tous les transporteurs.
Navigation
Page d'entrée du module Transport (route /carriers). Titre : « Répertoire transporteurs ».
- Affichage principal : un datatable listant tous les transporteurs actifs (les archivés sont masqués par défaut — filtre dédié).
- Clic sur une ligne → écran Consultation transporteur (page dédiée).
- Bouton « + Ajouter » (haut droite, si
manage) → écran Ajouter un transporteur. - Bouton « Filtrer » (haut droite) → panneau de filtres.
- Bouton « Exporter » (haut droite) → télécharge un XLSX des transporteurs affichés (cf. filtres actifs). Format dans
spec-back.md § 4.6.
Panneau de filtres (bouton « Filtrer »)
Réutilise le pattern M1/M2/M3. Filtres branchés sur les query params de GET /api/carriers (cf. spec-back.md § 4.1) :
| Filtre | Composant | Query param back |
|---|---|---|
| Recherche (nom) | <MalioInputText> |
?search= |
| Certification | <MalioSelectCheckbox> (QUALIMAT / GMP+ / OVOCOM / Compte-propre / Autre) |
?certificationType= |
| Inclure les archivés | <MalioCheckbox> |
?includeArchived=true |
- À l'application des filtres →
setFilters(...)deusePaginatedList(retombe en page 1). - État 100 % local (jamais dans l'URL — règle ABSOLUE n°6).
Datatable du Répertoire
Composant : <MalioDataTable> branché sur usePaginatedList<Carrier>({ url: '/carriers' }) (règle frontend obligatoire — pagination Hydra, état 100 % local). Colonnes :
| Colonne | Source | Tri |
|---|---|---|
| Nom | carrier.name |
ASC par défaut |
| Certification | carrier.certificationType (libellé i18n) |
Non |
| Date de validité | carrier.qualimatCarrier.validityDate (format JJ-MM-AAAA) — fond rouge si < aujourd'hui (RG-4.04) |
Non |
| Dernière activité | carrier.updatedAt (format JJ-MM-AAAA) |
Oui |
Clic sur une ligne → écran Consultation. Pagination : standard Starseed 10 / 25 / 50 (défaut 10). Tri serveur
name ASCpar défaut.
Écran « Ajouter un transporteur »
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. L'onglet Adresses n'est accessible qu'une fois le formulaire principal validé. Cf. spec-back.md § 2.9 (PATCH partiels par groupe de sérialisation).
Accès : bouton « + Ajouter » du Répertoire. Rôles : Admin, Bureau.
Barre d'onglets : Qualimat · Adresses · Contacts · Prix.
Formulaire principal (pré-onglets)
1er bloc à remplir. Sans validation, les onglets ne sont pas accessibles. Une fois validé → POST /api/carriers, puis bascule sur l'onglet Qualimat/Adresses ; les champs passent en readonly.
| Champ | Type composant | Obligatoire | Règle |
|---|---|---|---|
| Nom (saisie assistée reliée à QUALIMAT) | <MalioInputText> (autocomplete) |
Oui | RG-4.01 ; RG-4.13 (UPPERCASE serveur) ; RG-4.12 (unicité) |
| Liste certification transport | <MalioSelect> (GMP+ / OVOCOM / Compte-propre / Autre) |
Oui | RG-4.02 ; auto = QUALIMAT (lecture seule) si transporteur QUALIMAT sélectionné |
| Affréter | <MalioCheckbox> |
Non | RG-4.03 |
| Indexation % | <MalioInputNumber> |
Conditionnel | RG-4.03 — visible + obligatoire si « Affréter » coché |
| Benne / Fond mouvant | <MalioRadioButton> |
Conditionnel | RG-4.03 — visible + obligatoire si « Affréter » coché |
| Volume m³ | <MalioInputNumber> |
Conditionnel | RG-4.03 — visible + obligatoire si « Affréter » coché |
| Décharge | <MalioInputUpload> (cf. note) |
Conditionnel (obligatoire si AUTRE) | RG-4.02 — visible et obligatoire si certification = AUTRE. Upload via infra Shared (spec-back.md § 2.7) |
| Liste immatriculation LIOT | <MalioInputText> (ou TextArea) |
Cas LIOT | RG-4.01 — visible uniquement si nom = LIOT ; les autres champs disparaissent. Immatriculations séparées par ; |
Comportement RG-4.01 (saisie assistée) : à la saisie du nom, recherche dans le référentiel QUALIMAT via
GET /api/qualimat_carriers?search=. Sélection d'un résultat → modal de confirmation « Êtes-vous sûr de vouloir intégrer ce transporteur ? ». Si confirmé : le Nom et la certification (=QUALIMAT, lecture seule) se remplissent automatiquement, ainsi que l'onglet Adresse (copie pays/CP/ville/voie depuis le référentiel). La FK QUALIMAT est conservée (traçabilité + date de validité RG-4.04).
- Cas transporteur non trouvé (pas QUALIMAT) : l'utilisateur choisit une autre certification (RG-4.02) → affichage des champs associés.
- Cas LIOT : si le nom saisi est exactement
LIOT, seul le champ « Liste immatriculation LIOT » s'affiche, les autres champs sont masqués.
Note
<MalioInputUpload>: si le composant ne couvre pas le drag & drop / type fichier requis, exception autorisée documentée (// TODO migrer quand Malio couvre) — cf. exceptions @.claude/rules/frontend.md.
Action : « Valider » (<MalioButton>) → POST /api/carriers (spec-back.md § 4.3). Succès → onglet « Qualimat » / « Adresses ».
Onglet « Qualimat »
Sélectionner un transporteur de la liste QUALIMAT afin de mettre à jour les informations du transporteur (saisie assistée — voir RG-4.01).
Colonnes du tableau de sélection :
| Colonne | Règle |
|---|---|
| Sélection (bouton / clic ligne) | RG-4.03 (docx) — clic → modal « Êtes-vous sûr de vouloir intégrer ce transporteur ? » → remplit Nom + certification + onglet adresse |
| Nom | — |
| Adresse | — |
| Date de validité | RG-4.04 — fond rouge si < date du jour |
Cet onglet alimente le formulaire principal et l'onglet Adresse par copie (RG-4.01 / RG-4.05). Source :
GET /api/qualimat_carriers?search=(lecture seule, lignes actives uniquement).
Onglet « Adresses »
Saisir l'adresse du transporteur (un bloc par adresse).
| Champ | Type | Obligatoire | Règle |
|---|---|---|---|
| Pays | <MalioSelect> (préremplie « France ») |
Conditionnel | RG-4.05 |
| Code postal | <MalioInputText> (saisie assistée) |
Conditionnel | RG-4.06, RG-4.05 — déclenche autocomplete ville (BAN) |
| Ville | <MalioSelect> (saisie assistée) |
Conditionnel | RG-4.06, RG-4.05 — alimentée par api-adresse.data.gouv.fr |
| Adresse | <MalioInputText> (saisie assistée) |
Conditionnel | RG-4.05 |
| Adresse complémentaire | <MalioInputText> |
Non | — |
RG-4.05 : les champs sont déjà remplis si le transporteur est QUALIMAT (copie). Si « Affréter » est coché, l'adresse devient obligatoire (Pays, Code postal, Ville, Adresse). RG-4.06 : la ville est préremplie automatiquement à partir du code postal via l'API BAN (
useAddressAutocomplete(), réutilisé M1/M2/M3). Si plusieurs villes → choix dans le select. L'adresse est une saisie assistée basée sur le CP et la ville. RG-4.07 : le bouton « Valider » n'apparaît pas pour un transporteur QUALIMAT (adresse remplie automatiquement).
Actions : « Valider » → PATCH /api/carriers/{id}/addresses (sauf QUALIMAT, RG-4.07).
Onglet « Contacts »
Saisir un ou plusieurs contacts associés au transporteur.
| Champ | Type | Obligatoire | Règle |
|---|---|---|---|
| Nom | <MalioInputText> |
Non | RG-4.08 + RG-4.13 (Capitalize) |
| Prénom | <MalioInputText> |
Non | RG-4.08 + RG-4.13 (Capitalize) |
| Fonction | <MalioInputText> |
Non | RG-4.08 |
| Téléphone (x1, +1 possible, max 2) | <MalioInputText> |
Non | RG-4.08 + RG-4.13 (format) |
<MalioInputText> type email |
Non | RG-4.08 + RG-4.13 (lowercase) |
RG-4.08 : un bloc Contact est valide dès qu'au moins 1 champ est rempli. Impossible d'ajouter un nouveau bloc tant que le précédent n'est pas valide.
Actions :
- « + Nouveau contact » : ajoute un bloc. Désactivé tant que le bloc précédent n'a aucun champ rempli (RG-4.08).
- « Supprimer » (icône) : modal de confirmation, puis suppression du bloc.
- « Valider » → PATCH
/api/carriers/{id}/contacts.
Onglet « Prix »
Saisir un suivi de prix du transporteur (un bloc par prix). Tous les champs sont masqués par défaut sauf le radio « Client / Fournisseur » (RG-4.09).
Bloc Prix :
| Champ | Type | Obligatoire | Règle |
|---|---|---|---|
| Client / Fournisseur | <MalioRadioButton> |
Oui | RG-4.09 |
| Client | <MalioSelect> (liste des clients) |
Conditionnel | RG-4.10 — si Client |
| Adresse de livraison | <MalioSelect> (adresses du client sélectionné) |
Conditionnel | RG-4.10 — si Client |
| Adresse de départ | <MalioSelect> (86 / 17 / 82) |
Conditionnel | RG-4.10 — si Client ; = un des 3 sites |
| Fournisseur | <MalioSelect> (liste des fournisseurs) |
Conditionnel | RG-4.11 — si Fournisseur |
| Adresse d'approvisionnement | <MalioSelect> (adresses du fournisseur) |
Conditionnel | RG-4.11 — si Fournisseur |
| Adresse de livraison | <MalioSelect> (86 / 17 / 82) |
Conditionnel | RG-4.11 — si Fournisseur ; = un des 3 sites |
| Benne / Fond mouvant (FM) | <MalioRadioButton> |
Oui | — |
| Forfait / Tonne | <MalioRadioButton> |
Oui | — |
| Prix | <MalioInputAmount> (monnaie) |
Oui | — |
| État du prix | <MalioSelect> (En cours / Validé / Non validé) |
Oui | — |
RG-4.10 : si Client sélectionné → champs liés au client affichés et obligatoires ; champs fournisseur masqués et non obligatoires. RG-4.11 : si Fournisseur sélectionné → champs liés au fournisseur affichés et obligatoires ; champs client masqués et non obligatoires. Adresse de départ / livraison « 86 / 17 / 82 » = les 3
Sitefixes (cf. switcher de site Châtellerault / Saint-Jean / Pommevic en haut de l'app). La sélection stocke un ID de Site (spec-back.md § 3.2).
Actions :
- « + Nouveau prix » : ajoute un bloc. Bloqué tant que le précédent n'est pas valide.
- « Supprimer » (icône) : modal de confirmation puis suppression.
- « Valider » → PATCH
/api/carriers/{id}/prices.
Écran « Consultation d'un transporteur »
Consulter en lecture seule la fiche complète. Affiche en haut du bloc les infos principales du transporteur (comme l'écran d'ajout) ainsi que les onglets Adresses, Contacts, Prix. Tous les champs sont en lecture seule.
Accès : clic sur une ligne du Répertoire. La page s'ouvre par défaut sur l'onglet Adresses. Icône « flèche » à gauche pour revenir au répertoire. Deux boutons à droite :
- « Modifier » (visible si
transport.carriers.manage→ Admin, Bureau). - « Archiver » (visible uniquement Admin via
transport.carriers.archive) → modal de confirmation, puis PATCH/api/carriers/{id}{ "isArchived": true }.
Un transporteur archivé peut être restauré (
isArchived: false) — bouton « Restaurer » remplace « Archiver » dans la consultation d'un archivé.
Onglet Adresses (consultation)
Un bloc par adresse du transporteur. Chaque bloc, 5 champs en lecture seule : Pays / Code postal / Ville / Adresse / Adresse complémentaire.
Onglet Contacts (consultation)
Un bloc par contact. 5 champs en lecture seule : Nom / Prénom / Fonction / Téléphone (x1 ou x2) / Email.
Onglet Prix (consultation)
Un tableau regroupant les prix par type (Fond Mouvant / Benne) :
| Colonne | Description |
|---|---|
| Colonne de regroupement | « Fond Mouvant » / « Benne » |
| Transporteurs | Nom du transporteur |
| Adresse APRO ou Adresse Sites | Si prix « Client » → Adresse APRO sinon Adresse Sites |
| Adresse livraisons | — |
| Forfait € | Prix |
| Tonne € | Prix |
| Indexation | Pourcentage d'indexation (vide si non rempli) |
| État du prix | Validé / Non Validé / En cours |
Action : « Exporter » → exporte le tableau au format Excel (GET /api/carriers/{id}/prices/export.xlsx).
Écran « Modification d'un transporteur »
Modifier les informations d'un transporteur existant. Identique à l'écran « Ajouter un transporteur » — mêmes formulaires, mêmes règles métier (RG-4.01 à RG-4.11) — sauf :
- Les champs sont pré-remplis avec les valeurs actuelles.
- Validation par onglet : on peut modifier UN onglet sans toucher aux autres (PATCH partiel).
- Accès : depuis l'écran Consultation, bouton « Modifier » (Admin, Bureau).
Composants UI à utiliser (@malio/layer-ui)
- Datatable :
<MalioDataTable>(+usePaginatedList) - Input texte :
<MalioInputText> - Input nombre / montant :
<MalioInputNumber>(indexation, volume),<MalioInputAmount>(prix) - Select simple :
<MalioSelect>(certification, pays, ville, client, fournisseur, adresses, sites, état du prix) - Select multi (cases à cocher) :
<MalioSelectCheckbox>(filtres certification) - Radio :
<MalioRadioButton>(Benne/Fond mouvant, Forfait/Tonne, Client/Fournisseur) - Checkbox :
<MalioCheckbox>(Affréter, inclure archivés) - Upload :
<MalioInputUpload>(Décharge — exception documentée si type non couvert) - Bouton :
<MalioButton>,<MalioButtonIcon> - Toasts : standards via
useApi() - Validation par champ :
useFormErrors(mapping 422 inline — règle frontend obligatoire)
Exceptions autorisées (commenter // TODO migrer quand Malio couvre) :
- Modal de confirmation : wrapper partagé dans
frontend/shared/(réutiliser celui du M1/M2/M3). <MalioInputUpload>si le type fichier / drag & drop n'est pas couvert.
Composables & appels API
usePaginatedList<Carrier>({ url: '/carriers' })— liste paginée (obligatoire). Consommename,certificationType,qualimatCarrier.validityDate(RG-4.04),updatedAt(cf.spec-back.md § 2.11 / § 4.0).useCarrier(id)— charge le détail viaGET /api/carriers/{id}, qui embarqueaddresses,contacts,prices(avecclient/supplier/sites imbriqués) +qualimatCarrier. Écrans Consultation et Modification peuplés depuis cette seule réponse. DoD avant intégration : vérifier le JSON réel (cf.spec-back.md § 4.0.bis).useCarrierForm()— workflow par onglet (POST principal + PATCH partiels par groupe), miroir deuseSupplierForm()/useProviderForm()+ gestion des champs conditionnels (Affréter, AUTRE→Décharge, cas LIOT).useQualimatSearch()— saisie assistée du nom :GET /api/qualimat_carriers?search=, modal de confirmation, copie des champs + FK (RG-4.01).useAddressAutocomplete()— réutilisé du M1/M2/M3 (BAN), pas de réécriture (RG-4.06).useUpload()(NOUVEAU, infra Shared) — POST multipart/api/uploaded_documents→ renvoie l'IRI à poser surcarrier.dischargeDocument(RG-4.02).usePermissions()— masque l'item sidebar et les boutons selon les permissions.- Tous les appels passent par
useApi()(jamais$fetchdirect — règle ABSOLUE n°4). - Filter
formatPhoneFR()— réutilisé pour l'affichageXX XX XX XX XX.
Règles de formatage et normalisation
Le serveur normalise systématiquement (RG-4.13 — cf. spec-back.md) :
| Champ | Normalisation serveur | Affichage front |
|---|---|---|
Nom transporteur (name) |
UPPERCASE intégral | UPPERCASE |
| Nom + Prénom contact | Capitalize | identique |
Téléphones (CarrierContact) |
Chiffres uniquement en BDD | Formaté XX XX XX XX XX (filter Vue) |
| lowercase intégral | identique | |
| Immatriculations LIOT | ;-split, trim, UPPER |
listées |
Le front ne normalise pas : il envoie la valeur saisie, le serveur normalise et renvoie la valeur normalisée que l'UI affiche.
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/M2/M3 (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 (RG-4.06 : si plusieurs villes, choix dans le select). - À 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 les modules précédents
| Zone | M2/M3 | M4 transporteurs |
|---|---|---|
| Source du nom | saisie libre | saisie assistée reliée à QUALIMAT (référentiel synchronisé) |
| Onglet Comptabilité / RIB | présent (M2/M3) | Absent |
| Cloisonnement par site | M3 : oui | Non (référentiel global) |
| Champs conditionnels formulaire principal | peu | Nombreux (Affréter, AUTRE→Décharge, cas LIOT) |
| Onglet Prix | absent | Présent (Client/Fournisseur, sites départ/livraison) |
| Upload de fichier | aucun | Décharge (infra upload Shared, réutilisable) |
| Module | Commercial / Technique | Transport (existant, ERP-150) |
Points résolus côté back
| # | Zone d'ombre | Résolution (cf. spec-back.md) |
|---|---|---|
| 1 | Lien QUALIMAT | FK qualimatCarrier + copie éditable des champs (§ 2.5) |
| 2 | Cas LIOT | Champ liotPlates (;-séparé), autres champs masqués (RG-4.01) |
| 3 | Certification QUALIMAT | Valeur QUALIMAT lecture seule si lié (§ 2.5) |
| 4 | Décharge (upload) | Infra upload générique Shared réutilisable (§ 2.7) |
| 5 | Onglet Prix — branches | M2M absentes : FK Client/Supplier + adresses + sites (RG-4.10/4.11, § 3.2) |
| 6 | Adresse de départ/livraison 86/17/82 | = les 3 Site fixes (FK Site) |
| 7 | Workflow par onglet | Sauvegarde incrémentale (POST principal + PATCH partiels) — pas d'état « draft » |
| 8 | Archive vs delete | Flag is_archived séparé ; archivage Admin seul ; soft delete = HP |
| 9 | Unicité métier | Nom seul (§ 2.6) |
| 10 | Référentiel QUALIMAT | Endpoint lecture seule GET /api/qualimat_carriers?search= (§ 4.7) |
| 11 | Format export | XLSX (répertoire + onglet Prix regroupé Benne/FM) |
| 12 | RBAC | transport.carriers.view/manage/archive ; Compta + Usine sans accès (§ 5.2) |
📦 Tickets Lesstime
TaskGroup Lesstime : à créer — M4 — Répertoire transporteurs (projet ERP / Starseed, projectId=6). Découpe détaillée (back en tête) → spec-back.md § Tickets Lesstime.
| Ordre | Sujet | Tag |
|---|---|---|
| 0 | Permissions transport.carriers.* + sidebar + 3 sources RBAC |
Backend |
| 1 | Infra upload générique Shared (uploaded_document + FileUploader + endpoint) |
Backend |
| 2 | Migration BDD M4 (carrier + sous-collections + index + COMMENT) | Backend |
| 3 | Entité QualimatCarrier (lecture seule) + endpoint recherche |
Backend |
| 4 | Entités + Repositories Carrier* | Backend |
| 5 | CarrierProvider + CarrierProcessor (champs conditionnels, archive, LIOT) | Backend |
| 6 | Sous-ressources Adresses / Contacts / Prix (RG-4.10/4.11) | Backend |
| 7 | Export XLSX (répertoire + onglet Prix) | Backend |
| 8 | Tests PHPUnit RG-4.01→4.14 + capture contrat JSON | Backend |
| 9 | Page Répertoire (/carriers) + usePaginatedList |
Frontend |
| 10 | Page Ajouter + formulaire principal + saisie assistée QUALIMAT | Frontend |
| 11 | Onglets Adresses (BAN) / Contacts / Prix | Frontend |
| 12 | Pages Consultation + Modification | Frontend |
| 13 | i18n + libellés audit + upload front (useUpload) | Frontend |