Merge origin/release/test and preserve procurement direction with request unlock
This commit is contained in:
@@ -15,10 +15,19 @@ beforeEach(() => {
|
||||
vi.mocked(http.put).mockResolvedValue({ data: command('EDIT') })
|
||||
vi.mocked(http.delete).mockResolvedValue({ data: draft() })
|
||||
})
|
||||
it('reads and writes original dispatch appointment allocations with lossless versions', async () => {
|
||||
const value = { dispatchNo: 'PC/1', recordVersion: '9007199254740993', items: [], edit: { allowed: true, blockCode: null, blockReason: null } }
|
||||
vi.mocked(http.get).mockResolvedValueOnce({ data: value })
|
||||
expect(await api.getDispatchAppointmentAllocations('PC/1')).toEqual(value)
|
||||
expect(http.get).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/PC%2F1/appointment-allocations')
|
||||
const body = { recordVersion: 0, idempotencyKey: 'allocation-key', dispatchItemIds: ['11'], batchAllocations: [{ planPalletId: '21', batchKey: 'FBA_APPOINTMENT:9', customerId: '101', sourceKey: 'ORDER:1', destinationKey: 'FBA:ACY2', packageCount: 10, recordVersion: 0 }] }
|
||||
await api.saveDispatchAppointmentAllocations('PC/1', body)
|
||||
expect(http.put).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/PC%2F1/appointment-allocations', body)
|
||||
})
|
||||
|
||||
describe('native whole-vehicle dispatch API', () => {
|
||||
it('round-trips this trip maintenance data and its vehicle photo references without altering actual departure', async () => {
|
||||
const maintenance = { ...blankVehicleMaintenance(), plannedDeliveryDate: '2026-11-02', deliveryMethod: '外配', fleetEmail: 'fleet@example.test', appointmentNo: 'APPT-1' }
|
||||
const maintenance = { ...blankVehicleMaintenance(), plannedDeliveryDate: '2026-11-02', deliveryMethod: '外配', fleetEmail: 'fleet@example.test', destinationAppointments: [{ destinationKey: 'FBA:ONT8', appointmentNo: 'APPT-1' }] }
|
||||
const value = detail()
|
||||
value.vehicleInfo.maintenance = maintenance
|
||||
value.vehicleInfo.vehicle!.evidenceFileIds = ['9007199254740993']
|
||||
@@ -26,7 +35,7 @@ describe('native whole-vehicle dispatch API', () => {
|
||||
const saved = await api.getDispatch('PC/1')
|
||||
expect(saved.vehicleInfo.maintenance).toEqual(maintenance)
|
||||
expect(saved.vehicleInfo.vehicle!.evidenceFileIds).toEqual(['9007199254740993'])
|
||||
await api.updateDispatch('PC/1', { recordVersion: saved.recordVersion, idempotencyKey: 'maintenance-key', vehicle: saved.vehicleInfo.vehicle, driver: saved.vehicleInfo.driver, maintenance, plannedDepartureAt: null, estimatedArrivalAt: null, remark: null, publishLooseboardDemand: true })
|
||||
await api.updateDispatch('PC/1', { recordVersion: saved.recordVersion, idempotencyKey: 'maintenance-key', vehicle: saved.vehicleInfo.vehicle, driver: saved.vehicleInfo.driver, maintenance, plannedDepartureAt: null, estimatedArrivalAt: null, remark: null })
|
||||
expect(http.put).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/PC%2F1', expect.objectContaining({ maintenance, vehicle: expect.objectContaining({ evidenceFileIds: ['9007199254740993'] }) }))
|
||||
expect(vi.mocked(http.put).mock.calls[0]![1]).not.toHaveProperty('departedAt')
|
||||
})
|
||||
@@ -111,7 +120,7 @@ describe('native whole-vehicle dispatch API', () => {
|
||||
expect(http.post).not.toHaveBeenCalled(); await invoke(0); expect(vi.mocked(http.post).mock.calls[0]![1]).toEqual(expect.objectContaining({ recordVersion: 0 }))
|
||||
})
|
||||
it('updates vehicle resources and timing with the explicit dispatch version', async () => {
|
||||
const request: UpdateDispatch = { publishLooseboardDemand: true, ...body, vehicle: null, driver: null, plannedDepartureAt: null, estimatedArrivalAt: null, remark: null }
|
||||
const request: UpdateDispatch = { ...body, vehicle: null, driver: null, plannedDepartureAt: null, estimatedArrivalAt: null, remark: null }
|
||||
await api.updateDispatch('PC/1', request); expect(http.put).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/PC%2F1', request)
|
||||
await expect(api.updateDispatch('PC/1', { ...request, recordVersion: undefined as unknown as Version })).rejects.toThrow('版本')
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import type { AppointmentAllocations, AppointmentAllocationCommand } from '../dispatchContracts'
|
||||
import type { MarkDispatchException, DispatchEvidenceKind, DispatchRoute, DispatchRouteCommand } from '../dispatchContracts'
|
||||
import { requireVersion, requireBatchVersions, type AddCargo, type CandidateQuery, type ConvertDraft, type CreateDispatch, type DispatchQuery, type DraftContainer, type DraftSelection, type LoadingComplete, type ReasonCommand, type ReviewCommand, type UpdateDispatch, type VersionCommand, type DispatchBatchAllocation } from '../dispatchContracts'
|
||||
import { normalizeCandidateList, normalizeConvertedDraft, normalizeDispatchCommand, normalizeDispatchDetail, normalizeDispatchDraft, normalizeDispatchItems, normalizeDispatchPage, normalizeEvidenceFile, normalizeLoadingPreview, type CandidateListWire, type CommandResultWire, type ConvertedDraftWire, type DispatchDetailWire, type DispatchDraftWire, type DispatchEvidenceFileWire, type DispatchItemsWire, type DispatchPageWire, type LoadingPreviewWire } from '../dispatchWire'
|
||||
@@ -17,6 +18,19 @@ export async function listDispatches(query: DispatchQuery) {
|
||||
}
|
||||
export const getDispatch = (dispatchNo: string) => get<DispatchDetailWire>(path(dispatchNo)).then(normalizeDispatchDetail)
|
||||
export const getDispatchItems = (no: string) => get<DispatchItemsWire>(`${path(no)}/items`).then(normalizeDispatchItems)
|
||||
export async function getDispatchAppointmentAllocations(no: string) {
|
||||
const value = await get<AppointmentAllocations>(`${path(no)}/appointment-allocations`)
|
||||
requireVersion(value.recordVersion)
|
||||
value.items.forEach(item => { requireBatchVersions(item.allocations); item.sources.forEach(source => source.options.forEach(option => requireVersion(option.recordVersion))) })
|
||||
return value
|
||||
}
|
||||
export const saveDispatchAppointmentAllocations = (no: string, body: AppointmentAllocationCommand) => {
|
||||
versioned(body); requireBatchVersions(body.batchAllocations)
|
||||
return postAppointmentAllocations(no, body)
|
||||
}
|
||||
async function postAppointmentAllocations(no: string, body: AppointmentAllocationCommand) {
|
||||
return normalizeDispatchCommand(unwrapApiResponse(await http.put<ApiEnvelope<CommandResultWire>, ApiEnvelope<CommandResultWire>>(`${path(no)}/appointment-allocations`, body)))
|
||||
}
|
||||
export const getDispatchRoute = (no: string) => get<DispatchRoute>(`${path(no)}/route`)
|
||||
export async function reorderDispatchRoute(no: string, body: DispatchRouteCommand) { return normalizeDispatchCommand(unwrapApiResponse(await http.put<ApiEnvelope<CommandResultWire>, ApiEnvelope<CommandResultWire>>(`${path(no)}/route`, versioned(body)))) }
|
||||
const evidencePath = (no: string, kind: DispatchEvidenceKind, id?: string) => `${path(no)}/evidence/${kind}${id ? `/${encodeURIComponent(id)}` : ''}`
|
||||
|
||||
Reference in New Issue
Block a user