fix(dispatch): submit and preserve independent loading groups

This commit is contained in:
2026-10-05 03:30:06 +08:00
parent 058b0778a2
commit 28eb43893a
4 changed files with 267 additions and 13 deletions
@@ -1,10 +1,27 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import { cancelDispatch, createDispatchDraftContainer, deleteDispatchDraftContainer, getDispatch, getDispatchBolPdf, getDispatchExternalFreight, getDispatchFeeCoverage, listDispatchCandidates, listDispatchDrafts, listDispatches, lockDispatchDraftPallet, preArrangeDispatch, releaseDispatchDraft, transferDispatchToDelivery, unlockDispatchDraftPallet, updateDispatch } from './dispatches'
import { cancelDispatch, createDispatchDraftContainer, deleteDispatchDraftContainer, getDispatch, getDispatchBolPdf, getDispatchExternalFreight, getDispatchFeeCoverage, listDispatchCandidates, listDispatchDrafts, listDispatches, lockDispatchDraftPallet, preArrangeDispatch, preArrangeDraftDispatch, releaseDispatchDraft, transferDispatchToDelivery, unlockDispatchDraftPallet, updateDispatch } from './dispatches'
vi.mock('@/shared/api/http', async (importOriginal) => ({ ...(await importOriginal<typeof import('@/shared/api/http')>()), http: { get: vi.fn(), post: vi.fn(), put: vi.fn(), delete: vi.fn() } }))
describe('dispatch overseas API', () => {
it('submits all explicit draft groups once and preserves container and source identities', async () => {
const payload = { draftToken: 'original-draft', groups: [
{ draftContainerId: '190000000000000099', planPalletIds: ['11', '13'], returnReceiptIds: [] },
{ draftContainerId: '190000000000000100', planPalletIds: ['12'], returnReceiptIds: ['22'] },
] }
const result = payload.groups.map((group, index) => ({ draftContainerId: group.draftContainerId, dispatch: { id: String(index), dispatchNo: `DS-${index}` } }))
vi.mocked(http.post).mockResolvedValue({ code: '200', data: result })
expect(await preArrangeDraftDispatch(payload)).toEqual(result)
expect(http.post).toHaveBeenCalledExactlyOnceWith('/platform/v1/last-leg/dispatches/drafts/pre-arrange', payload)
})
it('propagates a batch rejection without falling back to a flat or repeated command', async () => {
vi.mocked(http.post).mockResolvedValue({ code: 'A0409', message: '草稿来源已变化', data: null })
await expect(preArrangeDraftDispatch({ draftToken: 'original-draft', groups: [
{ draftContainerId: 'container', planPalletIds: ['11'], returnReceiptIds: [] },
] })).rejects.toThrow('草稿来源已变化')
expect(http.post).toHaveBeenCalledTimes(1)
})
it('locks and submits actual return receipts without pretending they are plan pallets', async () => {
vi.mocked(http.post).mockResolvedValue({ code: '200', data: null })
await lockDispatchDraftPallet('RETURN:190000000000000099', 'draft-return', 'container-1')
@@ -71,6 +71,20 @@ export interface PreArrangeDispatchPayload {
relabelNo?: string
}
export interface PreArrangeDispatchDraftGroup {
draftContainerId: string
planPalletIds: string[]
returnReceiptIds: string[]
}
export interface PreArrangeDispatchDraftPayload {
draftToken: string
groups: PreArrangeDispatchDraftGroup[]
}
export interface PreArrangeDispatchDraftResult {
draftContainerId: string
dispatch: DispatchSummaryDto
}
export interface DispatchSummaryDto {
id: string
dispatchNo: string
@@ -202,6 +216,13 @@ export async function preArrangeDispatch(payload: PreArrangeDispatchPayload) {
return unwrapApiResponse(response)
}
export async function preArrangeDraftDispatch(payload: PreArrangeDispatchDraftPayload) {
const response = await http.post<ApiEnvelope<PreArrangeDispatchDraftResult[]>, ApiEnvelope<PreArrangeDispatchDraftResult[]>>(
'/platform/v1/last-leg/dispatches/drafts/pre-arrange', payload,
)
return unwrapApiResponse(response)
}
function draftSource(selection: string) {
return selection.startsWith('RETURN:')
? { sourceType: 'RETURN_RECEIPT', returnReceiptId: selection.slice(7) }