|
|
import { compareUiTierSortOrder } from "@/lib/constants/quote";
|
|
|
import { filterQuotesForMotherShipUiDisplay } from "@/lib/constants/mothership-ui-tiers";
|
|
|
import { RpaDataInvalidError } from "@/modules/quote/types";
|
|
|
|
|
|
type QuoteTierKey = {
|
|
|
service_level: string;
|
|
|
rate_option: string;
|
|
|
carrier?: string;
|
|
|
raw_total?: number;
|
|
|
final_total?: number;
|
|
|
};
|
|
|
|
|
|
function tierKey(quote: QuoteTierKey): string {
|
|
|
const carrier = (quote.carrier ?? "").trim().toLowerCase();
|
|
|
const amount =
|
|
|
typeof quote.raw_total === "number"
|
|
|
? quote.raw_total
|
|
|
: typeof quote.final_total === "number"
|
|
|
? quote.final_total
|
|
|
: "";
|
|
|
return carrier
|
|
|
? `${quote.service_level}/${quote.rate_option}/${carrier}/${amount}`
|
|
|
: `${quote.service_level}/${quote.rate_option}`;
|
|
|
}
|
|
|
|
|
|
/** 保留 MotherShip 实际返回的全部档位,仅去重 + 排序(不作固定档位白名单) */
|
|
|
export function normalizeToFourTiers<T extends QuoteTierKey>(
|
|
|
quotes: T[],
|
|
|
): T[] {
|
|
|
const map = new Map<string, T>();
|
|
|
for (const quote of quotes) {
|
|
|
map.set(tierKey(quote), quote);
|
|
|
}
|
|
|
|
|
|
const normalized = [...map.values()].sort((a, b) =>
|
|
|
compareUiTierSortOrder(
|
|
|
a.service_level,
|
|
|
a.rate_option,
|
|
|
b.service_level,
|
|
|
b.rate_option,
|
|
|
),
|
|
|
);
|
|
|
|
|
|
if (normalized.length < 1) {
|
|
|
throw new RpaDataInvalidError("报价档位数不足");
|
|
|
}
|
|
|
|
|
|
return normalized;
|
|
|
}
|
|
|
|
|
|
/** 至少 1 档;具体组合随 MotherShip 实际返回 */
|
|
|
export function assertFourTiers(quotes: QuoteTierKey[]): void {
|
|
|
normalizeToFourTiers(quotes);
|
|
|
}
|
|
|
|
|
|
/** API 全量档位 → 展示/入库格式(去重排序,不删档不补档) */
|
|
|
export function toMotherShipUiQuotes<T extends QuoteTierKey>(quotes: T[]): T[] {
|
|
|
const ui = filterQuotesForMotherShipUiDisplay(quotes);
|
|
|
if (ui.length < 1) {
|
|
|
throw new RpaDataInvalidError("官网展示档位为空");
|
|
|
}
|
|
|
// 官网可能仅返回 guaranteed/dedicated;有价即可入库,不再强制要求 standard
|
|
|
if (!ui.some((q) => q.service_level === "standard")) {
|
|
|
console.warn(
|
|
|
"[quote-completeness] 无 standard 档,保留官网返回档位: " +
|
|
|
ui.map((q) => `${q.service_level}/${q.rate_option}`).join(","),
|
|
|
);
|
|
|
}
|
|
|
return ui;
|
|
|
}
|
|
|
|
|
|
/** 校验 API 全量档位后,转为官网展示档位(入库 / 缓存 / 响应统一入口) */
|
|
|
export function prepareMotherShipStorageQuotes<T extends QuoteTierKey>(
|
|
|
quotes: T[],
|
|
|
): T[] {
|
|
|
assertFourTiers(quotes);
|
|
|
return toMotherShipUiQuotes(quotes);
|
|
|
}
|