优化
This commit is contained in:
@@ -9,24 +9,24 @@ import { useAuthStore } from '@/core/auth/auth'
|
||||
import { ApiResponseError } from '@/shared/api/http'
|
||||
import {
|
||||
adjustInboundFeeDetail, createInboundFeeDetail, deleteInboundFeeDetail,
|
||||
listInboundFeeDetails, listInboundFeeItemOptions, listInboundFeePartnerOptions,
|
||||
listInboundFeeDetails, listInboundFeeItemOptions, listInboundFeeSupplierOptions,
|
||||
reviewInboundFeeDetail, updateInboundFeeDetail, voidInboundFeeDetail,
|
||||
} from '@/modules/unified-orders/api/inboundFeeDetails'
|
||||
import InboundFeeDetailManager from './InboundFeeDetailManager.vue'
|
||||
import type { InboundFeeDetail } from '@/modules/unified-orders/api/inboundFeeDetails'
|
||||
|
||||
vi.mock('@/modules/unified-orders/api/inboundFeeDetails', () => ({
|
||||
listInboundFeeDetails: vi.fn(), listInboundFeeItemOptions: vi.fn(), listInboundFeePartnerOptions: vi.fn(),
|
||||
listInboundFeeDetails: vi.fn(), listInboundFeeItemOptions: vi.fn(), listInboundFeeSupplierOptions: vi.fn(),
|
||||
createInboundFeeDetail: vi.fn(), updateInboundFeeDetail: vi.fn(), deleteInboundFeeDetail: vi.fn(),
|
||||
reviewInboundFeeDetail: vi.fn(), adjustInboundFeeDetail: vi.fn(), voidInboundFeeDetail: vi.fn(),
|
||||
}))
|
||||
|
||||
const pending: InboundFeeDetail = {
|
||||
id: '11', inboundId: '88', feeItemId: '31', sourceType: 'MANUAL', sourceFeeVersion: 1,
|
||||
inboundCode: 'RK-88', direction: 'RECEIVABLE', partnerId: null, partnerName: null,
|
||||
inboundCode: 'RK-88', direction: 'RECEIVABLE', supplierId: null, supplierName: null, supplierCategory: null,
|
||||
businessDate: '2026-08-12', customerName: '测试客户', feeTypeNameSnapshot: '操作费',
|
||||
unitPrice: 10, currency: 'CNY', amount: 100, remark: 'marker', reviewStatus: 'PENDING',
|
||||
reviewReason: null, reviewerName: null, reviewedAt: null, publicationStatus: 'DRAFT', settlementIncluded: true,
|
||||
reviewReason: null, reviewerName: null, reviewedAt: null, publicationStatus: 'DRAFT',
|
||||
}
|
||||
const approved: InboundFeeDetail = { ...pending, id: '12', sourceFeeVersion: 3, reviewStatus: 'APPROVED', publicationStatus: 'PUBLISHED' }
|
||||
const source = readFileSync(join(process.cwd(), 'src/modules/unified-orders/components/InboundFeeDetailManager.vue'), 'utf8')
|
||||
@@ -44,8 +44,8 @@ describe('InboundFeeDetailManager', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks(); document.body.innerHTML = ''
|
||||
vi.mocked(listInboundFeeDetails).mockResolvedValue([pending, approved])
|
||||
vi.mocked(listInboundFeeItemOptions).mockResolvedValue([{ id: '31', feeTypeName: '操作费', warehouseReceivable: true, warehousePayable: true }])
|
||||
vi.mocked(listInboundFeePartnerOptions).mockResolvedValue([{ id: '41', partnerName: '测试往来单位' }])
|
||||
vi.mocked(listInboundFeeItemOptions).mockResolvedValue([{ id: '31', feeTypeName: '操作费', feeCode: 'OPERATION', supplierCategory: 'TRUCKING', warehouseReceivable: true, warehousePayable: true }])
|
||||
vi.mocked(listInboundFeeSupplierOptions).mockResolvedValue([{ id: '41', supplierName: '测试供应商', category: 'TRUCKING' }])
|
||||
vi.mocked(createInboundFeeDetail).mockResolvedValue(pending)
|
||||
vi.mocked(updateInboundFeeDetail).mockResolvedValue(pending)
|
||||
vi.mocked(adjustInboundFeeDetail).mockResolvedValue({ ...approved, reviewStatus: 'PENDING' })
|
||||
@@ -144,14 +144,14 @@ describe('InboundFeeDetailManager', () => {
|
||||
expect(source).toContain('@keyframes fee-refresh-spin')
|
||||
})
|
||||
|
||||
it('loads RECEIVABLE fee items without requesting counterparties', async () => {
|
||||
it('loads RECEIVABLE fee items without requesting suppliers', async () => {
|
||||
const wrapper = mountManager(['firstleg:inbound:fee-detail:view', 'firstleg:inbound:fee-detail:edit', 'firstleg:fee-item:view'])
|
||||
await flushPromises()
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('新增费用'))?.trigger('click')
|
||||
await flushPromises()
|
||||
expect(listInboundFeeItemOptions).toHaveBeenCalledTimes(1)
|
||||
expect(listInboundFeePartnerOptions).not.toHaveBeenCalled()
|
||||
expect(document.body.textContent).toContain('缺少往来单位查看权限')
|
||||
expect(listInboundFeeSupplierOptions).not.toHaveBeenCalled()
|
||||
expect(document.body.textContent).toContain('缺少供应商查看权限')
|
||||
expect(document.body.textContent).toContain('应收费用不受影响')
|
||||
})
|
||||
|
||||
@@ -162,25 +162,41 @@ describe('InboundFeeDetailManager', () => {
|
||||
expect(listInboundFeeItemOptions).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps fee items usable when the independent counterparty request fails', async () => {
|
||||
vi.mocked(listInboundFeeDetails).mockResolvedValue([{ ...pending, direction: 'PAYABLE', partnerId: '41', partnerName: '测试往来单位' }])
|
||||
vi.mocked(listInboundFeePartnerOptions).mockRejectedValue(new ApiResponseError('往来单位不可用', 'A0403', 403, null, 'request-partner', 'trace-partner'))
|
||||
it('keeps fee items usable but blocks payable save when the supplier request fails', async () => {
|
||||
vi.mocked(listInboundFeeDetails).mockResolvedValue([{ ...pending, direction: 'PAYABLE', supplierId: '41', supplierName: '测试供应商', supplierCategory: 'TRUCKING' }])
|
||||
vi.mocked(listInboundFeeSupplierOptions).mockRejectedValue(new ApiResponseError('供应商不可用', 'A0403', 403, null, 'request-supplier', 'trace-supplier'))
|
||||
const wrapper = mountManager([
|
||||
'firstleg:inbound:fee-detail:view', 'firstleg:inbound:fee-detail:edit',
|
||||
'firstleg:fee-item:view', 'platform:counterparty:list',
|
||||
'firstleg:fee-item:view', 'platform:supplier:list',
|
||||
])
|
||||
await flushPromises()
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('编辑'))?.trigger('click')
|
||||
await flushPromises()
|
||||
expect(listInboundFeeItemOptions).toHaveBeenCalledTimes(1)
|
||||
expect(listInboundFeePartnerOptions).toHaveBeenCalledTimes(1)
|
||||
expect(listInboundFeeSupplierOptions).toHaveBeenCalledWith('TRUCKING')
|
||||
expect(document.body.textContent).toContain('当前账号无权访问该数据')
|
||||
expect(document.body.textContent).toContain('A0403')
|
||||
expect(document.body.textContent).toContain('request-partner')
|
||||
expect(document.body.textContent).toContain('trace-partner')
|
||||
expect(document.body.textContent).toContain('request-supplier')
|
||||
expect(document.body.textContent).toContain('trace-supplier')
|
||||
expect(document.querySelector('.fee-form .el-select')?.classList.contains('is-disabled')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails closed when a payable fee item has no supplier category', async () => {
|
||||
vi.mocked(listInboundFeeItemOptions).mockResolvedValue([{ id: '31', feeTypeName: '未映射费用', feeCode: 'UNMAPPED', supplierCategory: null, warehouseReceivable: false, warehousePayable: true }])
|
||||
const wrapper = mountManager([
|
||||
'firstleg:inbound:fee-detail:view', 'firstleg:inbound:fee-detail:edit',
|
||||
'firstleg:fee-item:view', 'platform:supplier:list',
|
||||
])
|
||||
await flushPromises()
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('新增费用'))?.trigger('click')
|
||||
await flushPromises()
|
||||
const state = (wrapper.vm.$ as unknown as { setupState: { save(): Promise<void>; form: { direction: string; feeItemId: string; supplierId: string | null; amount: number } } }).setupState
|
||||
state.form.direction = 'PAYABLE'; state.form.feeItemId = '31'; state.form.supplierId = '41'; state.form.amount = 100; await flushPromises()
|
||||
await state.save(); await flushPromises()
|
||||
expect(createInboundFeeDetail).not.toHaveBeenCalled()
|
||||
expect(document.body.textContent).toContain('该应付费用项目未配置供应商类别,已阻断保存')
|
||||
})
|
||||
|
||||
it('refreshes fee rows and the order detail after every successful write', () => {
|
||||
expect(source).toContain("async function finishAction(message: string) {\n await load(); emit('changed')")
|
||||
expect(source).toMatch(/createInboundFeeDetail[\s\S]*updateInboundFeeDetail[\s\S]*adjustInboundFeeDetail[\s\S]*await finishAction\(/)
|
||||
|
||||
Reference in New Issue
Block a user