mcs150: census-prefilled intake-completion flow + completeness gate

Closes the data gap for orders that bypass the full intake (e.g. the DOT
compliance-remediation pipeline) and for all MCS-150 variants:

- Worker intake-completeness gate (mcs150_update): before filling, check the
  customer-required operational fields the FMCSA census cannot supply
  (operation classification, cargo, CURRENT annual mileage, email; plus
  signer/address for new-registration/reactivation, and states-of-operation
  for 150B hazmat). If missing, email the customer a census-pre-filled intake
  link and hold the order at fulfillment_status='awaiting_intake' with an admin
  todo, instead of fabricating a blank filing. The existing intake PUT endpoint
  already re-dispatches the worker on submit, so filing auto-resumes.
- Intake wizard (Wizard.astro): when resuming ?order=CO-xxx for a DOT/MCS order,
  seed still-empty fields from the FMCSA census (name/address/fleet/interstate)
  so the customer only confirms the operational details.
- /api/v1/dot/census now also returns total_drivers + a normalized
  carrier_operation_code for the prefill.
- MCS150Step.astro extended to collect every field the filler needs across all
  variants: mailing address, cdl_drivers, primary_vehicle_type,
  reason_for_filing, usdot_revoked, cell/fax, hazmat-safety-permit block
  (needs_hmsp, operating states, security plan), and intermodal-equipment
  provider counts; all prefill from intake_data.

verify_mcs150_variants.py covers 150/150B/150C end-to-end (ALL PASS).
This commit is contained in:
justin 2026-06-10 14:03:28 -05:00
parent 38739e023c
commit a3aeedd716
4 changed files with 439 additions and 2 deletions

View file

@ -973,8 +973,14 @@ router.get("/api/v1/dot/census", async (req, res) => {
phy_zip: c.phy_zip || null,
power_units: c.nbr_power_unit ?? null,
drivers: c.driver_total ?? null,
total_drivers: c.driver_total ?? null,
for_hire: c.authorized_for_hire || false,
carrier_operation: c.carrier_operation || null,
// Normalized interstate/intrastate code (A/B/C) if the stored value
// encodes it, for the intake prefill.
carrier_operation_code: (typeof c.carrier_operation === "string"
&& /^[ABC]$/i.test(c.carrier_operation.trim()))
? c.carrier_operation.trim().toUpperCase() : null,
});
} catch (err) {
console.error("[dot-census] Error:", err);