import { ref } from 'vue' /** * Charge les referentiels (listes courtes) alimentant les selects de l'ecran * « Ajouter un client » : categories, sites, modes de TVA, delais et types de * reglement, banques, et les listes distributeurs / courtiers. * * Toutes les collections sont recuperees en entier via l'echappatoire prevue * `?pagination=false` (referentiels de quelques dizaines d'entrees max), avec * l'en-tete `Accept: application/ld+json` impose par API Platform 4 pour obtenir * l'enveloppe Hydra (`member`). Les valeurs d'option sont les IRI Hydra (`@id`) * pour pouvoir etre renvoyees telles quelles dans les payloads POST/PATCH * (relations ManyToOne / ManyToMany). * * Etat 100 % local a l'instance (refs) — aucune persistance URL. */ /** Option generique au format attendu par MalioSelect / MalioSelectCheckbox ({ label, value }). */ export interface RefOption { value: string label: string } /** Option de type de reglement enrichie de son code stable (RG-1.12 / RG-1.13). */ export interface PaymentTypeOption extends RefOption { code: string } /** Option de categorie enrichie de son code stable (filtrage RG-1.29 cote adresse). */ export interface CategoryOption extends RefOption { code: string } /** Option de client (distributeur / courtier) — value = IRI du client lie. */ export type ClientOption = RefOption interface HydraMember { '@id': string } interface CategoryMember extends HydraMember { code: string name: string } interface SiteMember extends HydraMember { name: string postalCode: string } interface ReferentialMember extends HydraMember { code: string label: string } interface ClientMember extends HydraMember { companyName: string } const LD_JSON_HEADERS = { Accept: 'application/ld+json' } export function useClientReferentials() { const api = useApi() const categories = ref([]) const sites = ref([]) const tvaModes = ref([]) const paymentDelays = ref([]) const paymentTypes = ref([]) const banks = ref([]) const distributors = ref([]) const brokers = ref([]) /** Recupere une collection complete (pagination desactivee) en Hydra. */ async function fetchAll( url: string, query: Record = {}, ): Promise { const res = await api.get<{ member?: T[] }>( url, { pagination: 'false', ...query }, { headers: LD_JSON_HEADERS, toast: false }, ) return res.member ?? [] } /** * Charge en parallele les referentiels communs (hors distributeurs/courtiers, * charges a la demande selon la relation choisie). * * Chargement RESILIENT (Promise.allSettled) : chaque referentiel est isole. * Necessaire pour les roles metier qui n'ont pas toutes les permissions de * lecture — ex. Compta a `commercial.clients.view` (donc /tva_modes, /banks... * accessibles) mais PAS `catalog.categories.view` ni `sites.view` : sans * isolation, le 403 sur /categories ferait echouer tout le bloc et viderait * les selects comptables dont Compta a besoin sur l'ecran de modification. * Un referentiel en echec reste simplement vide (l'ecran d'edition complete * l'affichage des valeurs courantes depuis l'embed du detail client). */ async function loadCommon(): Promise { await Promise.allSettled([ fetchAll('/categories') .then((cats) => { categories.value = cats.map(c => ({ value: c['@id'], label: c.name, code: c.code })) }), fetchAll('/sites') // Libelle = numero de departement (2 premiers chiffres du code // postal du site), ex: 86100 -> « 86 ». Le code postal est deja // expose par /sites (groupe site:read) — aucune colonne a ajouter. .then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2) })) }), fetchAll('/tva_modes') .then((tva) => { tvaModes.value = tva.map(t => ({ value: t['@id'], label: t.label })) }), fetchAll('/payment_delays') .then((delays) => { paymentDelays.value = delays.map(d => ({ value: d['@id'], label: d.label })) }), fetchAll('/payment_types') .then((types) => { paymentTypes.value = types.map(t => ({ value: t['@id'], label: t.label, code: t.code })) }), fetchAll('/banks') .then((banksList) => { banks.value = banksList.map(b => ({ value: b['@id'], label: b.label })) }), ]) } /** Liste des clients pouvant etre choisis comme distributeur (code DISTRIBUTEUR). */ async function loadDistributors(): Promise { if (distributors.value.length > 0) { return } const clients = await fetchAll('/clients', { categoryCode: 'DISTRIBUTEUR' }) distributors.value = clients.map(c => ({ value: c['@id'], label: c.companyName })) } /** Liste des clients pouvant etre choisis comme courtier (code COURTIER). */ async function loadBrokers(): Promise { if (brokers.value.length > 0) { return } const clients = await fetchAll('/clients', { categoryCode: 'COURTIER' }) brokers.value = clients.map(c => ({ value: c['@id'], label: c.companyName })) } return { categories, sites, tvaModes, paymentDelays, paymentTypes, banks, distributors, brokers, loadCommon, loadDistributors, loadBrokers, } }