import { Prisma } from "@prisma/client"; import { PRICE_DEVIATION_THRESHOLD } from "@/lib/constants/rpa"; import { prisma } from "@/lib/prisma"; import { writeAlert } from "@/modules/alert/service"; import type { RawQuoteTier } from "@/modules/pricing/engine"; import { getStandardLowestTotal } from "@/modules/rpa/quote-mapper"; /** 偏差检测 + quote_cache_meta 更新(task-051 最小实现,供 RPA 成功路径调用) */ export async function detectDeviation( cargoHash: string, newQuotes: RawQuoteTier[], quoteId?: string, ): Promise { const newStandardTotal = getStandardLowestTotal(newQuotes); if (newStandardTotal === null) { return; } const guaranteedTotal = newQuotes.find( (q) => q.service_level === "guaranteed" && q.rate_option === "lowest", )?.raw_total ?? newStandardTotal; const existing = await prisma.quoteCacheMeta.findUnique({ where: { cargoHash }, }); if (!existing) { await prisma.quoteCacheMeta.create({ data: { cargoHash, rawTotalStandard: newStandardTotal, rawTotalGuaranteed: guaranteedTotal, lastQuotesJson: newQuotes as unknown as Prisma.InputJsonValue, }, }); return; } const prevTotal = Number(existing.rawTotalStandard); const deviation = prevTotal > 0 ? Math.abs(newStandardTotal - prevTotal) / prevTotal : 0; if (deviation >= PRICE_DEVIATION_THRESHOLD) { const deviationPercent = Math.round( (Math.abs(newStandardTotal - prevTotal) / prevTotal) * 10_000, ) / 100; await writeAlert("PRICE_DEVIATION", { quoteId, cargoHash, detail: { prev_total: prevTotal, curr_total: newStandardTotal, deviation_percent: deviationPercent, }, }); } await prisma.quoteCacheMeta.update({ where: { cargoHash }, data: { rawTotalStandard: newStandardTotal, rawTotalGuaranteed: guaranteedTotal, lastQuotesJson: newQuotes as unknown as Prisma.InputJsonValue, refreshedAt: new Date(), }, }); }