fix(front+back) : suppression de la categorie du bloc adresse prestataire (ERP-193)
La categorie portee par l'ADRESSE du prestataire (M2M provider_address_category) est retiree de toutes les couches : champ + prop du bloc adresse, type/payload/ mapping front, entite ProviderAddress (M2M, Assert\Count, validateCategoryType, accesseurs), fixtures, contexte de serialisation. Nouvelle migration de drop de la table (namespace racine pour l'ordre post-creation). La categorie du PRESTATAIRE lui-meme (provider_category, repertoire, filtre, formulaire principal) est conservee.
This commit is contained in:
@@ -23,19 +23,6 @@
|
||||
@update:model-value="(v: (string | number)[]) => update('siteIris', v.map(String))"
|
||||
/>
|
||||
|
||||
<!-- Categories de type PRESTATAIRE (>= 1 obligatoire, RG-3.09). -->
|
||||
<MalioSelectCheckbox
|
||||
:model-value="model.categoryIris"
|
||||
:options="categoryOptions"
|
||||
:label="t('technique.providers.form.address.categories')"
|
||||
:display-tag="true"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:required="!readonly && !disabled"
|
||||
:error="errors?.categories"
|
||||
@update:model-value="(v: (string | number)[]) => update('categoryIris', v.map(String))"
|
||||
/>
|
||||
|
||||
<!-- Contacts rattaches (M2M, facultatif) : alimente par l'onglet Contact. -->
|
||||
<MalioSelectCheckbox
|
||||
:model-value="model.contactIris"
|
||||
@@ -151,8 +138,6 @@ const POSTAL_CODE_MASK = '#####'
|
||||
const props = defineProps<{
|
||||
/** Brouillon de l'adresse (v-model). */
|
||||
modelValue: ProviderAddressFormDraft
|
||||
/** Categories autorisees sur une adresse (type PRESTATAIRE). */
|
||||
categoryOptions: RefOption[]
|
||||
/** Sites Starseed disponibles. */
|
||||
siteOptions: RefOption[]
|
||||
/** Contacts deja saisis, rattachables a l'adresse. */
|
||||
|
||||
@@ -46,7 +46,6 @@ function mountBlock(overrides: Record<string, unknown> = {}, errors?: Record<str
|
||||
return mount(ProviderAddressBlock, {
|
||||
props: {
|
||||
modelValue: { ...emptyProviderAddress(), ...overrides },
|
||||
categoryOptions: [],
|
||||
siteOptions: [],
|
||||
contactOptions: [],
|
||||
countryOptions: [],
|
||||
@@ -79,17 +78,14 @@ describe('ProviderAddressBlock — version simplifiee M3 (pas de type/bennes/tri
|
||||
})
|
||||
|
||||
describe('ProviderAddressBlock — mapping erreur par champ (ERP-101)', () => {
|
||||
it('affiche les erreurs serveur sur sites et categories (RG-3.05 / RG-3.09)', () => {
|
||||
it('affiche l\'erreur serveur sur sites (RG-3.05)', () => {
|
||||
const wrapper = mountBlock({}, {
|
||||
sites: 'Au moins un site est obligatoire.',
|
||||
categories: 'Au moins une catégorie est obligatoire.',
|
||||
})
|
||||
const checkboxes = wrapper.findAll('malio-select-checkbox-stub')
|
||||
const sitesField = checkboxes.find(el => el.attributes('label') === 'technique.providers.form.address.sites')
|
||||
const categoriesField = checkboxes.find(el => el.attributes('label') === 'technique.providers.form.address.categories')
|
||||
|
||||
expect(sitesField?.attributes('error')).toBe('Au moins un site est obligatoire.')
|
||||
expect(categoriesField?.attributes('error')).toBe('Au moins une catégorie est obligatoire.')
|
||||
})
|
||||
|
||||
it('affiche l\'erreur serveur sur le code postal', () => {
|
||||
|
||||
@@ -330,17 +330,16 @@ describe('useProviderForm — onglet Adresse (ERP-143)', () => {
|
||||
return form
|
||||
}
|
||||
|
||||
/** Remplit un bloc adresse valide (site + categorie + scalaires requis). */
|
||||
/** Remplit un bloc adresse valide (site + scalaires requis). */
|
||||
function fillValidAddress(form: ProviderForm, index = 0): void {
|
||||
const a = addressAt(form, index)
|
||||
a.siteIris = [SITE_86]
|
||||
a.categoryIris = [CAT_MAINT]
|
||||
a.postalCode = '86100'
|
||||
a.city = 'Châtellerault'
|
||||
a.street = '1 rue du Test'
|
||||
}
|
||||
|
||||
it('RG-3.05 : « + Nouvelle adresse » desactive tant que site + categorie manquent', () => {
|
||||
it('RG-3.05 : « + Nouvelle adresse » desactive tant que le site manque', () => {
|
||||
const form = createdForm()
|
||||
expect(form.canAddAddress.value).toBe(false)
|
||||
|
||||
@@ -349,8 +348,6 @@ describe('useProviderForm — onglet Adresse (ERP-143)', () => {
|
||||
expect(form.addresses.value).toHaveLength(1)
|
||||
|
||||
addressAt(form).siteIris = [SITE_86]
|
||||
expect(form.canAddAddress.value).toBe(false) // categorie manquante
|
||||
addressAt(form).categoryIris = [CAT_MAINT]
|
||||
expect(form.canAddAddress.value).toBe(true)
|
||||
form.addAddress()
|
||||
expect(form.addresses.value).toHaveLength(2)
|
||||
@@ -377,7 +374,7 @@ describe('useProviderForm — onglet Adresse (ERP-143)', () => {
|
||||
expect(ok).toBe(true)
|
||||
const [url, body, opts] = mockPost.mock.calls[0] ?? []
|
||||
expect(url).toBe('/providers/7/addresses')
|
||||
expect(body).toMatchObject({ sites: [SITE_86], categories: [CAT_MAINT], city: 'Châtellerault' })
|
||||
expect(body).toMatchObject({ sites: [SITE_86], city: 'Châtellerault' })
|
||||
expect(opts).toMatchObject({ toast: false, headers: { Accept: 'application/ld+json' } })
|
||||
expect(addressAt(form).id).toBe(88)
|
||||
expect(form.isValidated('address')).toBe(true)
|
||||
|
||||
@@ -104,7 +104,6 @@
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
:model-value="address"
|
||||
:category-options="referentials.categories.value"
|
||||
:site-options="referentials.sites.value"
|
||||
:contact-options="contactOptions"
|
||||
:country-options="countryOptions"
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
v-for="(view, index) in addressViews"
|
||||
:key="index"
|
||||
:model-value="view.draft"
|
||||
:category-options="view.categoryOptions"
|
||||
:site-options="view.siteOptions"
|
||||
:contact-options="contactOptions"
|
||||
:country-options="countryOptionsFor(view.draft.country)"
|
||||
@@ -242,16 +241,15 @@ const contacts = computed(() => {
|
||||
// Contacts rattachables (pour resoudre les libelles des contacts lies aux adresses).
|
||||
const contactOptions = computed(() => contactOptionsOf(provider.value?.contacts))
|
||||
|
||||
// Vue par adresse : brouillon + options propres a l'adresse (sites/categories embarques).
|
||||
// Vue par adresse : brouillon + options propres a l'adresse (sites embarques).
|
||||
const addressViews = computed(() => {
|
||||
const views = (provider.value?.addresses ?? []).map(address => ({
|
||||
draft: mapAddressToDraft(address),
|
||||
siteOptions: siteOptionsOf(address.sites),
|
||||
categoryOptions: categoryOptionsOf(address.categories),
|
||||
}))
|
||||
return views.length > 0
|
||||
? views
|
||||
: [{ draft: emptyProviderAddress(), siteOptions: [], categoryOptions: [] }]
|
||||
: [{ draft: emptyProviderAddress(), siteOptions: [] }]
|
||||
})
|
||||
|
||||
/** Pays : une seule option (la valeur courante), suffisant pour l'affichage readonly. */
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
v-for="(address, index) in addresses"
|
||||
:key="index"
|
||||
:model-value="address"
|
||||
:category-options="referentials.categories.value"
|
||||
:site-options="referentials.sites.value"
|
||||
:contact-options="contactOptions"
|
||||
:country-options="countryOptions"
|
||||
|
||||
@@ -97,8 +97,6 @@ export interface ProviderAddressFormDraft {
|
||||
city: string | null
|
||||
street: string | null
|
||||
streetComplement: string | null
|
||||
/** IRI des categories rattachees (type PRESTATAIRE, RG-3.09 ; >= 1). */
|
||||
categoryIris: string[]
|
||||
/** IRI des sites rattaches a l'adresse (M2M `provider_address_site`, RG-3.05 ; >= 1). */
|
||||
siteIris: string[]
|
||||
/** IRI des contacts rattaches (= blocs Contact deja persistes de l'onglet Contact). */
|
||||
@@ -114,7 +112,6 @@ export function emptyProviderAddress(): ProviderAddressFormDraft {
|
||||
city: null,
|
||||
street: null,
|
||||
streetComplement: null,
|
||||
categoryIris: [],
|
||||
siteIris: [],
|
||||
contactIris: [],
|
||||
}
|
||||
|
||||
@@ -12,21 +12,15 @@ import { emptyProviderAddress } from '~/modules/technique/types/providerForm'
|
||||
*/
|
||||
describe('providerAddress helpers', () => {
|
||||
const SITE = '/api/sites/1'
|
||||
const CAT = '/api/categories/7'
|
||||
|
||||
describe('isProviderAddressValid (RG-3.05 / RG-3.09)', () => {
|
||||
describe('isProviderAddressValid (RG-3.05)', () => {
|
||||
it('false sans site', () => {
|
||||
const address = { ...emptyProviderAddress(), categoryIris: [CAT] }
|
||||
const address = { ...emptyProviderAddress() }
|
||||
expect(isProviderAddressValid(address)).toBe(false)
|
||||
})
|
||||
|
||||
it('false sans categorie', () => {
|
||||
it('true avec au moins un site', () => {
|
||||
const address = { ...emptyProviderAddress(), siteIris: [SITE] }
|
||||
expect(isProviderAddressValid(address)).toBe(false)
|
||||
})
|
||||
|
||||
it('true avec au moins un site ET une categorie', () => {
|
||||
const address = { ...emptyProviderAddress(), siteIris: [SITE], categoryIris: [CAT] }
|
||||
expect(isProviderAddressValid(address)).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -39,7 +33,6 @@ describe('providerAddress helpers', () => {
|
||||
city: 'Châtellerault',
|
||||
street: '1 rue du Test',
|
||||
siteIris: [SITE],
|
||||
categoryIris: [CAT],
|
||||
contactIris: ['/api/provider_contacts/9'],
|
||||
})
|
||||
expect(payload).toEqual({
|
||||
@@ -48,7 +41,6 @@ describe('providerAddress helpers', () => {
|
||||
city: 'Châtellerault',
|
||||
street: '1 rue du Test',
|
||||
streetComplement: null,
|
||||
categories: [CAT],
|
||||
sites: [SITE],
|
||||
contacts: ['/api/provider_contacts/9'],
|
||||
})
|
||||
@@ -61,7 +53,6 @@ describe('providerAddress helpers', () => {
|
||||
const payload = buildProviderAddressPayload({
|
||||
...emptyProviderAddress(),
|
||||
siteIris: [SITE],
|
||||
categoryIris: [CAT],
|
||||
})
|
||||
expect(payload).not.toHaveProperty('postalCode')
|
||||
expect(payload).not.toHaveProperty('city')
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('providerDetail helpers', () => {
|
||||
})
|
||||
|
||||
describe('mapAddressToDraft', () => {
|
||||
it('extrait les IRI des sites / categories / contacts embarques', () => {
|
||||
it('extrait les IRI des sites / contacts embarques', () => {
|
||||
const draft = mapAddressToDraft({
|
||||
'@id': '/api/provider_addresses/3',
|
||||
id: 3,
|
||||
@@ -85,11 +85,9 @@ describe('providerDetail helpers', () => {
|
||||
city: 'Châtellerault',
|
||||
street: '1 rue du Test',
|
||||
sites: [{ '@id': '/api/sites/1' }],
|
||||
categories: [{ '@id': '/api/categories/7' }],
|
||||
contacts: [{ '@id': '/api/provider_contacts/5' }, '/api/provider_contacts/6'],
|
||||
})
|
||||
expect(draft.siteIris).toEqual(['/api/sites/1'])
|
||||
expect(draft.categoryIris).toEqual(['/api/categories/7'])
|
||||
expect(draft.contactIris).toEqual(['/api/provider_contacts/5', '/api/provider_contacts/6'])
|
||||
expect(draft.id).toBe(3)
|
||||
})
|
||||
|
||||
@@ -14,12 +14,12 @@ import type { ProviderAddressFormDraft } from '~/modules/technique/types/provide
|
||||
const REQUIRED_NON_NULLABLE_KEYS = ['postalCode', 'city', 'street'] as const
|
||||
|
||||
/**
|
||||
* RG-3.05 (+ RG-3.09) : une adresse est « valide » pour autoriser l'ajout d'un
|
||||
* nouveau bloc des qu'elle porte au moins un site ET au moins une categorie. Les
|
||||
* scalaires (CP/ville/rue) restent valides par le back (422 inline).
|
||||
* RG-3.05 : une adresse est « valide » pour autoriser l'ajout d'un nouveau bloc
|
||||
* des qu'elle porte au moins un site. Les scalaires (CP/ville/rue) restent valides
|
||||
* par le back (422 inline).
|
||||
*/
|
||||
export function isProviderAddressValid(address: ProviderAddressFormDraft): boolean {
|
||||
return address.siteIris.length >= 1 && address.categoryIris.length >= 1
|
||||
return address.siteIris.length >= 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,6 @@ export function buildProviderAddressPayload(address: ProviderAddressFormDraft):
|
||||
city: address.city || null,
|
||||
street: address.street || null,
|
||||
streetComplement: address.streetComplement || null,
|
||||
categories: [...address.categoryIris],
|
||||
sites: [...address.siteIris],
|
||||
contacts: [...address.contactIris],
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ export interface AddressRead extends HydraRef {
|
||||
street?: string | null
|
||||
streetComplement?: string | null
|
||||
sites?: SiteRead[]
|
||||
categories?: CategoryRead[]
|
||||
// L'embed M2M des contacts d'adresse peut etre un objet (partiel) ou un IRI nu.
|
||||
contacts?: Array<HydraRef | string>
|
||||
}
|
||||
@@ -146,7 +145,6 @@ export function mapAddressToDraft(address: AddressRead): ProviderAddressFormDraf
|
||||
city: address.city ?? null,
|
||||
street: address.street ?? null,
|
||||
streetComplement: address.streetComplement ?? null,
|
||||
categoryIris: (address.categories ?? []).map(c => c['@id']),
|
||||
siteIris: (address.sites ?? []).map(s => s['@id']),
|
||||
contactIris: (address.contacts ?? []).map(c => (typeof c === 'string' ? c : c['@id'])),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user