r""" conditions/injection_admin_code.py — document #20: an injection code billed without 96372 gets 96372 added, Units 1, on every payer except Medicare (operator, 2026-10-13: the client's 41-code list as given; 96372 is the only admin code; always Units 1). python tests\test_conditions_injection_admin_code.py Uses tests/fixtures/vaccine_claim.html — its Fee Schedule picker lists 96372 — reshaped per case with `seedCptRows`. """ import io import sys import pathlib import inspect import contextlib ROOT = pathlib.Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "src")) FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "vaccine_claim.html" from ecw_bot.conditions import injection_admin_code as inj # noqa: E402 from ecw_bot.conditions import CONDITIONS # noqa: E402 from ecw_bot.conditions.base import ConditionResult, run_all # noqa: E402 from ecw_bot.core import charge_summary as cs # noqa: E402 from ecw_bot.pages import claim_form # noqa: E402 CASES = [] def case(fn): CASES.append(fn) return fn def _quiet(fn, *a, **k): with contextlib.redirect_stdout(io.StringIO()) as out: result = fn(*a, **k) return result, out.getvalue() def _row(code, billed=True, fee="40.00"): return {"code": code, "billed": billed, "billed_fee": fee, "units": "1"} def _data(cpt, payer="Medicaid"): return {"cpt": cpt, "insurance": [{"Name": payer}] if payer is not None else []} _CLIENT_LIST = ( "J0561 J0696 J1000 J1010 J1020 J1030 J1050 J1055 J1100 J1200 J1815 " "J1885 J2001 J2003 J2004 J2315 J2360 J2405 J2550 J2788 J2919 J2920 " "J2930 J3030 J3140 J3301 J3420 J3490 J7296 J7297 J7298 J7300 J7301 " "J7307 J7512 J7609 J7620 J7621 J7633 J7644 J8499").split() # ── recognition (no browser) ───────────────────────────────────────────────── @case def the_list_is_the_clients_41_codes(): assert len(_CLIENT_LIST) == 41 assert inj.INJECTION_CODES == frozenset(_CLIENT_LIST) @case def every_listed_code_but_j2001_and_j2930_is_an_injection_row(): for code in _CLIENT_LIST: expected = code not in ("J2001", "J2930") assert inj.is_injection_row(_row(code)) is expected, code assert inj.is_injection_row(_row(" j1885 ")) is True, "case and spaces" for code in ("96372", "90734", "99213", "J9999"): assert inj.is_injection_row(_row(code)) is False, code @case def only_a_96372_the_claim_will_bill_counts_as_admin_billed(): assert inj.admin_present([_row("96372")]) is True assert inj.admin_present([_row("96372", fee="0.00")]) is False, \ "a checked 96372 at 0.00 is unchecked by zero_fee_uncheck first" assert inj.admin_present([_row("96372", billed=False, fee="0.00")]) \ is False, "unchecked at 0.00 bills nothing" for other in ("96373", "96374", "90471"): assert inj.admin_present([_row(other)]) is False, other @case def an_unchecked_96372_with_a_fee_counts_it_is_checked_at_the_end(): """Review, 2026-10-14: priced_line_check (last) checks it, so a second 96372 added here would bill 96372 twice.""" row = _row("96372", billed=False, fee="25.00") assert inj.admin_present([row]) is True data = _data([_row("J1885"), row]) (fired, out) = _quiet(inj.detect, "C1", data) assert fired is False, out assert "priced_line_check checks it" in out, out assert inj.needs_review("C1", data) is None # No payer read: still nothing to add, and no Review asking for one by # hand — the 96372 is there. assert inj.needs_review("C1", _data([_row("J1885"), row], payer="")) \ is None # ── detect / needs_review ─────────────────────────────────────────────────── @case def detect_an_injection_without_96372(): assert inj.detect("C1", _data([_row("99213"), _row("J1885")])) is True @case def detect_nothing_when_96372_is_billed(): data = _data([_row("J1885"), _row("96372")]) (fired, _) = _quiet(inj.detect, "C1", data) assert fired is False assert inj.needs_review("C1", data) is None @case def an_unchecked_or_zero_fee_injection_is_not_billed(): assert inj.detect("C1", _data([_row("J1885", billed=False)])) is False assert inj.detect("C1", _data([_row("J1885", fee="0.00")])) is False @case def j2001_or_j2930_alone_never_needs_96372(): for code in ("J2001", "J2930"): data = _data([_row(code)]) assert inj.detect("C1", data) is False, code assert inj.needs_review("C1", data) is None, code @case def medicare_is_left_alone_and_not_review(): data = _data([_row("J1885")], payer="Medicare") (fired, _) = _quiet(inj.detect, "C1", data) assert fired is False assert inj.needs_review("C1", data) is None @case def an_unmapped_or_unread_payer_is_review(): for payer, words in (("NO SUCH PAYER XYZ", "cannot classify"), ("", "no primary payer name")): data = _data([_row("J1885")], payer=payer) (fired, _) = _quiet(inj.detect, "C1", data) assert fired is False, payer why = inj.needs_review("C1", data) assert why and words in why and "96372" in why, why # ── apply (browser) ───────────────────────────────────────────────────────── def _fresh(page, rows): page.goto(FIXTURE.as_uri()) page.evaluate("rows => window.seedCptRows(rows)", rows) def _rows_for(page, code): return [r for r in claim_form.extract(page)["cpt"] if r["code"] == code] _TWO_INJECTIONS = [ {"code": "99213", "title": "OFFICE VISIT EST LEVEL 3", "fee": "120.00"}, {"code": "J1885", "title": "Toradol (30mg) ketorolac", "fee": "15.00"}, {"code": "J3420", "title": "INJ VIT B-12 CYNOCOBLMN TO 1000 MCG", "fee": "10.00"}, ] @case def apply_adds_96372_once_with_units_1_for_two_injections(page): _fresh(page, _TWO_INJECTIONS) data = claim_form.extract(page) result, out = _quiet(inj.apply, page, "C1", data) assert isinstance(result, ConditionResult) assert result.changed is True and result.review == "", (result, out) added = _rows_for(page, "96372") assert len(added) == 1, added assert added[0]["units"] == "1", added c = result.changes[0] assert c["code"] == "96372" and c["added"] is True, c assert c["injections"] == ["J1885", "J3420"], c assert "96372 added" in inj.summary_comment(result) text = inj.describe(result) assert "J1885, J3420" in text and "Added 96372" in text, text @case def apply_adds_nothing_when_96372_is_already_billed(page): _fresh(page, _TWO_INJECTIONS + [ {"code": "96372", "title": "THER/PROPH/DIAG INJ SC/IM", "fee": "25.00"}]) result, _ = _quiet(inj.apply, page, "C1", claim_form.extract(page)) assert result.changed is False assert len(_rows_for(page, "96372")) == 1 @case def a_96372_the_picker_cannot_find_is_review_add_by_hand(page): _fresh(page, _TWO_INJECTIONS) page.evaluate("() => window.removeFromFeeSchedule('96372')") result, _ = _quiet(inj.apply, page, "C1", claim_form.extract(page)) assert result.changed is False, result assert "add it by hand" in result.review, result assert _rows_for(page, "96372") == [] @case def run_all_adds_96372_and_the_summary_says_so(page): _fresh(page, _TWO_INJECTIONS) data = claim_form.extract(page) data["progress_notes"] = {"opened": "modal", "text": "Office visit."} report = {} results, _ = _quiet(run_all, page, "C1", data, report=report) assert "injection_admin_code" in [r.condition_name for r in results] assert report["review"] == [] and report["failed"] == [], report data["_conditions"] = {"fired": [r.condition_name for r in results], "saved": False, "failed": [], "review": [], "comments": report["comments"]} outcome = cs.claim_outcome(True, data) assert outcome["Category"] == "Fail", outcome assert "injection admin code 96372 added" in outcome["Comments"], outcome @case def run_all_bills_96372_once_when_it_sat_unchecked_with_a_fee(page): """The duplicate the review found: J1885 checked, 96372 unchecked at 25.00. Nothing is added, and priced_line_check checks the 96372 — one 96372 billed, not two.""" _fresh(page, [ {"code": "99213", "title": "OFFICE VISIT EST LEVEL 3", "fee": "120.00"}, {"code": "J1885", "title": "Toradol (30mg) ketorolac", "fee": "15.00"}, {"code": "96372", "title": "THER/PROPH/DIAG INJ SC/IM", "fee": "25.00", "checked": False}]) data = claim_form.extract(page) data["progress_notes"] = {"opened": "modal", "text": "Office visit."} report = {} results, out = _quiet(run_all, page, "C1", data, report=report) changed = [r.condition_name for r in results if r.changed] assert "injection_admin_code" not in changed, out assert "priced_line_check" in changed, out admin = _rows_for(page, "96372") assert len(admin) == 1, admin assert admin[0]["billed"] is True, admin assert report["review"] == [], report @case def it_is_registered_after_j2930_and_before_priced_line_check(): names = [m.NAME for m in CONDITIONS] i = names.index("injection_admin_code") assert names.index("j2930_j2001_update") < i < names.index( "priced_line_check"), names assert inj.DENTAL_UNSUPPORTED def _run_cases() -> int: from playwright.sync_api import sync_playwright failures = 0 with sync_playwright() as pw: browser = pw.chromium.launch(headless=True) page = browser.new_page() for fn in CASES: name = fn.__name__.replace("_", " ") try: if len(inspect.signature(fn).parameters) == 0: fn() else: fn(page) print(f" ok {name}") except AssertionError as exc: print(f" FAIL {name}: {exc}") failures += 1 except Exception as exc: print(f" ERROR {name}: {type(exc).__name__}: {exc}") failures += 1 browser.close() print(f"\n{len(CASES) - failures}/{len(CASES)} passed") return 1 if failures else 0 def main() -> int: """shot() writes into the operator's Screenshots\\ folder; not here.""" import tempfile from ecw_bot import settings as _cfg orig = (_cfg.SCREENSHOTS, _cfg.SAVE_CORRECTIONS) with tempfile.TemporaryDirectory() as tmp: _cfg.SCREENSHOTS = pathlib.Path(tmp) # These cases exercise eCW's own click and Add flow, as a LIVE-WRITE # run does. VERIFY clicks no box and adds no row (eCW saves both at # once, 2026-10-16): that is tests/test_verify_no_live_writes.py. _cfg.SAVE_CORRECTIONS = True try: return _run_cases() finally: _cfg.SCREENSHOTS, _cfg.SAVE_CORRECTIONS = orig if __name__ == "__main__": sys.exit(main())