perf: use container finance aggregate
This commit is contained in:
@@ -6,17 +6,13 @@ import { readFileSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { useAuthStore } from '@/core/auth/auth'
|
||||
import { getFinanceSettlement, listFinancePayableSettlements, listFinanceReceivableSettlements } from '@/modules/finance'
|
||||
import { adjustContainerFee, createContainerFee, listApplicableFeeItems, listContainerCostDetails, listContainerFeeSupplierOptions, listContainerFees, uploadContainerFeePaymentVoucher } from '../api/containerFees'
|
||||
import { adjustContainerFee, createContainerFee, getContainerSettlementDetails, listApplicableFeeItems, listContainerFeeSupplierOptions, listContainerFees, uploadContainerFeePaymentVoucher } from '../api/containerFees'
|
||||
import ContainerFeesPanel from './ContainerFeesPanel.vue'
|
||||
|
||||
vi.mock('../api/containerFees', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('../api/containerFees')>()
|
||||
return { ...actual, listContainerFees: vi.fn(), listApplicableFeeItems: vi.fn(), listContainerFeeSupplierOptions: vi.fn(), listContainerCostDetails: vi.fn(), createContainerFee: vi.fn(), adjustContainerFee: vi.fn(), uploadContainerFeePaymentVoucher: vi.fn(), approveContainerFee: vi.fn(), rejectContainerFee: vi.fn(), voidContainerFee: vi.fn() }
|
||||
return { ...actual, listContainerFees: vi.fn(), listApplicableFeeItems: vi.fn(), listContainerFeeSupplierOptions: vi.fn(), getContainerSettlementDetails: vi.fn(), createContainerFee: vi.fn(), adjustContainerFee: vi.fn(), uploadContainerFeePaymentVoucher: vi.fn(), approveContainerFee: vi.fn(), rejectContainerFee: vi.fn(), voidContainerFee: vi.fn() }
|
||||
})
|
||||
vi.mock('@/modules/finance', () => ({
|
||||
getFinanceSettlement: vi.fn(), listFinancePayableSettlements: vi.fn(), listFinanceReceivableSettlements: vi.fn(),
|
||||
}))
|
||||
|
||||
const panel = readFileSync(resolve(process.cwd(), 'src/modules/loading-lists/components/ContainerFeesPanel.vue'), 'utf8')
|
||||
const detail = readFileSync(resolve(process.cwd(), 'src/modules/loading-lists/components/LoadingListDetailDrawer.vue'), 'utf8')
|
||||
@@ -35,11 +31,8 @@ beforeEach(() => {
|
||||
vi.stubGlobal('ResizeObserver', ResizeObserverStub); vi.stubGlobal('localStorage', memoryStorage()); vi.stubGlobal('sessionStorage', memoryStorage())
|
||||
vi.mocked(listContainerFees).mockReset().mockResolvedValue([]); vi.mocked(listApplicableFeeItems).mockReset().mockResolvedValue([])
|
||||
vi.mocked(listContainerFeeSupplierOptions).mockReset().mockResolvedValue([])
|
||||
vi.mocked(listContainerCostDetails).mockReset().mockResolvedValue([]); vi.mocked(createContainerFee).mockReset()
|
||||
vi.mocked(getContainerSettlementDetails).mockReset().mockResolvedValue({ customerId: '11', containerId: '99', settledSourceFeeIds: [], costs: [] }); vi.mocked(createContainerFee).mockReset()
|
||||
vi.mocked(adjustContainerFee).mockReset().mockResolvedValue({} as never)
|
||||
vi.mocked(getFinanceSettlement).mockReset().mockResolvedValue({} as never)
|
||||
vi.mocked(listFinancePayableSettlements).mockReset().mockResolvedValue([])
|
||||
vi.mocked(listFinanceReceivableSettlements).mockReset().mockResolvedValue([])
|
||||
vi.mocked(uploadContainerFeePaymentVoucher).mockReset().mockResolvedValue({ fileId: '9001', fileName: '付款凭证.pdf' })
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
@@ -84,7 +77,7 @@ describe('ContainerFeesPanel contract', () => {
|
||||
})
|
||||
|
||||
it('shows only server allocations and supplier snapshots', () => {
|
||||
expect(panel).toContain('listContainerCostDetails')
|
||||
expect(panel).toContain('getContainerSettlementDetails')
|
||||
expect(panel).toContain('仅展示 Finance 已持久化结果')
|
||||
expect(panel).toContain("cost.supplierName || '服务端未返回'")
|
||||
expect(panel).toContain('尚无与该柜次关联的财务分摊结果')
|
||||
@@ -108,29 +101,25 @@ describe('ContainerFeesPanel contract', () => {
|
||||
resolveFirst([{ id: 'old', loadingPlanId: '9', containerBookingId: '99', containerNo: null, feeItemId: '1', feeItemName: '旧客户费用', direction: 'RECEIVABLE', supplierId: null, supplierName: null, supplierCategory: null, businessDate: '2026-08-12', amount: 10, currency: 'CNY', reviewStatus: 'PENDING', sourceStatus: 'ACTIVE', sourceVersion: 1, remark: null, reviewerName: null, reviewedAt: null, reviewReason: null }])
|
||||
await flushPromises()
|
||||
expect(state.fees).toEqual([])
|
||||
expect(listContainerCostDetails).not.toHaveBeenCalledWith('11', expect.anything())
|
||||
expect(getContainerSettlementDetails).not.toHaveBeenCalledWith('11', expect.anything())
|
||||
})
|
||||
|
||||
it('does not request any Finance data when container fees are empty', async () => {
|
||||
vi.mocked(listContainerFees).mockResolvedValue([])
|
||||
await mountPanel(['firstleg:inbound:fee-detail:view', 'platform:finance:settlement-ar:list', 'platform:finance:settlement-ap:list'])
|
||||
expect(listContainerCostDetails).not.toHaveBeenCalled()
|
||||
expect(listFinanceReceivableSettlements).not.toHaveBeenCalled()
|
||||
expect(listFinancePayableSettlements).not.toHaveBeenCalled()
|
||||
expect(getFinanceSettlement).not.toHaveBeenCalled()
|
||||
await mountPanel(['firstleg:inbound:fee-detail:view'])
|
||||
expect(getContainerSettlementDetails).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('loads Finance data only on an explicit single request when fee rows agree', async () => {
|
||||
vi.mocked(listContainerFees).mockResolvedValue([
|
||||
{ id: '1', loadingPlanId: '9', containerBookingId: '99', containerNo: null, feeItemId: '1', feeItemName: '费用A', direction: 'RECEIVABLE', supplierId: null, supplierName: null, supplierCategory: null, businessDate: '2026-08-12', amount: 10, currency: 'CNY', reviewStatus: 'PENDING', sourceStatus: 'ACTIVE', sourceVersion: 1, remark: null, reviewerName: null, reviewedAt: null, reviewReason: null },
|
||||
])
|
||||
const wrapper = await mountPanel(['firstleg:inbound:fee-detail:view', 'platform:finance:settlement-ar:list'])
|
||||
expect(listContainerCostDetails).not.toHaveBeenCalled()
|
||||
expect(listFinanceReceivableSettlements).not.toHaveBeenCalled()
|
||||
const wrapper = await mountPanel(['firstleg:inbound:fee-detail:view'])
|
||||
expect(getContainerSettlementDetails).not.toHaveBeenCalled()
|
||||
await wrapper.findAll('button').find((button) => button.text() === '加载财务状态')!.trigger('click')
|
||||
await flushPromises()
|
||||
expect(listContainerCostDetails).toHaveBeenCalledWith('11', '99')
|
||||
expect(listFinanceReceivableSettlements).toHaveBeenCalledTimes(1)
|
||||
expect(getContainerSettlementDetails).toHaveBeenCalledWith('11', '99')
|
||||
expect(getContainerSettlementDetails).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('fails closed when fee rows disagree with the summary container', async () => {
|
||||
@@ -141,7 +130,7 @@ describe('ContainerFeesPanel contract', () => {
|
||||
await wrapper.findAll('button').find((button) => button.text() === '加载财务状态')!.trigger('click')
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).toContain('财务状态加载失败')
|
||||
expect(listContainerCostDetails).not.toHaveBeenCalled()
|
||||
expect(getContainerSettlementDetails).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('blocks write entry points without a selected customer or edit permission', async () => {
|
||||
@@ -165,17 +154,15 @@ describe('ContainerFeesPanel contract', () => {
|
||||
vi.mocked(listContainerFees).mockResolvedValue([
|
||||
{ id: '1', loadingPlanId: '9', containerBookingId: '99', containerNo: null, feeItemId: '1', feeItemName: '海运费', direction: 'RECEIVABLE', supplierId: null, supplierName: null, supplierCategory: null, businessDate: '2026-08-12', amount: 300, currency: 'CNY', reviewStatus: 'APPROVED', sourceStatus: 'ACTIVE', sourceVersion: 1, remark: null, reviewerName: null, reviewedAt: null, reviewReason: null },
|
||||
])
|
||||
vi.mocked(listFinanceReceivableSettlements).mockResolvedValue([{ id: 'ar-1', status: 'PAID', paymentStatus: 'PAID' } as never])
|
||||
vi.mocked(getFinanceSettlement).mockResolvedValue({ lines: [{ sourceType: 'CONTAINER_FEE', sourceFeeId: '1' }] } as never)
|
||||
vi.mocked(getContainerSettlementDetails).mockResolvedValue({ customerId: '11', containerId: '99', settledSourceFeeIds: ['1'], costs: [] })
|
||||
const wrapper = await mountPanel([
|
||||
'firstleg:inbound:fee-detail:view', 'firstleg:inbound:fee-detail:edit', 'firstleg:inbound:fee-detail:review',
|
||||
'platform:finance:settlement-ar:list',
|
||||
])
|
||||
await wrapper.findAll('button').find((button) => button.text() === '加载财务状态')!.trigger('click')
|
||||
await flushPromises()
|
||||
expect(wrapper.findAll('button').some((button) => button.text() === '调整')).toBe(false)
|
||||
expect(wrapper.findAll('button').some((button) => button.text() === '作废')).toBe(false)
|
||||
expect(getFinanceSettlement).toHaveBeenCalledWith('ar-1')
|
||||
expect(getContainerSettlementDetails).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('hides adjustment and void actions for directly paid payable fees', async () => {
|
||||
|
||||
Reference in New Issue
Block a user