feat: support customer and supplier role selection for partners
This commit is contained in:
parent
1c316d0105
commit
8dd0427adb
|
|
@ -73,6 +73,90 @@ async function clickSave(wrapper) {
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function businessRoleCheckboxes(wrapper) {
|
||||||
|
const item = wrapper.findAll('.el-form-item').find(
|
||||||
|
node => node.find('.el-form-item__label').text() === '业务分类'
|
||||||
|
)
|
||||||
|
expect(item.text()).toContain('客户')
|
||||||
|
expect(item.text()).toContain('供应商')
|
||||||
|
return item.findAll('input[type="checkbox"]')
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('伙伴客户和供应商身份多选', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
partnersApi.list.mockReset().mockResolvedValue({ data: { items: [], total: 0 } })
|
||||||
|
partnersApi.create.mockReset().mockResolvedValue({ data: {} })
|
||||||
|
partnersApi.update.mockReset().mockResolvedValue({ data: {} })
|
||||||
|
})
|
||||||
|
afterEach(() => { vi.restoreAllMocks() })
|
||||||
|
|
||||||
|
test.each([['supplier', '供应商', false, true], ['customer', '客户', true, false]])(
|
||||||
|
'%s 新增默认当前身份,可双选并提交两个身份', async (role, title, customer, supplier) => {
|
||||||
|
const wrapper = mountPartner(role, title)
|
||||||
|
await flushPromises()
|
||||||
|
await openCreateDialog(wrapper, title)
|
||||||
|
const checkboxes = businessRoleCheckboxes(wrapper)
|
||||||
|
expect(checkboxes[0].element.checked).toBe(customer)
|
||||||
|
expect(checkboxes[1].element.checked).toBe(supplier)
|
||||||
|
for (const checkbox of checkboxes) await checkbox.setValue(true)
|
||||||
|
await inputByLabel(wrapper, '伙伴编码').setValue('BOTH-001')
|
||||||
|
await inputByLabel(wrapper, '企业名称').setValue('双身份公司')
|
||||||
|
await clickSave(wrapper)
|
||||||
|
expect(partnersApi.create).toHaveBeenCalledWith(expect.objectContaining({ is_customer: true, is_supplier: true }))
|
||||||
|
wrapper.unmount()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
test.each([['supplier', '供应商', true, false], ['customer', '客户', false, true]])(
|
||||||
|
'%s 编辑回显双身份并允许取消当前页面身份', async (role, title, customer, supplier) => {
|
||||||
|
const row = { id: 7, partner_code: 'BOTH-001', legal_name: '双身份公司', is_customer: true, is_supplier: true,
|
||||||
|
customer_status: 'suspended', supplier_status: 'active' }
|
||||||
|
partnersApi.list.mockResolvedValue({ data: { items: [row], total: 1 } })
|
||||||
|
const wrapper = mountPartner(role, title)
|
||||||
|
await flushPromises()
|
||||||
|
await findButton(wrapper, '编辑').trigger('click')
|
||||||
|
await flushPromises()
|
||||||
|
const checkboxes = businessRoleCheckboxes(wrapper)
|
||||||
|
expect(checkboxes.every(checkbox => checkbox.element.checked)).toBe(true)
|
||||||
|
await checkboxes[0].setValue(customer)
|
||||||
|
await checkboxes[1].setValue(supplier)
|
||||||
|
expect(row.is_customer).toBe(true)
|
||||||
|
expect(row.is_supplier).toBe(true)
|
||||||
|
await clickSave(wrapper)
|
||||||
|
expect(partnersApi.update).toHaveBeenCalledWith(7, expect.objectContaining({ is_customer: customer, is_supplier: supplier,
|
||||||
|
customer_status: 'suspended', supplier_status: 'active' }))
|
||||||
|
await openCreateDialog(wrapper, title)
|
||||||
|
const reset = businessRoleCheckboxes(wrapper)
|
||||||
|
expect(reset[0].element.checked).toBe(role === 'customer')
|
||||||
|
expect(reset[1].element.checked).toBe(role === 'supplier')
|
||||||
|
wrapper.unmount()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
test.each(['create', 'edit'])('%s 不允许取消所有业务分类', async mode => {
|
||||||
|
const warnSpy = vi.spyOn(ElMessage, 'warning').mockImplementation(() => {})
|
||||||
|
partnersApi.list.mockResolvedValue({ data: { items: [{ id: 7, partner_code: 'SUP-001', legal_name: '示例公司',
|
||||||
|
is_supplier: true, is_customer: false }], total: 1 } })
|
||||||
|
const wrapper = mountPartner()
|
||||||
|
await flushPromises()
|
||||||
|
if (mode === 'create') {
|
||||||
|
await openCreateDialog(wrapper, '供应商')
|
||||||
|
await inputByLabel(wrapper, '伙伴编码').setValue('SUP-002')
|
||||||
|
await inputByLabel(wrapper, '企业名称').setValue('示例公司')
|
||||||
|
} else {
|
||||||
|
await findButton(wrapper, '编辑').trigger('click')
|
||||||
|
await flushPromises()
|
||||||
|
}
|
||||||
|
for (const checkbox of businessRoleCheckboxes(wrapper)) await checkbox.setValue(false)
|
||||||
|
await clickSave(wrapper)
|
||||||
|
expect(warnSpy).toHaveBeenCalledWith('请至少选择一项业务分类')
|
||||||
|
expect(partnersApi.create).not.toHaveBeenCalled()
|
||||||
|
expect(partnersApi.update).not.toHaveBeenCalled()
|
||||||
|
expect(findButton(wrapper, '保存')).toBeDefined()
|
||||||
|
wrapper.unmount()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('伙伴表单必填校验', () => {
|
describe('伙伴表单必填校验', () => {
|
||||||
let warnSpy
|
let warnSpy
|
||||||
|
|
||||||
|
|
@ -264,7 +348,7 @@ describe('伙伴列表分页', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('伙伴业务分类多选', () => {
|
describe('伙伴合作范围多选', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
partnersApi.list.mockReset().mockResolvedValue({ data: { items: [], total: 0 } })
|
partnersApi.list.mockReset().mockResolvedValue({ data: { items: [], total: 0 } })
|
||||||
partnersApi.create.mockReset().mockResolvedValue({ data: {} })
|
partnersApi.create.mockReset().mockResolvedValue({ data: {} })
|
||||||
|
|
@ -279,8 +363,8 @@ describe('伙伴业务分类多选', () => {
|
||||||
await openCreateDialog(wrapper, title)
|
await openCreateDialog(wrapper, title)
|
||||||
await inputByLabel(wrapper, '伙伴编码').setValue('PARTNER-001')
|
await inputByLabel(wrapper, '伙伴编码').setValue('PARTNER-001')
|
||||||
await inputByLabel(wrapper, '企业名称').setValue('示例公司')
|
await inputByLabel(wrapper, '企业名称').setValue('示例公司')
|
||||||
const item = wrapper.findAll('.el-form-item').find(node => node.text().includes('业务分类'))
|
const item = wrapper.findAll('.el-form-item').find(node => node.text().includes('合作范围'))
|
||||||
expect(item, '表单提供业务分类多选').toBeDefined()
|
expect(item, '表单提供合作范围多选').toBeDefined()
|
||||||
for (const checkbox of item.findAll('input[type="checkbox"]')) await checkbox.setValue(true)
|
for (const checkbox of item.findAll('input[type="checkbox"]')) await checkbox.setValue(true)
|
||||||
await clickSave(wrapper)
|
await clickSave(wrapper)
|
||||||
expect(partnersApi.create).toHaveBeenCalledWith(expect.objectContaining({
|
expect(partnersApi.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
|
@ -311,8 +395,8 @@ describe('伙伴业务分类多选', () => {
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
await findButton(wrapper, '编辑').trigger('click')
|
await findButton(wrapper, '编辑').trigger('click')
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
const item = wrapper.findAll('.el-form-item').find(node => node.text().includes('业务分类'))
|
const item = wrapper.findAll('.el-form-item').find(node => node.text().includes('合作范围'))
|
||||||
expect(item, '表单提供业务分类多选').toBeDefined()
|
expect(item, '表单提供合作范围多选').toBeDefined()
|
||||||
const checkboxes = item.findAll('input[type="checkbox"]')
|
const checkboxes = item.findAll('input[type="checkbox"]')
|
||||||
await checkboxes[0].setValue(false)
|
await checkboxes[0].setValue(false)
|
||||||
await checkboxes[1].setValue(true)
|
await checkboxes[1].setValue(true)
|
||||||
|
|
@ -323,7 +407,7 @@ describe('伙伴业务分类多选', () => {
|
||||||
expect(wrapper.find('.el-table__body tbody tr').text()).not.toContain('成品级(经营买卖)')
|
expect(wrapper.find('.el-table__body tbody tr').text()).not.toContain('成品级(经营买卖)')
|
||||||
await findButton(wrapper, '编辑').trigger('click')
|
await findButton(wrapper, '编辑').trigger('click')
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
const reopened = wrapper.findAll('.el-form-item').find(node => node.text().includes('业务分类')).findAll('input[type="checkbox"]')
|
const reopened = wrapper.findAll('.el-form-item').find(node => node.text().includes('合作范围')).findAll('input[type="checkbox"]')
|
||||||
expect(reopened[0].element.checked).toBe(true)
|
expect(reopened[0].element.checked).toBe(true)
|
||||||
expect(reopened[1].element.checked).toBe(false)
|
expect(reopened[1].element.checked).toBe(false)
|
||||||
await reopened[0].setValue(false)
|
await reopened[0].setValue(false)
|
||||||
|
|
@ -331,7 +415,8 @@ describe('伙伴业务分类多选', () => {
|
||||||
await clickSave(wrapper)
|
await clickSave(wrapper)
|
||||||
expect(partnersApi.update).toHaveBeenCalledWith(1, expect.objectContaining({ supplier_categories: ['finished_product'], customer_categories: ['finished_product'] }))
|
expect(partnersApi.update).toHaveBeenCalledWith(1, expect.objectContaining({ supplier_categories: ['finished_product'], customer_categories: ['finished_product'] }))
|
||||||
await openCreateDialog(wrapper, '供应商')
|
await openCreateDialog(wrapper, '供应商')
|
||||||
expect(wrapper.findAll('input[type="checkbox"]').every(input => !input.element.checked)).toBe(true)
|
const ranges = wrapper.findAll('.el-form-item').find(node => node.text().includes('合作范围'))
|
||||||
|
expect(ranges.findAll('input[type="checkbox"]').every(input => !input.element.checked)).toBe(true)
|
||||||
wrapper.unmount()
|
wrapper.unmount()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -341,8 +426,8 @@ describe('伙伴业务分类多选', () => {
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
await wrapper.find('.btn-next').trigger('click')
|
await wrapper.find('.btn-next').trigger('click')
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
const filter = wrapper.findAllComponents(SelectStub).find(select => select.props('placeholder') === '全部业务分类')
|
const filter = wrapper.findAllComponents(SelectStub).find(select => select.props('placeholder') === '全部合作范围')
|
||||||
expect(filter, '列表提供业务分类筛选').toBeDefined()
|
expect(filter, '列表提供合作范围筛选').toBeDefined()
|
||||||
filter.vm.$emit('update:modelValue', 'material')
|
filter.vm.$emit('update:modelValue', 'material')
|
||||||
filter.vm.$emit('change', 'material')
|
filter.vm.$emit('change', 'material')
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<el-button type="primary" @click="openCreate">新增{{ title }}</el-button>
|
<el-button type="primary" @click="openCreate">新增{{ title }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<el-select v-model="categoryFilter" placeholder="全部业务分类" clearable @change="load(1)">
|
<el-select v-model="categoryFilter" placeholder="全部合作范围" clearable @change="load(1)">
|
||||||
<el-option v-for="(label, value) in CATEGORY_LABELS" :key="value" :label="label" :value="value" />
|
<el-option v-for="(label, value) in CATEGORY_LABELS" :key="value" :label="label" :value="value" />
|
||||||
<el-option label="未分类" value="unclassified" />
|
<el-option label="未分类" value="unclassified" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
>
|
>
|
||||||
<el-table-column prop="partner_code" label="伙伴编码" width="140" />
|
<el-table-column prop="partner_code" label="伙伴编码" width="140" />
|
||||||
<el-table-column prop="legal_name" label="企业名称" min-width="180" />
|
<el-table-column prop="legal_name" label="企业名称" min-width="180" />
|
||||||
<el-table-column label="业务分类" min-width="220">
|
<el-table-column label="合作范围" min-width="220">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="row[categoriesField]?.length">
|
<template v-if="row[categoriesField]?.length">
|
||||||
<el-tag v-for="category in row[categoriesField]" :key="category" class="category-tag">{{ CATEGORY_LABELS[category] || category }}</el-tag>
|
<el-tag v-for="category in row[categoriesField]" :key="category" class="category-tag">{{ CATEGORY_LABELS[category] || category }}</el-tag>
|
||||||
|
|
@ -40,7 +40,13 @@
|
||||||
<el-form :model="form" label-width="130px">
|
<el-form :model="form" label-width="130px">
|
||||||
<el-form-item label="伙伴编码" required><el-input v-model="form.partner_code" :disabled="Boolean(editingId)" /></el-form-item>
|
<el-form-item label="伙伴编码" required><el-input v-model="form.partner_code" :disabled="Boolean(editingId)" /></el-form-item>
|
||||||
<el-form-item label="企业名称" required><el-input v-model="form.legal_name" /></el-form-item>
|
<el-form-item label="企业名称" required><el-input v-model="form.legal_name" /></el-form-item>
|
||||||
<el-form-item label="业务分类">
|
<el-form-item label="业务分类" required>
|
||||||
|
<el-checkbox-group v-model="businessRoles">
|
||||||
|
<el-checkbox value="customer">客户</el-checkbox>
|
||||||
|
<el-checkbox value="supplier">供应商</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="合作范围">
|
||||||
<el-checkbox-group v-model="form[categoriesField]">
|
<el-checkbox-group v-model="form[categoriesField]">
|
||||||
<el-checkbox v-for="(label, value) in CATEGORY_LABELS" :key="value" :value="value">{{ label }}</el-checkbox>
|
<el-checkbox v-for="(label, value) in CATEGORY_LABELS" :key="value" :value="value">{{ label }}</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
|
|
@ -75,6 +81,7 @@ const loading = ref(false)
|
||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const editingId = ref(null)
|
const editingId = ref(null)
|
||||||
|
const businessRoles = ref([])
|
||||||
|
|
||||||
// 伙伴新增/编辑弹窗开着时切换公司会丢弃未保存内容,先确认。
|
// 伙伴新增/编辑弹窗开着时切换公司会丢弃未保存内容,先确认。
|
||||||
useOrganizationSwitchGuard(() => dialogVisible.value)
|
useOrganizationSwitchGuard(() => dialogVisible.value)
|
||||||
|
|
@ -111,9 +118,15 @@ async function load(currentPage = pagination.currentPage) {
|
||||||
watch(() => props.role, () => { categoryFilter.value = ''; load(1) })
|
watch(() => props.role, () => { categoryFilter.value = ''; load(1) })
|
||||||
// 用 replaceAllKeys 而不是 Object.assign:后者删不掉上次编辑残留的 id,
|
// 用 replaceAllKeys 而不是 Object.assign:后者删不掉上次编辑残留的 id,
|
||||||
// 新增时会把别人的 id 一起提交上去。
|
// 新增时会把别人的 id 一起提交上去。
|
||||||
function openCreate() { editingId.value = null; replaceAllKeys(form, emptyForm()); dialogVisible.value = true }
|
function openCreate() {
|
||||||
|
editingId.value = null
|
||||||
|
replaceAllKeys(form, emptyForm())
|
||||||
|
businessRoles.value = [props.role]
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
function openEdit(row) {
|
function openEdit(row) {
|
||||||
editingId.value = row.id
|
editingId.value = row.id
|
||||||
|
businessRoles.value = ['customer', 'supplier'].filter(role => row[`is_${role}`])
|
||||||
replaceAllKeys(form, { ...emptyForm(), ...row, status: row[statusField.value] || 'active',
|
replaceAllKeys(form, { ...emptyForm(), ...row, status: row[statusField.value] || 'active',
|
||||||
supplier_categories: [...(row.supplier_categories || [])], customer_categories: [...(row.customer_categories || [])] })
|
supplier_categories: [...(row.supplier_categories || [])], customer_categories: [...(row.customer_categories || [])] })
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
|
|
@ -121,14 +134,15 @@ function openEdit(row) {
|
||||||
function payload() {
|
function payload() {
|
||||||
return {
|
return {
|
||||||
...form,
|
...form,
|
||||||
is_supplier: form.is_supplier || props.role === 'supplier',
|
is_supplier: businessRoles.value.includes('supplier'),
|
||||||
is_customer: form.is_customer || props.role === 'customer',
|
is_customer: businessRoles.value.includes('customer'),
|
||||||
[`${props.role}_status`]: form.status
|
[`${props.role}_status`]: form.status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function save() {
|
async function save() {
|
||||||
if (!form.partner_code.trim()) { ElMessage.warning('请填写伙伴编码'); return }
|
if (!form.partner_code.trim()) { ElMessage.warning('请填写伙伴编码'); return }
|
||||||
if (!form.legal_name.trim()) { ElMessage.warning('请填写企业名称'); return }
|
if (!form.legal_name.trim()) { ElMessage.warning('请填写企业名称'); return }
|
||||||
|
if (!businessRoles.value.length) { ElMessage.warning('请至少选择一项业务分类'); return }
|
||||||
saving.value = true
|
saving.value = true
|
||||||
// 保存后停在第几页由 load 的默认参数决定:留在当前页,不把用户甩回第一页
|
// 保存后停在第几页由 load 的默认参数决定:留在当前页,不把用户甩回第一页
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user