mcs150: trim FMCSA instruction pages from form templates
The official MCS-150/150B/150C PDFs ship with 8 (150/150B) or 4 (150C) FMCSA instruction/example pages before the actual fillable form. We were generating + faxing/submitting all of them. Trimmed the source templates down to the FORM pages only: MCS-150 11 -> 3 pages (289 fields preserved) MCS-150B 12 -> 4 pages (349 fields preserved) MCS-150C 6 -> 2 pages (33 fields preserved) The filler iterates writer.pages (no absolute index) and signature anchors are derived dynamically via enumerate(reader.pages), so no page-specific markup needed fixing. Removed one-off diag script.
This commit is contained in:
parent
4447905864
commit
386467bedf
5 changed files with 10 additions and 62 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,55 +0,0 @@
|
||||||
"""Diagnostic: inspect the actual MCS-150 fill output.
|
|
||||||
Reports, per page: the AcroForm fields present (name + value + rect), and the
|
|
||||||
rendered text, so we can see WHERE data lands vs WHERE the blank/example fields
|
|
||||||
are. Run in the workers container against the live template + a fresh fill.
|
|
||||||
"""
|
|
||||||
import sys, json
|
|
||||||
sys.path.insert(0, "/app")
|
|
||||||
from pypdf import PdfReader
|
|
||||||
|
|
||||||
TEMPLATE = "/app/docs/MCS-150 Form.pdf"
|
|
||||||
|
|
||||||
|
|
||||||
def field_rows(reader, label):
|
|
||||||
print(f"\n===== {label} =====")
|
|
||||||
for i, pg in enumerate(reader.pages):
|
|
||||||
annots = pg.get("/Annots")
|
|
||||||
if not annots:
|
|
||||||
continue
|
|
||||||
annots = annots.get_object() if hasattr(annots, "get_object") else annots
|
|
||||||
rows = []
|
|
||||||
for a in annots:
|
|
||||||
o = a.get_object()
|
|
||||||
t = o.get("/T")
|
|
||||||
if t is None and o.get("/Parent"):
|
|
||||||
t = o["/Parent"].get_object().get("/T")
|
|
||||||
v = o.get("/V")
|
|
||||||
rect = o.get("/Rect")
|
|
||||||
ft = o.get("/FT")
|
|
||||||
if t:
|
|
||||||
rows.append((str(t), str(ft), str(v) if v is not None else "", [round(float(x)) for x in rect] if rect else None))
|
|
||||||
if rows:
|
|
||||||
print(f"-- PDF page {i+1} ({len(rows)} fields) --")
|
|
||||||
for name, ft, val, rect in rows:
|
|
||||||
vstr = f" = {val!r}" if val else ""
|
|
||||||
print(f" {name} [{ft}]{vstr} rect={rect}")
|
|
||||||
|
|
||||||
|
|
||||||
# 1) the template as-is — what fields + any example values?
|
|
||||||
r = PdfReader(TEMPLATE)
|
|
||||||
field_rows(r, "TEMPLATE (original)")
|
|
||||||
|
|
||||||
# 2) a fresh fill
|
|
||||||
from scripts.document_gen.templates.mcs150_pdf_filler import fill_mcs150
|
|
||||||
intake = {
|
|
||||||
"dot_number": "1609564", "legal_name": "MITCHELL W ALLEN",
|
|
||||||
"dba_name": "", "entity_type": "sole_proprietorship",
|
|
||||||
"business_street": "123 Main St", "business_city": "Town",
|
|
||||||
"business_state": "TX", "business_zip": "75001",
|
|
||||||
"phone": "5125551234", "ein": "123456789",
|
|
||||||
"signer_name": "Mitchell W Allen", "signer_title": "Owner",
|
|
||||||
"power_units": "2", "drivers": "1",
|
|
||||||
}
|
|
||||||
p = fill_mcs150(intake, order_number="DIAG")
|
|
||||||
print("\nfilled file:", p)
|
|
||||||
field_rows(PdfReader(p), "FILLED")
|
|
||||||
|
|
@ -4,10 +4,12 @@ Fills the official FMCSA MCS-150/150B/150C fillable PDF forms using
|
||||||
intake data from the order. Produces a ready-to-fax or electronically
|
intake data from the order. Produces a ready-to-fax or electronically
|
||||||
submit PDF.
|
submit PDF.
|
||||||
|
|
||||||
Forms stored at:
|
Forms stored at (FORM pages only -- the FMCSA instruction/example pages are
|
||||||
docs/MCS-150 Form.pdf — standard (289 fields)
|
trimmed off the source PDFs so the filled output is fax/submit-ready and never
|
||||||
docs/MCS-150B Form.pdf — hazmat safety permit (349 fields)
|
includes the instruction pages):
|
||||||
docs/MCS-150C Form.pdf — intermodal equipment (33 fields)
|
docs/MCS-150 Form.pdf — standard (3 pages, 289 fields)
|
||||||
|
docs/MCS-150B Form.pdf — hazmat safety permit (4 pages, 349 fields)
|
||||||
|
docs/MCS-150C Form.pdf — intermodal equipment (2 pages, 33 fields)
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
from scripts.document_gen.templates.mcs150_pdf_filler import fill_mcs150
|
from scripts.document_gen.templates.mcs150_pdf_filler import fill_mcs150
|
||||||
|
|
@ -209,9 +211,10 @@ def fill_mcs150(intake: dict, order_number: str = "") -> str:
|
||||||
checkbox_on["certifyBox"] = True
|
checkbox_on["certifyBox"] = True
|
||||||
|
|
||||||
# ── Apply fields to PDF ──────────────────────────────────────────
|
# ── Apply fields to PDF ──────────────────────────────────────────
|
||||||
# Apply text-field values to every page. The fields live on pages 9-11 of
|
# Apply text-field values to every page. The template ships with only the
|
||||||
# the official form, so we update across all pages (pypdf silently ignores
|
# fillable FORM pages (the FMCSA instruction pages are trimmed off the
|
||||||
# field names not present on a given page). auto_regenerate=True makes pypdf
|
# source PDF so we never fax/submit them), so we update across all pages
|
||||||
|
# (pypdf silently ignores field names not present on a given page). auto_regenerate=True makes pypdf
|
||||||
# build appearance streams from the values, so viewers that ignore
|
# build appearance streams from the values, so viewers that ignore
|
||||||
# /NeedAppearances (Preview, Chrome) still render the text.
|
# /NeedAppearances (Preview, Chrome) still render the text.
|
||||||
text_values = {k: v for k, v in field_updates.items() if v}
|
text_values = {k: v for k, v in field_updates.items() if v}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue