add POST /api/v1/dot/name-check: parallel SOS + FMCSA name availability check
- Checks state SOS for entity name availability (via workers adapter) - Checks FMCSA census for exact + fuzzy name matches - Returns: sos_available, fmcsa_in_use, fmcsa_matches, combined 'available' flag - 20s timeout on SOS lookup, FMCSA query is instant (local DB)
This commit is contained in:
parent
340a364d8c
commit
08e80e11f9
1 changed files with 93 additions and 0 deletions
|
|
@ -669,6 +669,99 @@ router.get("/api/v1/dot/search", async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// ── Name Availability Check (SOS + FMCSA parallel) ───────────────
|
||||
|
||||
router.post("/api/v1/dot/name-check", async (req, res) => {
|
||||
const { name, state } = req.body ?? {};
|
||||
if (!name || name.length < 2) {
|
||||
res.status(400).json({ error: "name is required (at least 2 characters)." });
|
||||
return;
|
||||
}
|
||||
const stateCode = (state || "").toUpperCase().trim();
|
||||
|
||||
try {
|
||||
// Run SOS check and FMCSA check in parallel
|
||||
const [sosResult, fmcsaResult] = await Promise.allSettled([
|
||||
// 1. SOS name availability via workers /entity-status
|
||||
stateCode && stateCode.length === 2
|
||||
? fetch(`${WORKER_URL}/entity-status`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ entity_name: name, state_code: stateCode }),
|
||||
signal: AbortSignal.timeout(20000),
|
||||
}).then(r => r.json())
|
||||
: Promise.resolve({ skipped: true }),
|
||||
|
||||
// 2. FMCSA census — exact and fuzzy name match
|
||||
pool.query(
|
||||
`SELECT dot_number, legal_name, dba_name, phy_state, carrier_operation
|
||||
FROM fmcsa_carriers
|
||||
WHERE legal_name ILIKE $1 OR dba_name ILIKE $1
|
||||
ORDER BY CASE WHEN UPPER(legal_name) = UPPER($2) THEN 0 ELSE 1 END, legal_name
|
||||
LIMIT 20`,
|
||||
[`%${name}%`, name],
|
||||
),
|
||||
]);
|
||||
|
||||
// Parse SOS result
|
||||
let sosAvailable: boolean | null = null;
|
||||
let sosEntity: Record<string, unknown> | null = null;
|
||||
if (sosResult.status === "fulfilled") {
|
||||
const sos = sosResult.value as Record<string, unknown>;
|
||||
if (sos.skipped) {
|
||||
sosAvailable = null; // No state provided
|
||||
} else if (sos.found) {
|
||||
sosAvailable = false; // Name is taken
|
||||
sosEntity = sos as Record<string, unknown>;
|
||||
} else {
|
||||
sosAvailable = true; // Name is available
|
||||
}
|
||||
}
|
||||
|
||||
// Parse FMCSA result
|
||||
let fmcsaMatches: Record<string, unknown>[] = [];
|
||||
let fmcsaExactMatch = false;
|
||||
if (fmcsaResult.status === "fulfilled") {
|
||||
fmcsaMatches = fmcsaResult.value.rows || [];
|
||||
fmcsaExactMatch = fmcsaMatches.some(
|
||||
(r: Record<string, unknown>) =>
|
||||
(r.legal_name as string || "").toUpperCase() === name.toUpperCase(),
|
||||
);
|
||||
}
|
||||
|
||||
res.json({
|
||||
name,
|
||||
state: stateCode || null,
|
||||
sos_available: sosAvailable,
|
||||
sos_entity: sosEntity ? {
|
||||
status: sosEntity.status,
|
||||
entity_number: sosEntity.entity_number,
|
||||
entity_type: sosEntity.entity_type,
|
||||
} : null,
|
||||
fmcsa_in_use: fmcsaExactMatch,
|
||||
fmcsa_matches: fmcsaMatches.slice(0, 10).map((r: Record<string, unknown>) => ({
|
||||
dot_number: r.dot_number,
|
||||
legal_name: r.legal_name,
|
||||
dba_name: r.dba_name,
|
||||
state: r.phy_state,
|
||||
})),
|
||||
available: sosAvailable !== false && !fmcsaExactMatch,
|
||||
message: fmcsaExactMatch
|
||||
? `"${name}" is already registered with FMCSA (DOT# ${(fmcsaMatches.find((r: Record<string, unknown>) => (r.legal_name as string || "").toUpperCase() === name.toUpperCase()) as Record<string, unknown>)?.dot_number}). Choose a different name or use your existing entity.`
|
||||
: sosAvailable === false
|
||||
? `"${name}" is already registered in ${stateCode}. The name may still be usable if it's your entity.`
|
||||
: sosAvailable === true
|
||||
? `"${name}" is available in ${stateCode} and not found in FMCSA records.`
|
||||
: !stateCode
|
||||
? `"${name}" ${fmcsaExactMatch ? "is" : "is not"} found in FMCSA records. Provide a state to also check Secretary of State availability.`
|
||||
: `Could not verify availability. Check with the ${stateCode} Secretary of State directly.`,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[name-check] Error:", err);
|
||||
res.status(500).json({ error: "Name check failed." });
|
||||
}
|
||||
});
|
||||
|
||||
// ── State Requirements Lookup ──────────────────────────────────────
|
||||
|
||||
router.get("/api/v1/dot/state-requirements", async (req, res) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue