129 lines
7.5 KiB
TypeScript
129 lines
7.5 KiB
TypeScript
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
|||
|
|
import type {
|
||
|
|
ContainerBookingResource,
|
||
|
|
ContainerPage,
|
||
|
|
ContainerQuery,
|
||
|
|
ContainerSaveRequest,
|
||
|
|
SmartLoadingCandidate,
|
||
|
|
SmartLoadingItem,
|
||
|
|
SmartLoadingPlan,
|
||
|
|
} from '../types'
|
||
|
|
|
||
|
|
const containerPath = '/platform/v1/containers'
|
||
|
|
const smartLoadingPath = '/platform/v1/first-leg/smart-loading'
|
||
|
|
|
||
|
|
function id(value: unknown): string { return value == null ? '' : String(value) }
|
||
|
|
function optionalId(value: unknown): string | null { return value == null ? null : String(value) }
|
||
|
|
function numberValue(value: unknown, fallback = 0): number {
|
||
|
|
const parsed = Number(value)
|
||
|
|
return Number.isFinite(parsed) ? parsed : fallback
|
||
|
|
}
|
||
|
|
function operationId(prefix: string) { return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}` }
|
||
|
|
|
||
|
|
function container(raw: ContainerBookingResource): ContainerBookingResource {
|
||
|
|
return {
|
||
|
|
...raw,
|
||
|
|
id: id(raw.id),
|
||
|
|
planId: optionalId(raw.planId),
|
||
|
|
warehouseId: id(raw.warehouseId),
|
||
|
|
shippingCompanyId: optionalId(raw.shippingCompanyId),
|
||
|
|
version: numberValue(raw.version),
|
||
|
|
capacityCbm: raw.capacityCbm == null ? null : numberValue(raw.capacityCbm),
|
||
|
|
maxWeightKg: raw.maxWeightKg == null ? null : numberValue(raw.maxWeightKg),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function item(raw: SmartLoadingItem): SmartLoadingItem {
|
||
|
|
return {
|
||
|
|
...raw,
|
||
|
|
id: id(raw.id), loadingPlanId: id(raw.loadingPlanId), accountId: id(raw.accountId),
|
||
|
|
inboundId: id(raw.inboundId), inboundDetailId: id(raw.inboundDetailId), orderId: id(raw.orderId),
|
||
|
|
destinationWarehouseId: optionalId(raw.destinationWarehouseId), version: numberValue(raw.version),
|
||
|
|
packageCount: numberValue(raw.packageCount),
|
||
|
|
productQuantity: raw.productQuantity == null ? null : numberValue(raw.productQuantity),
|
||
|
|
grossWeightKg: raw.grossWeightKg == null ? null : numberValue(raw.grossWeightKg),
|
||
|
|
volumeCbm: raw.volumeCbm == null ? null : numberValue(raw.volumeCbm),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function plan(raw: SmartLoadingPlan): SmartLoadingPlan {
|
||
|
|
return { ...raw, id: id(raw.id), bookingId: id(raw.bookingId), version: numberValue(raw.version), items: (raw.items || []).map(item) }
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function listContainers(query: ContainerQuery): Promise<ContainerPage> {
|
||
|
|
const response = await http.get<ApiEnvelope<ContainerPage>, ApiEnvelope<ContainerPage>>(containerPath, { params: query })
|
||
|
|
const result = unwrapApiResponse(response)
|
||
|
|
return { ...result, records: (result.records || []).map(container), page: numberValue(result.page, query.page), size: numberValue(result.size, query.size), total: numberValue(result.total), pages: numberValue(result.pages) }
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function getContainer(containerId: string) {
|
||
|
|
const response = await http.get<ApiEnvelope<ContainerBookingResource>, ApiEnvelope<ContainerBookingResource>>(`${containerPath}/${encodeURIComponent(containerId)}`)
|
||
|
|
return container(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function createContainer(payload: ContainerSaveRequest) {
|
||
|
|
const response = await http.post<ApiEnvelope<ContainerBookingResource>, ApiEnvelope<ContainerBookingResource>>(containerPath, payload)
|
||
|
|
return container(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function updateContainer(containerId: string, version: number, data: ContainerSaveRequest) {
|
||
|
|
const response = await http.put<ApiEnvelope<ContainerBookingResource>, ApiEnvelope<ContainerBookingResource>>(`${containerPath}/${encodeURIComponent(containerId)}`, { version, data })
|
||
|
|
return container(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function updateContainerTransport(containerId: string, version: number, payload: { containerNo: string | null; voyageNo: string | null }) {
|
||
|
|
const response = await http.patch<ApiEnvelope<ContainerBookingResource>, ApiEnvelope<ContainerBookingResource>>(`${containerPath}/${encodeURIComponent(containerId)}/transport`, { ...payload, version })
|
||
|
|
return container(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function listSmartLoadingCandidates(warehouseId: string) {
|
||
|
|
const response = await http.get<ApiEnvelope<SmartLoadingCandidate[]>, ApiEnvelope<SmartLoadingCandidate[]>>(`${smartLoadingPath}/candidates`, { params: { warehouseId } })
|
||
|
|
return unwrapApiResponse(response).map((raw) => ({
|
||
|
|
...raw, accountId: id(raw.accountId), inboundId: id(raw.inboundId), inboundDetailId: id(raw.inboundDetailId),
|
||
|
|
orderId: id(raw.orderId), warehouseId: id(raw.warehouseId), destinationWarehouseId: optionalId(raw.destinationWarehouseId),
|
||
|
|
availablePackageCount: numberValue(raw.availablePackageCount),
|
||
|
|
unitWeightKg: raw.unitWeightKg == null ? null : numberValue(raw.unitWeightKg),
|
||
|
|
unitVolumeCbm: raw.unitVolumeCbm == null ? null : numberValue(raw.unitVolumeCbm),
|
||
|
|
}))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function getSmartLoadingPlanByBooking(bookingId: string) {
|
||
|
|
const response = await http.get<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/by-booking/${encodeURIComponent(bookingId)}`)
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function getSmartLoadingPlan(planId: string) {
|
||
|
|
const response = await http.get<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}`)
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function createSmartLoadingPlan(bookingId: string, remark: string | null) {
|
||
|
|
const response = await http.post<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans`, { bookingId, remark })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function assignSmartLoadingItem(planId: string, payload: { inboundId: string; inboundDetailId: string; packageCount: number; expectedVersion: number }) {
|
||
|
|
const response = await http.post<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}/assignments`, { ...payload, operationId: operationId('assign') })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function recommendSmartLoading(planId: string, expectedVersion: number) {
|
||
|
|
const response = await http.post<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}/recommend`, { expectedVersion, operationId: operationId('recommend') })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function adjustSmartLoadingItem(planId: string, itemId: string, packageCount: number, expectedPlanVersion: number, expectedItemVersion: number) {
|
||
|
|
const response = await http.patch<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}/items/${encodeURIComponent(itemId)}`, { packageCount, expectedPlanVersion, expectedItemVersion, operationId: operationId('adjust') })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function removeSmartLoadingItem(planId: string, itemId: string, expectedPlanVersion: number, expectedItemVersion: number) {
|
||
|
|
const response = await http.delete<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}/items/${encodeURIComponent(itemId)}`, { data: { expectedPlanVersion, expectedItemVersion, operationId: operationId('remove') } })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function pushSmartLoadingPreload(planId: string, expectedVersion: number) {
|
||
|
|
const response = await http.post<ApiEnvelope<SmartLoadingPlan>, ApiEnvelope<SmartLoadingPlan>>(`${smartLoadingPath}/plans/${encodeURIComponent(planId)}/push-preload`, { expectedVersion }, { headers: { 'Idempotency-Key': operationId('push-preload') } })
|
||
|
|
return plan(unwrapApiResponse(response))
|
||
|
|
}
|