This commit is contained in:
2026-08-10 15:36:53 +08:00
parent 5d97c7517a
commit f6556c57b5
54 changed files with 4107 additions and 170 deletions
@@ -1,17 +1,25 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import {
adjustSmartLoadingItem,
assignSmartLoadingItem,
completeLoading,
confirmingPreload,
deleteSmartLoadingItem,
getContainerBooking,
getOutboundDispatch,
getPicking,
getPreload,
listSmartLoadingCandidates,
pushSmartLoadingPreload,
recommendSmartLoading,
smartSplit,
uploadEvidenceFile,
voidEvidence,
} from './api'
vi.mock('@/shared/api/http', () => ({
http: { get: vi.fn(), post: vi.fn() },
http: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), delete: vi.fn() },
unwrapApiResponse: <T>(response: { data: T }) => response.data,
}))
@@ -19,6 +27,8 @@ describe('unified order workflow API contract', () => {
beforeEach(() => {
vi.mocked(http.get).mockReset()
vi.mocked(http.post).mockReset()
vi.mocked(http.patch).mockReset()
vi.mocked(http.delete).mockReset()
})
it('uses the C03 preload endpoints and expected version', async () => {
@@ -75,4 +85,69 @@ describe('unified order workflow API contract', () => {
expect.objectContaining({ params: { tenantId: '2' }, headers: { 'Idempotency-Key': expect.any(String) } }),
)
})
it('normalizes smart-loading long identifiers as strings', async () => {
vi.mocked(http.get)
.mockResolvedValueOnce({ data: { id: '2086085512165634050', warehouseId: '2086085512165634051', capacityCbm: '68', maxWeightKg: '25000', version: 2 } })
.mockResolvedValueOnce({ data: [{
accountId: '2086085512165634052', inboundId: '2086085512165634053', inboundDetailId: '2086085512165634054',
orderId: '2086085512165634055', warehouseId: '2086085512165634051', availablePackageCount: '12',
unitWeightKg: '10.5', unitVolumeCbm: '0.25',
}] })
const container = await getContainerBooking('2086085512165634050')
const candidates = await listSmartLoadingCandidates(container.warehouseId!)
expect(container).toMatchObject({ id: '2086085512165634050', warehouseId: '2086085512165634051', capacityCbm: 68 })
expect(candidates[0]).toMatchObject({
accountId: '2086085512165634052', inboundId: '2086085512165634053',
inboundDetailId: '2086085512165634054', orderId: '2086085512165634055', availablePackageCount: 12,
})
})
it('normalizes preload and outbound aggregate identifiers as strings', async () => {
vi.mocked(http.get)
.mockResolvedValueOnce({ data: {
id: '2086085512165634050', inboundId: '2086085512165634051', tenantId: '2086085512165634052',
status: 'PENDING', version: 1, items: [],
} })
.mockResolvedValueOnce({ data: [{
orderId: '2086085512165634053', inboundId: '2086085512165634051',
containerBookingId: '2086085512165634054', loadingPlanId: '2086085512165634055',
oceanBookingId: '2086085512165634056', truckAppointmentId: '2086085512165634057', gate: null,
}] })
const preload = await getPreload('2086085512165634052', '2086085512165634051')
const dispatch = await getOutboundDispatch('2086085512165634052', '2086085512165634053', '2086085512165634051')
expect(preload).toMatchObject({ id: '2086085512165634050', inboundId: '2086085512165634051', tenantId: '2086085512165634052' })
expect(dispatch).toMatchObject({
orderId: '2086085512165634053', containerBookingId: '2086085512165634054',
loadingPlanId: '2086085512165634055', oceanBookingId: '2086085512165634056', truckAppointmentId: '2086085512165634057',
})
})
it('uses optimistic locks and operation identifiers for smart-loading mutations', async () => {
const plan = { id: '91', bookingId: '81', status: 'EDITING', version: 4, items: [] }
vi.mocked(http.post).mockResolvedValue({ data: plan })
vi.mocked(http.patch).mockResolvedValue({ data: plan })
vi.mocked(http.delete).mockResolvedValue({ data: plan })
await assignSmartLoadingItem('91', { inboundId: '71', inboundDetailId: '72', packageCount: 3, expectedVersion: 4 })
await recommendSmartLoading('91', 4)
await adjustSmartLoadingItem('91', '92', { packageCount: 2, expectedPlanVersion: 4, expectedItemVersion: 1 })
await deleteSmartLoadingItem('91', '92', { expectedPlanVersion: 4, expectedItemVersion: 1 })
await pushSmartLoadingPreload('91', 4)
expect(http.post).toHaveBeenNthCalledWith(1, '/platform/v1/first-leg/smart-loading/plans/91/assignments', {
inboundId: '71', inboundDetailId: '72', packageCount: 3, expectedVersion: 4,
operationId: expect.stringContaining('smart-loading-assign'),
})
expect(http.post).toHaveBeenNthCalledWith(2, '/platform/v1/first-leg/smart-loading/plans/91/recommend', {
expectedVersion: 4, operationId: expect.stringContaining('smart-loading-recommend'),
})
expect(http.patch).toHaveBeenCalledWith('/platform/v1/first-leg/smart-loading/plans/91/items/92', expect.objectContaining({
expectedPlanVersion: 4, expectedItemVersion: 1, operationId: expect.stringContaining('smart-loading-adjust'),
}))
expect(http.delete).toHaveBeenCalledWith('/platform/v1/first-leg/smart-loading/plans/91/items/92', {
data: expect.objectContaining({ expectedPlanVersion: 4, expectedItemVersion: 1, operationId: expect.stringContaining('smart-loading-delete') }),
})
expect(http.post).toHaveBeenNthCalledWith(3, '/platform/v1/first-leg/smart-loading/plans/91/push-preload', { expectedVersion: 4 }, {
headers: { 'Idempotency-Key': expect.stringContaining('smart-loading-push') },
})
})
})