feat(commercial) : types d'adresse Courtier et Distributeur (ERP-119)
Ajoute deux types d'adresse autonomes (exclusifs, comme la Prospection) : - back : colonnes is_broker / is_distributor sur client_address (migration modulaire, append + 2 CHECK miroir d'exclusivite + COMMENT ON COLUMN), proprietes ClientAddress (getters Groups + SerializedName), Callback validateExclusiveAddressTypes, validateAddressTypeRequired etendue, catalogue des commentaires SQL mis a jour. - front : type AddressType (+broker/distributor), drapeaux, mappers, option du select Type d'adresse, labels i18n, payloads create/edit et lecture. - tests back (acceptation + exclusivite + contrat de serialisation) et front.
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
isRibRequiredForPaymentType,
|
||||
omitEmptyRequired,
|
||||
showsRelationAndTriageFields,
|
||||
type AddressFlagsDraft,
|
||||
type AddressValidityDraft,
|
||||
type ContactDraft,
|
||||
type ContactFillableDraft,
|
||||
@@ -149,83 +150,79 @@ describe('hasAtLeastOneValidContact (RG-1.14)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
/** Drapeaux d'adresse complets (5 types) avec surcharge partielle. */
|
||||
function flags(overrides: Partial<AddressFlagsDraft> = {}): AddressFlagsDraft {
|
||||
return {
|
||||
isProspect: false, isDelivery: false, isBilling: false, isBroker: false, isDistributor: false,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
describe('exclusivite Prospect / Livraison / Facturation (RG-1.06/07/08)', () => {
|
||||
it('Prospect est selectionnable tant que ni Livraison ni Facturation', () => {
|
||||
expect(canSelectProspect({ isProspect: false, isDelivery: false, isBilling: false })).toBe(true)
|
||||
expect(canSelectProspect({ isProspect: false, isDelivery: true, isBilling: false })).toBe(false)
|
||||
expect(canSelectProspect({ isProspect: false, isDelivery: false, isBilling: true })).toBe(false)
|
||||
expect(canSelectProspect(flags())).toBe(true)
|
||||
expect(canSelectProspect(flags({ isDelivery: true }))).toBe(false)
|
||||
expect(canSelectProspect(flags({ isBilling: true }))).toBe(false)
|
||||
})
|
||||
|
||||
it('Livraison / Facturation selectionnables tant que pas Prospect', () => {
|
||||
expect(canSelectDeliveryOrBilling({ isProspect: false, isDelivery: false, isBilling: false })).toBe(true)
|
||||
expect(canSelectDeliveryOrBilling({ isProspect: true, isDelivery: false, isBilling: false })).toBe(false)
|
||||
expect(canSelectDeliveryOrBilling(flags())).toBe(true)
|
||||
expect(canSelectDeliveryOrBilling(flags({ isProspect: true }))).toBe(false)
|
||||
})
|
||||
|
||||
it('cocher Prospect efface Livraison et Facturation', () => {
|
||||
const next = applyProspectExclusivity(
|
||||
{ isProspect: false, isDelivery: true, isBilling: true },
|
||||
'isProspect',
|
||||
true,
|
||||
)
|
||||
expect(next).toEqual({ isProspect: true, isDelivery: false, isBilling: false })
|
||||
const next = applyProspectExclusivity(flags({ isDelivery: true, isBilling: true }), 'isProspect', true)
|
||||
expect(next).toEqual(flags({ isProspect: true }))
|
||||
})
|
||||
|
||||
it('cocher Livraison efface Prospect', () => {
|
||||
const next = applyProspectExclusivity(
|
||||
{ isProspect: true, isDelivery: false, isBilling: false },
|
||||
'isDelivery',
|
||||
true,
|
||||
)
|
||||
expect(next).toEqual({ isProspect: false, isDelivery: true, isBilling: false })
|
||||
const next = applyProspectExclusivity(flags({ isProspect: true }), 'isDelivery', true)
|
||||
expect(next).toEqual(flags({ isDelivery: true }))
|
||||
})
|
||||
|
||||
it('cocher Facturation efface Prospect mais conserve Livraison', () => {
|
||||
const next = applyProspectExclusivity(
|
||||
{ isProspect: true, isDelivery: true, isBilling: false },
|
||||
'isBilling',
|
||||
true,
|
||||
)
|
||||
expect(next).toEqual({ isProspect: false, isDelivery: true, isBilling: true })
|
||||
const next = applyProspectExclusivity(flags({ isProspect: true, isDelivery: true }), 'isBilling', true)
|
||||
expect(next).toEqual(flags({ isDelivery: true, isBilling: true }))
|
||||
})
|
||||
|
||||
it('decocher un drapeau ne reactive rien d autre', () => {
|
||||
const next = applyProspectExclusivity(
|
||||
{ isProspect: false, isDelivery: true, isBilling: true },
|
||||
'isBilling',
|
||||
false,
|
||||
)
|
||||
expect(next).toEqual({ isProspect: false, isDelivery: true, isBilling: false })
|
||||
const next = applyProspectExclusivity(flags({ isDelivery: true, isBilling: true }), 'isBilling', false)
|
||||
expect(next).toEqual(flags({ isDelivery: true }))
|
||||
})
|
||||
})
|
||||
|
||||
describe('isBillingEmailRequired (RG-1.11)', () => {
|
||||
it('obligatoire uniquement si Facturation est coche', () => {
|
||||
expect(isBillingEmailRequired({ isProspect: false, isDelivery: false, isBilling: true })).toBe(true)
|
||||
expect(isBillingEmailRequired({ isProspect: false, isDelivery: true, isBilling: false })).toBe(false)
|
||||
expect(isBillingEmailRequired(flags({ isBilling: true }))).toBe(true)
|
||||
expect(isBillingEmailRequired(flags({ isDelivery: true }))).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
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 })
|
||||
expect(addressFlagsFromType('prospect')).toEqual(flags({ isProspect: true }))
|
||||
expect(addressFlagsFromType('delivery')).toEqual(flags({ isDelivery: true }))
|
||||
expect(addressFlagsFromType('billing')).toEqual(flags({ isBilling: true }))
|
||||
expect(addressFlagsFromType('delivery_billing')).toEqual(flags({ isDelivery: true, isBilling: true }))
|
||||
expect(addressFlagsFromType('broker')).toEqual(flags({ isBroker: true }))
|
||||
expect(addressFlagsFromType('distributor')).toEqual(flags({ isDistributor: 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 reconstruit le type (Prospect/Courtier/Distributeur autonomes, livraison+facturation groupes)', () => {
|
||||
expect(addressTypeFromFlags(flags({ isProspect: true }))).toBe('prospect')
|
||||
expect(addressTypeFromFlags(flags({ isDelivery: true }))).toBe('delivery')
|
||||
expect(addressTypeFromFlags(flags({ isBilling: true }))).toBe('billing')
|
||||
expect(addressTypeFromFlags(flags({ isDelivery: true, isBilling: true }))).toBe('delivery_billing')
|
||||
expect(addressTypeFromFlags(flags({ isBroker: true }))).toBe('broker')
|
||||
expect(addressTypeFromFlags(flags({ isDistributor: true }))).toBe('distributor')
|
||||
})
|
||||
|
||||
it('addressTypeFromFlags retourne null quand aucun drapeau (amorce vierge -> bouton bloque)', () => {
|
||||
expect(addressTypeFromFlags({ isProspect: false, isDelivery: false, isBilling: false })).toBeNull()
|
||||
expect(addressTypeFromFlags(flags())).toBeNull()
|
||||
})
|
||||
|
||||
it('aller-retour type -> drapeaux -> type stable pour les 4 types', () => {
|
||||
for (const type of ['prospect', 'delivery', 'billing', 'delivery_billing'] as const) {
|
||||
it('aller-retour type -> drapeaux -> type stable pour les 6 types', () => {
|
||||
for (const type of ['prospect', 'delivery', 'billing', 'delivery_billing', 'broker', 'distributor'] as const) {
|
||||
expect(addressTypeFromFlags(addressFlagsFromType(type))).toBe(type)
|
||||
}
|
||||
})
|
||||
@@ -325,6 +322,8 @@ describe('isAddressValid (gating « + Adresse » + validation onglet)', () => {
|
||||
isProspect: false,
|
||||
isDelivery: true,
|
||||
isBilling: false,
|
||||
isBroker: false,
|
||||
isDistributor: false,
|
||||
categoryIris: ['/api/client_categories/1'],
|
||||
siteIris: ['/api/sites/1'],
|
||||
billingEmail: null,
|
||||
|
||||
Reference in New Issue
Block a user