From fc1a0588f71f8e9fa137b54d1b36eb258534900d Mon Sep 17 00:00:00 2001 From: justin Date: Tue, 2 Jun 2026 03:34:40 -0500 Subject: [PATCH] feat(advisory): prerequisite-aware DOT lookup + state recommendations - DOT lookup now returns prerequisite_status {usdot_active, authority_active, authority_pending} from live FMCSA data so the order flow can advise sequencing BEFORE a customer places an order. - State-requirements recommendations annotated with prerequisite + label (e.g. IRP/IFTA/state taxes need an active USDOT) for UI warnings. --- api/src/routes/dot-lookup.ts | 47 +++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/api/src/routes/dot-lookup.ts b/api/src/routes/dot-lookup.ts index 7078ad4..6682927 100644 --- a/api/src/routes/dot-lookup.ts +++ b/api/src/routes/dot-lookup.ts @@ -598,6 +598,20 @@ router.get("/api/v1/dot/lookup", async (req, res) => { const yellowCount = checks.filter(c => c.status === "yellow").length; if (res.headersSent) return; // deadline already responded + + // Prerequisite status — lets the order flow / advisory know whether the + // upstream items a state/authority service depends on are ACTIVE at FMCSA, + // so we can advise sequencing BEFORE the customer places an order. + const usdotActive = carrier?.allowedToOperate === "Y" + && !carrier?.oosDate + && (carrier?.statusCode === "A" || carrier?.statusCode == null); + const authorityActive = carrier?.commonAuthorityStatus === "A" + || carrier?.contractAuthorityStatus === "A" + || carrier?.brokerAuthorityStatus === "A"; + const authorityPending = carrier?.commonAuthorityStatus === "P" + || carrier?.contractAuthorityStatus === "P" + || carrier?.brokerAuthorityStatus === "P"; + res.json({ dot_number: rawDot, legal_name: name, @@ -613,6 +627,11 @@ router.get("/api/v1/dot/lookup", async (req, res) => { mcs150_date: census?.mcs150_parsed || null, carrier_type: carrier?.censusTypeId?.censusTypeDesc || census?.carrier_operation || null, for_hire: census?.authorized_for_hire || false, + prerequisite_status: { + usdot_active: Boolean(usdotActive), + authority_active: Boolean(authorityActive), + authority_pending: Boolean(authorityPending), + }, checks, summary: { red: redCount, @@ -878,16 +897,38 @@ router.get("/api/v1/dot/state-requirements", async (req, res) => { const seen = new Set(); const uniqueRecs = recommended.filter(r => { if (seen.has(r.slug)) return false; seen.add(r.slug); return true; }); + // Prerequisite-awareness: annotate each recommendation with what must be + // active at FMCSA before it can be filed, so the UI can warn / sequence + // services rather than letting a customer order something blocked. + const PREREQUISITES: Record = { + "irp-registration": { needs: "usdot_active", label: "an active USDOT number" }, + "ifta-application": { needs: "usdot_active", label: "an active USDOT number" }, + "ifta-quarterly": { needs: "ifta_account", label: "an active IFTA account" }, + "intrastate-authority": { needs: "usdot_active", label: "an active USDOT number" }, + "or-weight-mile-tax": { needs: "usdot_active", label: "an active USDOT number" }, + "ny-hut-registration": { needs: "usdot_active", label: "an active USDOT number" }, + "ky-kyu-registration": { needs: "usdot_active", label: "an active USDOT number" }, + "nm-weight-distance": { needs: "usdot_active", label: "an active USDOT number" }, + "ct-highway-use-fee": { needs: "usdot_active", label: "an active USDOT number" }, + "ca-mcp-carb": { needs: "usdot_active", label: "an active USDOT number" }, + }; + const annotatedRecs = uniqueRecs.map(r => { + const pre = PREREQUISITES[r.slug]; + return pre + ? { ...r, prerequisite: pre.needs, prerequisite_label: pre.label } + : r; + }); + // Add bundle if 3+ recommendations - if (uniqueRecs.length >= 3) { - uniqueRecs.push({ slug: "state-trucking-bundle", name: "State Compliance Bundle", price_cents: 59900, reason: "Bundle saves vs. individual services" }); + if (annotatedRecs.length >= 3) { + annotatedRecs.push({ slug: "state-trucking-bundle", name: "State Compliance Bundle", price_cents: 59900, reason: "Bundle saves vs. individual services" }); } res.json({ base_state: baseState || null, operating_states: opStates, requirements, - recommended_services: uniqueRecs, + recommended_services: annotatedRecs, }); } catch (err) { console.error("[dot-state-requirements] Error:", err);