feat: separate container fee workbenches

This commit is contained in:
2026-09-08 22:03:03 +08:00
parent 9570e0fd18
commit 653ce1c511
11 changed files with 325 additions and 48 deletions
@@ -0,0 +1,25 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { overseasHttp } from '@/shared/api/overseasHttp'
import { adjustOverseasContainerFee, createOverseasContainerFee, listOverseasContainerCustomers, listOverseasContainerFees, reviewOverseasContainerFee, submitOverseasContainerFee, voidOverseasContainerFee, type OverseasContainerFeeSaveRequest } from './overseasContainerFees'
const raw = { id: 91, sourceFeeId: 81, sourceVersion: 2, customerId: 11, customerName: '客户A', sourceType: 'OVERSEAS_CONTAINER_FEE', businessType: 'OVERSEAS_CONTAINER', businessId: 99, businessNo: 'CONT-99', containerBookingId: 99, containerNo: 'CONT-99', feeItemCode: 'PORT_FEE', feeItemName: '港口费', direction: 'PAYABLE', amount: 300, currency: 'CNY', reviewStatus: 'DRAFT', sourceStatus: 'ACTIVE', businessDate: '2026-09-08' }
const fee: OverseasContainerFeeSaveRequest = { customerId: '11', customerName: '客户A', sourceType: 'OVERSEAS_CONTAINER_FEE', businessType: 'OVERSEAS_CONTAINER', businessId: '99', businessNo: 'CONT-99', orderId: null, inboundId: null, inboundCode: null, containerId: null, containerBookingId: '99', containerNo: 'CONT-99', warehouseId: null, feeItemCode: 'PORT_FEE', feeItemName: '港口费', direction: 'PAYABLE', supplierId: '71', supplierName: '港口服务商', supplierCategory: 'TRUCKING', settlementMode: 'ON_ACCOUNT', paidAt: null, paymentMethod: null, paymentReferenceNo: null, paymentVoucherFileIds: null, businessDate: '2026-09-08', currency: 'CNY', amount: 300 }
describe('overseas container fees API', () => {
beforeEach(() => vi.restoreAllMocks())
it('loads all fees and customers with two container aggregate requests', async () => {
const get = vi.spyOn(overseasHttp, 'get').mockResolvedValueOnce({ code: '200', data: [raw] }).mockResolvedValueOnce({ code: '200', data: [{ customerId: 11, customerName: '客户A' }] })
await expect(listOverseasContainerFees('99')).resolves.toMatchObject([{ sourceFeeId: '81', containerBookingId: '99', feeItemCode: 'PORT_FEE' }])
await expect(listOverseasContainerCustomers('99')).resolves.toEqual([{ customerId: '11', customerName: '客户A' }])
expect(get).toHaveBeenNthCalledWith(1, '/platform/v1/last-leg/finance-fee-sources', { params: { containerBookingId: '99' } })
expect(get).toHaveBeenNthCalledWith(2, '/platform/v1/last-leg/finance-fee-sources/container-customers', { params: { containerBookingId: '99' } })
})
it('uses the exact create and lifecycle action contracts', async () => {
const post = vi.spyOn(overseasHttp, 'post').mockResolvedValue({ code: '200', data: raw })
await createOverseasContainerFee(fee, 'create-1'); await submitOverseasContainerFee('81', 'submit-1'); await reviewOverseasContainerFee('81', 'APPROVE', null, 'review-1'); await adjustOverseasContainerFee('81', 2, fee, 'adjust-1'); await voidOverseasContainerFee('81', 2, '重复费用', 'void-1')
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources', fee, { headers: { 'Idempotency-Key': 'create-1' } })
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources/81/submit', { idempotencyKey: 'submit-1' })
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources/81/review', { decision: 'APPROVE', reason: null, idempotencyKey: 'review-1' })
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources/81/adjust', { expectedVersion: 2, fee, idempotencyKey: 'adjust-1' })
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources/81/void', { expectedVersion: 2, reason: '重复费用', idempotencyKey: 'void-1' })
})
})