Merge origin/dev into release/test preserving current workflows
This commit is contained in:
@@ -12,8 +12,8 @@ export interface DispatchQuery {
|
||||
}
|
||||
|
||||
export interface DispatchPalletCandidateDto {
|
||||
planId: string
|
||||
planPalletId: string
|
||||
planId?: string | null
|
||||
planPalletId?: string | null
|
||||
warehousePalletId?: string | null
|
||||
orderId: string
|
||||
customerId?: string | null
|
||||
@@ -36,8 +36,9 @@ export interface DispatchPalletCandidateDto {
|
||||
fbaWarehouseCode?: string | null
|
||||
packageCount?: number | null
|
||||
volumeCbm?: number | null
|
||||
sourceStage?: 'PLAN' | 'RECEIVED' | null
|
||||
sourceStage?: 'PLAN' | 'RECEIVED' | 'RELABEL' | null
|
||||
cartonMarks?: string | null
|
||||
relabelCartonMarks?: string | null
|
||||
}
|
||||
|
||||
export interface DispatchCandidateQuery {
|
||||
@@ -57,6 +58,7 @@ export interface PreArrangeDispatchPayload {
|
||||
fbaAppointmentStatus?: string
|
||||
vehicleAppointmentStatus?: string
|
||||
draftToken?: string
|
||||
relabelNo?: string
|
||||
}
|
||||
|
||||
export interface DispatchSummaryDto {
|
||||
@@ -166,6 +168,13 @@ export async function cancelDispatch(dispatchNo: string) {
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function removeDispatchItem(dispatchNo: string, itemId: string) {
|
||||
const response = await overseasHttp.delete<ApiEnvelope<DispatchSummaryDto>, ApiEnvelope<DispatchSummaryDto>>(
|
||||
`/platform/v1/last-leg/dispatches/${encodeURIComponent(dispatchNo)}/items/${encodeURIComponent(itemId)}`,
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function listDispatchCandidates(query: DispatchCandidateQuery) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<DispatchPalletCandidateDto[]>, ApiEnvelope<DispatchPalletCandidateDto[]>>(
|
||||
'/platform/v1/last-leg/dispatches/candidates',
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface LastMileOrderQuery {
|
||||
page: number
|
||||
size: number
|
||||
orderNo?: string
|
||||
relabelNo?: string
|
||||
orderType?: string
|
||||
inboundCode?: string
|
||||
lxCode?: string
|
||||
@@ -77,6 +78,7 @@ export interface LastMileOrderSummaryDto {
|
||||
actualArrivalAt?: string | null
|
||||
estimatedWarehouseAt?: string | null
|
||||
inboundOrderNo?: string | null
|
||||
dispatchStatus?: 'SCHEDULED' | 'UNSCHEDULED' | null
|
||||
/** Legacy read-only association retained for compatibility; absent from current service DTO. */
|
||||
deliveryOrderNo?: string | null
|
||||
outboundOrderNo?: string | null
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { getWarehouseTransfer, listWarehouseTransfers, reviewWarehouseTransfer } from './warehouseTransfers'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn(), post: vi.fn() } }))
|
||||
|
||||
describe('warehouseTransfers API', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
it('always scopes platform list and detail requests to the selected customer', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValueOnce({ code: '200', data: { records: [], page: 1, size: 10, total: 0, pages: 0 } })
|
||||
vi.mocked(overseasHttp.get).mockResolvedValueOnce({ code: '200', data: { transferNo: 'WT-1', items: [], cartons: [], relabelBindings: [] } })
|
||||
await listWarehouseTransfers('20001', { page: 1, size: 10, status: 'PENDING_REVIEW' })
|
||||
await getWarehouseTransfer('20001', 'WT-1')
|
||||
expect(vi.mocked(overseasHttp.get).mock.calls[0]).toEqual(['/platform/v1/last-leg/warehouse-transfers', { params: { page: 1, size: 10, status: 'PENDING_REVIEW', customerId: '20001' } }])
|
||||
expect(vi.mocked(overseasHttp.get).mock.calls[1]).toEqual(['/platform/v1/last-leg/warehouse-transfers/WT-1', { params: { customerId: '20001' } }])
|
||||
})
|
||||
|
||||
it('posts the real review decision with customer scope', async () => {
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', data: { transferNo: 'WT-1', items: [], cartons: [], relabelBindings: [] } })
|
||||
await reviewWarehouseTransfer('20001', 'WT-1', 'APPROVE', '资料无误')
|
||||
expect(overseasHttp.post).toHaveBeenCalledWith(
|
||||
'/platform/v1/last-leg/warehouse-transfers/WT-1/review',
|
||||
{ decision: 'APPROVE', remark: '资料无误' },
|
||||
{ params: { customerId: '20001' } },
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,117 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders'
|
||||
|
||||
export interface WarehouseTransferQuery {
|
||||
page: number
|
||||
size: number
|
||||
transferNo?: string
|
||||
operatingWarehouseId?: string
|
||||
fbaWarehouseCode?: string
|
||||
status?: string
|
||||
needRelabel?: boolean
|
||||
}
|
||||
|
||||
export interface WarehouseTransferSummaryDto {
|
||||
id: string
|
||||
transferNo: string
|
||||
inboundCode?: string | null
|
||||
lastlegOrderId?: string | null
|
||||
lastlegOrderNo?: string | null
|
||||
operatingWarehouseId?: string | null
|
||||
fbaWarehouseCode?: string | null
|
||||
packageCount: number
|
||||
deliveryMethod?: string | null
|
||||
needRelabel: boolean
|
||||
relabelNo?: string | null
|
||||
status: string
|
||||
estimatedArrivalAt?: string | null
|
||||
createdAt?: string | null
|
||||
}
|
||||
|
||||
export interface WarehouseTransferItemDto {
|
||||
id: string
|
||||
skuCode: string
|
||||
productNameZh: string
|
||||
packageCount: number
|
||||
shippingMark?: string | null
|
||||
}
|
||||
|
||||
export interface WarehouseTransferCartonDto {
|
||||
cartonMark?: string | null
|
||||
customerCartonMark?: string | null
|
||||
cartonIndex: number
|
||||
totalCartons: number
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface WarehouseTransferRelabelBindingDto {
|
||||
operationType: string
|
||||
customerCartonMark: string
|
||||
originalSku: string
|
||||
newSku?: string | null
|
||||
quantity: number
|
||||
fbaCartonMark?: string | null
|
||||
destinationWarehouseCode?: string | null
|
||||
remark?: string | null
|
||||
}
|
||||
|
||||
export interface WarehouseTransferPalletDto {
|
||||
id: string
|
||||
sequenceNo: number
|
||||
palletNo?: string | null
|
||||
cartonCount: number
|
||||
grossWeightKg: number
|
||||
volumeCbm: number
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface WarehouseTransferDetailDto extends WarehouseTransferSummaryDto {
|
||||
inboundOrderId?: string | null
|
||||
orderType?: string | null
|
||||
orderStatus?: string | null
|
||||
relabelApplicationId?: string | null
|
||||
relabelStatus?: string | null
|
||||
deliveryAddress?: string | null
|
||||
estimatedShipAt?: string | null
|
||||
fbaShipmentNo?: string | null
|
||||
trackingNo?: string | null
|
||||
fbaBoxNos?: string | null
|
||||
remark?: string | null
|
||||
items: WarehouseTransferItemDto[]
|
||||
cartons: WarehouseTransferCartonDto[]
|
||||
pallets: WarehouseTransferPalletDto[]
|
||||
relabelBindings: WarehouseTransferRelabelBindingDto[]
|
||||
customerConfirmedAt?: string | null
|
||||
actualShipAt?: string | null
|
||||
}
|
||||
|
||||
export async function listWarehouseTransfers(customerId: string, query: WarehouseTransferQuery) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<OverseasPagePayload<WarehouseTransferSummaryDto>>, ApiEnvelope<OverseasPagePayload<WarehouseTransferSummaryDto>>>(
|
||||
'/platform/v1/last-leg/warehouse-transfers',
|
||||
{ params: { ...query, customerId } },
|
||||
)
|
||||
return normalizeOverseasPage(unwrapApiResponse(response))
|
||||
}
|
||||
|
||||
export async function getWarehouseTransfer(customerId: string, transferNo: string) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<WarehouseTransferDetailDto>, ApiEnvelope<WarehouseTransferDetailDto>>(
|
||||
`/platform/v1/last-leg/warehouse-transfers/${encodeURIComponent(transferNo)}`,
|
||||
{ params: { customerId } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function reviewWarehouseTransfer(
|
||||
customerId: string,
|
||||
transferNo: string,
|
||||
decision: 'APPROVE' | 'REJECT',
|
||||
remark?: string,
|
||||
) {
|
||||
const response = await overseasHttp.post<ApiEnvelope<WarehouseTransferDetailDto>, ApiEnvelope<WarehouseTransferDetailDto>>(
|
||||
`/platform/v1/last-leg/warehouse-transfers/${encodeURIComponent(transferNo)}/review`,
|
||||
{ decision, remark },
|
||||
{ params: { customerId } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
Reference in New Issue
Block a user