合并海外仓入库预约与真实接口改动

This commit is contained in:
2026-08-20 18:27:30 +08:00
61 changed files with 1296 additions and 922 deletions
@@ -0,0 +1,18 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { overseasHttp } from '@/shared/api/overseasHttp'
import { getInboundPlan, listInboundPlans } from './inboundPlans'
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn() } }))
describe('inbound plan overseas API', () => {
beforeEach(() => vi.mocked(overseasHttp.get).mockReset())
it('pages plans with explicit customer scope', async () => {
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'ok', data: { records: [], page: 1, size: 20, total: 0, pages: 0 } })
await listInboundPlans({ customerId: '190000000000000001', page: 1, size: 20, inboundCode: 'IN-1' })
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/inbound-plans', { params: { customerId: '190000000000000001', page: 1, size: 20, inboundCode: 'IN-1' } })
})
it('gets detail by encoded plan number', async () => {
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'ok', data: { id: '1', planNo: 'IP/1', customerId: '2', sourceOrderId: '190000000000000099', lineCount: 0, palletCount: 0, totalVolumeCbm: 0, lines: [], pallets: [], allocations: [] } })
await getInboundPlan('IP/1', '2')
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/inbound-plans/IP%2F1', { params: { customerId: '2' } })
})
})
@@ -0,0 +1,66 @@
import { overseasHttp } from '@/shared/api/overseasHttp'
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
import type { OverseasPageResult } from './lastMileOrders'
export interface InboundPlanQuery {
customerId: string
page: number
size: number
planNo?: string
inboundCode?: string
status?: string
overseasWarehouseId?: string
destinationWarehouseCode?: string
fbaWarehouseCode?: string
appointmentStatus?: string
createdFrom?: string
createdTo?: string
}
export interface InboundPlanSummaryDto {
id: string
planNo: string
sourceOrderId: string
customerId: string
customerName?: string | null
orderType?: string | null
inboundCode?: string | null
containerNo?: string | null
overseasWarehouseId?: string | null
overseasWarehouseName?: string | null
destinationWarehouseId?: string | null
destinationWarehouseCode?: string | null
destinationWarehouseName?: string | null
fbaWarehouseCode?: string | null
packageCount?: number | null
totalVolumeCbm?: number | null
palletCount?: number | null
status?: string | null
appointmentStatus?: string | null
createdAt?: string | null
updatedAt?: string | null
}
export interface InboundPlanDetailDto {
id: string
planNo: string
customerId: string
sourceOrderId: string
containerNo?: string | null
status?: string | null
lineCount: number
palletCount: number
totalVolumeCbm: number
lines: Array<{ id: string; orderId: string; inboundCode?: string | null; fbaWarehouseCode?: string | null; destinationWarehouseId?: string | null; destinationWarehouseCode?: string | null; destinationWarehouseName?: string | null; volumeCbm?: number | null; requiredPackageCount: number; plannedPalletCount: number }>
pallets: Array<{ id: string; palletNo?: string | null; destinationWarehouseId?: string | null; destinationWarehouseCode?: string | null; destinationWarehouseName?: string | null; capacityCbm?: number | null; allocatedVolumeCbm?: number | null; sequenceNo: number; warehousePalletId?: string | null; warehouseLocationId?: string | null; warehouseResourceLockId?: string | null; assignmentStatus?: string | null; lockedAt?: string | null; actualVolumeCbm?: number | null; actualPackageCount: number }>
allocations: Array<{ lineId: string; palletId: string; allocatedVolumeCbm?: number | null; plannedPackageCount: number; countedPackageCount: number; pickedPackageCount: number; actualVolumeCbm?: number | null; status?: string | null; version: number }>
}
export async function listInboundPlans(query: InboundPlanQuery) {
const { customerId, ...params } = query
return unwrapApiResponse(await overseasHttp.get<ApiEnvelope<OverseasPageResult<InboundPlanSummaryDto>>, ApiEnvelope<OverseasPageResult<InboundPlanSummaryDto>>>('/platform/v1/last-leg/inbound-plans', { params: { customerId, ...params } }))
}
export async function getInboundPlan(planNo: string, customerId: string) {
return unwrapApiResponse(await overseasHttp.get<ApiEnvelope<InboundPlanDetailDto>, ApiEnvelope<InboundPlanDetailDto>>(`/platform/v1/last-leg/inbound-plans/${encodeURIComponent(planNo)}`, { params: { customerId } }))
}
@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { overseasHttp } from '@/shared/api/overseasHttp'
import { getInventorySummary, listInventoryBalances } from './inventory'
import { getInventorySummary, listInventoryBalances, listInventoryLedger, listInventoryPositions } from './inventory'
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn() } }))
@@ -17,4 +17,14 @@ describe('overseas inventory API', () => {
expect(overseasHttp.get).toHaveBeenNthCalledWith(1, '/platform/v1/last-leg/inventory/balances', { params: query })
expect(overseasHttp.get).toHaveBeenNthCalledWith(2, '/platform/v1/last-leg/inventory/summary', { params: { customerId: '100', skuCode: 'SKU-1', warehouseLocationCode: 'A-01' } })
})
it('uses the read-only position and ledger endpoints with explicit customer scope', async () => {
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', data: [] })
await listInventoryPositions('190000000000000099', '100')
await listInventoryLedger({ customerId: '100', page: 1, size: 20, skuCode: 'SKU-1' })
expect(overseasHttp.get).toHaveBeenNthCalledWith(1, '/platform/v1/last-leg/inventory/balances/190000000000000099/positions', { params: { customerId: '100' } })
expect(overseasHttp.get).toHaveBeenNthCalledWith(2, '/platform/v1/last-leg/inventory/ledger', { params: { customerId: '100', page: 1, size: 20, skuCode: 'SKU-1' } })
})
})
@@ -43,12 +43,66 @@ export interface InventoryDashboardDto {
procurementPackages: number
}
export interface InventoryPositionDto {
id: string
balanceId: string
customerId: string
overseasWarehouseId?: string | null
destinationWarehouseCode?: string | null
inboundOrderId?: string | null
inboundOrderNo?: string | null
inboundCode?: string | null
palletId?: string | null
palletNo?: string | null
batchNo?: string | null
warehouseLocationId?: string | null
warehouseLocationCode?: string | null
totalPackages: number
availablePackages: number
holdPackages: number
allocatedPackages: number
pickedPackages: number
receivingPackages: number
status?: string | null
updatedAt?: string | null
}
export interface InventoryLedgerDto {
id: string
customerId: string
overseasWarehouseId?: string | null
destinationWarehouseCode?: string | null
inboundOrderId?: string | null
inboundOrderNo?: string | null
inboundCode?: string | null
palletNo?: string | null
batchNo?: string | null
warehouseLocationCode?: string | null
skuCode?: string | null
businessType?: string | null
businessOrderNo?: string | null
outboundOrderNo?: string | null
statusFrom?: string | null
statusTo?: string | null
beforePackages: number
deltaPackages: number
afterPackages: number
operatorId?: string | null
remark?: string | null
occurredAt?: string | null
}
export interface InventoryBalanceQuery {
customerId: string
page: number
size: number
customerName?: string
overseasWarehouseId?: string
overseasWarehouseCode?: string
destinationWarehouseCode?: string
inboundOrderNo?: string
inboundCode?: string
businessOrderNo?: string
skuCode?: string
productName?: string
batchNo?: string
@@ -72,3 +126,42 @@ export async function getInventorySummary(query: InventoryBalanceQuery) {
)
return unwrapApiResponse(response)
}
export async function listInventoryPositions(
balanceId: string,
customerId: string,
query: { palletNo?: string; batchNo?: string; inventoryStatus?: string } = {},
) {
const response = await overseasHttp.get<ApiEnvelope<InventoryPositionDto[]>, ApiEnvelope<InventoryPositionDto[]>>(
`/platform/v1/last-leg/inventory/balances/${encodeURIComponent(balanceId)}/positions`,
{ params: { customerId, ...query } },
)
return unwrapApiResponse(response)
}
export interface InventoryLedgerQuery {
customerId: string
page: number
size: number
overseasWarehouseId?: string
destinationWarehouseCode?: string
businessType?: string
businessOrderNo?: string
inboundOrderNo?: string
inboundCode?: string
outboundOrderNo?: string
palletNo?: string
batchNo?: string
skuCode?: string
warehouseLocationCode?: string
occurredFrom?: string
occurredTo?: string
}
export async function listInventoryLedger(query: InventoryLedgerQuery) {
const response = await overseasHttp.get<ApiEnvelope<OverseasPageResult<InventoryLedgerDto>>, ApiEnvelope<OverseasPageResult<InventoryLedgerDto>>>(
'/platform/v1/last-leg/inventory/ledger',
{ params: { ...query } },
)
return unwrapApiResponse(response)
}