Add generic eSign portal for all compliance document types
Reusable signing flow: service handler generates document → inserts esign_records row → emails JWT link → client reviews PDF + signs → API stores signature + resumes pipeline. Works for RMD, CPNI, CALEA, 499-A engagement, discontinuance, CRTC, and any future doc types. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
37a22cf474
commit
40844b2aff
6 changed files with 879 additions and 0 deletions
|
|
@ -1556,6 +1556,60 @@ def handle_presign(payload: dict) -> dict:
|
|||
return {"error": str(exc)}
|
||||
|
||||
|
||||
def handle_esign_completed(payload: dict) -> dict:
|
||||
"""Generic eSign completion callback — resume the service pipeline.
|
||||
|
||||
Called by portal-esign-generic.ts after a client signs any document.
|
||||
Payload: { order_number, document_type, esign_record_id, signer_email }
|
||||
|
||||
Looks up the compliance order for this order_number and re-dispatches
|
||||
the service handler with client_approved=true so it continues past
|
||||
the signing checkpoint.
|
||||
"""
|
||||
order_number = payload.get("order_number", "")
|
||||
document_type = payload.get("document_type", "")
|
||||
if not order_number:
|
||||
return {"error": "order_number required"}
|
||||
|
||||
LOG.info("[esign_completed] Signature received for %s (type=%s)", order_number, document_type)
|
||||
|
||||
try:
|
||||
import psycopg2
|
||||
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"SELECT service_slug FROM compliance_orders WHERE order_number = %s",
|
||||
(order_number,),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
conn.close()
|
||||
|
||||
if not row:
|
||||
LOG.warning("[esign_completed] No compliance_order found for %s", order_number)
|
||||
return {"warning": f"No compliance order for {order_number}"}
|
||||
|
||||
service_slug = row[0]
|
||||
|
||||
# Re-dispatch the service handler with approval flag
|
||||
from scripts.workers.services import SERVICE_HANDLERS
|
||||
handler_cls = SERVICE_HANDLERS.get(service_slug)
|
||||
if handler_cls:
|
||||
LOG.info("[esign_completed] Re-dispatching %s for %s", service_slug, order_number)
|
||||
handler = handler_cls()
|
||||
handler.process(order_number, {
|
||||
"client_approved": True,
|
||||
"esign_document_type": document_type,
|
||||
"esign_signer_email": payload.get("signer_email", ""),
|
||||
})
|
||||
else:
|
||||
LOG.warning("[esign_completed] No handler for slug=%s", service_slug)
|
||||
|
||||
return {"success": True, "order_number": order_number, "document_type": document_type}
|
||||
except Exception as exc:
|
||||
LOG.error("[esign_completed] Error for %s: %s", order_number, exc)
|
||||
return {"error": str(exc)}
|
||||
|
||||
|
||||
def handle_resume_crtc_pipeline(payload: dict) -> dict:
|
||||
"""Resume the CRTC pipeline after an async pause (eSign, domain selection, etc.).
|
||||
|
||||
|
|
@ -1721,6 +1775,7 @@ JOB_HANDLERS = {
|
|||
"purchase_client_selections": handle_purchase_client_selections,
|
||||
# eSign / MinIO helpers
|
||||
"presign": handle_presign,
|
||||
"esign_completed": handle_esign_completed,
|
||||
"resume_crtc_pipeline": handle_resume_crtc_pipeline,
|
||||
# Compliance calendar renewal
|
||||
"renewal_payment": handle_renewal_payment,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue