76 lines
6.3 KiB
TypeScript
76 lines
6.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
const client = vi.hoisted(() => ({ get: vi.fn(), post: vi.fn() }))
|
|
vi.mock('@/shared/api/http', async original => ({ ...await original<typeof import('@/shared/api/http')>(), http: client }))
|
|
import { actOnOverseasFee, createOverseasFee, getOverseasFee, listBusinessFeeOptions, listBusinessOverseasFees, listOverseasFeeItems, listOverseasFees, listOverseasFeeRetries, type SaveOverseasFee } from './overseasFees'
|
|
const base = '/platform/v1/last-leg/finance-fee-sources'
|
|
const envelope = <T>(data: T) => ({ code: '200', message: 'success', data })
|
|
const row = { id: '9007199254740993', sourceFeeId: '9007199254740993', customerId: '1', businessId: '9007199254740995', direction: 'RECEIVABLE', allowedActions: ['APPROVE'] }
|
|
describe('海外费用真实接口', () => {
|
|
beforeEach(() => vi.clearAllMocks())
|
|
it('分页不退回旧非分页接口,长整型身份保持字符串', async () => {
|
|
client.get.mockResolvedValue(envelope({ records: [row], total: '1', pages: '1', page: 1, size: 20 }))
|
|
const result = await listOverseasFees({ page: 1, size: 20, feeItemCode: 'F1' })
|
|
expect(client.get).toHaveBeenCalledWith(`${base}/page`, { params: { page: 1, size: 20, feeItemCode: 'F1' } })
|
|
expect(result.records[0]?.businessId).toBe('9007199254740995')
|
|
expect(result.total).toBe(1)
|
|
client.get.mockResolvedValue(envelope(row))
|
|
expect((await getOverseasFee(row.sourceFeeId)).sourceFeeId).toBe(row.sourceFeeId)
|
|
})
|
|
it('创建传正式业务订单及幂等键,审核和锁款重试各用正式命令', async () => {
|
|
client.post.mockResolvedValue(envelope(row))
|
|
const payload = { businessNo: 'WT1', businessType: 'WAREHOUSE_TRANSFER', amount: 10 } as SaveOverseasFee
|
|
await createOverseasFee(payload, 'create-1')
|
|
expect(client.post).toHaveBeenCalledWith(base, payload, { headers: { 'Idempotency-Key': 'create-1' } })
|
|
await actOnOverseasFee(row.sourceFeeId, 'REJECT', { decision: 'REJECT', reason: '重复费用', idempotencyKey: 'review-1' })
|
|
expect(client.post).toHaveBeenLastCalledWith(`${base}/${row.sourceFeeId}/review`, { decision: 'REJECT', reason: '重复费用', idempotencyKey: 'review-1' })
|
|
await actOnOverseasFee(row.sourceFeeId, 'RETRY_FREEZE', { idempotencyKey: 'retry-1' })
|
|
expect(client.post).toHaveBeenLastCalledWith(`${base}/${row.sourceFeeId}/retry-funding`, { idempotencyKey: 'retry-1' })
|
|
await actOnOverseasFee(row.sourceFeeId, 'RETRY_PUBLISH', { expectedVersion: 1, eventId: 'original-event', idempotencyKey: 'retry-2' })
|
|
expect(client.post).toHaveBeenLastCalledWith(`${base}/${row.sourceFeeId}/retry-delivery`, { expectedVersion: 1, eventId: 'original-event', idempotencyKey: 'retry-2' })
|
|
})
|
|
it('目录和业务订单选项读取真实数据,不套用人民币默认价', async () => {
|
|
client.get.mockResolvedValueOnce(envelope([{ code: 'F1', name: '操作费', defaultPrice: 10 }]))
|
|
.mockResolvedValueOnce(envelope([{ businessId: '9007199254740995', customerId: '1', orderId: null, warehouseId: '2' }]))
|
|
expect(await listOverseasFeeItems()).toEqual([{ feeCode: 'F1', feeTypeName: '操作费', defaultPrice: 10 }])
|
|
expect(client.get).toHaveBeenLastCalledWith(`${base}/fee-items`, { params: { direction: 'RECEIVABLE' } })
|
|
expect((await listBusinessFeeOptions({ businessType: 'WAREHOUSE_TRANSFER', keyword: 'WT' }))[0]?.businessId).toBe('9007199254740995')
|
|
expect(client.get).toHaveBeenLastCalledWith(`${base}/business-options`, { params: { businessType: 'WAREHOUSE_TRANSFER', keyword: 'WT' } })
|
|
})
|
|
it('应付项目明确传递方向', async () => {
|
|
client.get.mockResolvedValue(envelope([]))
|
|
await listOverseasFeeItems('PAYABLE')
|
|
expect(client.get).toHaveBeenCalledWith(`${base}/fee-items`, { params: { direction: 'PAYABLE' } })
|
|
})
|
|
it('按稳定费用身份查询完整重试记录', async () => {
|
|
client.get.mockResolvedValue(envelope([]))
|
|
expect(await listOverseasFeeRetries(row.sourceFeeId)).toEqual([])
|
|
expect(client.get).toHaveBeenCalledWith(`${base}/${row.sourceFeeId}/retries`)
|
|
})
|
|
it('单据费用先严格匹配客户、类型及ID,合并去重后分页', async () => {
|
|
const business = { businessId: row.businessId, businessType: 'LASTLEG_ORDER', businessNo: 'TB1', customerId: '1', customerName: '测试客户', orderId: null, warehouseId: null }
|
|
const related = { ...business, businessId: 'return-1', businessType: 'RETURN_ORDER' }
|
|
const first = { ...row, businessType: business.businessType, createdAt: '2026-10-22T10:00:00' }
|
|
const second = { ...first, sourceFeeId: '9007199254740994', businessId: related.businessId, businessType: related.businessType }
|
|
client.get.mockResolvedValue(envelope([first, second, first,
|
|
{ ...first, sourceFeeId: 'wrong-id', businessId: 'another' },
|
|
{ ...first, sourceFeeId: 'wrong-type', businessType: 'RETURN_ORDER' },
|
|
{ ...first, sourceFeeId: 'wrong-customer', customerId: '2' },
|
|
]))
|
|
const result = await listBusinessOverseasFees([business, related], { page: 2, size: 1 })
|
|
expect(client.get).toHaveBeenCalledWith(base, { params: { customerId: '1', businessType: 'LASTLEG_ORDER', businessNo: 'TB1' } })
|
|
expect(result).toMatchObject({ total: 2, pages: 2, page: 2, size: 1 })
|
|
expect(result.records.map(fee => fee.sourceFeeId)).toEqual([first.sourceFeeId])
|
|
})
|
|
it.each(['RECEIVABLE', 'PAYABLE'] as const)('混合返回时先按 %s 分开,再统计分页,不遗漏第二页数据', async direction => {
|
|
const business = { businessId: row.businessId, businessType: 'LASTLEG_ORDER', businessNo: 'TB1', customerId: '1', customerName: '客户', orderId: null, warehouseId: null }
|
|
const first = { ...row, businessType: 'LASTLEG_ORDER', direction, createdAt: '2026-10-23T10:00:00' }
|
|
const second = { ...first, sourceFeeId: 'second', createdAt: '2026-10-23T11:00:00' }
|
|
const opposite = { ...first, sourceFeeId: 'opposite', direction: direction === 'RECEIVABLE' ? 'PAYABLE' : 'RECEIVABLE' }
|
|
client.get.mockResolvedValue(envelope([first, opposite, second, { ...first, sourceFeeId: 'unknown', direction: null }]))
|
|
const result = await listBusinessOverseasFees(business, { page: 2, size: 1 }, direction)
|
|
expect(result).toMatchObject({ total: 2, pages: 2 })
|
|
expect(result.records.map(fee => fee.sourceFeeId)).toEqual([first.sourceFeeId])
|
|
expect(result.records.every(fee => fee.direction === direction)).toBe(true)
|
|
})
|
|
})
|