Files
admin-web/src/modules/overseas-warehouse/api/relabelOrders.ts
T

273 lines
10 KiB
TypeScript
Raw Normal View History

2026-09-29 17:56:00 +08:00
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
2026-08-26 20:39:55 +08:00
import { listSharedReceivingOverseasWarehouseOptions } from '@/modules/iam'
import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders'
2026-08-20 09:10:36 +08:00
export interface RelabelOrderQuery {
page: number
size: number
2026-08-28 14:33:57 +08:00
relabelNo?: string
2026-08-20 09:10:36 +08:00
skuCode?: string
status?: string
}
2026-08-21 11:20:09 +08:00
export interface CreateRelabelItemPayload {
skuCode: string
productNameZh: string
totalPackageCount: number
notifiedPackageCount: number
shipmentNo: string
newSkuCode: string
labelRequirement?: string
productImageFileId?: string
productImageFileName?: string
productImageUrl?: string
trackingCode?: string
relabelFileId?: string
relabelFileName?: string
relabelFileUrl?: string
}
export interface CreateRelabelPayload {
customerOrderNo: string
2026-09-23 11:25:23 +08:00
operationWarehouseId?: string
/** @deprecated compatibility alias for older platform fixtures */
overseasWarehouseId?: string
2026-08-21 11:20:09 +08:00
labelDeadline: string
contactName: string
contactPhone: string
chargeAmount: number
2026-08-21 11:20:09 +08:00
remark?: string
idempotencyKey: string
items: CreateRelabelItemPayload[]
}
export interface RelabelWarehouseOptionDto {
id: string
customerId: string
warehouseCode: string
warehouseName: string
warehouseType: string
status: string
}
2026-08-20 09:10:36 +08:00
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
2026-10-13 13:46:56 +08:00
productNameZh?: string | null
labelRequirement?: string | null
2026-09-09 13:35:43 +08:00
totalFileId?: string | null
totalFileName?: string | null
totalFileUrl?: string | null
chargeAmount?: number | string | null
chargeCurrency?: string | null
walletStatus?: string | null
walletErrorMessage?: string | null
2026-09-10 15:33:54 +08:00
deliveryMethod?: string | null
printShippingLabel?: boolean | null
shippingLabelFileId?: string | null
shippingLabelFileName?: string | null
fulfillmentStatus?: string | null
outboundOrderNo?: string | null
customerConfirmedAt?: string | null
2026-09-23 11:25:23 +08:00
reviewChannel?: 'TAIL_ORDER' | 'RELABEL_ORDER' | null
reviewRemark?: string | null
2026-08-20 09:10:36 +08:00
createdAt?: string | null
}
export interface RelabelItemDto {
id: string
2026-10-13 13:46:56 +08:00
operationType?: 'CARTON_LABEL' | 'SKU_LABEL' | 'CARTON_AND_SKU'
skuItems?: Array<{ skuCode: string; newSkuCode: string; quantity: number; remark?: string }>
2026-08-20 09:10:36 +08:00
skuCode?: string | null
productNameZh?: string | null
totalPackageCount?: number | null
notifiedPackageCount?: number | null
newSkuCode?: string | null
labelRequirement?: string | null
2026-09-09 13:35:43 +08:00
relabelFileId?: string | null
2026-08-20 09:10:36 +08:00
relabelFileName?: string | null
relabelFileUrl?: string | null
2026-09-06 18:11:35 +08:00
shipmentNo?: string | null
trackingCode?: string | null
2026-10-08 15:34:19 +08:00
remark?: string
2026-09-06 18:11:35 +08:00
cartonMark?: string | null
fbaCartonMark?: string | null
destinationWarehouseId?: string | null
destinationFbaWarehouseCode?: string | null
2026-08-20 09:10:36 +08:00
}
export interface RelabelHistoryDto {
fromStatus?: string | null
toStatus?: string | null
operatorId?: string | null
2026-10-08 15:34:19 +08:00
remark?: string
2026-08-20 09:10:36 +08:00
createdAt?: string | null
}
export interface RelabelDetailDto {
application: RelabelSummaryDto
remark?: string | null
items: RelabelItemDto[]
history: RelabelHistoryDto[]
2026-09-10 15:33:54 +08:00
completionEvidence?: { taskId: string; photoFileIds: string[]; completionRemark?: string | null; reviewerName?: string | null; reviewRemark?: string | null; completedAt?: string | null } | null
2026-08-20 09:10:36 +08:00
}
2026-09-29 20:52:21 +08:00
export interface ReturnPackingPlanBoxItem {
skuCode: string
quantity: number
}
export interface ReturnPackingPlanBox {
boxNo?: number
items: ReturnPackingPlanBoxItem[]
length?: number
width?: number
height?: number
weight?: number
}
export interface ReturnPackingPlanPayload {
returnNos: string[]
2026-10-09 18:03:34 +08:00
mode: 'BOX' | 'SKU'
2026-09-29 20:52:21 +08:00
boxes: ReturnPackingPlanBox[]
remark?: string
idempotencyKey: string
2026-10-08 15:34:19 +08:00
sourceCartonMarks?: string[]
2026-10-12 13:43:21 +08:00
sourceDeductions?: Array<{ cartonMark: string; skuCode: string; quantity: number }>
2026-09-29 20:52:21 +08:00
}
2026-10-08 15:34:19 +08:00
export interface ReturnPackingPlanDto extends Omit<ReturnPackingPlanPayload, 'remark'> {
2026-09-29 20:52:21 +08:00
planNo: string
2026-10-08 15:34:19 +08:00
customerId?: string
overseasWarehouseId?: string
2026-09-29 20:52:21 +08:00
status: string
2026-10-08 15:34:19 +08:00
boxes: ReturnPackingPlanBox[]
remark?: string | null
createdAt?: string | null
2026-09-29 20:52:21 +08:00
pushedAt?: string | null
2026-10-08 15:34:19 +08:00
completedAt?: string | null
resultCartons?: import('./returnInventory').ReturnCartonDetail[]
2026-10-14 11:43:32 +08:00
sources?: Array<{ cartonMark: string; sourceReturnNo?: string; participation: 'FULL' | 'PARTIAL' | 'UNKNOWN'; items: ReturnPackingPlanBoxItem[]; originalItems: Array<{ skuCode: string; productNameZh?: string; quantity: number }> }>
completionCartons?: import('./returnInventory').ReturnCartonLabel[]
transfers?: import('./returnInventory').ReturnCartonMergeHistory[]
completedBy?: string
2026-09-29 20:52:21 +08:00
}
export async function createReturnPackingPlan(payload: ReturnPackingPlanPayload) {
2026-09-29 21:01:37 +08:00
const response = await http.post<ApiEnvelope<ReturnPackingPlanDto>, ApiEnvelope<ReturnPackingPlanDto>>(
2026-09-29 20:52:21 +08:00
'/platform/v1/last-leg/return-packing-plans', payload,
)
2026-09-29 21:01:37 +08:00
return unwrapApiResponse(response) as ReturnPackingPlanDto
2026-09-29 20:52:21 +08:00
}
2026-10-08 15:34:19 +08:00
export interface ReturnPackingPlanQuery { page: number; size: number; status?: string; planNo?: string; customerId?: string; overseasWarehouseId?: string; skuCode?: string }
export async function listReturnPackingPlans(query: ReturnPackingPlanQuery) {
const response = await http.get<ApiEnvelope<OverseasPagePayload<ReturnPackingPlanDto>>, ApiEnvelope<OverseasPagePayload<ReturnPackingPlanDto>>>('/platform/v1/last-leg/return-packing-plans', { params: query })
return normalizeOverseasPage(unwrapApiResponse(response))
}
export async function reviewReturnPackingPlan(planNo: string) {
const response = await http.post<ApiEnvelope<ReturnPackingPlanDto>, ApiEnvelope<ReturnPackingPlanDto>>(`/platform/v1/last-leg/return-packing-plans/${encodeURIComponent(planNo)}/review`)
return unwrapApiResponse(response) as ReturnPackingPlanDto
}
export async function cancelReturnPackingPlan(planNo: string) {
const response = await http.post<ApiEnvelope<ReturnPackingPlanDto>, ApiEnvelope<ReturnPackingPlanDto>>(`/platform/v1/last-leg/return-packing-plans/${encodeURIComponent(planNo)}/cancel`)
return unwrapApiResponse(response) as ReturnPackingPlanDto
}
2026-08-20 09:10:36 +08:00
export async function listRelabelOrders(query: RelabelOrderQuery) {
2026-09-29 17:56:00 +08:00
const response = await http.get<ApiEnvelope<OverseasPagePayload<RelabelSummaryDto>>, ApiEnvelope<OverseasPagePayload<RelabelSummaryDto>>>(
2026-08-21 11:20:09 +08:00
'/platform/v1/last-leg/relabel-applications', { params: query },
2026-08-20 09:10:36 +08:00
)
return normalizeOverseasPage(unwrapApiResponse(response))
2026-08-20 09:10:36 +08:00
}
2026-08-21 11:20:09 +08:00
export async function getRelabelOrder(relabelNo: string) {
2026-09-29 17:56:00 +08:00
const response = await http.get<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
2026-08-21 11:20:09 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}`,
)
return unwrapApiResponse(response)
}
2026-08-26 20:39:55 +08:00
export async function listRelabelWarehouseOptions() {
const records: RelabelWarehouseOptionDto[] = (await listSharedReceivingOverseasWarehouseOptions()).map((warehouse) => ({
id: warehouse.id,
customerId: '0',
warehouseCode: warehouse.warehouseCode,
warehouseName: warehouse.warehouseName,
warehouseType: 'OVERSEAS',
status: 'ACTIVE',
}))
return { records, page: 1, size: 200, total: records.length, pages: records.length ? 1 : 0 }
}
export async function createRelabelOrder(customerId: string, payload: CreateRelabelPayload) {
2026-09-29 17:56:00 +08:00
const response = await http.post<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
'/platform/v1/last-leg/relabel-applications', payload, { params: { customerId } },
2026-08-21 11:20:09 +08:00
)
return unwrapApiResponse(response)
}
export async function changeRelabelOrderStatus(relabelNo: string, status: string, remark?: string) {
2026-09-29 17:56:00 +08:00
const response = await http.put<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
2026-08-21 11:20:09 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/status`,
{ status, remark },
2026-08-20 09:10:36 +08:00
)
return unwrapApiResponse(response)
}
2026-09-09 13:35:43 +08:00
2026-09-15 15:20:28 +08:00
export async function getRelabelReviewTask(relabelNo: string) {
2026-09-29 17:56:00 +08:00
const response = await http.get<ApiEnvelope<{ version: number; taskStatus: string }>, ApiEnvelope<{ version: number; taskStatus: string }>>(`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/review-task`)
2026-09-15 15:20:28 +08:00
return unwrapApiResponse(response)
}
export async function returnRelabelForRework(relabelNo: string, expectedVersion: number, remark: string, idempotencyKey: string) {
2026-09-29 17:56:00 +08:00
const response = await http.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/rework`, { decision: 'REWORK', expectedVersion, remark, idempotencyKey })
2026-09-15 15:20:28 +08:00
return unwrapApiResponse(response)
}
2026-09-17 13:36:31 +08:00
export async function confirmRelabelCompletion(relabelNo: string, remark?: string) {
2026-09-29 17:56:00 +08:00
const response = await http.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(
2026-09-17 13:36:31 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/confirm-completion`,
{ idempotencyKey: crypto.randomUUID(), remark },
)
return unwrapApiResponse(response)
}
2026-09-09 13:35:43 +08:00
export async function uploadRelabelPdf(relabelNo: string, file: File, scope: 'TOTAL' | 'ITEM', itemId?: string) {
const body = new FormData()
body.append('file', file)
2026-09-29 17:56:00 +08:00
const response = await http.post<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
2026-09-09 13:35:43 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/files`, body,
{ params: { scope, itemId }, headers: { 'Content-Type': 'multipart/form-data' } },
)
return unwrapApiResponse(response)
}
export async function downloadRelabelPdf(relabelNo: string, fileId: string, scope: 'TOTAL' | 'ITEM', itemId?: string) {
2026-09-29 17:56:00 +08:00
return http.get<Blob, Blob>(
2026-09-09 13:35:43 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/files/${encodeURIComponent(fileId)}/download`,
{ params: { scope, itemId }, responseType: 'blob' },
)
}
2026-09-10 15:33:54 +08:00
export async function downloadRelabelCompletionPhoto(relabelNo: string, fileId: string) {
2026-09-29 17:56:00 +08:00
return http.get<Blob, Blob>(
2026-09-10 15:33:54 +08:00
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/completion-photos/${encodeURIComponent(fileId)}/download`,
{ responseType: 'blob' },
)
}