优化
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { getLastMileOrder, listLastMileOrders } from './lastMileOrders'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn() } }))
|
||||
|
||||
describe('last-mile order overseas API', () => {
|
||||
beforeEach(() => vi.mocked(overseasHttp.get).mockReset())
|
||||
|
||||
it('uses the gateway-relative platform list endpoint and explicit 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({ customerId: '190000000000000001', page: 2, size: 20, status: 'PENDING_ASSIGNMENT' })).resolves.toMatchObject({ page: 2 })
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders', {
|
||||
params: { customerId: '190000000000000001', page: 2, size: 20, status: 'PENDING_ASSIGNMENT' },
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves a long order id as a string in the detail path', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: { order: { id: '190000000000000099' }, cargo: [], statusHistory: [] } })
|
||||
await getLastMileOrder('190000000000000099', '190000000000000001')
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/orders/190000000000000099', {
|
||||
params: { customerId: '190000000000000001' },
|
||||
})
|
||||
})
|
||||
|
||||
it('does not call outbound or delivery endpoints', () => {
|
||||
const source = `${listLastMileOrders}${getLastMileOrder}`
|
||||
expect(source).not.toMatch(/outbound|delivery|dispatch/)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,110 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
|
||||
export interface OverseasPageResult<T> {
|
||||
records: T[]
|
||||
page: number
|
||||
size: number
|
||||
total: number
|
||||
pages: number
|
||||
}
|
||||
|
||||
export interface LastMileOrderQuery {
|
||||
customerId: string
|
||||
page: number
|
||||
size: number
|
||||
orderNo?: string
|
||||
inboundCode?: string
|
||||
containerNo?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
export interface LastMileOrderSummaryDto {
|
||||
id: string
|
||||
orderNo: string
|
||||
orderType?: string | null
|
||||
inboundCode?: string | null
|
||||
sourceOrderNo?: string | null
|
||||
customerName?: string | null
|
||||
overseasWarehouseName?: string | null
|
||||
transferWarehouseName?: string | null
|
||||
fbaWarehouseCode?: string | null
|
||||
containerNo?: string | null
|
||||
containerStatus?: string | null
|
||||
abnormal?: boolean | null
|
||||
detained?: boolean | null
|
||||
palletCount?: number | null
|
||||
packageCount?: number | null
|
||||
volumeCbm?: number | null
|
||||
productQuantity?: number | null
|
||||
volumeWeightKg?: number | null
|
||||
estimatedArrivalAt?: string | null
|
||||
actualArrivalAt?: string | null
|
||||
estimatedWarehouseAt?: string | null
|
||||
inboundOrderNo?: string | null
|
||||
outboundOrderNo?: string | null
|
||||
deliveryOrderNo?: string | null
|
||||
relabelOrderNo?: string | null
|
||||
relabelStatus?: string | null
|
||||
palletMergeFlag?: string | null
|
||||
currentStatus?: string | null
|
||||
privateRemark?: string | null
|
||||
customerRemark?: string | null
|
||||
warehouseRemark?: string | null
|
||||
}
|
||||
|
||||
export interface LastMileOrderDto extends LastMileOrderSummaryDto {
|
||||
customerId: string
|
||||
sourceOrderNo?: string | null
|
||||
subOrderStatus?: string | null
|
||||
createdAt?: string | null
|
||||
updatedAt?: string | null
|
||||
}
|
||||
|
||||
export interface LastMileCargoDto {
|
||||
id: string
|
||||
skuCode?: string | null
|
||||
productNameZh?: string | null
|
||||
productNameEn?: string | null
|
||||
packageCount?: number | null
|
||||
productQuantity?: number | null
|
||||
palletCount?: number | null
|
||||
grossWeightKg?: number | null
|
||||
dimensionalWeightKg?: number | null
|
||||
volumeCbm?: number | null
|
||||
destinationWarehouseName?: string | null
|
||||
fbaTrackingNo?: string | null
|
||||
shipmentNo?: string | null
|
||||
}
|
||||
|
||||
export interface LastMileStatusHistoryDto {
|
||||
id: string
|
||||
fromStatus?: string | null
|
||||
toStatus?: string | null
|
||||
eventId?: string | null
|
||||
remark?: string | null
|
||||
createdAt?: string | null
|
||||
}
|
||||
|
||||
export interface LastMileOrderDetailDto {
|
||||
order: LastMileOrderDto
|
||||
cargo: LastMileCargoDto[]
|
||||
statusHistory: LastMileStatusHistoryDto[]
|
||||
}
|
||||
|
||||
export async function listLastMileOrders(query: LastMileOrderQuery) {
|
||||
const { customerId, ...params } = query
|
||||
const response = await overseasHttp.get<ApiEnvelope<OverseasPageResult<LastMileOrderSummaryDto>>, ApiEnvelope<OverseasPageResult<LastMileOrderSummaryDto>>>(
|
||||
'/platform/v1/last-leg/orders',
|
||||
{ params: { customerId, ...params } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function getLastMileOrder(orderId: string, customerId: string) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<LastMileOrderDetailDto>, ApiEnvelope<LastMileOrderDetailDto>>(
|
||||
`/platform/v1/last-leg/orders/${encodeURIComponent(orderId)}`,
|
||||
{ params: { customerId } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { getRelabelOrder, listRelabelOrders } from './relabelOrders'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { get: vi.fn() } }))
|
||||
|
||||
describe('relabel overseas API', () => {
|
||||
beforeEach(() => vi.mocked(overseasHttp.get).mockReset())
|
||||
|
||||
it('uses explicit customer scope for the real page endpoint', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: { records: [], page: 1, size: 20, total: 0, pages: 0 } })
|
||||
await listRelabelOrders({ customerId: '190000000000000001', page: 1, size: 20, skuCode: 'SKU-1' })
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/relabel-applications', { params: { customerId: '190000000000000001', page: 1, size: 20, skuCode: 'SKU-1' } })
|
||||
})
|
||||
|
||||
it('encodes the relabel number and does not call a mutation endpoint', async () => {
|
||||
vi.mocked(overseasHttp.get).mockResolvedValue({ code: '200', message: 'success', data: { application: { id: '1', relabelNo: 'RL/1' }, items: [], history: [] } })
|
||||
await getRelabelOrder('RL/1', '190000000000000001')
|
||||
expect(overseasHttp.get).toHaveBeenCalledWith('/platform/v1/last-leg/relabel-applications/RL%2F1', { params: { customerId: '190000000000000001' } })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,71 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import type { OverseasPageResult } from './lastMileOrders'
|
||||
|
||||
export interface RelabelOrderQuery {
|
||||
customerId: string
|
||||
page: number
|
||||
size: number
|
||||
skuCode?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
export interface RelabelSummaryDto {
|
||||
id: string
|
||||
relabelNo: string
|
||||
lastlegOrderId?: string | null
|
||||
lastlegOrderNo?: string | null
|
||||
customerOrderNo?: string | null
|
||||
overseasWarehouseId?: string | null
|
||||
labelDeadline?: string | null
|
||||
contactName?: string | null
|
||||
contactPhone?: string | null
|
||||
status?: string | null
|
||||
itemCount?: number | null
|
||||
totalPackageCount?: number | null
|
||||
notifiedPackageCount?: number | null
|
||||
skuCodes?: string | null
|
||||
createdAt?: string | null
|
||||
}
|
||||
|
||||
export interface RelabelItemDto {
|
||||
id: string
|
||||
skuCode?: string | null
|
||||
productNameZh?: string | null
|
||||
totalPackageCount?: number | null
|
||||
notifiedPackageCount?: number | null
|
||||
newSkuCode?: string | null
|
||||
labelRequirement?: string | null
|
||||
relabelFileName?: string | null
|
||||
relabelFileUrl?: string | null
|
||||
}
|
||||
|
||||
export interface RelabelHistoryDto {
|
||||
fromStatus?: string | null
|
||||
toStatus?: string | null
|
||||
operatorId?: string | null
|
||||
remark?: string | null
|
||||
createdAt?: string | null
|
||||
}
|
||||
|
||||
export interface RelabelDetailDto {
|
||||
application: RelabelSummaryDto
|
||||
remark?: string | null
|
||||
items: RelabelItemDto[]
|
||||
history: RelabelHistoryDto[]
|
||||
}
|
||||
|
||||
export async function listRelabelOrders(query: RelabelOrderQuery) {
|
||||
const { customerId, ...params } = query
|
||||
const response = await overseasHttp.get<ApiEnvelope<OverseasPageResult<RelabelSummaryDto>>, ApiEnvelope<OverseasPageResult<RelabelSummaryDto>>>(
|
||||
'/platform/v1/last-leg/relabel-applications', { params: { customerId, ...params } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function getRelabelOrder(relabelNo: string, customerId: string) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
|
||||
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}`, { params: { customerId } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
Reference in New Issue
Block a user