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

72 lines
4.2 KiB
TypeScript
Raw Normal View History

import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
export interface PlanningCargo {
sourceKey: string
orderId: string
customerId: string
customerName: string | null
inboundCode: string | null
containerBookingId: string
containerNo: string | null
originWarehouseId: string
originWarehouseCode: string
originWarehouseName: string
destinationWarehouseCode: string
packages: number | null
receivedPackages: number | null
shippedPackages: number | null
sourcePalletCount: number | null
volumeCbm: number | null
estimatedArrivalAt: string | null
estimatedWarehouseAt: string | null
orderVersion: number
standardNode: string
shippingVersion: string | null
shippingObservedAt: string | null
shippingProvider: string | null
hasInboundPlan: boolean
hasActiveAppointment: boolean
detained: boolean
mixedDestinations: boolean
}
export interface PlanningCargoPage { records: PlanningCargo[]; page: number; size: number; total: number; pages: number }
export async function listPlanningCargo(query: { page: number; size: number; keyword?: string }, signal?: AbortSignal) {
const response = await http.get<ApiEnvelope<PlanningCargoPage>, ApiEnvelope<PlanningCargoPage>>(
'/platform/v1/last-leg/appointment-planning/cargo', { params: query, signal },
)
const page = unwrapApiResponse(response)
return { ...page, page: Number(page.page), size: Number(page.size), total: Number(page.total), pages: Number(page.pages) }
}
export type FollowupStage = 'DRAYAGE_CONTACT' | 'TERMINAL_APPOINTMENT' | 'WAREHOUSE_RECEIVING' | 'FBA_RECEIVING'
export interface FollowupRecord { stage: FollowupStage; version: number; contactedParty: string | null; result: string; nextAction: string | null; followupDate: string | null; operatorName: string | null; createdAt: string }
export interface FollowupHistory { history: { records: FollowupRecord[]; page: number; size: number; total: number; pages: number }; versions: Record<FollowupStage, number> }
export interface SaveFollowup { stage: FollowupStage; expectedVersion: number; idempotencyKey: string; contactedParty?: string; result: string; nextAction?: string; followupDate: string | null }
export async function getFollowups(sourceKey: string, customerId: string, page: number, size: number) {
const result = unwrapApiResponse(await http.get<ApiEnvelope<FollowupHistory>, ApiEnvelope<FollowupHistory>>(
`/platform/v1/last-leg/appointment-planning/sources/${encodeURIComponent(sourceKey)}/follow-ups`, { params: { customerId, page, size } },
))
return { ...result, history: { ...result.history, total: Number(result.history.total) }, versions: Object.fromEntries(Object.entries(result.versions).map(([stage, version]) => [stage, Number(version)])) as Record<FollowupStage, number> }
}
export async function saveFollowup(sourceKey: string, customerId: string, body: SaveFollowup) {
return unwrapApiResponse(await http.post<ApiEnvelope<FollowupRecord>, ApiEnvelope<FollowupRecord>>(
`/platform/v1/last-leg/appointment-planning/sources/${encodeURIComponent(sourceKey)}/follow-ups`, body, { params: { customerId } },
))
}
export interface PlanningSource {
sourceKey: string; customerId: string; orderId: string | null; inboundCode: string | null; bookingNo: string | null;
containerNo: string | null; originWarehouseId: string; originWarehouseName: string; destinationKey: string;
destinationWarehouseCode: string; packages: number | null; sourceVersion: string | null; canFollowup: boolean; blockReasons: string[];
}
export interface AppointmentCoverage {
status: string; missingFields: string[]; changeReviewRequired: boolean;
appointments: Array<{ appointmentNo: string; confirmationNo: string | null; status: string; confirmedAt: string | null; confirmedEndAt: string | null; timezone: string | null }>;
}
export interface ResolvedPlanningSource { source: PlanningSource; coverage: AppointmentCoverage }
export async function resolvePlanningSource(query: { sourceKey: string; customerId: string; destinationKey?: string }) {
return unwrapApiResponse(await http.get<ApiEnvelope<ResolvedPlanningSource>, ApiEnvelope<ResolvedPlanningSource>>(
'/platform/v1/last-leg/appointment-planning/sources/resolve', { params: query },
))
}