273 lines
10 KiB
TypeScript
273 lines
10 KiB
TypeScript
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
|
|
|
import { listSharedReceivingOverseasWarehouseOptions } from '@/modules/iam'
|
|
import { normalizeOverseasPage, type OverseasPagePayload } from './lastMileOrders'
|
|
|
|
export interface RelabelOrderQuery {
|
|
page: number
|
|
size: number
|
|
relabelNo?: string
|
|
skuCode?: string
|
|
status?: string
|
|
}
|
|
|
|
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
|
|
operationWarehouseId?: string
|
|
/** @deprecated compatibility alias for older platform fixtures */
|
|
overseasWarehouseId?: string
|
|
labelDeadline: string
|
|
contactName: string
|
|
contactPhone: string
|
|
chargeAmount: number
|
|
remark?: string
|
|
idempotencyKey: string
|
|
items: CreateRelabelItemPayload[]
|
|
}
|
|
|
|
export interface RelabelWarehouseOptionDto {
|
|
id: string
|
|
customerId: string
|
|
warehouseCode: string
|
|
warehouseName: string
|
|
warehouseType: 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
|
|
productNameZh?: string | null
|
|
labelRequirement?: string | null
|
|
totalFileId?: string | null
|
|
totalFileName?: string | null
|
|
totalFileUrl?: string | null
|
|
chargeAmount?: number | string | null
|
|
chargeCurrency?: string | null
|
|
walletStatus?: string | null
|
|
walletErrorMessage?: string | null
|
|
deliveryMethod?: string | null
|
|
printShippingLabel?: boolean | null
|
|
shippingLabelFileId?: string | null
|
|
shippingLabelFileName?: string | null
|
|
fulfillmentStatus?: string | null
|
|
outboundOrderNo?: string | null
|
|
customerConfirmedAt?: string | null
|
|
reviewChannel?: 'TAIL_ORDER' | 'RELABEL_ORDER' | null
|
|
reviewRemark?: string | null
|
|
createdAt?: string | null
|
|
}
|
|
|
|
export interface RelabelItemDto {
|
|
id: string
|
|
operationType?: 'CARTON_LABEL' | 'SKU_LABEL' | 'CARTON_AND_SKU'
|
|
skuItems?: Array<{ skuCode: string; newSkuCode: string; quantity: number; remark?: string }>
|
|
skuCode?: string | null
|
|
productNameZh?: string | null
|
|
totalPackageCount?: number | null
|
|
notifiedPackageCount?: number | null
|
|
newSkuCode?: string | null
|
|
labelRequirement?: string | null
|
|
relabelFileId?: string | null
|
|
relabelFileName?: string | null
|
|
relabelFileUrl?: string | null
|
|
shipmentNo?: string | null
|
|
trackingCode?: string | null
|
|
remark?: string
|
|
cartonMark?: string | null
|
|
fbaCartonMark?: string | null
|
|
destinationWarehouseId?: string | null
|
|
destinationFbaWarehouseCode?: string | null
|
|
}
|
|
|
|
export interface RelabelHistoryDto {
|
|
fromStatus?: string | null
|
|
toStatus?: string | null
|
|
operatorId?: string | null
|
|
remark?: string
|
|
createdAt?: string | null
|
|
}
|
|
|
|
export interface RelabelDetailDto {
|
|
application: RelabelSummaryDto
|
|
remark?: string | null
|
|
items: RelabelItemDto[]
|
|
history: RelabelHistoryDto[]
|
|
completionEvidence?: { taskId: string; photoFileIds: string[]; completionRemark?: string | null; reviewerName?: string | null; reviewRemark?: string | null; completedAt?: string | null } | null
|
|
}
|
|
|
|
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[]
|
|
mode: 'BOX' | 'SKU'
|
|
boxes: ReturnPackingPlanBox[]
|
|
remark?: string
|
|
idempotencyKey: string
|
|
sourceCartonMarks?: string[]
|
|
sourceDeductions?: Array<{ cartonMark: string; skuCode: string; quantity: number }>
|
|
}
|
|
|
|
export interface ReturnPackingPlanDto extends Omit<ReturnPackingPlanPayload, 'remark'> {
|
|
planNo: string
|
|
customerId?: string
|
|
overseasWarehouseId?: string
|
|
status: string
|
|
boxes: ReturnPackingPlanBox[]
|
|
remark?: string | null
|
|
createdAt?: string | null
|
|
pushedAt?: string | null
|
|
completedAt?: string | null
|
|
resultCartons?: import('./returnInventory').ReturnCartonDetail[]
|
|
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
|
|
}
|
|
|
|
export async function createReturnPackingPlan(payload: ReturnPackingPlanPayload) {
|
|
const response = await http.post<ApiEnvelope<ReturnPackingPlanDto>, ApiEnvelope<ReturnPackingPlanDto>>(
|
|
'/platform/v1/last-leg/return-packing-plans', payload,
|
|
)
|
|
return unwrapApiResponse(response) as ReturnPackingPlanDto
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
export async function listRelabelOrders(query: RelabelOrderQuery) {
|
|
const response = await http.get<ApiEnvelope<OverseasPagePayload<RelabelSummaryDto>>, ApiEnvelope<OverseasPagePayload<RelabelSummaryDto>>>(
|
|
'/platform/v1/last-leg/relabel-applications', { params: query },
|
|
)
|
|
return normalizeOverseasPage(unwrapApiResponse(response))
|
|
}
|
|
|
|
export async function getRelabelOrder(relabelNo: string) {
|
|
const response = await http.get<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
|
|
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}`,
|
|
)
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
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) {
|
|
const response = await http.post<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
|
|
'/platform/v1/last-leg/relabel-applications', payload, { params: { customerId } },
|
|
)
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
export async function changeRelabelOrderStatus(relabelNo: string, status: string, remark?: string) {
|
|
const response = await http.put<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
|
|
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/status`,
|
|
{ status, remark },
|
|
)
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
export async function getRelabelReviewTask(relabelNo: string) {
|
|
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`)
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
export async function returnRelabelForRework(relabelNo: string, expectedVersion: number, remark: string, idempotencyKey: string) {
|
|
const response = await http.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/rework`, { decision: 'REWORK', expectedVersion, remark, idempotencyKey })
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
export async function confirmRelabelCompletion(relabelNo: string, remark?: string) {
|
|
const response = await http.post<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(
|
|
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/confirm-completion`,
|
|
{ idempotencyKey: crypto.randomUUID(), remark },
|
|
)
|
|
return unwrapApiResponse(response)
|
|
}
|
|
|
|
export async function uploadRelabelPdf(relabelNo: string, file: File, scope: 'TOTAL' | 'ITEM', itemId?: string) {
|
|
const body = new FormData()
|
|
body.append('file', file)
|
|
const response = await http.post<ApiEnvelope<RelabelDetailDto>, ApiEnvelope<RelabelDetailDto>>(
|
|
`/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) {
|
|
return http.get<Blob, Blob>(
|
|
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/files/${encodeURIComponent(fileId)}/download`,
|
|
{ params: { scope, itemId }, responseType: 'blob' },
|
|
)
|
|
}
|
|
|
|
export async function downloadRelabelCompletionPhoto(relabelNo: string, fileId: string) {
|
|
return http.get<Blob, Blob>(
|
|
`/platform/v1/last-leg/relabel-applications/${encodeURIComponent(relabelNo)}/completion-photos/${encodeURIComponent(fileId)}/download`,
|
|
{ responseType: 'blob' },
|
|
)
|
|
}
|