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

32 lines
3.3 KiB
TypeScript

import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
import type { PlanningContainer } from './planningApi'
export interface ForecastFact { estimatedAt: string | null; actualAt: string | null; observedAt: string | null; providerCode: string | null; sourceReference: string | null }
export interface Impact { containerBookingId: string; impactNo: string; version: number; status: string; reason: string | null; ownerName: string | null; ownerId: string | null; baseline: ForecastFact | null; latest: ForecastFact | null; forecastToken: string; updatedAt: string }
export interface ImpactRow { container: PlanningContainer; impact: Impact | null }
export interface ImpactDetail {
impact: Impact
cargo: Array<{ inboundCode: string | null; customerName: string | null; packages: number | null; destination: string | null }>
appointments: Array<{ appointmentNo: string; status: string; destination: string; confirmedAt: string | null; timezone: string | null }>
transport: { trips: Array<{ tripNo: string; status: string; plannedDepartureAt: string | null }>; sameTripBookings: Array<{ tripNo: string; bookingNo: string; customerName: string | null; destinationLabel: string | null; status: string }> } | null
history: { records: Array<{ version: number; action: string; operatorName: string | null; result: string | null; nextAction: string | null; followupDate: string | null; createdAt: string }>; total: number }
}
export interface ImpactCommand { expectedVersion: number; forecastToken: string; idempotencyKey: string; action: 'CLAIM' | 'RECORD' | 'RESOLVE'; result: string | null; nextAction: string | null; followupDate: string | null }
const base = '/platform/v1/last-leg/appointment-planning/impacts'
export async function listImpacts(query: { page: number; size: number; keyword?: string }, signal?: AbortSignal) {
const result = unwrapApiResponse(await http.get<ApiEnvelope<{ records: ImpactRow[]; total: number }>, ApiEnvelope<{ records: ImpactRow[]; total: number }>>(base, { params: query, signal }))
return { ...result, total: Number(result.total) }
}
export async function refreshImpacts(query: { page: number; size: number; keyword?: string }) {
return unwrapApiResponse(await http.post<ApiEnvelope<Impact[]>, ApiEnvelope<Impact[]>>(`${base}/refresh`, query))
}
export async function getImpact(id: string, page = 1) {
const result = unwrapApiResponse(await http.get<ApiEnvelope<ImpactDetail>, ApiEnvelope<ImpactDetail>>(`${base}/${encodeURIComponent(id)}`, { params: { page, size: 20 } }))
return { ...result, impact: { ...result.impact, version: Number(result.impact.version) }, history: { ...result.history, total: Number(result.history.total) } }
}
export async function handleImpact(id: string, command: ImpactCommand) {
return unwrapApiResponse(await http.post<ApiEnvelope<Impact>, ApiEnvelope<Impact>>(`${base}/${encodeURIComponent(id)}/commands`, command))
}
export const impactStatus: Record<string, string> = { OPEN: '待处理', RESOLVED: '已核对处理', MONITORING: '暂无变化' }
export const impactReason: Record<string, string> = { FORECAST_MISSING: '到港预测待核实', FORECAST_CHANGED: '到港预测变化', ACTUAL_ARRIVAL_REVIEW: '实际到港已更新', SOURCE_CHANGED: '预测来源变化', UNCHANGED: '预测未变', BASELINE_ESTABLISHED: '已建立核对基准' }