govfee: itemize the estimate in the email + add a 'fix my fee' dispute path

The gov-fee email now lists exactly what the amount covers (full breakdown) so
the customer can check it for accuracy, with two clear actions: a  pay link and
a  'something looks wrong' link to /order/dispute.

New /order/dispute page shows the fee breakdown and lets the customer describe
what's wrong; it opens an 'issue' support ticket pre-tagged with the order
(amount + label + their note) via /api/v1/tickets, so ops corrects the fee
before any payment is taken. The /order/pay page also shows the itemized
breakdown and a dispute link.
This commit is contained in:
justin 2026-06-16 05:00:31 -05:00
parent ea695d6828
commit 1d6693adb9
3 changed files with 183 additions and 9 deletions

View file

@ -243,16 +243,28 @@ def gov_fee_payment_url(child_order_number: str) -> str:
return f"{SITE}/order/pay?order={child_order_number}"
def gov_fee_dispute_url(child_order_number: str) -> str:
"""Public 'this estimate looks wrong' page that opens a support ticket
pre-tagged with the order so ops can correct the fee."""
return f"{SITE}/order/dispute?order={child_order_number}"
def send_gov_fee_payment_email(customer_email: str, customer_name: str,
service_label: str, entity_name: str,
estimate: GovFeeEstimate, child_order_number: str) -> bool:
"""Email the customer a payment link for the government fee."""
"""Email the customer an itemized government-fee bill + payment link, plus a
link to dispute the amount if it looks wrong."""
if not customer_email:
return False
url = gov_fee_payment_url(child_order_number)
dispute = gov_fee_dispute_url(child_order_number)
amt = f"${estimate.cents / 100:,.2f}"
qualifier = "" if estimate.exact else (
" This is an estimate billed at cost; if the state's final fee differs we "
# Itemized breakdown so the customer can check it for accuracy.
items = "\n".join(f" - {line}" for line in (estimate.breakdown or [estimate.label]))
qualifier = (
"This amount is the state's confirmed fee."
if estimate.exact else
"This is an estimate billed at cost. If the state's final fee differs we "
"refund any overage or bill the small difference.")
try:
import smtplib
@ -260,13 +272,17 @@ def send_gov_fee_payment_email(customer_email: str, customer_name: str,
body = (
f"Hi {customer_name or 'there'},\n\n"
f"Your {service_label} for {entity_name} is ready to file. The only "
f"remaining step is the government/state fee, which we collect at cost:\n\n"
f" {service_label}\n"
f" Government fee: {amt}\n"
f" {estimate.label}\n\n"
f"Pay securely here (choose your preferred method — bank transfer/ACH "
f"has no processing fee):\n{url}\n\n"
f"remaining step is the government/state fee, which we collect at cost.\n\n"
f"Here is exactly what the {amt} covers — please review it for accuracy:\n\n"
f" {estimate.label}\n"
f"{items}\n"
f" ----------------------------------------\n"
f" Total government fee: {amt}\n\n"
f"{qualifier}\n\n"
f"✅ If this looks right, pay securely here (choose your method — "
f"bank transfer/ACH has no processing fee):\n{url}\n\n"
f"❓ If something looks wrong (wrong fleet size, states, weight, or "
f"amount), tell us here and we'll fix it before you pay:\n{dispute}\n\n"
f"As soon as the fee is paid we file with the state and send your "
f"confirmation.\n\n"
f"Order: {child_order_number}\n"