This commit is contained in:
2026-08-17 19:52:04 +08:00
parent d618683467
commit ee4cd35927
42 changed files with 702 additions and 226 deletions
@@ -11,15 +11,15 @@ import { createPlatformExportTask } from '@/modules/downloads'
import { ApiResponseError } from '@/shared/api/http'
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
import { createReconciliationStatement, getFinanceFeeSource, listFinanceFeePool, reviewFinanceFeeSource, updateFinanceFeeSourceSettlementInclusion } from '../api/finance'
import type { FinanceFeeSourceDetail } from '../types'
import { createReconciliationStatement, getFinanceFeeSource, listFinanceFeeSources, reviewFinanceFeeSource, updateFinanceFeeSourceSettlementInclusion } from '../api/finance'
import type { FinanceFeeSourceDetail, FinanceFeeSourceSummary } from '../types'
import FinanceCustomerArapView from './FinanceCustomerArapView.vue'
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn() }))
vi.mock('@/modules/downloads', () => ({ createPlatformExportTask: vi.fn() }))
vi.mock('@/shared/components/exportTaskCreatedDialog', () => ({ showExportTaskCreatedDialog: vi.fn() }))
vi.mock('../api/finance', () => ({
listFinanceFeePool: vi.fn(),
listFinanceFeeSources: vi.fn(),
getFinanceFeeSource: vi.fn(),
reviewFinanceFeeSource: vi.fn(),
updateFinanceFeeSourceSettlementInclusion: vi.fn(),
@@ -42,10 +42,18 @@ function createMemoryStorage(): Storage {
const detail: FinanceFeeSourceDetail = {
poolItemId: '42', feeSourceId: '42', direction: 'RECEIVABLE', sourceType: 'INBOUND_FEE', sourceId: '81', sourceFeeId: '81', sourceVersion: 3,
sourceSystem: 'FIRSTLEG', sourceBusinessId: 'IB-91',
customerId: '10001', customerName: '客户A', supplierId: null, supplierName: '', orderId: null, inboundId: '91', inboundCode: 'IB-91', containerId: null, containerNo: '',
businessDate: '2026-08-11', feeItemName: '运费', quantity: 2, unitPrice: 50, amount: 100, currency: 'CNY', reviewStatus: 'PENDING', settlementIncluded: false,
sourceStatus: 'AVAILABLE', status: 'AVAILABLE', statementGenerated: false, operationVersion: 3, createdAt: '2026-08-11', operationLogs: [],
}
const feeSummary: FinanceFeeSourceSummary = {
poolItemId: '42', feeSourceId: '42', sourceSystem: 'FIRSTLEG', sourceType: 'INBOUND_FEE', sourceBusinessId: 'IB-91',
sourceId: '81', sourceVersion: 3, customerId: '10001', customerName: '客户A', direction: 'RECEIVABLE', supplierId: null,
supplierName: '', orderId: null, inboundId: '91', inboundCode: 'IB-91', containerId: null, containerNo: '', businessDate: '2026-08-11',
feeItemName: '运费', quantity: 2, unitPrice: 50, amount: 100, currency: 'CNY', reviewStatus: 'PENDING', settlementIncluded: false,
sourceStatus: 'AVAILABLE', statementGenerated: false, status: 'AVAILABLE', createdAt: '2026-08-11',
}
async function mountView(permissions: string[], initialPath = '/finance/customer-arap') {
const pinia = createPinia(); setActivePinia(pinia)
@@ -81,7 +89,7 @@ describe('FinanceCustomerArapView G2 operations', () => {
document.body.innerHTML = ''
const customer = { id: '10001', tenantName: '客户A', status: 'ACTIVE' } as PlatformTenantResource
vi.mocked(listPlatformTenants).mockReset().mockResolvedValue({ records: [customer], page: 1, size: 200, total: 1, pages: 1 })
vi.mocked(listFinanceFeePool).mockReset().mockResolvedValue([{ poolItemId: 'RECEIVABLE:42', feeSourceId: '42', customerId: '10001', direction: 'RECEIVABLE', sourceType: 'INBOUND_FEE', sourceId: '81', sourceVersion: 3, orderId: null, inboundId: '91', containerId: null, feeItemName: '运费', amount: 100, currency: 'CNY', status: 'AVAILABLE', createdAt: '2026-08-11' }])
vi.mocked(listFinanceFeeSources).mockReset().mockResolvedValue({ records: [feeSummary], total: 1, pages: 1 })
vi.mocked(getFinanceFeeSource).mockReset().mockResolvedValue(detail)
vi.mocked(reviewFinanceFeeSource).mockReset().mockResolvedValue({ ...detail, reviewStatus: 'APPROVED', operationVersion: 4 })
vi.mocked(updateFinanceFeeSourceSettlementInclusion).mockReset().mockResolvedValue({ ...detail, reviewStatus: 'APPROVED', settlementIncluded: true, operationVersion: 4 })
@@ -106,20 +114,20 @@ describe('FinanceCustomerArapView G2 operations', () => {
it('loads all customers by default and keeps explicit customer filtering', async () => {
const wrapper = await mountView(['platform:finance:customer-arap:list', 'platform:customer:list'])
expect(listFinanceFeePool).toHaveBeenCalledWith(undefined, undefined)
expect(listFinanceFeeSources).toHaveBeenCalledWith(expect.objectContaining({ page: 1, size: 20, customerId: undefined, direction: undefined }))
const vm = wrapper.vm as unknown as { load(model: Record<string, string>): Promise<void> }
await vm.load({ customerId: '10001', direction: 'RECEIVABLE', status: '', keyword: '' })
expect(listFinanceFeePool).toHaveBeenLastCalledWith('10001', 'RECEIVABLE')
expect(listFinanceFeeSources).toHaveBeenLastCalledWith(expect.objectContaining({ customerId: '10001', direction: 'RECEIVABLE' }))
expect(wrapper.text()).not.toContain('全客户查询暂不可用')
})
it('maps each all-customer fee row with its backend customerId', async () => {
const customerB = { id: '10002', tenantName: '客户B', status: 'ACTIVE' } as PlatformTenantResource
vi.mocked(listPlatformTenants).mockResolvedValue({ records: [{ id: '10001', tenantName: '客户A', status: 'ACTIVE' } as PlatformTenantResource, customerB], page: 1, size: 200, total: 2, pages: 1 })
vi.mocked(listFinanceFeePool).mockResolvedValue([
{ poolItemId: 'RECEIVABLE:42', feeSourceId: '42', customerId: '10001', direction: 'RECEIVABLE', sourceType: 'INBOUND_FEE', sourceId: '81', sourceVersion: 3, orderId: null, inboundId: '91', containerId: null, feeItemName: '运费', amount: 100, currency: 'CNY', status: 'AVAILABLE', createdAt: '2026-08-11' },
{ poolItemId: 'PAYABLE:43', feeSourceId: null, customerId: '10002', direction: 'PAYABLE', sourceType: 'MANUAL_COST', sourceId: '43', sourceVersion: 1, orderId: '11', inboundId: null, containerId: null, feeItemName: '拖车费', amount: 200, currency: 'CNY', status: 'POSTED', createdAt: '2026-08-10' },
])
vi.mocked(listFinanceFeeSources).mockResolvedValue({ records: [
feeSummary,
{ ...feeSummary, poolItemId: '43', feeSourceId: '43', sourceBusinessId: 'CONT-43', customerId: '10002', customerName: '客户B', direction: 'PAYABLE', sourceType: 'CONTAINER_FEE', sourceId: '82', orderId: '11', inboundId: null, inboundCode: '', containerId: '31', containerNo: 'CONT-43', supplierId: '71', supplierName: '供应商A', feeItemName: '拖车费', amount: 200 },
], total: 2, pages: 1 })
const wrapper = await mountView(['platform:finance:customer-arap:list'])
const vm = wrapper.vm as unknown as { load(model: Record<string, string>): Promise<void> }
await vm.load({ customerId: '', direction: '', status: '', keyword: '' })
@@ -211,15 +219,18 @@ describe('FinanceCustomerArapView G2 operations', () => {
})
it('hides technical source identifiers and versions from list rows', async () => {
vi.mocked(listFinanceFeePool).mockResolvedValue([
{ poolItemId: 'PAYABLE:358', feeSourceId: '358', customerId: '10001', direction: 'PAYABLE', sourceType: 'CONTAINER_FEE', sourceId: '2088285842638942210', sourceVersion: 1, orderId: null, inboundId: null, containerId: '2088285834627821569', feeItemName: 'ADMIN-API-20260814152244615-整柜成本', amount: 300, currency: 'CNY', status: 'AVAILABLE', createdAt: '2026-08-14T23:25:19.684' },
])
vi.mocked(listFinanceFeeSources).mockResolvedValue({ records: [{
...feeSummary, poolItemId: '358', feeSourceId: '358', sourceType: 'CONTAINER_FEE', sourceBusinessId: 'CONT-20260814', sourceId: '2088285842638942210', sourceVersion: 1,
direction: 'PAYABLE', orderId: null, inboundId: null, inboundCode: '', containerId: '2088285834627821569', containerNo: 'CONT-20260814', supplierId: '71', supplierName: '供应商A',
feeItemName: 'ADMIN-API-20260814152244615-整柜成本', amount: 300, businessDate: '2026-08-14', createdAt: '2026-08-14',
}], total: 1, pages: 1 })
const wrapper = await mountView(['platform:finance:customer-arap:list'])
await (wrapper.vm as unknown as { load(model: Record<string, string>): Promise<void> }).load({ customerId: '', direction: '', status: '', keyword: '' })
const text = wrapper.text()
expect(text).toContain('应付费用 · 整柜成本')
expect(text).toContain('柜次费用 · 关联柜次')
expect(text).toContain('2026/8/14 23:25:19')
expect(text).toContain('整柜成本')
expect(text).toContain('柜次 CONT-20260814')
expect(text).toContain('供应商A')
expect(text).toContain('2026/8/14')
expect(text).not.toContain('PAYABLE:358')
expect(text).not.toContain('2088285842638942210')
expect(text).not.toContain('/v1')