feat: connect plan-level preload confirmation

This commit is contained in:
2026-08-15 17:04:00 +08:00
parent fc80d09faa
commit 835d1d0216
26 changed files with 398 additions and 267 deletions
@@ -7,12 +7,38 @@ export interface LoadingCustomer {
customerName: string | null
}
export type PreloadConfirmationStatus = 'PENDING' | 'PARTIALLY_CONFIRMED' | 'CONFIRMED'
export type PreloadBlockingReason =
| 'PRELOAD_NOT_PUSHED'
| 'LOADING_PLAN_NOT_EDITING'
| 'CONTAINER_NO_MISSING'
| 'PRELOAD_LINK_MISSING'
| 'OCEAN_BOOKING_NOT_LINKED'
| 'OCEAN_BOOKING_NOT_RELEASED'
| 'PDA_TASK_ALREADY_CREATED'
| 'PRELOAD_ALREADY_CONFIRMED'
export interface PreloadReadiness {
preloadPushed: boolean
containerNoReady: boolean
preloadLinkCount: number
confirmedPreloadCount: number
oceanBookingId: string | null
oceanBookingStatus: 'CONFIRMED' | 'CHANGE_PENDING' | 'RELEASED' | 'CANCELLED' | null
pdaTaskId: string | null
pdaTaskStatus: string | null
confirmationStatus: PreloadConfirmationStatus
canConfirm: boolean
readyForPda: boolean
blockingReasons: PreloadBlockingReason[]
}
export interface PreloadSummary {
planId: string
containerBookingId: string
preloadNo: string
containerNo: string | null
internalContainerNo: string | null
cabinetNo: string | null
customers: LoadingCustomer[]
warehouseId: string | null
warehouseName: string | null
@@ -26,6 +52,7 @@ export interface PreloadSummary {
totalGrossWeightKg: number
createdAt: string
version: number
readiness: PreloadReadiness
}
export interface ConfirmedSummary {
@@ -35,7 +62,7 @@ export interface ConfirmedSummary {
warehouseId: string | null
warehouseName: string | null
containerNo: string | null
internalContainerNo: string | null
cabinetNo: string | null
status: string
totalPackageCount: string
totalGrossWeightKg: number
@@ -142,6 +169,14 @@ export interface TransportUpdateRequest {
operationReason: string | null
}
export interface PreloadConfirmationResponse {
planId: string
containerBookingId: string
confirmationStatus: 'CONFIRMED'
version: number
readiness: PreloadReadiness
}
type RawId = string | number | null | undefined
type RawPage<T extends LoadingListSummary> = Omit<LoadingListPage<T>, 'page' | 'size' | 'total' | 'pages'> & {
page: string | number
@@ -160,6 +195,15 @@ function optionalId(value: RawId) {
return value === null || value === undefined ? null : String(value)
}
function normalizePreloadReadiness(raw: PreloadReadiness): PreloadReadiness {
return {
...raw,
oceanBookingId: optionalId(raw.oceanBookingId),
pdaTaskId: optionalId(raw.pdaTaskId),
blockingReasons: raw.blockingReasons || [],
}
}
function normalizePreloadSummary(raw: PreloadSummary): PreloadSummary {
return {
...raw,
@@ -168,6 +212,7 @@ function normalizePreloadSummary(raw: PreloadSummary): PreloadSummary {
warehouseId: optionalId(raw.warehouseId),
skuCount: String(raw.skuCount ?? '0'),
totalPackageCount: String(raw.totalPackageCount ?? '0'),
readiness: normalizePreloadReadiness(raw.readiness),
customers: (raw.customers || []).map((customer) => ({
...customer,
accountId: requiredId(customer.accountId),
@@ -206,6 +251,7 @@ function normalizeHistory(raw: LoadingHistory): LoadingHistory {
operatorId: requiredId(raw.operatorId),
}
}
function normalizeDocument(raw: BusinessDocument | null | undefined): BusinessDocument | null {
if (!raw) return null
return { ...raw, id: raw.id == null ? null : requiredId(raw.id), fileId: requiredId(raw.fileId), uploadedBy: optionalId(raw.uploadedBy), completedBy: optionalId(raw.completedBy), version: Number(raw.version ?? 0) }
@@ -262,6 +308,21 @@ export async function updatePreloadTransport(planId: string, warehouseId: string
}
}
export async function confirmPreloadPlan(planId: string, expectedVersion: number, operationId: string) {
const response = await http.post<ApiEnvelope<PreloadConfirmationResponse>, ApiEnvelope<PreloadConfirmationResponse>>(
`${basePath}/loading-plans/${encodeURIComponent(planId)}/confirm`,
{ expectedVersion },
{ headers: { 'Idempotency-Key': operationId } },
)
const result = unwrapApiResponse(response)
return {
...result,
planId: requiredId(result.planId),
containerBookingId: requiredId(result.containerBookingId),
readiness: normalizePreloadReadiness(result.readiness),
}
}
export async function getLoadingDeclaration(planId: string, warehouseId: string) {
const response = await http.get<ApiEnvelope<BusinessDocument | null>, ApiEnvelope<BusinessDocument | null>>(`${basePath}/loading-lists/${encodeURIComponent(planId)}/customs`, { params: { warehouseId } })
return normalizeDocument(unwrapApiResponse(response))