feat(sc-coc): SC intrastate Certificate of Compliance flow (insurance gate -> $25 fee -> file)
Routes SC intrastate-authority orders to the real SCDMV COC product instead of a
PSC certificate (which doesn't apply to property carriers):
- sc_coc_filing.py: emails the carrier a one-click yes/no — does your insurer
have / can they file a Form E (SC intrastate liability, $750k or $300k by
GVWR) with SCDMV? Records the answer; builds the filled COC package.
- state_trucking._handle_sc_coc_gate: SC intrastate gate —
no answer -> email the question once, HOLD
answered no -> broker referral opened, HOLD (ops todo)
answered yes-> proceed to bill the exact $25 SCDMV COC fee (at cost) + file
- API POST /compliance-orders/:id/sc-insurance: records yes/no in intake_data
(no schema change); NO opens an insurance_lead broker-referral ticket +
Telegram; YES re-dispatches the worker to bill the $25 + file.
- site/order/sc-insurance: customer one-click yes/no page (auto-submits when
the email links straight to ?have=yes|no).
Non-SC intrastate still uses the PSC/PUC email path or a manual todo.
This commit is contained in:
parent
dae9603808
commit
c46efe5730
4 changed files with 526 additions and 30 deletions
|
|
@ -713,6 +713,94 @@ class StateTruckingHandler:
|
|||
LOG.warning("[%s] Could not check gov-fee settlement: %s", order_number, exc)
|
||||
return False
|
||||
|
||||
def _handle_sc_coc_gate(self, order_number, entity_name, customer_email,
|
||||
customer_phone, intake) -> bool:
|
||||
"""SC intrastate Certificate of Compliance insurance gate.
|
||||
|
||||
SC for-hire property carriers register via the SCDMV COC, which requires
|
||||
their INSURER to file a Form E (liability). We ask the carrier a one-click
|
||||
yes/no first:
|
||||
- no answer yet -> email the question, HOLD (return True)
|
||||
- answered 'no' -> broker referral is in progress, HOLD (return True)
|
||||
- answered 'yes' -> insurance confirmed, PROCEED to bill the $25 COC
|
||||
fee (return False so the caller falls through to fee billing)
|
||||
"""
|
||||
answer = str(intake.get("sc_coc_insurance", "")).lower()
|
||||
|
||||
if answer == "yes":
|
||||
LOG.info("[%s] SC COC: insurance confirmed — proceeding to $25 COC fee", order_number)
|
||||
return False # proceed to bill the COC fee
|
||||
|
||||
if answer == "no":
|
||||
# Broker referral opened (by the response endpoint). Hold until ops
|
||||
# gets them covered, then they re-answer yes.
|
||||
LOG.info("[%s] SC COC: carrier needs insurance — broker referral, holding", order_number)
|
||||
try:
|
||||
notify_fulfillment_todo(
|
||||
title=f"SC COC — carrier needs insurance broker — {entity_name}",
|
||||
order_number=order_number,
|
||||
service_slug="intrastate-authority",
|
||||
priority="normal",
|
||||
description=(f"{entity_name} answered NO to the SC intrastate Form E "
|
||||
f"insurance question. A broker-referral ticket was opened.\n"
|
||||
f"Connect them with an SC intrastate liability insurer who can "
|
||||
f"file a Form E with SCDMV, then they re-confirm and we file the "
|
||||
f"$25 Certificate of Compliance.\nCustomer: {customer_email}"),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return True # hold
|
||||
|
||||
# No answer yet: send the yes/no insurance question (once).
|
||||
try:
|
||||
from scripts.workers.services.sc_coc_filing import send_insurance_question_email
|
||||
except Exception as exc: # noqa: BLE001
|
||||
LOG.error("[%s] sc_coc_filing import failed: %s", order_number, exc)
|
||||
return True # hold safely rather than mis-bill
|
||||
already = str(intake.get("sc_coc_insurance_asked", "")).lower() in ("1", "true", "yes")
|
||||
if not already:
|
||||
send_insurance_question_email(order_number, customer_email,
|
||||
intake.get("customer_name", ""), entity_name, intake)
|
||||
self._mark_intake_flag(order_number, "sc_coc_insurance_asked", "true")
|
||||
try:
|
||||
notify_fulfillment_todo(
|
||||
title=f"SC COC — insurance question sent — {entity_name}",
|
||||
order_number=order_number,
|
||||
service_slug="intrastate-authority",
|
||||
priority="low",
|
||||
description=(f"Asked {entity_name} whether their insurer can file a Form E "
|
||||
f"for SC intrastate. When they confirm YES we bill the $25 SCDMV "
|
||||
f"Certificate of Compliance fee and file; if NO we open a broker "
|
||||
f"referral.\nCustomer: {customer_email}"),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return True # hold pending their answer
|
||||
|
||||
def _mark_intake_flag(self, order_number: str, key: str, value: str) -> None:
|
||||
"""Best-effort set intake_data[key]=value on the order (no schema change)."""
|
||||
try:
|
||||
import json as _json
|
||||
import psycopg2
|
||||
conn = psycopg2.connect(os.environ.get("DATABASE_URL", ""))
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("SELECT intake_data FROM compliance_orders WHERE order_number = %s",
|
||||
(order_number,))
|
||||
row = cur.fetchone()
|
||||
if not row:
|
||||
conn.close()
|
||||
return
|
||||
data = row[0] or {}
|
||||
if isinstance(data, str):
|
||||
data = _json.loads(data)
|
||||
data[key] = value
|
||||
cur.execute("UPDATE compliance_orders SET intake_data = %s, updated_at = now() "
|
||||
"WHERE order_number = %s", (_json.dumps(data), order_number))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
LOG.warning("[%s] Could not set intake flag %s: %s", order_number, key, exc)
|
||||
|
||||
def _request_gov_fee_payment(self, order_number, service_slug, service_name,
|
||||
entity_name, customer_email, customer_phone, intake,
|
||||
signed_auth_key=None) -> bool:
|
||||
|
|
@ -751,39 +839,53 @@ class StateTruckingHandler:
|
|||
pass
|
||||
return sent
|
||||
|
||||
# ── Intrastate authority: email the PSC/PUC, wait for the fee invoice ──
|
||||
# (Falls through to manual todo when the state has no email submission
|
||||
# path — handled by returning False below.)
|
||||
# ── Intrastate authority ──────────────────────────────────────────────
|
||||
# Per-state: figure out what the carrier actually needs and route to it.
|
||||
# SC for-hire PROPERTY carriers register via the SCDMV Certificate of
|
||||
# Compliance (COC) — gated on a Form E liability filing by their insurer.
|
||||
# We email a yes/no insurance question first; once they confirm (or we've
|
||||
# referred them to a broker) we bill the exact $25 COC fee + file. Other
|
||||
# states fall through to the PSC/PUC email path or a manual todo.
|
||||
if service_slug == "intrastate-authority":
|
||||
try:
|
||||
from scripts.workers.services.intrastate_filing import (
|
||||
send_intrastate_submission, state_isa_contact,
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
LOG.error("[%s] intrastate_filing import failed: %s", order_number, exc)
|
||||
return False
|
||||
base_state = (intake.get("base_state") or intake.get("address_state") or "").upper()
|
||||
if not state_isa_contact(base_state):
|
||||
LOG.info("[%s] No intrastate email contact for %s — manual todo", order_number, base_state)
|
||||
return False
|
||||
sent = send_intrastate_submission(order_number, entity_name,
|
||||
intake.get("dot_number", ""), base_state, intake,
|
||||
signed_auth_key=signed_auth_key)
|
||||
if sent:
|
||||
|
||||
if base_state == "SC":
|
||||
if self._handle_sc_coc_gate(order_number, entity_name, customer_email,
|
||||
customer_phone, intake):
|
||||
return True # hold pending insurance answer / broker referral
|
||||
# else: insurance confirmed -> fall through to bill the $25 COC fee
|
||||
|
||||
else:
|
||||
# Non-SC: email the state PSC/PUC if we have a submission contact;
|
||||
# otherwise fall back to a manual todo.
|
||||
try:
|
||||
notify_fulfillment_todo(
|
||||
title=f"Intrastate authority submitted to {base_state} PSC — awaiting fee — {entity_name}",
|
||||
order_number=order_number,
|
||||
service_slug=service_slug,
|
||||
priority="normal",
|
||||
description=(f"Intrastate authority application emailed to the {base_state} "
|
||||
f"PSC/PUC with the signed POA.\nWaiting on their requirements + "
|
||||
f"fee invoice; when it arrives we auto-bill the customer the exact "
|
||||
f"amount and you'll get a Telegram alert.\nCustomer: {customer_email}"),
|
||||
from scripts.workers.services.intrastate_filing import (
|
||||
send_intrastate_submission, state_isa_contact,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return sent
|
||||
except Exception as exc: # noqa: BLE001
|
||||
LOG.error("[%s] intrastate_filing import failed: %s", order_number, exc)
|
||||
return False
|
||||
if not state_isa_contact(base_state):
|
||||
LOG.info("[%s] No intrastate email contact for %s — manual todo", order_number, base_state)
|
||||
return False
|
||||
sent = send_intrastate_submission(order_number, entity_name,
|
||||
intake.get("dot_number", ""), base_state, intake,
|
||||
signed_auth_key=signed_auth_key)
|
||||
if sent:
|
||||
try:
|
||||
notify_fulfillment_todo(
|
||||
title=f"Intrastate authority submitted to {base_state} PSC — awaiting fee — {entity_name}",
|
||||
order_number=order_number,
|
||||
service_slug=service_slug,
|
||||
priority="normal",
|
||||
description=(f"Intrastate authority application emailed to the {base_state} "
|
||||
f"PSC/PUC with the signed POA.\nWaiting on their requirements + "
|
||||
f"fee invoice; when it arrives we auto-bill the customer the exact "
|
||||
f"amount and you'll get a Telegram alert.\nCustomer: {customer_email}"),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return sent
|
||||
# ── IFTA / intrastate: published fee, bill the estimate now ───────────
|
||||
try:
|
||||
from scripts.workers.services.gov_fee import (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue