Files
ecw-charge-validation/tests/test_conditions_injection_admin_code.py
T
ManikandanandClaude Opus 5.5 ba15a574ab Initial import: eCW Charge Validation bot and results Portal
Snapshot of the working project as of 2026-10-23 (local 2d4d4fc), one
commit with no earlier history: the tracked files were de-identified
first (synthetic claim ids and patient data only; see Context.md
section 7). Credentials, run logs, screenshots, claim reports and client
workbooks are gitignored and not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:38:17 +05:30

307 lines
11 KiB
Python

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())