feat(admin): streamline appointments and fleet intake
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
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 },
|
||||
))
|
||||
}
|
||||
Reference in New Issue
Block a user