feat: split domestic and overseas container workbenches

This commit is contained in:
2026-09-08 19:57:42 +08:00
parent 296a8246ad
commit 8910e88563
26 changed files with 365 additions and 219 deletions
@@ -25,6 +25,8 @@ import type {
ContainerDocumentType,
ContainerOverview,
ContainerOverviewDocument,
ContainerWorkbenchKind,
ContainerWorkbenchRow,
} from '../types'
const containerPath = '/platform/v1/containers'
@@ -49,7 +51,7 @@ function overviewDocument(raw: ContainerOverviewDocument): ContainerOverviewDocu
function overview(raw: ContainerOverview): ContainerOverview {
return {
...raw,
container: { ...raw.container, id: id(raw.container.id), warehouseId: id(raw.container.warehouseId), version: numberValue(raw.container.version) },
container: { ...raw.container, id: id(raw.container.id), warehouseId: id(raw.container.warehouseId), pickupCodeUpdatedBy: optionalId(raw.container.pickupCodeUpdatedBy), version: numberValue(raw.container.version) },
loadingPlanId: optionalId(raw.loadingPlanId),
pda: raw.pda ? {
...raw.pda, taskId: id(raw.pda.taskId), loadingPlanId: id(raw.pda.loadingPlanId),
@@ -87,6 +89,7 @@ function container(raw: ContainerBookingResource): ContainerBookingResource {
shippingCompanyId: optionalId(raw.shippingCompanyId),
terminalTruckingCompanyId: optionalId(raw.terminalTruckingCompanyId),
emptyReportSourceVersion: optionalId(raw.emptyReportSourceVersion),
pickupCodeUpdatedBy: optionalId(raw.pickupCodeUpdatedBy),
version: numberValue(raw.version),
capacityCbm: raw.capacityCbm == null ? null : numberValue(raw.capacityCbm),
maxWeightKg: raw.maxWeightKg == null ? null : numberValue(raw.maxWeightKg),
@@ -95,6 +98,30 @@ function container(raw: ContainerBookingResource): ContainerBookingResource {
}
}
function normalizeWorkbenchRow(raw: ContainerWorkbenchRow | ({ container: ContainerBookingResource } & Partial<ContainerWorkbenchRow>)): ContainerWorkbenchRow {
const source = 'container' in raw ? raw.container : raw
const drayage = raw.terminalDrayage
return {
...container(source),
workbenchStage: raw.workbenchStage || null,
statusSummary: raw.statusSummary || {},
allowedActions: raw.allowedActions || [],
actualFacts: raw.actualFacts || {},
terminalDrayage: drayage ? {
...drayage,
containerBookingId: id(drayage.containerBookingId),
version: numberValue(drayage.version),
fleetSupplierId: optionalId(drayage.fleetSupplierId),
emptyReturnWarning: {
...drayage.emptyReturnWarning,
overdueHours: numberValue(drayage.emptyReturnWarning?.overdueHours),
overdueDays: numberValue(drayage.emptyReturnWarning?.overdueDays),
},
allowedActions: drayage.allowedActions || [],
} : null,
}
}
function item(raw: SmartLoadingItem): SmartLoadingItem {
return {
...raw,
@@ -133,10 +160,11 @@ function plan(raw: SmartLoadingPlan): SmartLoadingPlan {
}
}
export async function listContainers(query: ContainerQuery): Promise<ContainerPage> {
const response = await http.get<ApiEnvelope<ContainerPage>, ApiEnvelope<ContainerPage>>(containerPath, { params: query })
export async function listContainers(query: ContainerQuery, workbench: ContainerWorkbenchKind = 'DOMESTIC'): Promise<ContainerPage> {
const params = { ...query, scope: query.scope || 'ACTIVE' }
const response = await http.get<ApiEnvelope<ContainerPage>, ApiEnvelope<ContainerPage>>(`${containerPath}/${workbench.toLowerCase()}`, { params })
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) }
return { ...result, records: (result.records || []).map((record) => normalizeWorkbenchRow(record as ContainerWorkbenchRow)), page: numberValue(result.page, query.page), size: numberValue(result.size, query.size), total: numberValue(result.total), pages: numberValue(result.pages) }
}
export async function getCustomerContainerTransitSummary(customerId: string): Promise<CustomerContainerTransitSummary> {
@@ -151,9 +179,9 @@ export async function getCustomerContainerTransitSummary(customerId: string): Pr
}
}
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 getContainer(containerId: string, workbench: ContainerWorkbenchKind = 'DOMESTIC'): Promise<ContainerWorkbenchRow> {
const response = await http.get<ApiEnvelope<ContainerWorkbenchRow>, ApiEnvelope<ContainerWorkbenchRow>>(`${containerPath}/${workbench.toLowerCase()}/${encodeURIComponent(containerId)}`)
return normalizeWorkbenchRow(unwrapApiResponse(response))
}
export async function getContainerOverview(containerId: string) {
@@ -161,6 +189,14 @@ export async function getContainerOverview(containerId: string) {
return overview(unwrapApiResponse(response))
}
export async function updateContainerPickupCode(containerId: string, pickupCode: string, expectedVersion: number) {
const response = await http.put<ApiEnvelope<ContainerOverview>, ApiEnvelope<ContainerOverview>>(
`${containerPath}/${encodeURIComponent(containerId)}/pickup-code`,
{ pickupCode, expectedVersion },
)
return overview(unwrapApiResponse(response))
}
export async function markContainerException(containerId: string, expectedVersion: number, reason: string) {
const response = await http.post<ApiEnvelope<null>, ApiEnvelope<null>>(`${containerPath}/${encodeURIComponent(containerId)}/exception`, { expectedVersion, reason }, { headers: { 'Idempotency-Key': operationId('container-exception-mark') } })
unwrapApiResponse(response)
@@ -171,7 +207,7 @@ export async function cancelContainerException(containerId: string, expectedVers
unwrapApiResponse(response)
}
export async function uploadContainerDocument(containerId: string, documentType: Extract<ContainerDocumentType, 'DELIVERY_ORDER' | 'PICKUP_ORDER'>, file: File, expectedVersion: number, operationReason?: string | null) {
export async function uploadContainerDocument(containerId: string, documentType: Extract<ContainerDocumentType, 'DELIVERY_ORDER'>, file: File, expectedVersion: number, operationReason?: string | null) {
const body = new FormData()
body.append('file', file)
body.append('expectedVersion', String(expectedVersion))
@@ -180,7 +216,7 @@ export async function uploadContainerDocument(containerId: string, documentType:
return document(unwrapApiResponse(response))
}
export function downloadContainerDocument(containerId: string, documentType: Extract<ContainerDocumentType, 'DELIVERY_ORDER' | 'PICKUP_ORDER'>, fileId: string) {
export function downloadContainerDocument(containerId: string, documentType: Extract<ContainerDocumentType, 'DELIVERY_ORDER'>, fileId: string) {
return http.get<Blob, Blob>(`${containerPath}/${encodeURIComponent(containerId)}/documents/${documentType}/${encodeURIComponent(fileId)}/download`, { responseType: 'blob' })
}