Wire fulfillment alerts to Telegram + surface order progress in portal + even out ERPNext sync
Telegram notifications: - Add shared scripts/workers/telegram_notify.py (send_telegram, notify_fulfillment_todo, create_admin_todo) so every worker alerts the operator the same way; fire-and-forget. - Fire notify_fulfillment_todo after each admin_todos insert across all 8 service handlers (9 sites) so no fulfillment task waits unseen. (Orders + quotes + tickets already notified via checkout/quotes/tickets routes.) Client portal order progress: - order-timeline: derive real per-step status from live signals (payment paid, e-signature signed, fulfillment_status) instead of a static template; add current_step to the response. - Extract pure applyLiveStatus into order-timeline-status.ts (DB-free) + unit test (api/test/test_timeline_status.ts, 8 cases). - portal /me now returns compliance_orders.fulfillment_status. - Dashboard renders a client-safe Progress badge (In progress / Action needed / Filed-awaiting-confirmation / Completed); batches show the most actionable status. No back-office mechanics exposed. ERPNext sync parity: - Create a Sales Order for formation and fcc_carrier_registration orders (previously only canada_crtc + compliance synced); write erpnext_sales_order back to each table. Non-blocking, matches existing pattern. Verified: API tsc clean, timeline unit tests 8/8, Astro build 58 pages, cms10114/ink/paper_batch Python tests still green, no mechanics leaks.
This commit is contained in:
parent
41df4d9553
commit
28b1af341d
15 changed files with 706 additions and 73 deletions
|
|
@ -47,6 +47,8 @@ import logging
|
|||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from scripts.workers.telegram_notify import notify_fulfillment_todo
|
||||
|
||||
LOG = logging.getLogger("workers.services.mcs150_update")
|
||||
|
||||
|
||||
|
|
@ -246,6 +248,16 @@ class MCS150UpdateHandler:
|
|||
filed_method = filing_result.get("method", "pending") if filing_result else "pending"
|
||||
filed_ok = filing_result.get("success", False) if filing_result else False
|
||||
|
||||
todo_title = f"MCS-150 {'Filed' if filed_ok else 'Review'} — {entity_name} (DOT {dot_number})"
|
||||
todo_priority = "low" if filed_ok else "normal"
|
||||
todo_description = (
|
||||
f"MCS-150 for {entity_name} (DOT {dot_number}).\n"
|
||||
f"Filing method: {filed_method}\n"
|
||||
f"Status: {'SUBMITTED — verify in 5-10 days' if filed_ok else 'NEEDS MANUAL FILING'}\n"
|
||||
f"Customer: {customer_email}\n"
|
||||
f"PDF: {minio_path or 'not generated'}"
|
||||
)
|
||||
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("""
|
||||
INSERT INTO admin_todos (
|
||||
|
|
@ -253,16 +265,12 @@ class MCS150UpdateHandler:
|
|||
description, data, status
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, 'pending')
|
||||
""", (
|
||||
f"MCS-150 {'Filed' if filed_ok else 'Review'} — {entity_name} (DOT {dot_number})",
|
||||
todo_title,
|
||||
"filing",
|
||||
"low" if filed_ok else "normal",
|
||||
todo_priority,
|
||||
order_number,
|
||||
self.SERVICE_SLUG,
|
||||
f"MCS-150 for {entity_name} (DOT {dot_number}).\n"
|
||||
f"Filing method: {filed_method}\n"
|
||||
f"Status: {'SUBMITTED — verify in 5-10 days' if filed_ok else 'NEEDS MANUAL FILING'}\n"
|
||||
f"Customer: {customer_email}\n"
|
||||
f"PDF: {minio_path or 'not generated'}",
|
||||
todo_description,
|
||||
json.dumps({
|
||||
"order_number": order_number,
|
||||
"dot_number": dot_number,
|
||||
|
|
@ -271,6 +279,13 @@ class MCS150UpdateHandler:
|
|||
}),
|
||||
))
|
||||
conn.commit()
|
||||
notify_fulfillment_todo(
|
||||
title=todo_title,
|
||||
order_number=order_number,
|
||||
service_slug=self.SERVICE_SLUG,
|
||||
priority=todo_priority,
|
||||
description=todo_description,
|
||||
)
|
||||
conn.close()
|
||||
except Exception as exc:
|
||||
LOG.error("[%s] Failed to create admin todo: %s", order_number, exc)
|
||||
|
|
@ -311,6 +326,14 @@ class MCS150UpdateHandler:
|
|||
try:
|
||||
import psycopg2
|
||||
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
|
||||
todo_title = f"Awaiting client signature — {entity_name} (DOT {dot_number})"
|
||||
todo_description = (
|
||||
f"{slug} for {entity_name} (DOT {dot_number}).\n"
|
||||
f"Status: AWAITING CLIENT SIGNATURE before filing.\n"
|
||||
f"Signing link emailed to {customer_email}.\n"
|
||||
f"PDF: {minio_path or 'not generated'}\n"
|
||||
f"Filing auto-resumes once the client signs."
|
||||
)
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
|
|
@ -320,18 +343,21 @@ class MCS150UpdateHandler:
|
|||
) VALUES (%s, %s, %s, %s, %s, %s, %s, 'pending')
|
||||
""",
|
||||
(
|
||||
f"Awaiting client signature — {entity_name} (DOT {dot_number})",
|
||||
todo_title,
|
||||
"filing", "low", order_number, slug,
|
||||
f"{slug} for {entity_name} (DOT {dot_number}).\n"
|
||||
f"Status: AWAITING CLIENT SIGNATURE before filing.\n"
|
||||
f"Signing link emailed to {customer_email}.\n"
|
||||
f"PDF: {minio_path or 'not generated'}\n"
|
||||
f"Filing auto-resumes once the client signs.",
|
||||
todo_description,
|
||||
json.dumps({"order_number": order_number, "dot_number": dot_number,
|
||||
"entity_name": entity_name, "awaiting_signature": True}),
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
notify_fulfillment_todo(
|
||||
title=todo_title,
|
||||
order_number=order_number,
|
||||
service_slug=slug,
|
||||
priority="low",
|
||||
description=todo_description,
|
||||
)
|
||||
conn.close()
|
||||
LOG.info("[%s] Pending-signature todo created", order_number)
|
||||
except Exception as exc:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue