diff --git a/scripts/workers/services/mcs150_update.py b/scripts/workers/services/mcs150_update.py index 7c08735..1a2e82b 100644 --- a/scripts/workers/services/mcs150_update.py +++ b/scripts/workers/services/mcs150_update.py @@ -113,6 +113,17 @@ class MCS150UpdateHandler: LOG.warning("[%s] No FMCSA census data for DOT %s -- form may be sparse", order_number, dot_number) + # Backfill the signer's printed name from the signed certification when + # the intake didn't carry one. For a typed signature the client typed + # their full legal name, which is exactly what belongs in the form's + # "print/type name" certification field (certifyName). + if not intake.get("signer_name"): + signed_name = self._signed_signer_name(order_number) + if signed_name: + intake["signer_name"] = signed_name + LOG.info("[%s] Backfilled signer_name from signed certification: %s", + order_number, signed_name) + # Step 1: Fill the official MCS-150 PDF pdf_path = None try: @@ -145,6 +156,13 @@ class MCS150UpdateHandler: except Exception as exc: LOG.error("[%s] MinIO upload failed: %s", order_number, exc) + # If the client already signed (re-dispatched after signature), the + # signed PDF that the admin reviews must reflect the form we just + # (re)filled, not a stale earlier fill. Re-point the esign record at the + # fresh document and re-stamp the signature onto it. + if client_approved and minio_path: + self._restamp_signed_form(order_number, minio_path) + # Step 3: Check for photo ID photo_id_path = None if intake.get("photo_id_uploaded"): @@ -337,6 +355,70 @@ class MCS150UpdateHandler: return [minio_path] if minio_path else [] + def _restamp_signed_form(self, order_number: str, document_key: str) -> None: + """Point the signed esign record at ``document_key`` (the freshly filled + form) and re-stamp the signature onto it, so the signed PDF an admin + reviews reflects the current, complete form.""" + try: + import psycopg2 + conn = psycopg2.connect(os.environ.get("DATABASE_URL", "")) + try: + with conn.cursor() as cur: + cur.execute( + """SELECT id FROM esign_records + WHERE order_number = %s AND status = 'signed' + ORDER BY signed_at DESC LIMIT 1""", + (order_number,), + ) + row = cur.fetchone() + if not row: + return + rec_id = row[0] + # Re-point at the fresh document and clear the stale signed + # key so the stamper regenerates it. + cur.execute( + """UPDATE esign_records + SET document_minio_key = %s, + signed_document_minio_key = NULL, + updated_at = NOW() + WHERE id = %s""", + (document_key, rec_id), + ) + conn.commit() + finally: + conn.close() + + from scripts.workers.services.esign_stamp import stamp_esign_document + signed_key = stamp_esign_document(int(rec_id)) + if signed_key: + LOG.info("[%s] Re-stamped signature onto fresh form -> %s", + order_number, signed_key) + except Exception as exc: + LOG.warning("[%s] Re-stamp of signed form failed: %s", order_number, exc) + + def _signed_signer_name(self, order_number: str) -> str: + """Return the full name the client typed when signing the perjury + certification for this order (empty if no typed signature on file).""" + try: + import psycopg2 + conn = psycopg2.connect(os.environ.get("DATABASE_URL", "")) + try: + with conn.cursor() as cur: + cur.execute( + """SELECT signature_data FROM esign_records + WHERE order_number = %s AND status = 'signed' + AND signature_type = 'typed' + ORDER BY signed_at DESC LIMIT 1""", + (order_number,), + ) + row = cur.fetchone() + return (row[0] or "").strip() if row else "" + finally: + conn.close() + except Exception as exc: + LOG.warning("[%s] Could not read signed signer name: %s", order_number, exc) + return "" + def _fetch_fmcsa_carrier(self, dot_number: str) -> dict: """Fetch the raw FMCSA carrier census record for a DOT number.""" try: