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.

68 lines
2.0 KiB

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;
};
function tierKey(quote: QuoteTierKey): string {
const carrier = (quote.carrier ?? "").trim().toLowerCase();
return carrier
? `${quote.service_level}/${quote.rate_option}/${carrier}`
: `${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("官网展示档位为空");
}
const hasStandardEntry = ui.some((q) => q.service_level === "standard");
if (!hasStandardEntry) {
throw new RpaDataInvalidError("缺少标准档报价");
}
return ui;
}
/** 校验 API 全量档位后,转为官网展示档位(入库 / 缓存 / 响应统一入口) */
export function prepareMotherShipStorageQuotes<T extends QuoteTierKey>(
quotes: T[],
): T[] {
assertFourTiers(quotes);
return toMotherShipUiQuotes(quotes);
}