From a1db921c71bf55c8e6f70cedc9e4be949ed7a38a Mon Sep 17 00:00:00 2001 From: justin Date: Wed, 10 Jun 2026 17:22:38 -0500 Subject: [PATCH] mcs150/workers: don't fill MCS-150 for non-form services; quiet ERPNext workflow advance - MCS150UpdateHandler is the catch-all for many admin-assisted DOT services (UCR, MC authority, audit prep, ETA, name reservation, registered agent, annual report). It was filling an MCS-150 PDF for ALL of them -- e.g. a UCR order produced a wrong MCS-150 PDF. Now only MCS150_FORM_SLUGS fill the form; others get an admin-review todo (PDF 'not generated') for manual handling. Signature flow was already correctly scoped (UCR is not in DOT_SIGNING). - handle_process_compliance_service forced the Sales Order workflow_state to 'Review' via set_value, which bypasses ERPNext's allowed transitions and threw WorkflowPermissionError (Received -> Review) on every run. The Postgres fulfillment_status is the source of truth; the ERPNext workflow_state is a cosmetic mirror. Now try the proper apply_workflow action and stay quiet (debug, not warning) when no valid Review transition exists. --- scripts/workers/job_server.py | 25 +++++++++++++++++++---- scripts/workers/services/mcs150_update.py | 20 +++++++++++------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/scripts/workers/job_server.py b/scripts/workers/job_server.py index 90abda3..03d37ae 100644 --- a/scripts/workers/job_server.py +++ b/scripts/workers/job_server.py @@ -1345,12 +1345,29 @@ def handle_process_compliance_service(payload: dict) -> dict: except Exception as exc: LOG.warning("Could not update entity checkup timestamp: %s", exc) - # Advance workflow to Review after processing + # Advance the ERPNext Sales Order workflow to "Review" (best-effort, purely + # cosmetic). The authoritative status for compliance orders is the Postgres + # compliance_orders.fulfillment_status; the ERPNext workflow_state is a + # secondary mirror. A direct set_value("workflow_state","Review") bypasses + # the workflow's allowed transitions and ERPNext rejects "Received -> Review" + # with a WorkflowPermissionError. Use the proper workflow action when one is + # available, and stay quiet if the transition isn't defined for the current + # state (it's non-fatal and shouldn't spam the logs on every run). try: - client.set_value("Sales Order", order_name, "workflow_state", "Review") - LOG.info("Advanced %s to Review", order_name) + applied = False + for action in ("Processing Complete", "Submit for Review", "Ready for Review"): + try: + client.apply_workflow("Sales Order", order_name, action) + LOG.info("Advanced %s to Review via '%s'", order_name, action) + applied = True + break + except Exception: + continue + if not applied: + LOG.debug("Skipped ERPNext workflow advance for %s (no valid Review transition)", + order_name) except Exception as exc: - LOG.warning("Could not advance workflow for %s: %s", order_name, exc) + LOG.debug("ERPNext workflow advance skipped for %s: %s", order_name, exc) # ── Create compliance calendar deadlines for the customer ─────────── # After a filing is completed, create recurring deadline reminders diff --git a/scripts/workers/services/mcs150_update.py b/scripts/workers/services/mcs150_update.py index 69f461a..2bce48f 100644 --- a/scripts/workers/services/mcs150_update.py +++ b/scripts/workers/services/mcs150_update.py @@ -158,14 +158,20 @@ class MCS150UpdateHandler: order_number, missing) return [] - # Step 1: Fill the official MCS-150 PDF + # Step 1: Fill the official MCS-150 PDF. Only services that actually file + # an MCS-150 produce the form; the other admin-assisted DOT services + # routed to this handler (UCR, MC authority, audit prep, ETA, name + # reservation, registered agent, annual report, etc.) must NOT generate + # an MCS-150 -- they are handled manually by an admin from the review + # todo created below. pdf_path = None - try: - from scripts.document_gen.templates.mcs150_pdf_filler import fill_mcs150 - pdf_path = fill_mcs150(intake, order_number=order_number) - LOG.info("[%s] Filled MCS-150 PDF: %s", order_number, pdf_path) - except Exception as exc: - LOG.error("[%s] PDF fill failed: %s", order_number, exc) + if slug in self.MCS150_FORM_SLUGS: + try: + from scripts.document_gen.templates.mcs150_pdf_filler import fill_mcs150 + pdf_path = fill_mcs150(intake, order_number=order_number) + LOG.info("[%s] Filled MCS-150 PDF: %s", order_number, pdf_path) + except Exception as exc: + LOG.error("[%s] PDF fill failed: %s", order_number, exc) # Step 2: Upload PDF to MinIO for storage minio_path = None