import { parseServiceAuth } from "@/lib/api/auth-context"; import { prisma } from "@/lib/prisma"; import { fail, ok } from "@/lib/response"; import { AuthError } from "@/modules/auth/errors"; import { recordSecurityEvent } from "@/modules/audit/service"; import { serializeQuoteDetail } from "@/modules/quote/quote-serializer"; import { toMsRefineHoldPublic } from "@/lib/constants/ms-refine-hold"; import { readMsRefineHoldByQuoteId } from "@/lib/mothership/refine-hold-store"; import { readMsCheckoutStatus, toMsCheckoutPublic } from "@/lib/mothership/ms-checkout-store"; import { readFlockCheckoutStatus, toFlockCheckoutPublic, } from "@/lib/flock/flock-checkout-store"; import { readFlockPricingOptions, toFlockPricingOptionsPublic, } from "@/lib/flock/flock-pricing-options-store"; import { toFlockQuoteHoldPublic, shouldAutoDeclineFlockHold, } from "@/lib/constants/flock-quote-hold"; import { readFlockHoldCarriers, readFlockHoldFlexibility, readFlockQuoteHoldByQuoteId, } from "@/lib/flock/flock-quote-hold-store"; import { declineFlockQuoteHold } from "@/modules/flock/hold-service"; type RouteContext = { params: Promise<{ quote_id: string }>; }; export async function GET(request: Request, context: RouteContext) { let auth; try { auth = await parseServiceAuth(request); } catch (error) { if (error instanceof AuthError) { return fail(error.code, error.message, error.httpStatus); } throw error; } const { quote_id: quoteId } = await context.params; const businessCustomerId = new URL(request.url).searchParams .get("business_customer_id") ?.trim(); const record = await prisma.quoteRecord.findFirst({ where: { quoteId, isDeleted: false }, }); if (!record) { return fail("QUOTE_NOT_FOUND", "报价不存在", 404); } if (record.customerId !== auth.customerId) { void recordSecurityEvent( "FORBIDDEN_ACCESS", auth.customerId, quoteId, { attempted_quote_id: quoteId, owner_customer_id: record.customerId, }, ); return fail("FORBIDDEN", "无权访问该报价", 403); } if ( businessCustomerId && (record.businessCustomerId ?? "") !== businessCustomerId ) { return fail("FORBIDDEN", "无权访问该业务客户报价", 403); } const detail = serializeQuoteDetail(record); const hold = await readMsRefineHoldByQuoteId(quoteId); if (hold && hold.customer_id === auth.customerId) { // 填写中不自动放弃;仅在仍可用时透出 hold const pub = toMsRefineHoldPublic(hold); if (pub.available || hold.status === "refining" || hold.status === "filling") { detail.refine_hold = { ...pub, available: hold.status === "refining" || hold.status === "filling" ? true : pub.available, }; } } const checkout = await readMsCheckoutStatus(quoteId); if (checkout) { detail.ms_checkout = toMsCheckoutPublic(checkout); } const flockCheckout = await readFlockCheckoutStatus(quoteId); if (flockCheckout) { detail.flock_checkout = toFlockCheckoutPublic(flockCheckout); } const flockPricing = await readFlockPricingOptions(quoteId); if (flockPricing) { detail.flock_pricing_options = toFlockPricingOptionsPublic(flockPricing); } const flockHold = await readFlockQuoteHoldByQuoteId(quoteId); if (flockHold && flockHold.customer_id === auth.customerId) { if (shouldAutoDeclineFlockHold(flockHold)) { await declineFlockQuoteHold({ customerId: auth.customerId, quoteId, sessionId: flockHold.quote_session_id, }).catch(() => undefined); } else if ( (flockHold.status === "filling" || flockHold.status === "checking_out") && flockHold.total_deadline_ms <= Date.now() ) { await declineFlockQuoteHold({ customerId: auth.customerId, quoteId, sessionId: flockHold.quote_session_id, }).catch(() => undefined); } else { const pub = toFlockQuoteHoldPublic(flockHold); if ( pub.available || flockHold.status === "filling" || flockHold.status === "checking_out" ) { detail.flock_hold = { ...pub, available: flockHold.status === "filling" || flockHold.status === "checking_out" ? true : pub.available, }; } } } const flockFlex = await readFlockHoldFlexibility(quoteId); if (flockFlex && Object.keys(flockFlex).length > 0) { detail.flock_flexibility_by_tier = flockFlex; } const flockCarriers = await readFlockHoldCarriers(quoteId); if (flockCarriers && Object.keys(flockCarriers).length > 0) { detail.flock_carriers_by_tier = flockCarriers; } return ok(detail); }