trucking: compute coupon discounted prices on the fly (true per A/B arm) + fix CTA URL bug

Two correctness fixes that gate enabling the coupon test:

1. On-the-fly pricing. The coupon block hardcoded '$79 $47' (only true at 40%
   off) — a false claim on the 20/30% arms. Now build_trucking_campaigns.py
   reads api/src/service-catalog.ts (same source checkout uses) and computes
   coupon_price_full / coupon_price_deal per recipient as full - round(full*pct/100),
   exactly matching the server. Service-fee-only; non-discountable services
   (boc3-filing passthrough) get NO price and fall back to percent-only copy.
   Quotes the service the email is ABOUT (mcs150 $79, reactivation $149), not the
   bundle the CTA happens to link to. service-catalog.ts now ships in the worker
   image; helper degrades to percent-only if it can't be read.

2. CTA URL bug (likely a big driver of the zero-click problem). Main campaign
   CTAs render '/order/slug&utm_source=...' (no '?') -> HTTP 404, verified live.
   Deficiency CTAs would double-'?' once a coupon added '?code='. lp_link now
   owns the query (?dot=...&code=...) so every template appends with a leading
   '&' and is valid in all 4 states (main/deficiency x coupon on/off), verified
   against live URLs returning 200.

Deficiency _deal_box now shows real was/now prices (percent-only for boc3).
Tests: 7/7 pass (adds URL-wellformed + price-matches-checkout cases).
This commit is contained in:
justin 2026-06-20 17:43:11 -05:00
parent 6fce3ec9eb
commit 579919197d
4 changed files with 227 additions and 11 deletions

View file

@ -68,6 +68,52 @@ def test_coupon_attribs_reflects_pct():
}
def test_lp_link_well_formed_in_all_states():
"""The CTA URL must be valid whether or not a coupon is active. lp_link owns
the `?`-query so templates append their own params with a leading `&`."""
import urllib.parse
def cta(lp, lead): # mimic a template appending its own params
return f"{lp}{lead}utm_source=listmonk&utm_campaign=x"
for code in (None, "KQMTN"):
for ct, st in (("mcs150", None), ("irp_ifta", "CT")):
lp = btc.lp_link_with_coupon(ct, st, code, dot="1228791")
url = cta(lp, "&")
parts = urllib.parse.urlsplit(url)
assert "&" not in parts.path, url # no stray & in path
assert parts.query.count("?") == 0, url # no double ?
assert "dot=1228791" in parts.query, url
if code:
assert f"code={code}" in parts.query, url
def test_discounted_price_matches_checkout_formula():
"""coupon_price_deal must equal full - round(full*pct/100) for discountable
services, and be blank for non-discountable ones (e.g. boc3-filing)."""
cat = btc._load_service_catalog()
assert cat, "service catalog failed to load"
for ct, st in (("mcs150", None), ("inactive", None), ("irp_ifta", "CT"),
("hazmat", None), ("state_weight_tax", "NY"), ("state_emissions", "CA")):
slug = btc.price_slug_for(ct, st)
entry = cat[slug]
for pct in ("20", "30", "40"):
a = btc.discounted_price_attribs(ct, st, pct)
full = entry["price_cents"]
deal = full - round(full * int(pct) / 100)
exp_full = f"${full // 100}" if full % 100 == 0 else f"${full / 100:.2f}"
exp_deal = f"${deal // 100}" if deal % 100 == 0 else f"${deal / 100:.2f}"
assert a["coupon_price_full"] == exp_full, (ct, pct, a)
assert a["coupon_price_deal"] == exp_deal, (ct, pct, a)
assert a["coupon_priceable"] == "1"
# Non-discountable passthrough -> no price, percent-only fallback.
boc = btc.discounted_price_attribs("for_hire_boc3", None, "40")
assert boc == {"coupon_price_full": "", "coupon_price_deal": "", "coupon_priceable": ""}
# No coupon -> blank.
assert btc.discounted_price_attribs("mcs150", None, "")["coupon_priceable"] == ""
if __name__ == "__main__":
fns = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
for fn in fns: