c25c33116d
Auto Tag Develop / tag (push) Successful in 8s
Empilée sur ERP-143 (#105). ## Périmètre ERP-144 Onglet **Comptabilité** de l'écran `/providers/new` — gated par permission + blocs RIB conditionnels. - Champs (`Malio*`) : SIREN / Numéro de compte / Mode de TVA (`/api/tva_modes`) / N° de TVA / Délai (`/api/payment_delays`) / Type de règlement (`/api/payment_types`) / Banque (`/api/banks`). - **RG-3.07** : Banque visible **et** obligatoire **seulement si** Type = `VIREMENT` (affichage conditionnel + payload `bank` forcé à null sinon). - **RG-3.08** : blocs RIB (Libellé/BIC/IBAN) affichés et requis si Type = `LCR` ; « + RIB » gated (dernier RIB complet) / Supprimer (modal). À la validation, **POST des RIB AVANT** le PATCH des scalaires (le back valide RG-3.08 sur le PATCH). - **Gating** : onglet présent uniquement si `technique.providers.accounting.view` ; **éditable** uniquement si `.manage` (sinon lecture seule). Masqué pour Bureau/Commerciale. - « Valider » → PATCH `/api/providers/{id}` (groupe `provider:write:accounting`) + sous-ressource RIBs (`/providers/{id}/ribs` + `/provider_ribs/{id}`). Erreurs 422 inline (scalaires) et par ligne (RIB). - `useProviderReferentials.loadAccounting()` (chargé seulement si l'onglet est accessible). Helpers purs `utils/forms/providerAccounting.ts`. - i18n `technique.providers.form.accounting` + `confirmDelete.rib`. > NB : les placeholders **Rapports / Échanges** relèvent des écrans Consultation/Modification (ERP-145) — le flux de **création** ne porte que 3 onglets (Contact/Adresse/Comptabilité), conformément à la spec. ## Conformité - `useApi()` only ; `Malio*` only ; pas de masque email ; aucun texte FR en dur ; pas d'import inter-module (helpers ré-implémentés côté Technique, règle ABSOLUE n°1). ## Vérifications - Vitest : 454/454 (18 nouveaux : helpers compta RG-3.07/3.08, workflow VIREMENT/LCR, ordre RIB→scalaires, 422 inline + par ligne, lecture seule sans manage). - ESLint : OK. - `nuxi typecheck` : 0 erreur sur les fichiers source du ticket. - Golden path navigateur : page compile, onglet Comptabilité visible (gating accounting.view OK pour admin). Contenu de l'onglet gaté derrière le déverrouillage des 3 onglets (multiselect `Malio` non pilotable en a11y) — couvert par les tests unitaires + typecheck. Reviewed-on: #106 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
/**
|
|
* Helpers purs de l'onglet Comptabilite prestataire (M3 Technique, ERP-144) —
|
|
* miroir SIMPLIFIE des regles M2, reimplemente cote module Technique (regle
|
|
* ABSOLUE n°1 : pas d'import inter-module). Portent les RG inter-champs RG-3.07
|
|
* (banque si VIREMENT) et RG-3.08 (RIB si LCR), testables sans Vue ni API.
|
|
*/
|
|
|
|
import type {
|
|
ProviderAccountingDraft,
|
|
ProviderRibFormDraft,
|
|
} from '~/modules/technique/types/providerForm'
|
|
|
|
/** Code pivot du type de reglement imposant une banque (RG-3.07). */
|
|
const PAYMENT_TYPE_VIREMENT = 'VIREMENT'
|
|
/** Code pivot du type de reglement imposant au moins un RIB (RG-3.08). */
|
|
const PAYMENT_TYPE_LCR = 'LCR'
|
|
|
|
/** Champs RIB obligatoires non nullable cote back (NotBlank) — omis si vides au POST. */
|
|
const RIB_REQUIRED_NON_NULLABLE_KEYS = ['label', 'bic', 'iban'] as const
|
|
|
|
/** Vrai si une chaine porte au moins un caractere non-espace. */
|
|
function isFilled(value: string | null | undefined): boolean {
|
|
return value !== null && value !== undefined && value.trim() !== ''
|
|
}
|
|
|
|
/** RG-3.07 : la banque n'est requise/visible que pour un reglement par VIREMENT. */
|
|
export function isBankRequiredForPaymentType(code: string | null | undefined): boolean {
|
|
return code === PAYMENT_TYPE_VIREMENT
|
|
}
|
|
|
|
/** RG-3.08 : au moins un RIB n'est requis que pour un reglement par LCR. */
|
|
export function isRibRequiredForPaymentType(code: string | null | undefined): boolean {
|
|
return code === PAYMENT_TYPE_LCR
|
|
}
|
|
|
|
/** Vrai si AUCUN champ du bloc RIB n'est rempli (amorce vide a ignorer au submit). */
|
|
export function isRibBlank(rib: ProviderRibFormDraft): boolean {
|
|
return ![rib.label, rib.bic, rib.iban].some(isFilled)
|
|
}
|
|
|
|
/** Vrai si les 3 champs du RIB sont remplis (gating « + RIB »). */
|
|
export function isRibComplete(rib: ProviderRibFormDraft): boolean {
|
|
return isFilled(rib.label) && isFilled(rib.bic) && isFilled(rib.iban)
|
|
}
|
|
|
|
/**
|
|
* Payload du PATCH comptable (groupe `provider:write:accounting`). Les relations
|
|
* sont en IRI ; la banque n'est envoyee que si elle est requise (RG-3.07), sinon
|
|
* `null` (le back vide la relation hors VIREMENT).
|
|
*/
|
|
export function buildProviderAccountingPayload(
|
|
accounting: ProviderAccountingDraft,
|
|
isBankRequired: boolean,
|
|
): Record<string, unknown> {
|
|
return {
|
|
siren: accounting.siren || null,
|
|
accountNumber: accounting.accountNumber || null,
|
|
tvaMode: accounting.tvaModeIri,
|
|
nTva: accounting.nTva || null,
|
|
paymentDelay: accounting.paymentDelayIri,
|
|
paymentType: accounting.paymentTypeIri,
|
|
bank: isBankRequired ? accounting.bankIri : null,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Payload d'un RIB (sous-ressource, groupe `provider:write:accounting`). Les
|
|
* champs requis vides sont omis a la creation pour que la 422 NotBlank porte sur
|
|
* le champ.
|
|
*/
|
|
export function buildProviderRibPayload(rib: ProviderRibFormDraft): Record<string, unknown> {
|
|
const payload: Record<string, unknown> = {
|
|
label: rib.label,
|
|
bic: rib.bic,
|
|
iban: rib.iban,
|
|
}
|
|
|
|
for (const key of RIB_REQUIRED_NON_NULLABLE_KEYS) {
|
|
const value = payload[key]
|
|
if (value === null || value === undefined || value === '') {
|
|
delete payload[key]
|
|
}
|
|
}
|
|
|
|
return payload
|
|
}
|