优化
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { listDispatchCandidates, listDispatches, preArrangeDispatch } from './dispatches'
|
||||
import { listDispatchCandidates, listDispatches, lockDispatchDraftPallet, preArrangeDispatch, releaseDispatchDraft, unlockDispatchDraftPallet } from './dispatches'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn(), post: vi.fn() } }))
|
||||
|
||||
@@ -31,9 +31,31 @@ describe('dispatch overseas API', () => {
|
||||
it('loads candidates and creates a pre-arrange dispatch in an explicit customer scope', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: [] })
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', message: 'success', data: { id: '1', dispatchNo: 'PC-1' } })
|
||||
await listDispatchCandidates({ fbaWarehouseCode: 'ONT8', sourceStage: 'PLAN' })
|
||||
await listDispatchCandidates({ planIds: '101,102', fbaWarehouseCode: 'ONT8', sourceStage: 'PLAN' })
|
||||
await preArrangeDispatch({ planPalletIds: ['190000000000000099'], route: 'LAX -> ONT8' })
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/candidates', { params: { fbaWarehouseCode: 'ONT8', sourceStage: 'PLAN' } })
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/candidates', { params: { planIds: '101,102', fbaWarehouseCode: 'ONT8', sourceStage: 'PLAN' } })
|
||||
expect(overseasHttp.post).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/pre-arrange', { planPalletIds: ['190000000000000099'], route: 'LAX -> ONT8' })
|
||||
})
|
||||
|
||||
it('loads platform candidates without selected inbound plans', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: [] })
|
||||
|
||||
await listDispatchCandidates({ sourceStage: 'RECEIVED' })
|
||||
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/dispatches/candidates', {
|
||||
params: { sourceStage: 'RECEIVED' },
|
||||
})
|
||||
})
|
||||
|
||||
it('locks, unlocks, and releases intelligent dispatch drafts through dedicated endpoints', async () => {
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', message: 'success', data: null })
|
||||
|
||||
await lockDispatchDraftPallet('99', 'draft-1')
|
||||
await unlockDispatchDraftPallet('99', 'draft-1')
|
||||
await releaseDispatchDraft('draft-1')
|
||||
|
||||
expect(overseasHttp.post).toHaveBeenNthCalledWith(1, '/platform/v1/last-leg/dispatches/draft-locks/lock', { planPalletId: '99', draftToken: 'draft-1' })
|
||||
expect(overseasHttp.post).toHaveBeenNthCalledWith(2, '/platform/v1/last-leg/dispatches/draft-locks/unlock', { planPalletId: '99', draftToken: 'draft-1' })
|
||||
expect(overseasHttp.post).toHaveBeenNthCalledWith(3, '/platform/v1/last-leg/dispatches/draft-locks/release', { draftToken: 'draft-1' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -16,6 +16,14 @@ export interface DispatchPalletCandidateDto {
|
||||
planPalletId: string
|
||||
warehousePalletId?: string | null
|
||||
orderId: string
|
||||
customerId?: string | null
|
||||
customerName?: string | null
|
||||
planNo?: string | null
|
||||
orderType?: string | null
|
||||
volumeWeightKg?: number | null
|
||||
containerNo?: string | null
|
||||
appointmentAt?: string | null
|
||||
expectedLoadingAt?: string | null
|
||||
overseasWarehouseId?: string | null
|
||||
overseasWarehouseName?: string | null
|
||||
orderNo?: string | null
|
||||
@@ -29,9 +37,11 @@ export interface DispatchPalletCandidateDto {
|
||||
packageCount?: number | null
|
||||
volumeCbm?: number | null
|
||||
sourceStage?: 'PLAN' | 'RECEIVED' | null
|
||||
cartonMarks?: string | null
|
||||
}
|
||||
|
||||
export interface DispatchCandidateQuery {
|
||||
planIds?: string
|
||||
orderNo?: string
|
||||
fbaWarehouseCode?: string
|
||||
sourceStage?: 'PLAN' | 'RECEIVED'
|
||||
@@ -43,6 +53,7 @@ export interface PreArrangeDispatchPayload {
|
||||
fbaAppointmentNo?: string
|
||||
fbaAppointmentStatus?: string
|
||||
vehicleAppointmentStatus?: string
|
||||
draftToken?: string
|
||||
}
|
||||
|
||||
export interface DispatchSummaryDto {
|
||||
@@ -95,3 +106,24 @@ export async function preArrangeDispatch(payload: PreArrangeDispatchPayload) {
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function lockDispatchDraftPallet(planPalletId: string, draftToken: string) {
|
||||
const response = await overseasHttp.post<ApiEnvelope<null>, ApiEnvelope<null>>(
|
||||
'/platform/v1/last-leg/dispatches/draft-locks/lock', { planPalletId, draftToken },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function unlockDispatchDraftPallet(planPalletId: string, draftToken: string) {
|
||||
const response = await overseasHttp.post<ApiEnvelope<null>, ApiEnvelope<null>>(
|
||||
'/platform/v1/last-leg/dispatches/draft-locks/unlock', { planPalletId, draftToken },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function releaseDispatchDraft(draftToken: string) {
|
||||
const response = await overseasHttp.post<ApiEnvelope<null>, ApiEnvelope<null>>(
|
||||
'/platform/v1/last-leg/dispatches/draft-locks/release', { draftToken },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { getLastMileOrder, listLastMileOrders, transferLastMileOrders } from './lastMileOrders'
|
||||
import { convertLastMileOrderToInboundPlan, getLastMileOrder, listLastMileOrders, transferLastMileOrders } from './lastMileOrders'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn(), put: vi.fn() } }))
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn(), put: vi.fn(), post: vi.fn() } }))
|
||||
|
||||
describe('last-mile order overseas API', () => {
|
||||
beforeEach(() => vi.mocked(overseasHttp.get).mockReset())
|
||||
|
||||
it('loads all platform orders without a customer scope', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: { records: [], page: 2, size: 20, total: 0, pages: 0 } })
|
||||
await expect(listLastMileOrders({ page: 2, size: 20, status: 'PENDING_ASSIGNMENT' })).resolves.toMatchObject({ page: 2 })
|
||||
await expect(listLastMileOrders({ page: 2, size: 20, orderType: 'FIRST_LEG', currentStatus: 'PENDING_ASSIGNMENT', warehouse: 'LAX' })).resolves.toMatchObject({ page: 2 })
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders', {
|
||||
params: { page: 2, size: 20, status: 'PENDING_ASSIGNMENT' },
|
||||
params: { page: 2, size: 20, orderType: 'FIRST_LEG', currentStatus: 'PENDING_ASSIGNMENT', warehouse: 'LAX' },
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,6 +26,19 @@ describe('last-mile order overseas API', () => {
|
||||
expect(source).not.toMatch(/outbound|delivery|dispatch/)
|
||||
})
|
||||
|
||||
it('passes all supported list filters and pagination without customerId', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: { records: [], page: 2, size: 50, total: 0, pages: 0 } })
|
||||
await listLastMileOrders({
|
||||
page: 2, size: 50, orderNo: 'LM-1', inboundCode: 'IN-1', sourceOrderNo: 'SRC-1',
|
||||
containerNo: 'CONT-1', status: 'PENDING_DELIVERY', transferWarehouseCode: 'ONT8',
|
||||
abnormal: true, detained: false, createdFrom: '2026-08-01T00:00:00', createdTo: '2026-08-31T23:59:59',
|
||||
})
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders', {
|
||||
params: expect.objectContaining({ page: 2, size: 50, sourceOrderNo: 'SRC-1', transferWarehouseCode: 'ONT8', abnormal: true, detained: false }),
|
||||
})
|
||||
expect(JSON.stringify(vi.mocked(overseasHttp.get).mock.calls[0]?.[1])).not.toContain('customerId')
|
||||
})
|
||||
|
||||
it('uses the real destination transfer endpoint and edit contract', async () => {
|
||||
vi.mocked(overseasHttp.put).mockResolvedValue({ code: '200', message: 'success', data: 1 })
|
||||
await transferLastMileOrders({
|
||||
@@ -33,4 +46,11 @@ describe('last-mile order overseas API', () => {
|
||||
})
|
||||
expect(overseasHttp.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/destination', expect.objectContaining({ orderIds: ['190000000000000099'] }))
|
||||
})
|
||||
|
||||
it('uses the inbound-plan conversion endpoint without customerId', async () => {
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', message: 'success', data: {} })
|
||||
await convertLastMileOrderToInboundPlan({ orderId: '190000000000000099' })
|
||||
expect(overseasHttp.post).toHaveBeenCalledWith('/platform/v1/last-leg/inbound-plans/convert', { orderId: '190000000000000099' })
|
||||
expect(JSON.stringify(vi.mocked(overseasHttp.post).mock.calls[0]?.[1])).not.toContain('customerId')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,9 +13,12 @@ export interface LastMileOrderQuery {
|
||||
page: number
|
||||
size: number
|
||||
orderNo?: string
|
||||
orderType?: string
|
||||
inboundCode?: string
|
||||
containerNo?: string
|
||||
currentStatus?: string
|
||||
status?: string
|
||||
warehouse?: string
|
||||
sourceOrderNo?: string
|
||||
transferWarehouseCode?: string
|
||||
abnormal?: boolean
|
||||
@@ -103,6 +106,10 @@ export interface TransferDestinationPayload {
|
||||
remark?: string
|
||||
}
|
||||
|
||||
export interface ConvertInboundPlanPayload {
|
||||
orderId: string
|
||||
}
|
||||
|
||||
export interface LastMileOrderDetailDto {
|
||||
order: LastMileOrderDto
|
||||
cargo: LastMileCargoDto[]
|
||||
@@ -130,3 +137,10 @@ export async function transferLastMileOrders(payload: TransferDestinationPayload
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function convertLastMileOrderToInboundPlan(payload: ConvertInboundPlanPayload) {
|
||||
const response = await overseasHttp.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(
|
||||
'/platform/v1/last-leg/inbound-plans/convert', payload,
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ describe('overseas pallet API', () => {
|
||||
await updatePallet('200', '9', payload)
|
||||
await deletePallet('200', '9')
|
||||
|
||||
expect(overseasHttp.get).toHaveBeenNthCalledWith(1, '/platform/v1/warehouse-admin', { params: { page: 1, size: 200 } })
|
||||
expect(overseasHttp.get).toHaveBeenNthCalledWith(2, '/platform/v1/warehouse-admin/200/pallets', { params: { page: 1, size: 20, keyword: 'PLT' } })
|
||||
expect(overseasHttp.get).toHaveBeenNthCalledWith(3, '/platform/v1/warehouse-admin/200/pallets/9', {})
|
||||
expect(overseasHttp.post).toHaveBeenCalledWith('/platform/v1/warehouse-admin/200/pallets', payload)
|
||||
|
||||
@@ -41,7 +41,7 @@ export interface SavePalletPayload {
|
||||
export async function listCustomerWarehouses() {
|
||||
const response = await overseasHttp.get<ApiEnvelope<OverseasPageResult<CustomerWarehouseDto>>, ApiEnvelope<OverseasPageResult<CustomerWarehouseDto>>>(
|
||||
'/platform/v1/warehouse-admin',
|
||||
{ params: { page: 1, size: 200, status: 'ACTIVE' } },
|
||||
{ params: { page: 1, size: 200 } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user