feat(commercial) : onglet adresse — Select « Type d'adresse » + Sites en multiselect, ligne 1 réagencée (ERP-110)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 2m0s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m19s

- Sites Starseed : 3 cases -> multiselect a tags « Sites » (required).
- Usage adresse : 3 cases Prospect/Livraison/Facturation -> Select unique « Type d'adresse » (Prospect / Livraison / Facturation / Adresse + Facturation), obligatoire sans option vide, conditionnant le bouton « Valider ». Pur sucre front : le back recoit toujours isProspect/isDelivery/isBilling (aucune RG modifiee), exclusivite Prospect devenue structurelle.
- Email de facturation conditionnel (Facturation / Adresse + Facturation) deplace en ligne 1.
- Ligne 1 : Type d'adresse | Sites | Contact rattache | Email ; le reste (Categorie, Pays, CP, Ville, Adresse...) en lignes suivantes.
- Email : MalioInputText -> MalioInputEmail (lowercase, ERP-101/RG-1.21) sur facturation ET contact.
- Helpers front testables addressFlagsFromType / addressTypeFromFlags + gating canValidateAddresses (type obligatoire) dans new.vue / edit.vue.
This commit is contained in:
2026-06-04 15:58:01 +02:00
parent c2282fdac5
commit 5834d7b225
7 changed files with 146 additions and 83 deletions
@@ -1,5 +1,7 @@
import { describe, it, expect } from 'vitest'
import {
addressFlagsFromType,
addressTypeFromFlags,
applyProspectExclusivity,
buildClientFormTabKeys,
canSelectDeliveryOrBilling,
@@ -197,6 +199,32 @@ describe('isBillingEmailRequired (RG-1.11)', () => {
})
})
describe('type d\'adresse (Select front) <-> drapeaux back', () => {
it('addressFlagsFromType mappe chaque type vers les bons drapeaux', () => {
expect(addressFlagsFromType('prospect')).toEqual({ isProspect: true, isDelivery: false, isBilling: false })
expect(addressFlagsFromType('delivery')).toEqual({ isProspect: false, isDelivery: true, isBilling: false })
expect(addressFlagsFromType('billing')).toEqual({ isProspect: false, isDelivery: false, isBilling: true })
expect(addressFlagsFromType('delivery_billing')).toEqual({ isProspect: false, isDelivery: true, isBilling: true })
})
it('addressTypeFromFlags reconstruit le type (Prospect prioritaire, livraison+facturation groupes)', () => {
expect(addressTypeFromFlags({ isProspect: true, isDelivery: false, isBilling: false })).toBe('prospect')
expect(addressTypeFromFlags({ isProspect: false, isDelivery: true, isBilling: false })).toBe('delivery')
expect(addressTypeFromFlags({ isProspect: false, isDelivery: false, isBilling: true })).toBe('billing')
expect(addressTypeFromFlags({ isProspect: false, isDelivery: true, isBilling: true })).toBe('delivery_billing')
})
it('addressTypeFromFlags retourne null quand aucun drapeau (amorce vierge -> bouton bloque)', () => {
expect(addressTypeFromFlags({ isProspect: false, isDelivery: false, isBilling: false })).toBeNull()
})
it('aller-retour type -> drapeaux -> type stable pour les 4 types', () => {
for (const type of ['prospect', 'delivery', 'billing', 'delivery_billing'] as const) {
expect(addressTypeFromFlags(addressFlagsFromType(type))).toBe(type)
}
})
})
describe('regles type de reglement (RG-1.12 / RG-1.13)', () => {
it('banque obligatoire si VIREMENT', () => {
expect(isBankRequiredForPaymentType('VIREMENT')).toBe(true)