89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Phase-5 campaign segment validation (no production DB required).
|
|
|
|
Builds a synthetic in-memory fmcsa_carriers table and asserts that every
|
|
deficiency-flag segment in build_trucking_campaigns.DEFICIENCY_SEGMENTS:
|
|
- selects exactly the carriers carrying its flag,
|
|
- excludes blocked-domain + already-sent + unflagged carriers,
|
|
- routes to a valid order landing page (incl. per-state overrides).
|
|
|
|
Requires a reachable Postgres (DATABASE_URL) only to create a TEMP table; it
|
|
never reads real data. Run:
|
|
DATABASE_URL=postgresql://pw:pw_dev_2026@localhost:5434/performancewest \
|
|
python3 scripts/tests/check_campaign_segments.py
|
|
"""
|
|
from __future__ import annotations
|
|
import importlib.util
|
|
import os
|
|
import sys
|
|
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
BTC = os.path.join(ROOT, "scripts/build_trucking_campaigns.py")
|
|
if ROOT not in sys.path:
|
|
sys.path.insert(0, ROOT)
|
|
|
|
|
|
def main() -> int:
|
|
if not os.environ.get("DATABASE_URL"):
|
|
print("SKIP: DATABASE_URL not set (needs any reachable Postgres for TEMP table)")
|
|
return 0
|
|
import psycopg2
|
|
|
|
spec = importlib.util.spec_from_file_location("btc", BTC)
|
|
btc = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(btc)
|
|
|
|
conn = psycopg2.connect(os.environ["DATABASE_URL"])
|
|
cur = conn.cursor()
|
|
cur.execute("""
|
|
CREATE TEMP TABLE fmcsa_carriers (
|
|
dot_number text, email_address text, legal_name text, phy_state text,
|
|
mcs150_parsed timestamptz, oos_active boolean,
|
|
email_verified boolean, email_verify_result text,
|
|
listmonk_sent_at timestamptz, deficiency_flags text[]);
|
|
""")
|
|
rows = [
|
|
("1", "a@good.com", "For Hire Co", "NY", None, False, True, None, None, ["for_hire_carrier"]),
|
|
("2", "b@good.com", "IRP Co", "TX", None, False, True, None, None, ["interstate_needs_irp_ifta"]),
|
|
("3", "c@good.com", "Intrastate Co", "CA", None, False, True, None, None, ["intrastate_authority_CA"]),
|
|
("4", "d@good.com", "Weight Tax Co", "OR", None, False, True, None, None, ["state_weight_tax_OR"]),
|
|
("5", "e@good.com", "Emissions Co", "CO", None, False, True, None, None, ["state_emissions_CO"]),
|
|
("6", "f@good.com", "Hazmat Co", "OH", None, False, True, None, None, ["hazmat_carrier"]),
|
|
("7", "g@good.com", "Clean Co", "NY", None, False, True, None, None, []), # no flags
|
|
("8", "h@aol.com", "Blocked Co", "NY", None, False, True, None, None, ["for_hire_carrier"]), # blocked domain
|
|
("9", "i@good.com", "Sent Co", "NY", None, False, True, None, "2026-01-01", ["for_hire_carrier"]), # already sent
|
|
]
|
|
for r in rows:
|
|
cur.execute("INSERT INTO fmcsa_carriers VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", r)
|
|
conn.commit()
|
|
|
|
all_states = tuple(s for cfg in btc.TIMEZONE_CONFIG.values() for s in cfg["states"])
|
|
expected = {
|
|
"for_hire_boc3": 1, "irp_ifta": 1, "intrastate_authority": 1,
|
|
"state_weight_tax": 1, "state_emissions": 1, "hazmat": 1,
|
|
}
|
|
ok = True
|
|
for ctype in btc.DEFICIENCY_SEGMENTS:
|
|
got = len(btc.fetch_carriers(conn, all_states, ctype, 1000))
|
|
status = "OK" if got == expected[ctype] else "FAIL"
|
|
if got != expected[ctype]:
|
|
ok = False
|
|
print(f" {status}: {ctype:<22} matched {got} (expected {expected[ctype]})")
|
|
|
|
lp_ok = (
|
|
btc.build_lp_link("state_weight_tax", "OR").endswith("/order/or-weight-mile-tax")
|
|
and btc.build_lp_link("state_emissions", "CA").endswith("/order/ca-mcp-carb")
|
|
and btc.build_lp_link("hazmat", None).endswith("/order/hazmat-phmsa")
|
|
and btc.build_lp_link("irp_ifta", None).endswith("/order/state-trucking-bundle")
|
|
)
|
|
print(" LP routing:", "OK" if lp_ok else "FAIL")
|
|
conn.close()
|
|
|
|
passed = ok and lp_ok
|
|
print("CAMPAIGN SEGMENTS:", "PASS" if passed else "FAIL")
|
|
return 0 if passed else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|