This commit is contained in:
2026-10-10 16:12:38 +08:00
parent c69115f1b7
commit 081f79a9a1
3 changed files with 57 additions and 16 deletions
@@ -4,7 +4,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import OutboundsView from './OutboundsView.vue'
import { listPlatformTenants } from '@/modules/iam'
const api = vi.hoisted(() => ({ candidates: vi.fn(), create: vi.fn(), warehouses: vi.fn() }))
const api = vi.hoisted(() => ({ candidates: vi.fn(), create: vi.fn(), warehouses: vi.fn(), returnCandidates: vi.fn(), stock: vi.fn(), cartons: vi.fn(), carton: vi.fn() }))
vi.mock('../api/returnInventory', () => ({ listReturnStock: api.stock, listReturnCartons: api.cartons, getReturnCarton: api.carton }))
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) }))
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn().mockResolvedValue({ records: [] }) }))
@@ -13,7 +14,7 @@ vi.mock('../api/outbounds', () => ({
listOutbounds: vi.fn().mockResolvedValue({ records: [], total: 0 }),
listOneClickOutboundCandidates: api.candidates,
createOneClickDropshipOutbound: api.create,
cancelOutbound: vi.fn(), createReturnOutbound: vi.fn(), listReturnOutboundCandidates: vi.fn(),
cancelOutbound: vi.fn(), createReturnOutbound: vi.fn(), listReturnOutboundCandidates: api.returnCandidates,
}))
const fixtures = Array.from({ length: 7 }, (_, index) => ({
@@ -48,6 +49,40 @@ async function selectBothPages() {
}
describe('outbound candidate search and selection', () => {
it('limits single SKU quantities and selectable sources to loose stock of the selected return, excluding pallet and box contents', async () => {
vi.mocked(listPlatformTenants).mockResolvedValue({ records: [{ id: 'customer-a', tenantName: '客户甲', status: 'ACTIVE' }], page: 1, size: 200, total: 1, pages: 1 } as Awaited<ReturnType<typeof listPlatformTenants>>)
const sources = [
{ cartonMark: 'P-A', sourceUnitType: 'PALLET', skuCode: 'SKU-A', quantity: 5 },
{ cartonMark: 'P-B', sourceUnitType: 'PALLET', skuCode: 'SKU-B', quantity: 6 },
{ cartonMark: 'BOX-A', sourceUnitType: 'BOX', skuCode: 'SKU-A', quantity: 3 },
{ cartonMark: 'SP-A', sourceUnitType: 'PARCEL', skuCode: 'SKU-A', quantity: 1 },
{ cartonMark: 'SP-B', sourceUnitType: 'PARCEL', skuCode: 'SKU-B', quantity: 5 },
{ cartonMark: 'SP-OTHER', sourceUnitType: 'PARCEL', skuCode: 'SKU-A', quantity: 20 },
].map(row => ({ ...row, status: 'AVAILABLE', sourceReturnNo: row.cartonMark === 'SP-OTHER' ? 'RT-OTHER' : 'RT-MIXED' }))
api.returnCandidates.mockResolvedValue([])
api.stock.mockResolvedValue({ records: [{ skuCode: 'SKU-A', availableQuantity: 29 }, { skuCode: 'SKU-B', availableQuantity: 11 }] })
api.cartons.mockResolvedValue({ records: sources })
api.carton.mockImplementation(async (mark: string) => { const row = sources.find(row => row.cartonMark === mark)!; return { ...row, items: [{ skuCode: row.skuCode, quantity: row.quantity, availableQuantity: row.quantity }] } })
await openCreate()
const type = wrapper.findComponent({ name: 'ElRadioGroup' })
type.vm.$emit('update:modelValue', 'RETURN_OUTBOUND'); type.vm.$emit('change'); await flushPromises()
const customer = wrapper.findAllComponents(ElSelect).find(row => row.props('placeholder') === '请选择客户')!
customer.vm.$emit('update:modelValue', 'customer-a'); customer.vm.$emit('change'); await flushPromises()
const order = wrapper.findAllComponents(ElSelect).find(row => row.props('placeholder') === '选择已签收入库的退货单')!
order.vm.$emit('update:modelValue', 'RT-MIXED'); order.vm.$emit('change'); await flushPromises()
const mode = wrapper.findAllComponents({ name: 'ElRadioGroup' }).find(row => row.text().includes('单 SKU'))!
mode.vm.$emit('update:modelValue', 'SKU'); mode.vm.$emit('change'); await flushPromises()
const stock = wrapper.findAll('.return-list-card')[0]!
expect(stock.findAll('tbody tr').map(row => row.text().replace(/\s/g, ''))).toEqual(['SKU-A1', 'SKU-B5'])
stock.findAllComponents(ElCheckbox)[0]!.vm.$emit('change', true); await flushPromises()
const sourceTable = wrapper.findAll('.return-list-card')[1]!
expect(sourceTable.findAll('tbody tr')).toHaveLength(1)
expect(sourceTable.text()).toContain('SKU-A × 1')
sourceTable.findAllComponents(ElCheckbox)[0]!.vm.$emit('change', true); await flushPromises()
expect(wrapper.text()).toContain('所选散件来源可用 1 件')
mode.vm.$emit('update:modelValue', 'BOX'); mode.vm.$emit('change'); await flushPromises()
expect(wrapper.findAll('.return-list-card')[1]!.findAll('tbody tr')).toHaveLength(3)
})
beforeEach(() => {
vi.mocked(listPlatformTenants).mockReset().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 })
vi.stubGlobal('ResizeObserver', class { observe() {} unobserve() {} disconnect() {} })