weekly_partner_pipeline.py
Language Python2.4 KB44 lines
#!/usr/bin/env python3"""weekly_partner_pipeline.py: the deterministic engine of the Weekly Partner Client Pipeline.Lifetime value comes from a local, append-only order history(07-Automation/data/order_history.json), never from a single Plinth call:orders.fetch silently truncates large result sets (about 70 orders a response, no"has more" flag) and its offsets overlap, so an all-time query drops a long-standingclient's newest orders. The history is seeded once from the roster workbook, thengrown by day-sized pulls paged until a page adds nothing (see DECISIONS.md). Anapproved-merge registry (data/merge_registry.json) folds one person's duplicateaccounts together at classify time; entries are added only with explicit approval.The script calls no API. The scheduled session makes the Plinth and Bitrix callsand hands the raw responses to it. The code lives in partner_pipeline/.Commands, in run order (the SOP has the full procedure):seed-baseline one time: load the roster workbook as per-customer baselinesingest merge raw orders.fetch pages into the history; prints"INGEST: parsed=N added=N", which the paging loop readsclassify lifetime metrics and tiers from the history (partner-thresholds.md)verify no-shrink guardrail: exits 2 if any lifetime total decreasedwrite-stubs create or upgrade client stubs (guarded)refresh-xml add or stamp clients in partner-client-master-list.xml (guarded)refresh-workbook regenerate the Drive-swap roster workbook (guarded)reconcile-deals absorb a Bitrix deals pull into census blocks and stubs (guarded)route propose outreach candidates; read-only on the vault and Bitrixoutreach-pull-list list the deals whose stage history must be re-pulledoutreach-audit build Bitrix_Pipeline_Outreach_Audit_<date>.xlsx (after refresh-workbook)Guarded stages refuse while partner-thresholds.md still has a TBD in the active mode.Run any command with --help for its flags. Install: pip install -r 07-Automation/requirements.txt"""import sysfrom pathlib import Path# run_sample.py runs this file with runpy.run_path, which does not put the script's# directory on sys.path, so the package next to it has to be added by hand.sys.path.insert(0, str(Path(__file__).resolve().parent))from partner_pipeline.cli import main # noqa: E402if __name__ == "__main__":main()