new-site/scripts/workers/services/state_trucking_authorization.py
justin 7ed06780bb trucking: stamp e-signature exactly on form signature lines + state authorization gate
Capture-to-form signature placement so the customer's drawn or typed
signature lands right on the signature rule of the actual form, not in a
sidecar page.

- migration 085: esign_records.signature_anchors (JSONB exact PDF coords,
  lower-left origin, points) + signed_document_minio_key
- signature_stamper.py: signature_box() anchors; anchors_from_acroform()
  pulls the signature field /Rect from a real AcroForm (e.g. MCS-150
  certifySignature); stamp_signature() overlays PNG (auto-trimmed so ink
  rests on the rule) or typed name, scaled to actual page size
- state_trucking_authorization.py: renders the Limited Authorization to
  File PDF and returns (pdf_bytes, anchors)
- esign_stamp.py: stamp_esign_document() downloads unsigned PDF, stamps,
  uploads _signed.pdf, sets signed_document_minio_key (idempotent)
- dot_esign.py: extract certifySignature anchor for MCS-150/closeout forms
  so the federal perjury cert is signed on the line
- state_trucking.py: authorization gate — first run emails signing link
  and PAUSES; resumes with client_approved after signing
- job_server handle_esign_completed: stamp then re-dispatch
- tests: test_signature_placement.py (custom form), and
  test_mcs150_signature_placement.py (official AcroForm) both assert the
  signature lands inside the recorded signature box (verified visually)
2026-06-02 16:44:19 -05:00

278 lines
9.6 KiB
Python

"""Generate the state-trucking "Limited Authorization to File" PDF.
This is the signed authorization the customer must provide before Performance
West can file state motor-carrier compliance documents on their behalf (NY HUT,
CT HUF, OR Weight-Mile, CA MCP/CARB, KY KYU, NM WDT, IRP/IFTA, etc.). See
docs/trucking-state-authorization-plan.md.
The generator draws an explicit signature line and records its exact PDF
coordinates via :func:`signature_box`, so the e-signature stamper can place the
client's signature precisely on that line (see signature_stamper.py).
Returns ``(pdf_bytes, anchors)`` where ``anchors`` is the list to persist in
``esign_records.signature_anchors``.
"""
from __future__ import annotations
import io
import logging
from datetime import datetime, timezone
from typing import Any
try: # normal import when loaded as part of the services package
from .signature_stamper import signature_box
except ImportError: # pragma: no cover - standalone/CLI use
from signature_stamper import signature_box # type: ignore
LOG = logging.getLogger("workers.services.state_trucking_authorization")
NAVY = "#0b1f3a"
SLATE = "#475569"
RULE = "#94a3b8"
_AUTH_BODY = (
"By signing below, the Customer named above authorizes Performance West Inc. "
"(\"Performance West\") to act as its limited agent to:"
)
_AUTH_GRANTS = [
"prepare, review, submit, and amend the state motor carrier compliance "
"filing(s) identified in this authorization;",
"access state agency portals or tax systems where representative, "
"practitioner, bulk-filer, or delegate access is available;",
"communicate with state agencies about the filing and receive filing status, "
"notices, confirmations, decals, credentials, and deficiency messages;",
"coordinate with the Customer's insurer or insurance agent for any required "
"insurance filings;",
"remit government fees, taxes, card processing fees, decals, permits, bonds, "
"and pass-through charges when collected from the Customer;",
"retain a copy of this signed authorization for agency audit or request "
"purposes.",
]
_AUTH_ACK = [
"The Customer remains responsible for the accuracy and completeness of the "
"information it provides.",
"Government fees, taxes, card processing fees, bonds/security, decals, "
"permits, and insurance filing costs are pass-through charges and may be "
"billed separately if not known at the time of order.",
"Some state filings require the Customer to grant portal access/delegation or "
"approve account changes; Performance West will request this where needed.",
"This authorization is limited to the filing(s) listed and may be revoked in "
"writing, except as to filings already submitted.",
]
def build_state_trucking_authorization(
*,
order_number: str,
entity_name: str,
service_name: str,
dot_number: str = "",
mc_number: str = "",
fein_last4: str = "",
base_state: str = "",
operating_states: list[str] | None = None,
signer_name: str = "",
signer_title: str = "",
) -> tuple[bytes, list[dict[str, Any]]]:
"""Render the authorization PDF and return (pdf_bytes, signature_anchors)."""
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.pdfgen import canvas
buf = io.BytesIO()
page_w, page_h = letter # 612 x 792
c = canvas.Canvas(buf, pagesize=letter)
left = 0.85 * inch
right = page_w - 0.85 * inch
width = right - left
def wrap(text: str, font: str, size: float, max_w: float) -> list[str]:
c.setFont(font, size)
words = text.split()
lines: list[str] = []
cur = ""
for w in words:
trial = (cur + " " + w).strip()
if c.stringWidth(trial, font, size) <= max_w:
cur = trial
else:
if cur:
lines.append(cur)
cur = w
if cur:
lines.append(cur)
return lines
y = page_h - 0.9 * inch
# Header
c.setFillColor(HexColor(NAVY))
c.setFont("Helvetica-Bold", 16)
c.drawString(left, y, "Performance West Inc.")
y -= 18
c.setFont("Helvetica", 9.5)
c.setFillColor(HexColor(SLATE))
c.drawString(left, y, "DOT / State Motor Carrier Compliance Division | (888) 411-0383 | performancewest.net")
y -= 8
c.setStrokeColor(HexColor(RULE))
c.line(left, y, right, y)
y -= 26
c.setFillColor(HexColor(NAVY))
c.setFont("Helvetica-Bold", 13.5)
c.drawString(left, y, "Limited Authorization to File State Motor Carrier Compliance Documents")
y -= 22
# Customer / order block
def field_row(label: str, value: str) -> None:
nonlocal y
c.setFont("Helvetica-Bold", 10)
c.setFillColor(HexColor(NAVY))
c.drawString(left, y, label)
c.setFont("Helvetica", 10)
c.setFillColor(HexColor("#1f2937"))
c.drawString(left + 1.6 * inch, y, value or "")
y -= 15
states = ", ".join(operating_states or []) if operating_states else (base_state or "")
field_row("Customer (Carrier):", entity_name)
field_row("USDOT #:", dot_number)
if mc_number:
field_row("MC/MX/FF #:", mc_number)
if fein_last4:
field_row("FEIN (last 4):", fein_last4)
field_row("Covered filing:", service_name)
field_row("Covered state(s):", states)
field_row("Order #:", order_number)
y -= 8
# Body intro
c.setFillColor(HexColor("#1f2937"))
for ln in wrap(_AUTH_BODY, "Helvetica", 10, width):
c.setFont("Helvetica", 10)
c.drawString(left, y, ln)
y -= 14
y -= 4
# Numbered grants
for i, grant in enumerate(_AUTH_GRANTS, 1):
bullet = f"{i}."
c.setFont("Helvetica-Bold", 10)
c.drawString(left, y, bullet)
lines = wrap(grant, "Helvetica", 10, width - 0.3 * inch)
for j, ln in enumerate(lines):
c.setFont("Helvetica", 10)
c.drawString(left + 0.3 * inch, y, ln)
y -= 13
y -= 3
y -= 6
c.setFont("Helvetica-Bold", 10.5)
c.setFillColor(HexColor(NAVY))
c.drawString(left, y, "Acknowledgements")
y -= 16
for ack in _AUTH_ACK:
c.setFillColor(HexColor("#475569"))
c.setFont("Helvetica", 9.5)
c.drawString(left, y, "\u2022")
for j, ln in enumerate(wrap(ack, "Helvetica", 9.5, width - 0.25 * inch)):
c.drawString(left + 0.25 * inch, y, ln)
y -= 12
y -= 2
# ── Signature block ──────────────────────────────────────────────
# Reserve a fixed band near the bottom so the signature line position is
# deterministic. The signature box sits ON TOP of the rule.
sig_rule_y = 1.55 * inch
sig_box_h = 42.0
sig_box_w = 3.1 * inch
sig_x = left
c.setFillColor(HexColor(NAVY))
c.setFont("Helvetica-Bold", 10.5)
c.drawString(left, sig_rule_y + sig_box_h + 14, "Authorized Signature")
# The signature rule
c.setStrokeColor(HexColor("#334155"))
c.setLineWidth(1)
c.line(sig_x, sig_rule_y, sig_x + sig_box_w, sig_rule_y)
# Date rule to the right
date_x = sig_x + sig_box_w + 0.5 * inch
date_w = right - date_x
c.line(date_x, sig_rule_y, right, sig_rule_y)
c.setFont("Helvetica", 8.5)
c.setFillColor(HexColor(SLATE))
c.drawString(sig_x, sig_rule_y - 11, "Signature")
c.drawString(date_x, sig_rule_y - 11, "Date")
# Printed name / title beneath
ny = sig_rule_y - 30
c.setFont("Helvetica", 9.5)
c.setFillColor(HexColor("#1f2937"))
c.drawString(sig_x, ny, f"Printed name: {signer_name or '________________________'}")
c.drawString(date_x, ny, f"Title: {signer_title or '____________'}")
# Footer note
c.setFont("Helvetica-Oblique", 7.5)
c.setFillColor(HexColor("#94a3b8"))
c.drawString(
left,
0.75 * inch,
f"Generated {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')} | "
f"Order {order_number} | Performance West Inc.",
)
c.save()
buf.seek(0)
pdf_bytes = buf.getvalue()
# Record the exact signature box so the stamper lands the signature on the
# rule. The box bottom == the rule's y, height extends upward.
anchors = [
signature_box(
field="signer",
page=0,
x=sig_x + 4, # small inset from the line's left end
y=sig_rule_y + 1, # rest the signature just on top of the rule
w=sig_box_w - 8,
h=sig_box_h,
page_w=page_w,
page_h=page_h,
),
signature_box(
field="date",
page=0,
x=date_x + 4,
y=sig_rule_y + 1,
w=date_w - 8,
h=20.0,
page_w=page_w,
page_h=page_h,
),
]
return pdf_bytes, anchors
if __name__ == "__main__": # quick local render for visual verification
pdf, anchors = build_state_trucking_authorization(
order_number="CO-TEST1234",
entity_name="Acme Freight LLC",
service_name="New York Highway Use Tax (HUT) Registration",
dot_number="3456789",
mc_number="MC-987654",
fein_last4="1234",
base_state="NY",
operating_states=["NY", "PA", "OH"],
signer_name="John Smith",
signer_title="Owner",
)
with open("/tmp/state_trucking_authorization.pdf", "wb") as f:
f.write(pdf)
print("wrote /tmp/state_trucking_authorization.pdf")
print("anchors:", anchors)