Compare commits

...

2 commits

Author SHA1 Message Date
justin
f43957882f 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).
2026-06-18 09:38:51 -05:00
justin
5c1f239307 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.
2026-06-18 09:38:26 -05:00
2 changed files with 136 additions and 0 deletions

View file

@ -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 |

View file

@ -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")