Files
admin-web/src/modules/overseas-master-data/api/capacityOffers.ts
T

29 lines
5.0 KiB
TypeScript

import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
import type { CapacityOffer, CapacityInquiry, CapacityOfferDetail, CapacityLoad, OfferPage, OfferQuery, InquiryQuery, OfferWrite, OfferCommand, InquiryWrite, InquiryCommand, OfferResult, InquiryResult, OfferCustomerOption } from '../capacityOfferTypes'
import { normalizeFleetQuotePage, normalizeFleetQuoteSource, type WireQuotePage } from './fleetQuoteCandidates'
import type { TripBookingQuoteCriteria } from './tripBookings'
const base = '/platform/v1/last-leg/fleet/capacity-offers'
const path = (value: string) => `${base}/${encodeURIComponent(value)}`
const inquiryPath = (value: string) => `${base}/inquiries/${encodeURIComponent(value)}`
const number = (value: number) => { const n = Number(value); if (value == null || !Number.isFinite(n)) throw new Error('运力数据数值无效'); return n }
const nullable = (value: number | null) => value == null ? null : number(value)
const load = (value: CapacityLoad | null) => value == null ? null : { palletSpaces: number(value.palletSpaces), weightKg: number(value.weightKg), volumeCbm: number(value.volumeCbm) }
export function normalizeOffer(value: CapacityOffer): CapacityOffer { return { ...value, recordVersion: number(value.recordVersion), tripRecordVersion: number(value.tripRecordVersion), destinations: value.destinations.map(d => ({ ...d, deliveryIndex: number(d.deliveryIndex), remaining: load(d.remaining) })), segments: value.segments.map(s => ({ ...s, fromIndex: number(s.fromIndex), toIndex: number(s.toIndex), planned: load(s.planned), reserved: load(s.reserved), remaining: load(s.remaining) })) } }
export function normalizeInquiry(value: CapacityInquiry): CapacityInquiry { return { ...value, recordVersion: number(value.recordVersion), offerRecordVersion: number(value.offerRecordVersion), tripRecordVersion: number(value.tripRecordVersion), expectedPalletCount: nullable(value.expectedPalletCount), agreedAmount: nullable(value.agreedAmount), quoteSource: value.quoteSource ? normalizeFleetQuoteSource(value.quoteSource) : null, cargo: { ...value.cargo, packageCount: nullable(value.cargo.packageCount), palletSpaces: nullable(value.cargo.palletSpaces), weightKg: nullable(value.cargo.weightKg), volumeCbm: nullable(value.cargo.volumeCbm), unitPrice: nullable(value.cargo.unitPrice) } } }
function page<T>(value: OfferPage<T>, normalize: (row: T) => T): OfferPage<T> { return { records: value.records.map(normalize), page: number(value.page), size: number(value.size), total: number(value.total), pages: number(value.pages) } }
const offerResult = (value: OfferResult): OfferResult => ({ ...value, offer: normalizeOffer(value.offer) })
const inquiryResult = (value: InquiryResult): InquiryResult => ({ ...offerResult(value), inquiry: normalizeInquiry(value.inquiry) })
async function get<T>(url: string, params?: object) { return unwrapApiResponse(await http.get<ApiEnvelope<T>, ApiEnvelope<T>>(url, { params })) }
async function post<T>(url: string, body: object) { return unwrapApiResponse(await http.post<ApiEnvelope<T>, ApiEnvelope<T>>(url, body)) }
async function put<T>(url: string, body: object) { return unwrapApiResponse(await http.put<ApiEnvelope<T>, ApiEnvelope<T>>(url, body)) }
export async function listCapacityOffers(query: OfferQuery) { return page(await get<OfferPage<CapacityOffer>>(base, query), normalizeOffer) }
export async function getCapacityOffer(offerNo: string): Promise<CapacityOfferDetail> { const value = await get<CapacityOfferDetail>(path(offerNo)); return { offer: normalizeOffer(value.offer), inquiries: page(value.inquiries, normalizeInquiry) } }
export async function listCapacityInquiries(query: InquiryQuery) { return page(await get<OfferPage<CapacityInquiry>>(`${base}/inquiries`, query), normalizeInquiry) }
export async function getCapacityInquiry(bookingNo: string) { return normalizeInquiry(await get<CapacityInquiry>(inquiryPath(bookingNo))) }
export async function saveCapacityOffer(offerNo: string | null, body: OfferWrite) { return offerResult(await (offerNo ? put<OfferResult>(path(offerNo), body) : post<OfferResult>(base, body))) }
export async function commandCapacityOffer(offerNo: string, action: 'publish' | 'pause' | 'resume' | 'close', body: OfferCommand) { return offerResult(await post<OfferResult>(`${path(offerNo)}/${action}`, body)) }
export async function saveCapacityInquiry(offerNo: string, bookingNo: string | null, body: InquiryWrite) { return inquiryResult(await (bookingNo ? put<InquiryResult>(inquiryPath(bookingNo), body) : post<InquiryResult>(`${path(offerNo)}/inquiries`, body))) }
export async function commandCapacityInquiry(bookingNo: string, action: 'confirm' | 'cancel', body: InquiryCommand) { return inquiryResult(await post<InquiryResult>(`${inquiryPath(bookingNo)}/${action}`, body)) }
export const listOfferCustomers = (keyword?: string) => get<OfferCustomerOption[]>(`${base}/customer-options`, { keyword })
export async function listOfferQuotes(offerNo: string, query: TripBookingQuoteCriteria) { return normalizeFleetQuotePage(await get<WireQuotePage>(`${path(offerNo)}/quote-candidates`, query)) }