Files
admin-web/src/modules/appointment-calendar/scheduleApi.ts
T

74 lines
3.1 KiB
TypeScript

import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
export interface CalendarContainer {
containerBookingId: string
cabinetNo: string | null
containerNo: string | null
vesselName: string | null
voyageNo: string | null
destinationPortName: string | null
destinationWarehouseCode: string | null
arrivalAt: string | null
arrivalType: 'ACTUAL' | 'ESTIMATED'
}
export interface CalendarReturn {
containerBookingId: string
containerNo: string | null
fleetSupplierName: string | null
actualEmptyReturnAt: string | null
emptyReturnWarning: { status: string; deadlineAt: string | null }
}
export interface CalendarSources { containers: CalendarContainer[]; emptyReturns: CalendarReturn[]; emptyReturnsReadable: boolean }
export interface WarehouseArrival {
sourceContainerBookingId: string
cabinetNo?: string | null
containerNo: string | null
warehouseName: string | null
warehouseCode: string | null
plannedAt: string | null
actualAt: string | null
version: number
planCount: number
canEdit: boolean
plannedDate?: string | null
isDefault?: boolean
}
export interface ScheduleRange { from: string; to: string }
type WarehouseArrivalWire = Omit<WarehouseArrival, 'planCount' | 'plannedAt' | 'actualAt'> & {
planCount: string | number
plannedAt?: string | null
actualAt?: string | null
}
/** 在接口边界统一长整型数量,未知数量不能被当成零触发默认日期。 */
function normalizeWarehouseArrival(row: WarehouseArrivalWire): WarehouseArrival {
const count = row.planCount
if (typeof count !== 'number' && (typeof count !== 'string' || !/^(0|[1-9]\d*)$/.test(count))) {
throw new Error('到仓记录的入库计划数量无效,请刷新后重试')
}
const planCount = Number(count)
if (!Number.isSafeInteger(planCount) || planCount < 0) {
throw new Error('到仓记录的入库计划数量无效,请刷新后重试')
}
return { ...row, planCount, plannedAt: row.plannedAt ?? null, actualAt: row.actualAt ?? null }
}
export async function getCalendarSources(range: ScheduleRange, signal?: AbortSignal) {
return unwrapApiResponse(await http.get<ApiEnvelope<CalendarSources>, ApiEnvelope<CalendarSources>>(
'/platform/v1/terminal-drayages/calendar-sources', { params: range, signal },
))
}
export async function getWarehouseArrivals(range: ScheduleRange, sourceContainerBookingIds: string[], signal?: AbortSignal) {
const rows = unwrapApiResponse(await http.post<ApiEnvelope<WarehouseArrivalWire[]>, ApiEnvelope<WarehouseArrivalWire[]>>(
'/platform/v1/last-leg/appointment-calendar/warehouse-arrivals/query', { ...range, sourceContainerBookingIds }, { signal },
))
return rows.map(normalizeWarehouseArrival)
}
export interface WarehouseArrivalChange { estimatedWarehouseArrivalAt: string; expectedVersion: number }
export async function saveWarehouseArrival(containerId: string, body: WarehouseArrivalChange, key: string) {
return unwrapApiResponse(await http.put<ApiEnvelope<unknown>, ApiEnvelope<unknown>>(
`/platform/v1/last-leg/orders/container-summaries/${encodeURIComponent(containerId)}/expected-arrival`, body,
{ headers: { 'Idempotency-Key': key } },
))
}