You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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);
}