feat(commercial) : 2e email de facturation optionnel sur l'adresse client (ERP-119)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 2m9s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m10s

Pendant du telephone secondaire (max 2). Bump @malio/layer-ui 1.7.8 (prop
addable du MalioInputEmail).

- back : colonne billing_email_secondary (migration + COMMENT + catalogue),
  propriete ClientAddress (Email + Length), Callback etendu (2e email interdit
  hors facturation, optionnel sinon), normalisation lowercase au Processor.
- front : draft + flag UI hasSecondaryBillingEmail, mappers, payloads, champ
  MalioInputEmail :addable -> revele un 2e champ ; layout : 2e email qui coule
  dans la grille et Adresse complementaire sur une colonne.
- tests back (2 emails / 2e email hors facturation) et front (payload).
This commit is contained in:
2026-06-09 20:38:50 +02:00
parent ada4b156fa
commit dacf67535d
14 changed files with 205 additions and 26 deletions
@@ -160,10 +160,14 @@ describe('buildContactPayload / buildAddressPayload / buildRibPayload', () => {
id: 3, isProspect: false, isDelivery: false, isBilling: true, isBroker: false, isDistributor: false, country: 'France',
postalCode: '86100', city: 'Châtellerault', street: '1 rue X', streetComplement: null,
categoryIris: ['/api/categories/2'], siteIris: ['/api/sites/1'], contactIris: [],
billingEmail: 'facturation@acme.fr',
billingEmail: 'facturation@acme.fr', billingEmailSecondary: 'compta@acme.fr', hasSecondaryBillingEmail: true,
}
expect(buildAddressPayload(address, true).billingEmail).toBe('facturation@acme.fr')
expect(buildAddressPayload(address, false).billingEmail).toBeNull()
// 2e email : transmis si facturation + revele, sinon null (ERP-119).
expect(buildAddressPayload(address, true).billingEmailSecondary).toBe('compta@acme.fr')
expect(buildAddressPayload(address, false).billingEmailSecondary).toBeNull()
expect(buildAddressPayload({ ...address, hasSecondaryBillingEmail: false }, true).billingEmailSecondary).toBeNull()
})
it('rib : label / bic / iban transmis tels quels', () => {
@@ -187,7 +191,7 @@ describe('buildContactPayload / buildAddressPayload / buildRibPayload', () => {
id: null, isProspect: false, isDelivery: true, isBilling: false, isBroker: false, isDistributor: false, country: 'France',
postalCode: null, city: '', street: null, streetComplement: null,
categoryIris: ['/api/categories/2'], siteIris: ['/api/sites/1'], contactIris: [],
billingEmail: null,
billingEmail: null, billingEmailSecondary: null, hasSecondaryBillingEmail: false,
}
const payload = buildAddressPayload(address, false)
expect('postalCode' in payload).toBe(false)
@@ -63,6 +63,7 @@ export interface AddressRead extends HydraRef {
street?: string | null
streetComplement?: string | null
billingEmail?: string | null
billingEmailSecondary?: string | null
isProspect?: boolean
isDelivery?: boolean
isBilling?: boolean
@@ -222,6 +223,8 @@ export function mapAddressToDraft(address: AddressRead): AddressFormDraft {
siteIris: (address.sites ?? []).map(s => s['@id']),
contactIris: (address.contacts ?? []).map(c => (typeof c === 'string' ? c : c['@id'])),
billingEmail: address.billingEmail ?? null,
billingEmailSecondary: address.billingEmailSecondary ?? null,
hasSecondaryBillingEmail: (address.billingEmailSecondary ?? null) !== null && address.billingEmailSecondary !== '',
}
}
@@ -221,6 +221,7 @@ export function buildAddressPayload(
sites: address.siteIris,
contacts: address.contactIris,
billingEmail: isBillingEmailRequired ? (address.billingEmail || null) : null,
billingEmailSecondary: isBillingEmailRequired && address.hasSecondaryBillingEmail ? (address.billingEmailSecondary || null) : null,
}, ADDRESS_REQUIRED_NON_NULLABLE_KEYS)
}