From 2f0753f00ed208002e27e5aa30ce28ec315dfe0f Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 20 Jun 2026 17:43:46 -0500 Subject: [PATCH] trucking: add idempotent patcher for main-campaign coupon blocks (186/188 computed prices) --- scripts/patch_main_coupon_blocks.py | 132 ++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 scripts/patch_main_coupon_blocks.py diff --git a/scripts/patch_main_coupon_blocks.py b/scripts/patch_main_coupon_blocks.py new file mode 100644 index 0000000..1d809ca --- /dev/null +++ b/scripts/patch_main_coupon_blocks.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Patch the two main trucking source campaigns (MCS-150 #186, Inactive USDOT +#188) coupon blocks to use the build step's on-the-fly computed prices +(coupon_price_full / coupon_price_deal) instead of the hardcoded "$79 $47" / +"$149 $89", which were only true at 40% off and would be false on the 20/30% +A/B arms. + +Idempotent: re-running replaces the coupon if-block again with the same content. +Run inside the workers container on prod: + python3 scripts/patch_main_coupon_blocks.py [--dry-run] +""" +from __future__ import annotations + +import argparse +import os +import re +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if ROOT not in sys.path: + sys.path.insert(0, ROOT) + +from scripts import build_trucking_campaigns as b # reuse lm_api + auth + + +def _deal_block(service_phrase: str, extra_expiry_line: str = "") -> str: + """Coupon-aware offer block matching the deficiency _deal_box structure: + real was/now prices when priceable, percent-only otherwise.""" + priced = ( + '

' + f'{service_phrase} for ' + '' + '{{ .Subscriber.Attribs.coupon_price_full }} ' + '{{ .Subscriber.Attribs.coupon_price_deal }}.

' + ) + unpriced = ( + '

' + f'{service_phrase}.

' + ) + expiry = "Expires {{ .Subscriber.Attribs.coupon_expires }}." + if extra_expiry_line: + expiry += " " + extra_expiry_line + return ( + '{{ if .Subscriber.Attribs.coupon_code }}\n' + '
\n' + '

TODAY ONLY - {{ .Subscriber.Attribs.coupon_pct }}% OFF OUR SERVICE FEE

\n' + '{{ if .Subscriber.Attribs.coupon_priceable }}' + priced + '{{ else }}' + unpriced + '{{ end }}\n' + '

Use code ' + '{{ .Subscriber.Attribs.coupon_code }} ' + '(already applied when you click below).

\n' + f'

{expiry}

\n' + '
\n' + ) + + +# Per-campaign: the new coupon if-block (deal branch + original else branch). +BLOCKS = { + 186: ( + _deal_block("We file your MCS-150 update") + + '{{ else }}\n' + '
\n' + '

' + 'We can file your MCS-150 update for you.

\n' + '

No Login.gov needed. ' + 'No government portals. We handle everything.

\n' + '
\n' + '{{ end }}' + ), + 188: ( + _deal_block("Reactivate your USDOT", "Reactivation takes as few as 5 business days.") + + '{{ else }}\n' + '
\n' + '

' + 'Reactivation takes as few as 5 business days.

\n' + '

We file electronically with ' + 'FMCSA - no Login.gov account needed.

\n' + '
\n' + '{{ end }}' + ), +} + +_BLOCK_RE = re.compile( + r"\{\{\s*if\s+\.Subscriber\.Attribs\.coupon_code\s*\}\}.*?\{\{\s*end\s*\}\}", + re.DOTALL, +) + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--dry-run", action="store_true") + args = ap.parse_args() + + for cid, new_block in BLOCKS.items(): + camp = b.get_base_campaign(cid) + body = camp.get("body") or "" + matches = _BLOCK_RE.findall(body) + if len(matches) != 1: + print(f" [#{cid}] SKIP: found {len(matches)} coupon if-blocks (expected 1)") + continue + new_body, n = _BLOCK_RE.subn(new_block, body) + if "$47" in new_block or "$89" in new_block or "$79" in new_block or "$149" in new_block: + print(f" [#{cid}] ABORT: new block still contains a hardcoded price") + continue + # Sanity: no hardcoded coupon price survives in the rewritten coupon area. + if args.dry_run: + print(f" [#{cid}] DRY-RUN would update body ({len(body)} -> {len(new_body)} chars)") + continue + payload = { + "name": camp.get("name"), + "subject": camp.get("subject"), + "lists": [l["id"] for l in camp.get("lists", []) if isinstance(l, dict)] or [8], + "from_email": camp.get("from_email"), + "type": camp.get("type") or "regular", + "content_type": camp.get("content_type") or "html", + "body": new_body, + "altbody": camp.get("altbody"), + "template_id": camp.get("template_id") or 6, + "tags": camp.get("tags") or [], + "messenger": camp.get("messenger") or "email", + "headers": camp.get("headers") or [], + } + b.lm_api(f"/campaigns/{cid}", payload, "PUT") + print(f" [#{cid}] updated coupon block (body {len(body)} -> {len(new_body)} chars)") + return 0 + + +if __name__ == "__main__": + sys.exit(main())