Files
admin-web/src/modules/unified-orders/api/unifiedOrders.test.ts
T
2026-08-17 19:52:04 +08:00

130 lines
7.2 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import {
approvePlatformUnifiedOrder,
batchApprovePlatformUnifiedOrders,
addPlatformUnifiedOrderNote,
getPlatformUnifiedOrder,
listPlatformUnifiedOrders,
listPlatformUnifiedOrderFeeDetails,
} from './unifiedOrders'
vi.mock('@/shared/api/http', () => ({
http: { get: vi.fn(), post: vi.fn(), put: vi.fn() },
unwrapApiResponse: <T>(response: { data: T }) => response.data,
}))
describe('unified orders API contract', () => {
beforeEach(() => {
vi.mocked(http.get).mockReset()
vi.mocked(http.post).mockReset()
vi.mocked(http.put).mockReset()
})
it('uses the C02 platform orders endpoint and contract filters', async () => {
vi.mocked(http.get).mockResolvedValue({ data: { records: [], page: '2', size: '20', total: '0', pages: '0' } })
await expect(listPlatformUnifiedOrders({
keyword: 'CC', orderNo: 'CC-1', mainStatus: 'WAIT_SPLIT', customerId: '30001',
receivingWarehouseId: '11', destinationWarehouseId: '22', inboundCode: 'RK-1', internalOrderStatus: 'ACCEPTED',
expectedArrivalDate: '2026-08-10', feeReviewStatus: 'APPROVED', channelName: '海运', containerNo: 'CONT-1',
cabinetNo: 'CAB-1', sailingDate: '2026-08-12', loaded: true, fullContainer: false,
measurementReviewStatus: 'PENDING', fbaCode: 'FBA-1', createdFrom: '2026-08-01T00:00:00',
createdTo: '2026-08-31T23:59:59', page: 2, size: 20,
})).resolves.toMatchObject({ page: 2, size: 20, total: 0, pages: 0 })
expect(http.get).toHaveBeenCalledWith('/platform/v1/orders', {
params: {
keyword: 'CC', orderNo: 'CC-1', mainStatus: 'WAIT_SPLIT', customerId: '30001',
receivingWarehouseId: '11', destinationWarehouseId: '22', inboundCode: 'RK-1', internalOrderStatus: 'ACCEPTED',
expectedArrivalDate: '2026-08-10', feeReviewStatus: 'APPROVED', channelName: '海运', containerNo: 'CONT-1',
cabinetNo: 'CAB-1', sailingDate: '2026-08-12', loaded: true, fullContainer: false,
measurementReviewStatus: 'PENDING', fbaCode: 'FBA-1', createdFrom: '2026-08-01T00:00:00',
createdTo: '2026-08-31T23:59:59', page: 2, size: 20,
},
})
})
it('omits empty optional filters while preserving false boolean values', async () => {
vi.mocked(http.get).mockResolvedValue({ data: { records: [], page: 1, size: 20, total: 0, pages: 0 } })
await listPlatformUnifiedOrders({ keyword: '', loaded: false, fullContainer: false, page: 1, size: 20 })
expect(http.get).toHaveBeenCalledWith('/platform/v1/orders', {
params: { loaded: false, fullContainer: false, page: 1, size: 20 },
})
})
it('forwards every main-status tab with search and pagination unchanged', async () => {
const statuses = [
'PENDING_REVIEW', 'WAIT_MEASURE', 'WAIT_SPLIT',
'LOADING', 'LOADED', 'DELIVERED',
] as const
vi.mocked(http.get).mockResolvedValue({ data: { records: [], page: 3, size: 20, total: 0, pages: 0 } })
for (const mainStatus of statuses) {
await listPlatformUnifiedOrders({ keyword: 'CC-2026', orderNo: 'FL-77', mainStatus, page: 3, size: 20 })
}
expect(vi.mocked(http.get).mock.calls).toEqual(statuses.map((mainStatus) => [
'/platform/v1/orders',
{ params: { keyword: 'CC-2026', orderNo: 'FL-77', mainStatus, page: 3, size: 20 } },
]))
})
it('normalizes C02 row IDs and keeps inboundId for measurement routing', async () => {
vi.mocked(http.get).mockResolvedValue({ data: {
records: [{ orderId: '90001', tenantId: '208', inboundId: '77', inboundVersion: 3, mainStatus: 'WAIT_MEASURE', locationCodes: 'A0-01, B2-03', actualGrossWeightKg: '12.5', actualVolumeCbm: '0.45', totalPalletCount: '3', totalNetWeightKg: '11.2', chargeableVolumeCbm: '0.5', totalQuantity: '48', skuNos: ['SKU-1', ''], requestedPickupAt: '2026-08-18T09:30:00', customerRemark: '客户备注', latestInternalNote: '最新内部备注', relation: { role: 'PARENT', rootOrderId: 90001, parentOrderId: null, splitSequence: null, childCount: '2' }, measurement: null, preload: null, loading: null, delivery: null, transport: null }],
page: 1, size: 20, total: 1, pages: 1,
} })
await expect(listPlatformUnifiedOrders({ page: 1, size: 20 })).resolves.toMatchObject({
records: [{ orderId: '90001', tenantId: '208', inboundId: '77', inboundVersion: 3, locationCodes: 'A0-01, B2-03', actualGrossWeightKg: 12.5, actualVolumeCbm: 0.45, totalPalletCount: 3, totalNetWeightKg: 11.2, chargeableVolumeCbm: 0.5, totalQuantity: 48, skuNos: ['SKU-1'], requestedPickupAt: '2026-08-18T09:30:00', customerRemark: '客户备注', latestInternalNote: '最新内部备注', relation: { role: 'PARENT', rootOrderId: '90001', childCount: 2 } }],
})
})
it('loads the C02 detail shape and passes tenantId only on the detail boundary', async () => {
vi.mocked(http.get).mockResolvedValue({ data: {
summary: { orderId: '90001', tenantId: '208', mainStatus: 'WAIT_SPLIT' },
order: { order: {}, cargoes: [], parties: [], internalNotes: [], statusHistory: [] },
timeline: [],
} })
await expect(getPlatformUnifiedOrder('208', '90001')).resolves.toMatchObject({
summary: { orderId: '90001' }, order: { internalNotes: [] }, timeline: [],
})
expect(http.get).toHaveBeenCalledWith('/platform/v1/orders/90001', { params: { tenantId: '208' } })
})
it('uses the explicit first-leg approval boundary for pending review', async () => {
vi.mocked(http.post).mockResolvedValue({ data: null })
await approvePlatformUnifiedOrder('208', '90001')
expect(http.post).toHaveBeenCalledWith('/platform/v1/orders/first-leg/90001/approve', undefined, { params: { tenantId: '208' } })
})
it('uses the tenant-scoped batch approval contract and preserves long IDs', async () => {
vi.mocked(http.post).mockResolvedValue({ data: {
total: 2, successCount: 1, failureCount: 1,
successOrderIds: ['2089223263733518337'],
failedOrders: [{ orderId: '2089223263733518338', code: 'A0409', message: '订单状态已变化' }],
} })
await expect(batchApprovePlatformUnifiedOrders('2089176869176389634', [
'2089223263733518337', '2089223263733518338',
])).resolves.toMatchObject({ successCount: 1, failureCount: 1 })
expect(http.post).toHaveBeenCalledWith(
'/platform/v1/orders/first-leg/batch-approve',
{ orderIds: ['2089223263733518337', '2089223263733518338'] },
{ params: { tenantId: '2089176869176389634' } },
)
})
it('writes platform internal notes through the unified order boundary', async () => {
vi.mocked(http.post).mockResolvedValue({ data: '91001' })
await expect(addPlatformUnifiedOrderNote('208', '90001', '已确认船期')).resolves.toBe('91001')
expect(http.post).toHaveBeenCalledWith('/platform/v1/orders/90001/internal-notes', { content: '已确认船期' }, { params: { tenantId: '208' } })
})
it('loads fee detail rows from the inbound fee-detail contract', async () => {
vi.mocked(http.get).mockResolvedValue({ data: [{ id: '1', inboundId: '88', reviewStatus: 'APPROVED', amount: 100 }] })
await expect(listPlatformUnifiedOrderFeeDetails('208', '88')).resolves.toHaveLength(1)
expect(http.get).toHaveBeenCalledWith('/platform/v1/inbounds/88/fee-details', { params: { accountId: '208' } })
})
})