From 5c1f239307b70895461e60e390b85c8ffe1df717 Mon Sep 17 00:00:00 2001 From: justin Date: Thu, 18 Jun 2026 09:38:26 -0500 Subject: [PATCH 1/2] test(workers): NPI recurring-cycle fulfillment path (13 assertions) Runs the real _BaseNPIHandler.handle() with _create_todo monkeypatched (no DB / ERPNext / email side effects) and asserts: - first OIG/SAM screening has no [Monthly cycle] prefix / RECURRING banner - a recurring_cycle order gets the [Monthly cycle] title prefix, the "RECURRING MONTHLY CYCLE" banner, the invoice id, and the re-run-against- CURRENT-data + issue-NEW-certificate instructions - recurring_cycle works with and without an invoice id - the bundle handler's first run is not flagged recurring Verified passing both locally and inside the deployed workers container. --- .../workers/services/test_npi_recurring.py | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 scripts/workers/services/test_npi_recurring.py diff --git a/scripts/workers/services/test_npi_recurring.py b/scripts/workers/services/test_npi_recurring.py new file mode 100644 index 0000000..7c892ca --- /dev/null +++ b/scripts/workers/services/test_npi_recurring.py @@ -0,0 +1,113 @@ +""" +Logic tests for the OIG/SAM recurring-monitoring fulfillment path in +npi_provider.py. Runs the REAL _BaseNPIHandler.handle() with _create_todo +monkeypatched to capture the todo (so no DB / ERPNext / email side effects), +asserting the recurring-cycle branch produces the right title prefix + notes. + +Run: python3 -m pytest scripts/workers/services/test_npi_recurring.py -q + or: python3 scripts/workers/services/test_npi_recurring.py +""" + +import asyncio +import os +import sys + +# Make 'scripts' importable when run directly from repo root. +_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) +if _REPO not in sys.path: + sys.path.insert(0, _REPO) + +from scripts.workers.services import npi_provider as M # noqa: E402 + +_FAILS = [] + + +def check(label, cond): + print((" PASS " if cond else " FAIL ") + label) + if not cond: + _FAILS.append(label) + + +def run_handler(handler_cls, order_data, order_number="HC-TEST-1"): + """Run handler.handle() capturing the todo via a monkeypatched _create_todo.""" + captured = {} + + def fake_create_todo(self, order_number, intake, title, description, priority="normal"): + captured["order_number"] = order_number + captured["title"] = title + captured["description"] = description + captured["priority"] = priority + + orig = M._BaseNPIHandler._create_todo + M._BaseNPIHandler._create_todo = fake_create_todo + try: + h = handler_cls() + asyncio.run(h.handle(order_data, order_number)) + finally: + M._BaseNPIHandler._create_todo = orig + return captured + + +BASE_INTAKE = { + "npi": "1234567890", + "provider_name": "Dr. Jane Smith", + "specialty": "Internal Medicine", + "practice_state": "TX", + "email": "jane@example.com", +} + + +# ── 1. OIG/SAM first fulfillment (NOT recurring) ──────────────────────────── +first = run_handler( + M.OIGSAMScreeningHandler, + {"intake_data": dict(BASE_INTAKE), "customer_name": "Jane Smith"}, +) +check("first screening has no [Monthly cycle] prefix", "[Monthly cycle]" not in first["title"]) +check("first screening has no RECURRING note", "RECURRING MONTHLY CYCLE" not in first["description"]) +check("first screening title names the provider", "Dr. Jane Smith" in first["title"]) +check("first screening title has the NPI", "1234567890" in first["title"]) + + +# ── 2. OIG/SAM recurring monthly cycle ────────────────────────────────────── +renew = run_handler( + M.OIGSAMScreeningHandler, + { + "intake_data": dict(BASE_INTAKE), + "customer_name": "Jane Smith", + "recurring_cycle": True, + "recurring_invoice_id": "in_LIVE123", + }, +) +check("recurring title HAS [Monthly cycle] prefix", renew["title"].startswith("[Monthly cycle] ")) +check("recurring desc has RECURRING MONTHLY CYCLE banner", "RECURRING MONTHLY CYCLE" in renew["description"]) +check("recurring desc references the invoice id", "in_LIVE123" in renew["description"]) +check("recurring desc says re-run against CURRENT data", "CURRENT OIG LEIE" in renew["description"]) +check("recurring desc says issue NEW dated certificate", "NEW dated certificate" in renew["description"]) + + +# ── 3. recurring_cycle without invoice id still works ─────────────────────── +renew_noinv = run_handler( + M.OIGSAMScreeningHandler, + {"intake_data": dict(BASE_INTAKE), "recurring_cycle": True}, +) +check("recurring (no invoice) still has prefix", renew_noinv["title"].startswith("[Monthly cycle] ")) +check("recurring (no invoice) has banner", "RECURRING MONTHLY CYCLE" in renew_noinv["description"]) + + +# ── 4. Bundle handler: first screening, no recurring prefix on first run ───── +bundle = run_handler( + M.ProviderComplianceBundleHandler, + {"intake_data": dict(BASE_INTAKE), "customer_name": "Jane Smith"}, +) +check("bundle first run has no [Monthly cycle] prefix", "[Monthly cycle]" not in bundle["title"]) + + +# ── 5. recurring flag default is falsey ───────────────────────────────────── +check("recurring branch is off by default", "[Monthly cycle]" not in first["title"]) + + +print() +if _FAILS: + print(f"{len(_FAILS)} FAILED: " + ", ".join(_FAILS)) + sys.exit(1) +print("ALL NPI RECURRING TESTS PASSED") From f43957882f2520b211ae5e1493fce1e0519908cf Mon Sep 17 00:00:00 2001 From: justin Date: Thu, 18 Jun 2026 09:38:51 -0500 Subject: [PATCH 2/2] docs(billing): record OIG/SAM recurring validation status Checkout half proven against live Stripe (dry-run session created + expired, zero charge), webhook subscription-id extraction + worker renewal fulfillment covered by unit tests (31 + 13). Remaining gap: full E2E with a Stripe test clock, which needs test-mode keys in the server .env (currently unset). --- docs/billing.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/billing.md b/docs/billing.md index a56e0d0..55cb2d9 100644 --- a/docs/billing.md +++ b/docs/billing.md @@ -235,6 +235,29 @@ screening; customers are converted to the $79/mo monitoring subscription after that first cycle (the standalone $948/yr of monitoring is no longer given away inside the bundle). +**Validation status (2026-06-18):** +- ✅ *Checkout half — proven against LIVE Stripe.* A dry-run created a real + `mode:subscription` Checkout Session with the exact production params + (recurring `price_data`, `unit_amount=7900`, `recurring.interval=month`, + `card`+`us_bank_account`, metadata) — Stripe returned `amount_total=7900`, + `type=recurring`, then the session was immediately **expired** (creating a + session never charges anyone; only a completed hosted page does). Net effect + on prod: zero. +- ✅ *Webhook subscription-id extraction* — `invoiceSubscriptionId()` unit tests + (31 in `api/tests/recurring-subscription.test.ts`) cover acacia (top-level) + AND dahlia (nested) invoice shapes, renewal-cycle gating, surcharge + suppression, recurring line-item build. +- ✅ *Worker renewal fulfillment* — `scripts/workers/services/test_npi_recurring.py` + (13 assertions) runs the real handler and asserts the `[Monthly cycle]` / + re-screen behaviour; passes locally + in the deployed workers container. +- ⏳ *Full end-to-end with a Stripe test clock* — NOT yet run. Requires + `STRIPE_TEST_SECRET_KEY` / `STRIPE_TEST_WEBHOOK_SECRET` in the server `.env` + (currently unset; prod is `NODE_ENV=production`). Once those exist: place a + test-card subscription, advance a billing cycle via a test clock, and confirm + the live `invoice.paid` (subscription_cycle) re-dispatches the screening + worker and a fresh certificate is issued. This is the last gap before a real + recurring charge should be marketed. + ### Formation Maintenance Bundles | Bundle | Price | Includes | Savings |