mcs150 handler: derive admin-assisted intake from census; gate ready_to_file

Admin-assisted DOT services (UCR, BOC-3) routed to this handler were marked
ready_to_file with whatever intake existed -- e.g. a UCR with only a DOT number,
missing legal name / state / fleet-size bracket (which sets the UCR fee tier).
That made the admin 'ready to file' status dishonest and unfileable.

Now, for ADMIN_ASSISTED_REQUIRED services we first enrich intake from the FMCSA
census (legal_name, address_state, power_units) + the order email, and derive
the UCR fleet_size_bracket from power units (UCR_FLEET_BRACKETS). If every
required field is then present we persist it and mark intake validated (falls
through to the admin review gate -> ready_to_file). If anything is still
missing, we persist what we have, set fulfillment_status=awaiting_intake, and
email the customer to complete intake -- instead of falsely showing ready_to_file.
This commit is contained in:
justin 2026-06-16 02:46:10 -05:00
parent 8e1e2f16bf
commit 3df3a08221

View file

@ -69,6 +69,34 @@ class MCS150UpdateHandler:
"dot-full-compliance",
})
# Admin-assisted DOT services routed to this handler that do NOT produce an
# MCS-150 form, but still need a minimum set of intake fields before a human
# can actually file them. Without this, a paid order would be marked
# ready_to_file with empty intake (e.g. UCR with only a DOT number -- no
# legal name / state / fleet size, which determine the UCR fee bracket and
# the filing itself). Most of these can be DERIVED from the FMCSA census +
# the order email (see _enrich_admin_assisted_intake); we only hold the order
# at awaiting_intake for whatever genuinely can't be filled in. Keys are
# service slugs; values are the required intake_data fields. Mirrors
# REQUIRED_FIELDS in api/src/routes/compliance-orders.ts.
ADMIN_ASSISTED_REQUIRED = {
"ucr-registration": ["dot_number", "legal_name", "address_state", "email", "fleet_size_bracket"],
"boc3-filing": ["dot_number", "legal_name", "email"],
}
# UCR fee tiers by total power units (FMCSA 2025 schedule). Used to derive
# fleet_size_bracket from the carrier's census power-unit count so we don't
# have to ask the customer for something the public record already states.
# (low, high_inclusive, bracket_label)
UCR_FLEET_BRACKETS = [
(0, 2, "0-2"),
(3, 5, "3-5"),
(6, 20, "6-20"),
(21, 100, "21-100"),
(101, 1000, "101-1000"),
(1001, 10**9, "1001+"),
]
async def process(self, order_data: dict) -> list[str]:
"""Entry point called by job_server. Delegates to handle()."""
order_number = order_data.get("order_number", order_data.get("name", ""))
@ -158,6 +186,34 @@ class MCS150UpdateHandler:
order_number, missing)
return []
# INTAKE-COMPLETENESS GATE for admin-assisted (non-MCS-150) services.
# These don't produce a form, but we still must not mark them
# ready_to_file with empty intake (e.g. a UCR with only a DOT number).
# First DERIVE everything we can from the FMCSA census + the order email,
# then -- if any required field is still missing -- email the customer to
# complete intake and hold the order at awaiting_intake. When all
# required fields are present (derived or supplied) we fall through to the
# admin review gate, which marks it ready_to_file for a human to file.
if slug in self.ADMIN_ASSISTED_REQUIRED:
intake = self._enrich_admin_assisted_intake(slug, intake, customer_email)
order_data["intake_data"] = intake # persist derived values downstream
missing = [f for f in self.ADMIN_ASSISTED_REQUIRED[slug]
if intake.get(f) in (None, "", [], {})]
if missing:
self._persist_intake(order_number, intake)
self._set_fulfillment_status(order_number, "awaiting_intake")
self._request_intake_completion(
order_number, entity_name, customer_email, dot_number, missing)
LOG.info("[%s] Admin-assisted %s held for intake; missing=%s",
order_number, slug, missing)
return []
# All required fields present -- persist the census-derived values so
# the admin (and validation) sees a complete intake.
self._persist_intake(order_number, intake)
self._mark_intake_validated(order_number)
LOG.info("[%s] Admin-assisted %s intake complete (derived from census)",
order_number, slug)
# Step 1: Fill the official MCS-150 PDF. Only services that actually file
# an MCS-150 produce the form; the other admin-assisted DOT services
# routed to this handler (UCR, MC authority, audit prep, ETA, name
@ -701,6 +757,76 @@ class MCS150UpdateHandler:
except Exception as exc:
LOG.warning("[%s] Failed to set fulfillment_status=%s: %s", order_number, status, exc)
def _enrich_admin_assisted_intake(self, slug: str, intake: dict, customer_email: str) -> dict:
"""Fill an admin-assisted service's required intake from data we already
have: the FMCSA census (legal_name, address_state, power_units) and the
order's customer_email. Customer-supplied values always win. Returns a
new merged dict; never raises.
"""
out = dict(intake or {})
dot = out.get("dot_number", "")
try:
census = self._fetch_carrier_record(dot) if dot else {}
except Exception as exc: # noqa: BLE001
LOG.warning("[enrich] census fetch failed for DOT %s: %s", dot, exc)
census = {}
# Census fills only what the customer didn't already provide.
for k in ("legal_name", "address_state", "address_city", "address_street",
"address_zip", "power_units", "ein", "phone"):
if not out.get(k) and census.get(k):
out[k] = census[k]
# Contact email: fall back to the order's customer email.
if not out.get("email") and customer_email:
out["email"] = customer_email
# UCR fee bracket: derive from power units when not supplied.
if slug == "ucr-registration" and not out.get("fleet_size_bracket"):
pu = out.get("power_units") or census.get("power_units")
try:
n = int(str(pu).strip())
except (TypeError, ValueError):
n = None
if n is not None:
for lo, hi, label in self.UCR_FLEET_BRACKETS:
if lo <= n <= hi:
out["fleet_size_bracket"] = label
break
return out
def _persist_intake(self, order_number: str, intake: dict):
"""Write the (possibly census-enriched) intake_data back to the order so
the admin view, validation, and any later re-dispatch see it."""
try:
import psycopg2
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
with conn.cursor() as cur:
cur.execute(
"UPDATE compliance_orders SET intake_data=%s, updated_at=now() "
"WHERE order_number=%s",
(json.dumps(intake), order_number),
)
conn.commit()
conn.close()
except Exception as exc: # noqa: BLE001
LOG.warning("[%s] Failed to persist intake_data: %s", order_number, exc)
def _mark_intake_validated(self, order_number: str):
"""Flag intake as complete so the order stops getting reminder nudges and
the admin sees a green 'intake complete'. Only call once every required
field is present (derived or supplied)."""
try:
import psycopg2
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
with conn.cursor() as cur:
cur.execute(
"UPDATE compliance_orders SET intake_data_validated=TRUE, "
"validation_errors=NULL, updated_at=now() WHERE order_number=%s",
(order_number,),
)
conn.commit()
conn.close()
except Exception as exc: # noqa: BLE001
LOG.warning("[%s] Failed to mark intake validated: %s", order_number, exc)
def _create_admin_review_todo(self, order_number, entity_name, dot_number,
slug, minio_path, customer_email, client_signed):
"""High-priority admin todo: verify the prepared filing BEFORE submission.