"""MCS-150 Biennial Update Form Generator. Generates a filled MCS-150 form as DOCX (converted to PDF) for faxing to FMCSA at 202-366-3477. The generated document mirrors the official FMCSA Form MCS-150 layout with all fields populated from intake data. Includes a cover sheet with fax instructions. Usage: from scripts.document_gen.templates.mcs150_form_generator import generate_mcs150 paths = generate_mcs150(intake_data, order_number="CO-12345") """ from __future__ import annotations import logging import os import tempfile from datetime import datetime from pathlib import Path LOG = logging.getLogger("document_gen.mcs150_form") try: from docx import Document from docx.shared import Pt, Inches, RGBColor, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT from docx.oxml.ns import qn except ImportError: LOG.warning("python-docx not installed") Document = None NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None ORANGE = RGBColor(0xF9, 0x73, 0x16) if Document else None GRAY = RGBColor(0x64, 0x74, 0x8B) if Document else None FMCSA_FAX = "202-366-3477" FMCSA_ADDRESS = ( "Federal Motor Carrier Safety Administration\n" "Office of Registration and Safety Information\n" "1200 New Jersey Avenue SE, Room W65-206\n" "Washington, DC 20590" ) CARGO_LABELS = { "general": "General Freight", "household": "Household Goods", "metal": "Metal/Sheets/Coils", "motor_vehicles": "Motor Vehicles", "drivetow": "Drive/Tow Away", "logs": "Logs/Poles/Lumber", "building_materials": "Building Materials", "mobile_homes": "Mobile Homes", "machinery": "Machinery/Large Objects", "fresh_produce": "Fresh Produce", "liquids": "Liquids/Gases", "intermodal": "Intermodal Containers", "passengers": "Passengers", "oilfield": "Oilfield Equipment", "livestock": "Livestock", "grain": "Grain/Feed/Hay", "coal": "Coal/Coke", "meat": "Meat", "garbage": "Garbage/Refuse", "chemicals": "Chemicals", "commodities_dry": "Commodities Dry Bulk", "refrigerated": "Refrigerated Food", "beverages": "Beverages", "paper": "Paper Products", "utilities": "Utility", "farm_supplies": "Farm Supplies", "construction": "Construction", "water_well": "Water Well", "other": "Other", } ENTITY_TYPE_LABELS = { "sole_proprietorship": "Sole Proprietorship", "partnership": "Partnership", "corporation": "Corporation", "llc": "Limited Liability Company (LLC)", "other": "Other", } CARRIER_OP_LABELS = { "authorized_for_hire": "Authorized For-Hire", "exempt_for_hire": "Exempt For-Hire", "private_property": "Private (Property)", "private_passengers": "Private (Passengers)", "us_mail": "U.S. Mail", "federal_government": "Federal Government", "state_government": "State Government", "local_government": "Local Government", "indian_tribe": "Indian Tribe", } INTERSTATE_LABELS = { "interstate": "Interstate", "intrastate_hazmat": "Intrastate — Hazmat", "intrastate_non_hazmat": "Intrastate — Non-Hazmat", } def _set_cell(cell, text, bold=False, size=10, color=None): """Set cell text with formatting.""" cell.text = "" p = cell.paragraphs[0] run = p.add_run(str(text)) run.font.size = Pt(size) run.font.name = "Calibri" if bold: run.font.bold = True if color: run.font.color.rgb = color def _add_field_row(table, label, value, bold_value=False): """Add a label-value row to a table.""" row = table.add_row() _set_cell(row.cells[0], label, bold=True, size=9, color=GRAY) _set_cell(row.cells[1], value or "—", bold=bold_value, size=10) return row def generate_mcs150(intake: dict, order_number: str = "") -> list[str]: """Generate MCS-150 form document. Args: intake: Dict with all MCS-150 fields from the intake form. order_number: Order number for reference. Returns: List of generated file paths (DOCX). """ if Document is None: LOG.error("python-docx not installed") return [] doc = Document() # Page setup section = doc.sections[0] section.page_width = Inches(8.5) section.page_height = Inches(11) section.top_margin = Inches(0.75) section.bottom_margin = Inches(0.5) section.left_margin = Inches(0.75) section.right_margin = Inches(0.75) # ── Cover Sheet ────────────────────────────────────────────────── p = doc.add_paragraph() p.alignment = WD_ALIGN_PARAGRAPH.CENTER run = p.add_run("FAX COVER SHEET") run.font.size = Pt(18) run.font.bold = True run.font.color.rgb = NAVY p2 = doc.add_paragraph() p2.alignment = WD_ALIGN_PARAGRAPH.CENTER run2 = p2.add_run("MCS-150 BIENNIAL UPDATE") run2.font.size = Pt(14) run2.font.bold = True run2.font.color.rgb = ORANGE doc.add_paragraph("") # Fax details table cover_table = doc.add_table(rows=0, cols=2) cover_table.columns[0].width = Inches(1.5) cover_table.columns[1].width = Inches(5.5) for label, value in [ ("TO:", "FMCSA — Office of Registration and Safety Information"), ("FAX:", FMCSA_FAX), ("FROM:", "Performance West Inc."), ("DATE:", datetime.now().strftime("%B %d, %Y")), ("RE:", f"MCS-150 Biennial Update — {intake.get('legal_name', '')} (DOT# {intake.get('dot_number', '')})"), ("ORDER:", order_number), ("PAGES:", "2 (including cover)"), ]: row = cover_table.add_row() _set_cell(row.cells[0], label, bold=True, size=11) _set_cell(row.cells[1], value, size=11) doc.add_paragraph("") note = doc.add_paragraph() run_note = note.add_run( "Please process the attached MCS-150 Biennial Update for the carrier identified above. " "This filing is submitted on behalf of the carrier by Performance West Inc., " "an authorized compliance consulting firm. " "The carrier has authorized this filing as part of their compliance service agreement." ) run_note.font.size = Pt(10) run_note.font.color.rgb = GRAY doc.add_paragraph("") contact = doc.add_paragraph() run_c = contact.add_run( "Performance West Inc.\n" "525 Randall Ave Ste 100-1195, Cheyenne, WY 82001\n" "Phone: (888) 411-0383 | Fax: (888) 411-0383\n" "info@performancewest.net" ) run_c.font.size = Pt(9) run_c.font.color.rgb = GRAY # Page break for the actual form doc.add_page_break() # ── MCS-150 Form ───────────────────────────────────────────────── header = doc.add_paragraph() header.alignment = WD_ALIGN_PARAGRAPH.CENTER h_run = header.add_run("FORM MCS-150 — MOTOR CARRIER IDENTIFICATION REPORT") h_run.font.size = Pt(14) h_run.font.bold = True h_run.font.color.rgb = NAVY sub = doc.add_paragraph() sub.alignment = WD_ALIGN_PARAGRAPH.CENTER s_run = sub.add_run("BIENNIAL UPDATE") s_run.font.size = Pt(11) s_run.font.color.rgb = ORANGE s_run.font.bold = True doc.add_paragraph("") # Section A: Entity Information sec_a = doc.add_paragraph() run_a = sec_a.add_run("SECTION A: ENTITY INFORMATION") run_a.font.size = Pt(11) run_a.font.bold = True run_a.font.color.rgb = NAVY table_a = doc.add_table(rows=0, cols=2) table_a.columns[0].width = Inches(2.5) table_a.columns[1].width = Inches(4.5) _add_field_row(table_a, "1. Legal Entity Name", intake.get("legal_name", ""), bold_value=True) _add_field_row(table_a, "2. DBA / Trade Name", intake.get("dba_name", "")) _add_field_row(table_a, "USDOT Number", intake.get("dot_number", ""), bold_value=True) _add_field_row(table_a, "MC/MX/FF Number", intake.get("mc_number", "")) address = f"{intake.get('address_street', '')}" city_state_zip = f"{intake.get('address_city', '')}, {intake.get('address_state', '')} {intake.get('address_zip', '')}" _add_field_row(table_a, "3-6. Principal Address", address) _add_field_row(table_a, "", city_state_zip) _add_field_row(table_a, "Phone", intake.get("phone", "")) doc.add_paragraph("") # Section B: Entity Type & Operations sec_b = doc.add_paragraph() run_b = sec_b.add_run("SECTION B: ENTITY TYPE & OPERATIONS") run_b.font.size = Pt(11) run_b.font.bold = True run_b.font.color.rgb = NAVY table_b = doc.add_table(rows=0, cols=2) table_b.columns[0].width = Inches(2.5) table_b.columns[1].width = Inches(4.5) entity_type = ENTITY_TYPE_LABELS.get(intake.get("entity_type", ""), intake.get("entity_type", "")) carrier_op = CARRIER_OP_LABELS.get(intake.get("carrier_operation", ""), intake.get("carrier_operation", "")) interstate = INTERSTATE_LABELS.get(intake.get("interstate_intrastate", ""), intake.get("interstate_intrastate", "")) hazmat = "Yes" if intake.get("hazmat") == "yes" else "No" _add_field_row(table_b, "Entity Type", entity_type) _add_field_row(table_b, "Carrier Operation", carrier_op) _add_field_row(table_b, "Interstate/Intrastate", interstate) _add_field_row(table_b, "Hazardous Materials", hazmat, bold_value=(hazmat == "Yes")) doc.add_paragraph("") # Section C: Fleet Information sec_c = doc.add_paragraph() run_c2 = sec_c.add_run("SECTION C: FLEET INFORMATION") run_c2.font.size = Pt(11) run_c2.font.bold = True run_c2.font.color.rgb = NAVY table_c = doc.add_table(rows=0, cols=2) table_c.columns[0].width = Inches(2.5) table_c.columns[1].width = Inches(4.5) power_units = intake.get("power_units", "") drivers = intake.get("drivers", "") miles = intake.get("annual_miles", "") if miles: try: miles = f"{int(miles):,}" except (ValueError, TypeError): pass _add_field_row(table_c, "Number of Power Units", str(power_units), bold_value=True) _add_field_row(table_c, "Number of Drivers", str(drivers), bold_value=True) _add_field_row(table_c, "Annual Miles (last 12 mo.)", str(miles) if miles else "—") doc.add_paragraph("") # Section D: Cargo Types sec_d = doc.add_paragraph() run_d = sec_d.add_run("SECTION D: CARGO CLASSIFICATIONS") run_d.font.size = Pt(11) run_d.font.bold = True run_d.font.color.rgb = NAVY cargo_types = intake.get("cargo_types", []) if cargo_types: cargo_labels = [CARGO_LABELS.get(c, c.replace("_", " ").title()) for c in cargo_types] cargo_p = doc.add_paragraph() cargo_run = cargo_p.add_run(", ".join(cargo_labels)) cargo_run.font.size = Pt(10) else: cargo_p = doc.add_paragraph() cargo_run = cargo_p.add_run("None specified") cargo_run.font.size = Pt(10) cargo_run.font.color.rgb = GRAY doc.add_paragraph("") # Section E: Certification sec_e = doc.add_paragraph() run_e = sec_e.add_run("SECTION E: CERTIFICATION") run_e.font.size = Pt(11) run_e.font.bold = True run_e.font.color.rgb = NAVY cert_text = doc.add_paragraph() cert_run = cert_text.add_run( "I certify that the information contained in this report is accurate and complete " "to the best of my knowledge and belief. I understand that making a false statement " "or misrepresentation on this form may subject the filer to criminal penalties under " "18 U.S.C. § 1001." ) cert_run.font.size = Pt(9) cert_run.font.italic = True cert_run.font.color.rgb = GRAY doc.add_paragraph("") table_e = doc.add_table(rows=0, cols=2) table_e.columns[0].width = Inches(2.5) table_e.columns[1].width = Inches(4.5) signer_name = intake.get("signer_name", "") signer_title = intake.get("signer_title", "") _add_field_row(table_e, "Authorized Signer", signer_name, bold_value=True) _add_field_row(table_e, "Title", signer_title) _add_field_row(table_e, "Date", datetime.now().strftime("%B %d, %Y")) doc.add_paragraph("") # Signature line sig = doc.add_paragraph() sig_run = sig.add_run("_" * 50) sig_run.font.size = Pt(10) sig2 = doc.add_paragraph() sig2_run = sig2.add_run("Signature of Authorized Official") sig2_run.font.size = Pt(9) sig2_run.font.color.rgb = GRAY # Footer doc.add_paragraph("") footer = doc.add_paragraph() footer.alignment = WD_ALIGN_PARAGRAPH.CENTER f_run = footer.add_run( f"Prepared by Performance West Inc. | Order {order_number} | {datetime.now().strftime('%Y-%m-%d')}" ) f_run.font.size = Pt(8) f_run.font.color.rgb = GRAY # Save work_dir = tempfile.mkdtemp(prefix="pw_mcs150_") date_str = datetime.now().strftime("%Y%m%d") dot = intake.get("dot_number", "unknown") filename = f"MCS150_DOT{dot}_{date_str}.docx" filepath = os.path.join(work_dir, filename) doc.save(filepath) LOG.info("Generated MCS-150 form: %s", filepath) return [filepath] if __name__ == "__main__": # Test with sample data test_intake = { "legal_name": "ADAMS LUMBER INC", "dba_name": "Adams Trucking", "dot_number": "1157913", "mc_number": "MC-456789", "address_street": "123 Timber Lane", "address_city": "Portland", "address_state": "OR", "address_zip": "97201", "phone": "(503) 555-1234", "entity_type": "corporation", "carrier_operation": "authorized_for_hire", "interstate_intrastate": "interstate", "hazmat": "no", "power_units": "5", "drivers": "6", "annual_miles": "250000", "cargo_types": ["general", "building_materials", "logs"], "signer_name": "Mark Adams", "signer_title": "President", } paths = generate_mcs150(test_intake, order_number="CO-TEST123") print(f"Generated: {paths}")