Files
ecw-charge-validation/tests/test_conditions_vaccine_admin_codes.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

1367 lines
56 KiB
Python

r"""
conditions/vaccine_admin_codes.py — Charge Condition Document row 18:
vaccine codes billed without an immunization-admin code get the admin
code(s) added — 90460/90461 for age 18 and below, 90471/90472 above 18 —
with the "each additional" code's Units = vaccine count - 1.
python tests\test_conditions_vaccine_admin_codes.py
Pure-data cases first (detection, payer gate, age), then page cases
against fixtures/vaccine_claim.html, whose Fee Schedule picker is the same
simulation hcfa_claim.html uses for G2025 — `add_cpt_row()` is exercised for
real (click Add, search, pick the exact match, OK), never stubbed.
The three "no change" data cases at the end mirror live claims the client
had already fixed by hand (9131000, 9132000, 9133000): the condition must
leave every one of them alone.
Every checked vaccine or admin row a page case seeds carries its own fee.
The fixture's `seedCptRows` prices a row with no `fee` at 0.00, and since
the operator's ruling of 2026-09-30 a CHECKED line billed at zero is not
billed at all — zero_fee_uncheck unchecks it first — so it no longer counts
as a vaccine, or as "admin already billed". A case that meant a billed line
says so with a price; the cases about a zero-fee line say "0.00".
"""
import contextlib
import io
import sys
import pathlib
import inspect
ROOT = pathlib.Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "src"))
FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "vaccine_claim.html"
UB_FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "ub_claim.html"
HCFA_FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "hcfa_claim.html"
from ecw_bot import conditions # noqa: E402
from ecw_bot.conditions import vaccine_admin_codes as vac # noqa: E402
from ecw_bot.conditions.base import ConditionResult, run_all # noqa: E402
from ecw_bot.pages import claim_form # noqa: E402
from ecw_bot.selectors import claim_form as sel # noqa: E402
CASES = []
def case(fn):
CASES.append(fn)
return fn
# =============================================================================
# Data helpers
# =============================================================================
def _row(code, desc="", billed=True, sdos="07/07/2026", units="1"):
return {"code": code, "description": desc, "billed": billed,
"sdos": sdos, "units": units}
def _data(cpt, payer="Medicaid", dob="01/02/1976", age_sex=" 50Y, M",
claim_date="07/07/2026"):
return {
"cpt": cpt,
"insurance": [{"Name": payer}] if payer is not None else [],
"patient": {"dob": dob, "age_sex": age_sex},
"header": {"claim_date": claim_date},
}
def _age(data):
return vac.patient_age(data, vac.checked_vaccine_rows(data.get("cpt")))[0]
_TDAP = "TETANUS DIPHTHERIA TOXOIDS AND ACELLULAR PERTUSSIS VACC"
_ADMIN_1ST = "IMMUNIZATION ADMIN SINGLE OR COMBINATION"
_ADMIN_ADD = "IMMUNIZATION ADMIN, EACH ADD"
# =============================================================================
# Vaccine / admin row recognition
# =============================================================================
_CLIENT_VACCINES = ("90633", "90648", "90651", "90656", "90657", "90660",
"90680", "90687", "90698", "90707", "90710", "90713",
"90716", "90732", "90734", "90744", "90746", "91321",
"91322")
@case
def every_code_on_the_client_vaccine_list_is_a_vaccine():
"""Operator, 2026-10-13: the 19 codes of the client's list, by code."""
assert vac.VACCINE_CODES == frozenset(_CLIENT_VACCINES)
for code in _CLIENT_VACCINES:
assert vac.is_vaccine_row(_row(code)), code
@case
def a_listed_code_is_a_vaccine_whatever_its_hover_text():
assert vac.is_vaccine_row(_row("90732", "PCV20"))
assert vac.is_vaccine_row(_row("90746", ""))
@case
def a_code_off_the_list_is_not_a_vaccine_whatever_its_hover_text():
# The earlier rule took "VACC" in the hover text or 90476-90759; both
# are gone (operator, 2026-10-13) — the list is the whole rule.
for code, hover in (("90715", _TDAP), ("90677", "PCV20"),
("90750", "Shingrix"), ("90686", "FLU VACC"),
("90476", ""), ("90759", ""),
("Q2037", "FLU VACC FLUVIRIN 3 YRS & >"),
("99213", "Office Visit, Est Pt., Level 3")):
assert not vac.is_vaccine_row(_row(code, hover)), code
@case
def only_the_four_admin_codes_are_admin_rows():
for code in ("90460", "90461", "90471", "90472"):
assert vac.is_admin_row(_row(code)), code
assert not vac.is_vaccine_row(_row(code)), code
# Other administration codes, and "ADMIN" in the hover text, are not
# this condition's admin codes (operator, 2026-10-13).
for code, hover in (("90473", ""), ("90474", ""), ("90480", ""),
("G0008", ""), ("G0009", ""), ("G0010", ""),
("0002A", "IMMUNIZATION ADMIN COVID 2ND")):
assert not vac.is_admin_row(_row(code, hover)), code
@case
def a_covid_vaccine_with_90480_billed_still_gets_its_admin_code():
"""90480 is not one of the four admin codes, so it is not "admin
already billed": 91321 on an adult gets 90471 added."""
cpt = [_row("99396"), _row("91321"), _row("90480")]
assert [r["code"] for r in vac.checked_vaccine_rows(cpt)] == ["91321"]
assert vac.checked_admin_present(cpt) is False
assert vac.detect("C1", _data(cpt)) is True
@case
def flu_plus_covid_count_as_two_vaccines():
data = _data([_row("90656"), _row("91322"), _row("90480")])
assert vac._plan("C1", data, data["cpt"])["vaccines"] == ["90656", "91322"]
@case
def vaccine_count_is_rows_not_units():
# Ruling 4: one vaccine row at Units 3 is ONE vaccine -> 90471 x1 only.
data = _data([_row("99396"), _row("90734", _TDAP, units="3")])
assert vac._plan("C1", data, data["cpt"])["vaccines"] == ["90734"]
data = _data([_row("90734", _TDAP, units="2"),
_row("90732", "PCV20", units="1")])
assert len(vac._plan("C1", data, data["cpt"])["vaccines"]) == 2
@case
def unchecked_vaccine_is_not_counted():
cpt = [_row("99396"), _row("90734", _TDAP, billed=False)]
assert vac.checked_vaccine_rows(cpt) == []
assert vac.detect("C1", _data(cpt)) is False
@case
def unknown_checkbox_state_counts_as_checked():
# billed=None: the row has no "Assign To Patient" box at all; an absent
# key is a snapshot from before extract() read it. Neither may silently
# drop a vaccine.
none_row = _row("90734", _TDAP, billed=None)
missing = {"code": "90732", "description": "PCV20"}
assert vac.checked_vaccine_rows([none_row, missing]) == [none_row, missing]
# =============================================================================
# A checked line billed at zero — zero_fee_uncheck unchecks it first
# (operator ruling, 2026-09-30)
# =============================================================================
def _fee(row, fee):
"""`row` with a Billed Fee as extract() reads it."""
return dict(row, billed_fee=fee)
@case
def a_checked_zero_fee_admin_line_is_not_admin_already_billed():
# zero_fee_uncheck, registered first, unchecks it before this
# condition's apply() runs — counting it would leave the vaccine billed
# with no admin code (document #18's own case).
for fee in ("0.00", "", "0", "$0.00"):
cpt = [_fee(_row("90734", _TDAP), "60.00"),
_fee(_row("90471", _ADMIN_1ST), fee)]
assert vac.checked_admin_present(cpt) is False, fee
assert vac.detect("C1", _data(cpt)) is True, fee
plan = vac._plan("C1", _data(cpt), cpt)
assert (plan["first"], plan["vaccines"]) == ("90471", ["90734"]), (fee, plan)
@case
def a_checked_priced_admin_line_is_still_admin_already_billed():
for fee in ("30.00", "$30.00", "N/A"): # N/A: does not parse, not zero
cpt = [_fee(_row("90734", _TDAP), "60.00"),
_fee(_row("90471", _ADMIN_1ST), fee)]
assert vac.checked_admin_present(cpt) is True, fee
assert vac.detect("C1", _data(cpt)) is False, fee
@case
def a_zero_fee_admin_line_with_an_unknown_checkbox_still_counts():
# billed None keeps today's behaviour: zero_fee_uncheck never touches a
# row with no "Assign To Patient" checkbox, so it stays "billed".
cpt = [_fee(_row("90734", _TDAP), "60.00"),
_fee(_row("90471", _ADMIN_1ST, billed=None), "0.00")]
assert vac.checked_admin_present(cpt) is True
assert vac.detect("C1", _data(cpt)) is False
@case
def an_admin_line_whose_fee_was_never_read_still_counts():
# No billed_fee key at all (a snapshot from before extract() read fees,
# or a hand-built row): the fee is unknown, not zero — today's behaviour.
cpt = [_row("90734", _TDAP), _row("90471", _ADMIN_1ST)]
assert "billed_fee" not in cpt[1]
assert vac.checked_admin_present(cpt) is True
assert vac.detect("C1", _data(cpt)) is False
@case
def a_checked_zero_fee_vaccine_is_not_counted():
# The same ruling for a vaccine row: zero_fee_uncheck unchecks it, so it
# is not billed — one vaccine left, so 90471 alone, no 90472.
tdap = _fee(_row("90734", _TDAP), "0.00")
pcv = _fee(_row("90732", "PCV20"), "290.00")
assert vac.checked_vaccine_rows([tdap, pcv]) == [pcv]
plan = vac._plan("C1", _data([tdap, pcv]), [tdap, pcv])
assert plan["vaccines"] == ["90732"], plan
assert plan["first"] == "90471", plan
@case
def a_claim_whose_only_vaccine_is_checked_at_zero_fires_nothing():
cpt = [_fee(_row("99396"), "250.00"), _fee(_row("90734", _TDAP), "0.00")]
assert vac.checked_vaccine_rows(cpt) == []
assert vac.detect("C1", _data(cpt)) is False
@case
def a_zero_fee_vaccine_with_an_unknown_checkbox_still_counts():
none_row = _fee(_row("90734", _TDAP, billed=None), "0.00")
assert vac.checked_vaccine_rows([none_row]) == [none_row]
assert vac.detect("C1", _data([none_row])) is True
@case
def a_checked_admin_line_with_no_fee_input_still_counts():
# billed_fee None: extract() found NO Billed Fee input on the row
# (review finding, 2026-09-30). zero_fee_uncheck's apply() skips such a
# row (`uncheck_zero_fee_cpt_rows`: no fee input -> left alone), so it is
# still billed when this condition's apply() runs — it must count.
cpt = [_fee(_row("90734", _TDAP), "60.00"),
_fee(_row("90471", _ADMIN_1ST), None)]
assert vac.unchecked_by_zero_fee_rule(cpt[1]) is False
assert vac.checked_admin_present(cpt) is True
assert vac.detect("C1", _data(cpt)) is False
@case
def a_checked_vaccine_with_no_fee_input_still_counts():
tdap = _fee(_row("90734", _TDAP), None)
pcv = _fee(_row("90732", "PCV20"), "290.00")
assert vac.checked_vaccine_rows([tdap, pcv]) == [tdap, pcv]
plan = vac._plan("C1", _data([tdap, pcv]), [tdap, pcv])
assert plan["vaccines"] == ["90734", "90732"], plan
# =============================================================================
# detect()
# =============================================================================
@case
def detect_true_for_checked_vaccines_without_admin():
cpt = [_row("99396"), _row("90732", "PCV20"), _row("90734", _TDAP)]
assert vac.detect("C1", _data(cpt)) is True
@case
def detect_false_when_a_checked_admin_code_is_present():
cpt = [_row("90734", _TDAP), _row("90471", _ADMIN_1ST)]
assert vac.detect("C1", _data(cpt)) is False
@case
def an_admin_by_hover_text_does_not_count_as_admin_billed():
# By code only since 2026-10-13: 0002A is not one of the four.
cpt = [_row("90734", _TDAP), _row("0002A", "IMMUNIZATION ADMIN COVID 2ND")]
assert vac.detect("C1", _data(cpt)) is True
@case
def detect_still_true_when_the_only_admin_code_is_unchecked():
# Live claim 9132000's unchecked 90460 at 0.00 is not "present".
cpt = [_row("90656", "FLU VACC IIV3 NO PRSV 0.5ML IM"),
_row("90460", "IMMUNIZATION ADMIN", billed=False)]
assert vac.detect("C1", _data(cpt)) is True
@case
def detect_false_with_no_vaccine_at_all():
assert vac.detect("C1", _data([_row("99213")])) is False
assert vac.detect("C1", {}) is False
assert vac.detect("C1", None) is False
@case
def detect_false_for_medicare():
cpt = [_row("90734", _TDAP)]
assert vac.detect("C1", _data(cpt, payer="Humana Medicare")) is False
@case
def detect_false_for_an_unmapped_payer_or_no_payer():
cpt = [_row("90734", _TDAP)]
assert vac.detect("C1", _data(cpt, payer="Some New Carrier Inc")) is False
assert vac.detect("C1", _data(cpt, payer=None)) is False
@case
def detect_true_for_every_known_non_medicare_group():
# The PAYER GATE only, on data shaped like a UB-form read. Commercial
# ("United Health Care") claims open on the professional/HCFA screen —
# end to end in hcfa_screen_vaccine_claim_fires_on_the_payer_from_the_
# insurances_grid below — and Dental claims never reach run_all at all
# (is_dental_claim_form).
cpt = [_row("90734", _TDAP)]
for payer in ("Medicaid", "BH COLORADO ACCESS", "United Health Care",
"DentaQuest", "OUTREACH PROGRAM"):
assert vac.detect("C1", _data(cpt, payer=payer)) is True, payer
@case
def detect_false_when_no_age_can_be_determined():
cpt = [_row("90734", _TDAP)]
assert vac.detect("C1", _data(cpt, dob="", age_sex="")) is False
# =============================================================================
# needs_review() — "did not fire" that is not "clean" (review item D2)
# =============================================================================
@case
def needs_review_names_an_unmapped_payer():
cpt = [_row("90734", _TDAP)]
why = vac.needs_review("C1", _data(cpt, payer="Some New Carrier Inc"))
assert why and "Some New Carrier Inc" in why and "90734" in why, why
assert "add the admin code by hand" in why, why
@case
def needs_review_names_a_claim_with_no_payer_name_read():
why = vac.needs_review("C1", _data([_row("90734", _TDAP)], payer=None))
assert why and "no primary payer name was read" in why, why
@case
def needs_review_names_a_claim_with_no_usable_age():
why = vac.needs_review("C1", _data([_row("90734", _TDAP)], dob="",
age_sex=""))
assert why and "no usable DOB or age" in why, why
@case
def needs_review_is_silent_for_medicare():
"""Document #19 is Medicare's own rule: not covered, not unfinished."""
cpt = [_row("90734", _TDAP)]
why = vac.needs_review("C1", _data(cpt, payer="Humana Medicare"))
assert why is None, why
@case
def needs_review_is_silent_when_an_admin_code_is_already_billed():
# Even with a payer it could not classify: nothing is missing.
cpt = [_row("90734", _TDAP), _row("90471", _ADMIN_1ST)]
why = vac.needs_review("C1", _data(cpt, payer="Some New Carrier Inc"))
assert why is None, why
@case
def needs_review_is_silent_with_no_vaccine_or_when_detect_fires():
assert vac.needs_review("C1", _data([_row("99213", "OFFICE VISIT")],
payer="Some New Carrier Inc")) is None
assert vac.needs_review("C1", {}) is None
assert vac.needs_review("C1", _data([_row("90734", _TDAP)])) is None
@case
def needs_review_does_not_log_the_decision_a_second_time():
data = _data([_row("90734", _TDAP)], payer="Some New Carrier Inc")
out = io.StringIO()
with contextlib.redirect_stdout(out):
vac.detect("C1", data)
vac.needs_review("C1", data)
logged = out.getvalue()
assert logged.count("leaving the claim as read") == 1, logged
@case
def run_all_reports_the_unmapped_payer_as_review():
report = {}
data = _data([_row("90734", _TDAP)], payer="Some New Carrier Inc")
with contextlib.redirect_stdout(io.StringIO()):
results = run_all(None, "C1", data, conditions=[vac], report=report)
assert results == [], results
assert report["fired"] == [] and report["failed"] == [], report
assert [r["name"] for r in report["review"]] == [vac.NAME], report
# =============================================================================
# Age
# =============================================================================
@case
def age_is_whole_years_on_the_first_vaccine_rows_date_of_service():
cpt = [_row("99396", sdos="01/01/2020"),
_row("90734", _TDAP, sdos="07/07/2026")]
assert _age(_data(cpt, dob="01/02/1976")) == 50
@case
def eighteenth_birthday_on_the_dos_is_still_18_pediatric():
cpt = [_row("90734", _TDAP, sdos="03/15/2026")]
assert _age(_data(cpt, dob="03/15/2008")) == 18
assert vac.admin_codes_for_age(18) == ("90460", "90461")
@case
def nineteenth_birthday_on_the_dos_is_19_adult():
cpt = [_row("90734", _TDAP, sdos="03/15/2026")]
assert _age(_data(cpt, dob="03/15/2007")) == 19
assert vac.admin_codes_for_age(19) == ("90471", "90472")
@case
def day_before_the_nineteenth_birthday_is_still_18():
cpt = [_row("90734", _TDAP, sdos="03/14/2026")]
assert _age(_data(cpt, dob="03/15/2007")) == 18
@case
def age_falls_back_to_the_claim_date_when_the_row_has_no_sdos():
cpt = [_row("90734", _TDAP, sdos="")]
assert _age(_data(cpt, dob="03/15/2007", claim_date="03/15/2026")) == 19
@case
def age_falls_back_to_age_sex_when_dob_is_unusable():
cpt = [_row("90734", _TDAP)]
assert _age(_data(cpt, dob="", age_sex=" 50Y, M")) == 50
assert _age(_data(cpt, dob="not a date", age_sex="7Y, F")) == 7
# a DOB after the date of service is not a usable DOB either
assert _age(_data(cpt, dob="01/01/2030", age_sex=" 50Y, M")) == 50
@case
def months_or_days_only_age_sex_is_zero_years():
cpt = [_row("90734", _TDAP)]
assert _age(_data(cpt, dob="", age_sex=" 12M 12D, F")) == 0
assert _age(_data(cpt, dob="", age_sex="3D, M")) == 0
assert _age(_data(cpt, dob="", age_sex="")) is None
# =============================================================================
# Live samples the client already fixed by hand — must stay untouched
# =============================================================================
@case
def live_9131000_adult_with_admin_already_billed_no_change():
# The live vaccines (90677, 90750, 90715) are off the client's list
# since 2026-10-13; listed codes stand in so the admin rule is tested.
cpt = [_row("99396"), _row("90732", "PCV20"), _row("90746", "Shingrix"),
_row("90734", _TDAP),
_row("90471", _ADMIN_1ST, units="1"),
_row("90472", _ADMIN_ADD, units="2")]
assert vac.detect("9131000", _data(cpt, age_sex=" 50Y, F")) is False
@case
def live_9132000_adult_with_checked_90471_and_unchecked_90460_no_change():
# 90673 is off the client's vaccine list (2026-10-13): no vaccine at
# all now, as well as an admin code already billed.
cpt = [_row("99397"), _row("90673", "FLU VACC RIV3 NO PRESERV"),
_row("90471", _ADMIN_1ST),
_row("90460", "IMMUNIZATION ADMIN THROUGH 18 YRS", billed=False)]
assert vac.detect("9132000",
_data(cpt, dob="02/10/1968", age_sex=" 58Y, F")) is False
@case
def live_9133000_infant_with_pediatric_admin_already_billed_no_change():
cpt = [_row("99392"), _row("90732", "PCV20"),
_row("90716", "VARICELLA VIRUS VACCINE LIVE FOR SUBCUTANEOUS USE"),
_row("90707", "MMR VIRUS VACCINE LIVE SUBCUTANEOUS"),
_row("90633", "HEPA VACCINE PED/ADOL-2 DOSE IM"),
_row("90460", "IMMUNIZATION ADMIN THROUGH 18 YRS"),
_row("90461", "IMMUNIZATION ADMIN EACH ADD", units="3")]
assert vac.detect("9133000",
_data(cpt, dob="07/07/2025", age_sex=" 12M, M")) is False
# =============================================================================
# Registry
# =============================================================================
@case
def registered_last_of_the_specific_conditions():
"""
After every other specific condition, so it re-reads a grid they have
already changed. After it come only injection_admin_code (#20, which
adds a line the same way, 2026-10-13), medicare_pps_code (#25, which
adds one too, 2026-10-23) and priced_line_check — the common rule's
reverse half, registered LAST on 2026-09-30 so it only ever sees lines
the exclusion conditions have already zeroed.
"""
from ecw_bot.conditions import (injection_admin_code, medicare_pps_code,
priced_line_check)
assert conditions.CONDITIONS[-4] is vac, conditions.CONDITIONS
assert conditions.CONDITIONS[-3] is injection_admin_code, conditions.CONDITIONS
assert conditions.CONDITIONS[-2] is medicare_pps_code, conditions.CONDITIONS
assert conditions.CONDITIONS[-1] is priced_line_check, conditions.CONDITIONS
assert conditions.BY_NAME["vaccine_admin_codes"] is vac
assert vac.NAME == "vaccine_admin_codes"
# =============================================================================
# Page helpers
# =============================================================================
def _fresh(page):
page.goto(FIXTURE.as_uri())
def _seed(page, rows, dob=None, age_sex=None):
page.evaluate("rows => window.seedCptRows(rows)", rows)
if dob is not None or age_sex is not None:
page.evaluate("([d, a]) => window.setPatient(d, a)",
[dob or "", age_sex or ""])
def _live(page):
return claim_form.extract(page)
def _rows_for(page, code):
return [r for r in _live(page)["cpt"] if r["code"] == code]
_ADULT_ONE = [
{"code": "99396", "title": "PREVENTIVE VISIT EST AGE 40-64", "fee": "250.00"},
{"code": "90734", "title": _TDAP, "fee": "60.00", "icd1": "2"},
]
_CHILD_FOUR = [
{"code": "99392", "title": "PREV VISIT EST AGE 1-4", "fee": "180.00"},
{"code": "90732", "title": "PCV20", "fee": "290.00", "icd1": "2"},
{"code": "90716", "title": "VARICELLA VIRUS VACCINE LIVE FOR SUBCUTANEOUS USE",
"fee": "180.00", "icd1": "2"},
{"code": "90707", "title": "MMR VIRUS VACCINE LIVE SUBCUTANEOUS",
"fee": "95.00", "icd1": "2"},
{"code": "90633", "title": "HEPA VACCINE PED/ADOL-2 DOSE IM",
"fee": "70.00", "icd1": "2"},
]
# =============================================================================
# Extractor: the additive `billed` field
# =============================================================================
@case
def extract_reports_billed_from_the_assign_to_patient_checkbox(page):
_fresh(page)
_seed(page, [{"code": "90734", "title": _TDAP},
{"code": "90460", "title": "IMMUNIZATION ADMIN", "checked": False},
{"code": "90732", "title": "PCV20", "noCheckbox": True}])
cpt = _live(page)["cpt"]
assert [r["billed"] for r in cpt] == [True, False, None], cpt
assert cpt[0]["description"] == _TDAP, cpt[0]
@case
def extract_billed_is_none_on_a_ub_form_without_the_checkbox(page):
# ub_claim.html's rows carry no updateBillToIns( checkbox — unknown,
# which the condition treats as checked, never as "not billed".
page.goto(UB_FIXTURE.as_uri())
cpt = _live(page)["cpt"]
assert cpt and all(r["billed"] is None for r in cpt), cpt
assert cpt[0]["code"] == "H0023", "existing fields must be unchanged"
@case
def extract_reports_billed_fee_none_for_a_row_with_no_fee_input(page):
# None ("never read"), not "" — "" is a blank fee that WAS read, which
# is_zero_fee() calls zero. Told apart, zero_fee_uncheck.detect() and
# this condition's pre-read agree with uncheck_zero_fee_cpt_rows(),
# which leaves a row with no fee input alone (review finding 2026-09-30).
_fresh(page)
_seed(page, [{"code": "90734", "title": _TDAP, "fee": "60.00"},
{"code": "90471", "title": _ADMIN_1ST, "noFee": True}])
cpt = _live(page)["cpt"]
assert [r["billed_fee"] for r in cpt] == ["60.00", None], cpt
@case
def run_all_counts_a_checked_admin_line_with_no_fee_input_as_billed(page):
"""
The claim-level shape of the finding: a checked 90471 with no Billed
Fee input. zero_fee_uncheck never unchecks it (no fee input -> left
alone), so it IS the admin code billed — no second 90471 is added.
Before the fix extract() read its fee as "" (zero): vaccine_admin_codes
fired and added a 90471 on top, two admin lines billed.
"""
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90471", "title": _ADMIN_1ST,
"noFee": True}])
data = _live(page)
assert vac.detect("9113000", data) is False
results = run_all(page, "9113000", data)
assert [r.condition_name for r in results] == [], results
assert [r["billed"] for r in _rows_for(page, "90471")] == [True]
@case
def run_all_counts_a_checked_vaccine_with_no_fee_input(page):
# The mirror: a checked vaccine with no fee input stays billed, so it is
# counted — two vaccines, 90471 AND 90472, not 90471 alone.
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90716", "title": _CHILD_FOUR[2]["title"],
"noFee": True, "icd1": "2"}])
results = run_all(page, "9113000", _live(page))
assert [r.condition_name for r in results] == ["vaccine_admin_codes"], results
added = [c["code"] for c in results[0].changes if c.get("added")]
assert added == ["90471", "90472"], results[0].changes
# =============================================================================
# PINNED, NEEDS AN OPERATOR RULING — an admin code the Fee Schedule prices
# at 0.00. Today's outcome, not the settled one (review finding 2026-09-30).
# =============================================================================
@case
def pinned_needs_ruling_an_admin_code_added_at_zero_adds_again_next_run(page):
"""
PINNED, NEEDS A RULING. Run 1: the picker prices the added 90471 at
0.00 — it lands checked at 0.00 and stays checked (zero_fee_uncheck ran
FIRST, before it existed; priced_line_check only ever checks), and
describe() reports it with no warning. Run 2 on the same claim, still
in the queue: that 90471 is a checked zero-fee admin line, which ruling
B says does not count, so zero_fee_uncheck unchecks it and
vaccine_admin_codes adds ANOTHER 90471 at 0.00 — one more per run.
Whether a line added at 0.00 should be flagged, failed, or left is
beyond rulings A/B/C.
"""
_fresh(page)
page.evaluate("([c, f]) => window.setFeeScheduleFee(c, f)", ["90471", "0.00"])
_seed(page, _ADULT_ONE)
def grid():
return [(r["code"], r["billed"], r["billed_fee"])
for r in _live(page)["cpt"]]
results = run_all(page, "9113000", _live(page))
assert [r.condition_name for r in results] == ["vaccine_admin_codes"], results
assert "CHECK" not in vac.describe(results[0]).upper(), vac.describe(results[0])
assert grid()[-1] == ("90471", True, "0.00"), grid()
results = run_all(page, "9113000", _live(page))
assert [r.condition_name for r in results] == ["zero_fee_uncheck", "vaccine_admin_codes"], results
assert grid()[2:] == [("90471", False, "0.00"), ("90471", True, "0.00")], ("today: a second 90471 added", grid())
@case
def default_fixture_is_what_detect_fires_on(page):
_fresh(page)
data = _live(page)
assert data["insurance"][0]["Name"] == "Medicaid", data["insurance"]
assert data["patient"]["dob"] == "01/02/1976", data["patient"]
assert vac.detect("9113000", data) is True
# =============================================================================
# apply()
# =============================================================================
@case
def apply_adult_one_vaccine_adds_90471_x1_only(page):
_fresh(page)
_seed(page, _ADULT_ONE)
data = _live(page)
result = vac.apply(page, "9113000", data)
assert isinstance(result, ConditionResult)
assert result.condition_name == "vaccine_admin_codes"
assert result.changed is True, result
assert [c["code"] for c in result.changes] == ["90471"], result.changes
assert result.changes[0]["added"] is True
assert result.changes[0]["units"] == "1", result.changes
added = _rows_for(page, "90471")
assert len(added) == 1 and added[0]["units"] == "1", added
assert added[0]["billed_fee"] == "30.00", added
assert _rows_for(page, "90472") == [], "one vaccine needs no 90472"
assert _rows_for(page, "90460") == [], "an adult never gets 90460"
@case
def apply_adult_three_vaccines_adds_90471_x1_and_90472_x1(page):
"""
The operator's simplified rule (2026-09-29): more than one vaccine ->
the two admin codes, each x1 — NOT 90472 x (vaccines - 1).
"""
_fresh(page) # the default grid: 90732, 90746, 90734 on a 50-year-old
data = _live(page)
result = vac.apply(page, "9113000", data)
assert result.changed is True
by_code = {c["code"]: c for c in result.changes}
assert set(by_code) == {"90471", "90472"}, result.changes
assert by_code["90471"]["units"] == "1", by_code
assert by_code["90472"]["units"] == "1", by_code
assert by_code["90472"]["billed_fee"] == "20.00", by_code
# Both landed: nothing for a human (control for unit D review finding 3).
assert result.review == "", result.review
row = _rows_for(page, "90472")
assert len(row) == 1 and row[0]["units"] == "1", row
assert row[0]["billed_fee"] == "20.00", row
@case
def apply_adult_two_vaccines_leaves_both_lines_as_ecw_priced_them(page):
# Both codes want Units 1 and the picker already gave 1 — so neither
# line's Units is touched; each is left exactly as eCW priced it.
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90732", "title": "PCV20", "icd1": "2",
"fee": "290.00"}])
result = vac.apply(page, "9113000", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert set(by_code) == {"90471", "90472"}, result.changes
assert by_code["90472"]["units"] == "1", by_code
assert by_code["90472"]["billed_fee"] == "20.00", by_code
for i in (3, 4):
units = page.locator(sel.SEL_CPT_ROWS).nth(i).locator(sel.SEL_CPT_UNITS).first
assert units.input_value() == "1"
assert units.get_attribute("data-blurred") is None, \
"a line eCW already gave 1 unit must be left as priced"
@case
def apply_child_four_vaccines_adds_90460_x1_and_90461_x1(page):
_fresh(page)
_seed(page, _CHILD_FOUR, dob="07/01/2025", age_sex=" 12M 6D, F")
data = _live(page)
result = vac.apply(page, "9133000", data)
assert result.changed is True
by_code = {c["code"]: c for c in result.changes}
assert set(by_code) == {"90460", "90461"}, result.changes
assert by_code["90460"]["units"] == "1", by_code
assert by_code["90461"]["units"] == "1", by_code
assert by_code["90461"]["billed_fee"] == "15.00", by_code
assert _rows_for(page, "90471") == [] and _rows_for(page, "90472") == []
@case
def apply_does_not_hand_fill_pos_or_icd_pointers(page):
# eCW fills POS / dates / ICD pointers on the new line itself (the
# fixture's picker fakes that by copying the first line). Whatever it
# put there must survive apply() untouched.
_fresh(page)
_seed(page, [{"code": "99396", "title": "PREVENTIVE VISIT", "pos": "22",
"icd1": "1", "icd2": "2"},
{"code": "90734", "title": _TDAP, "pos": "22", "icd1": "2",
"fee": "60.00"}])
vac.apply(page, "9113000", _live(page))
added = _rows_for(page, "90471")[0]
assert added["pos"] == "22" and added["icd1"] == "1" \
and added["icd2"] == "2", added
@case
def apply_still_adds_when_only_an_unchecked_admin_is_present(page):
_fresh(page)
_seed(page, [{"code": "99397", "title": "PREVENTIVE VISIT EST 65+"},
{"code": "90656", "title": "FLU VACC IIV3 NO PRSV 0.5ML IM",
"fee": "65.00"},
{"code": "90460", "title": "IMMUNIZATION ADMIN", "checked": False,
"fee": "0.00"}])
result = vac.apply(page, "9132000", _live(page))
assert result.changed is True
assert [c["code"] for c in result.changes] == ["90471"], result.changes
assert len(_rows_for(page, "90460")) == 1, "the unchecked 90460 is left alone"
@case
def apply_child_with_an_unchecked_90460_adds_a_new_90460_row(page):
_fresh(page)
_seed(page, [{"code": "99392", "title": "PREV VISIT EST AGE 1-4"},
{"code": "90732", "title": "PCV20", "fee": "290.00"},
{"code": "90460", "title": "IMMUNIZATION ADMIN", "checked": False,
"fee": "0.00"}],
dob="07/01/2020", age_sex=" 6Y, M")
result = vac.apply(page, "C1", _live(page))
assert result.changed is True
rows = _rows_for(page, "90460")
assert [r["billed"] for r in rows] == [False, True], rows
@case
def apply_add_that_leaves_no_new_row_counts_as_a_failure(page):
# add_cpt_row() verifies only that SOME 90460 row exists afterward —
# true here from the unchecked one alone. The new-row count is what
# tells a real add from a picker that silently did nothing.
_fresh(page)
_seed(page, [{"code": "90732", "title": "PCV20", "fee": "290.00"},
{"code": "90460", "title": "IMMUNIZATION ADMIN", "checked": False}],
dob="07/01/2020", age_sex=" 6Y, M")
page.evaluate("() => { window.feeScheduleOkAddsNothing = true; }")
result = vac.apply(page, "C1", _live(page))
assert result.changed is False, result
assert result.changes == []
assert len(_rows_for(page, "90460")) == 1
@case
def apply_first_code_add_failure_adds_nothing(page):
_fresh(page)
page.evaluate("() => window.removeFromFeeSchedule('90471')")
result = vac.apply(page, "9113000", _live(page))
assert result.changed is False, result
assert result.changes == []
# Declined, not none(): the claim still lacks its admin code (D2).
assert result == ConditionResult.declined(
vac.NAME, "90471 could not be added — add it by hand"), result
assert _rows_for(page, "90471") == []
assert _rows_for(page, "90472") == [], \
"90472 must not be attempted once 90471 could not be added"
assert not page.locator(sel.SEL_FEE_SCHEDULE_CPT_SEARCH).first.is_visible(), \
"the picker must be closed, not left blocking the claim form"
@case
def apply_additional_code_failure_keeps_the_first_and_reports_it(page):
_fresh(page)
page.evaluate("() => window.removeFromFeeSchedule('90472')")
result = vac.apply(page, "9113000", _live(page))
assert result.changed is True
by_code = {c["code"]: c for c in result.changes}
assert by_code["90471"]["added"] is True, by_code
assert by_code["90472"]["added"] is False, by_code
# The first code landed, the second did not: the claim still lacks an
# admin code, so it carries a review reason (review of unit D,
# 2026-10-05, finding 3 — this asserted review == "" before, which made
# the summary a Fail row reading "vaccine admin code added"). The
# removed fee-schedule entry means the picker added nothing.
assert result.review == "90472 could not be added — add it by hand", \
result.review
assert len(_rows_for(page, "90471")) == 1
text = vac.describe(result)
assert "90472" in text and "FAILED" in text, text
@case
def apply_decides_from_the_live_grid_not_the_pre_read_data(page):
# The pre-read data says "vaccines, no admin" — but by the time apply()
# runs, an admin code is on the live grid (e.g. added by hand or by an
# earlier condition). Nothing may be added on top of it.
_fresh(page)
data = _live(page)
_seed(page, [{"code": "90734", "title": _TDAP, "fee": "60.00"},
{"code": "90471", "title": _ADMIN_1ST, "fee": "30.00"}])
result = vac.apply(page, "9113000", data)
assert result.changed is False, result
assert len(_rows_for(page, "90471")) == 1
@case
def apply_live_plan_skips_a_checked_zero_fee_admin_line_the_same_as_detect(page):
"""
detect() and apply()'s live-grid plan share one rule (2026-09-30): the
claim as read has its only 90471 checked at 0.00, detect() fires on
it, and apply() — called straight here, zero_fee_uncheck never run —
reads the live grid the same way and adds 90471, rather than calling
the 0.00 line "admin already billed". In a real run zero_fee_uncheck
has unchecked that line first (test_conditions_zero_fee_uncheck.py).
"""
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90471", "title": _ADMIN_1ST,
"fee": "0.00"}])
data = _live(page)
assert vac.detect("9113000", data) is True
result = vac.apply(page, "9113000", data)
assert result.changed is True, result
assert [c["code"] for c in result.changes if c["added"]] == ["90471"], \
result.changes
assert [(r["billed"], r["billed_fee"]) for r in _rows_for(page, "90471")] \
== [(True, "0.00"), (True, "30.00")]
@case
def apply_live_plan_does_not_count_a_checked_zero_fee_vaccine(page):
# Two vaccine lines, one of them checked at 0.00: one billed vaccine,
# so 90471 alone — detect()'s plan and apply()'s agree.
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90732", "title": "PCV20",
"fee": "0.00", "icd1": "2"}])
data = _live(page)
assert vac._plan("9113000", data, data["cpt"])["vaccines"] == ["90734"]
result = vac.apply(page, "9113000", data)
assert [c["code"] for c in result.changes] == ["90471"], result.changes
assert _rows_for(page, "90472") == [], "one billed vaccine needs no 90472"
@case
def apply_leaves_a_medicare_claim_alone(page):
_fresh(page)
data = _live(page)
data["insurance"] = [{"Name": "Humana Medicare"}]
result = vac.apply(page, "9113000", data)
assert result.changed is False
assert _rows_for(page, "90471") == []
@case
def describe_names_vaccines_age_codes_and_units(page):
_fresh(page)
result = vac.apply(page, "9113000", _live(page))
text = vac.describe(result)
for bit in ("90732", "90746", "90734", "90471", "90472"):
assert bit in text, (bit, text)
# The age line itself — a bare "50" is already inside "90746".
assert "Patient age used: 50 (" in text and "above 18" in text, text
assert "Added 90471 x1" in text and "Added 90472 x1" in text, text
@case
def describe_names_the_pediatric_band_for_a_child(page):
_fresh(page)
_seed(page, _CHILD_FOUR, dob="07/01/2025", age_sex=" 12M 6D, F")
text = vac.describe(vac.apply(page, "9133000", _live(page)))
assert "Patient age used: 1 (" in text and "18 and below" in text, text
assert "Added 90460 x1" in text and "Added 90461 x1" in text, text
# --- vaccine count: rows, not units (ruling 4) --------------------------------
@case
def apply_counts_vaccine_rows_not_their_units(page):
_fresh(page)
_seed(page, [{"code": "99396", "title": "PREVENTIVE VISIT EST AGE 40-64"},
{"code": "90734", "title": _TDAP, "units": "2", "fee": "120.00"},
{"code": "90732", "title": "PCV20", "units": "1",
"fee": "290.00"}])
result = vac.apply(page, "9113000", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert set(by_code) == {"90471", "90472"}, result.changes
assert by_code["90472"]["units"] == "1", \
"2 vaccine ROWS -> 90472 x1, whatever units the vaccines carry"
# --- the new line is the one Units is written to ------------------------------
_CHILD_THREE_WITH_OLD_90461 = [
{"code": "99392", "title": "PREV VISIT EST AGE 1-4"},
{"code": "90732", "title": "PCV20", "fee": "290.00"},
{"code": "90716", "title": "VARICELLA VIRUS VACCINE LIVE FOR SUBCUTANEOUS USE",
"fee": "180.00"},
{"code": "90707", "title": "MMR VIRUS VACCINE LIVE SUBCUTANEOUS", "fee": "95.00"},
{"code": "90461", "title": "IMMUNIZATION ADMIN EACH ADD", "checked": False,
"fee": "0.00"},
]
def _assert_new_and_old_90461(rows, new_first):
assert len(rows) == 2, rows
new, old = (rows[0], rows[1]) if new_first else (rows[1], rows[0])
assert new["billed"] is True and new["units"] == "1" \
and new["billed_fee"] == "15.00", ("the NEW line gets Units 1", rows)
assert old["billed"] is False and old["units"] == "1" \
and old["billed_fee"] == "0.00", ("the old unchecked line is untouched", rows)
@case
def apply_sets_units_on_the_new_90461_not_an_old_unchecked_one(page):
# The 9132000 shape, pediatric: a leftover UNCHECKED 90461 at 0.00 sits
# above where the new one lands.
# The picker hands back Units 0, so the Units write actually runs —
# it must land on the NEW line, not the old one.
_fresh(page)
_seed(page, _CHILD_THREE_WITH_OLD_90461, dob="07/01/2020", age_sex=" 6Y, M")
page.evaluate("() => { window.feeScheduleNewLineUnits = '0'; }")
result = vac.apply(page, "C1", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert by_code["90461"]["units"] == "1", by_code
assert by_code["90461"]["error"] is None, by_code
_assert_new_and_old_90461(_rows_for(page, "90461"), new_first=False)
@case
def apply_sets_units_on_the_new_line_even_when_it_lands_above_an_old_one(page):
# A grid that inserts the new 90461 ABOVE the old one: "the last row
# with this code" would be the old unchecked line — the diff finds the
# real new one.
_fresh(page)
_seed(page, _CHILD_THREE_WITH_OLD_90461, dob="07/01/2020", age_sex=" 6Y, M")
page.evaluate("() => { window.feeScheduleInsertBeforeCode = '90461'; "
"window.feeScheduleNewLineUnits = '0'; }")
result = vac.apply(page, "C1", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert by_code["90461"]["units"] == "1", by_code
assert by_code["90461"]["error"] is None, by_code
_assert_new_and_old_90461(_rows_for(page, "90461"), new_first=True)
@case
def apply_reports_an_extra_line_the_picker_added_alongside(page):
# The second picker open keeps the first pick, so OK adds 90471 again
# with 90472: the 90472 add itself is fine, the stray line is reported.
_fresh(page)
_seed(page, _ADULT_ONE + [{"code": "90732", "title": "PCV20", "icd1": "2",
"fee": "290.00"}])
page.evaluate("() => { window.feeScheduleOkAlsoAdds = '90471'; }")
result = vac.apply(page, "9113000", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert by_code["90472"]["added"] is True, by_code
unexpected = " ".join(by_code["90472"]["unexpected"])
assert "90471" in unexpected, by_code
text = vac.describe(result)
assert "CHECK BY HAND" in text and "90471" in text, text
# --- a failed first add that still changed the grid ---------------------------
@case
def apply_first_add_that_rechecks_an_old_line_is_reported_not_hidden(page):
# OK re-checks and re-prices the claim's existing UNCHECKED 90460
# instead of appending one: nothing was "added", but the grid is not
# what it was — a result of "nothing changed" would let another
# condition's Save write it unreviewed.
_fresh(page)
_seed(page, [{"code": "99392", "title": "PREV VISIT EST AGE 1-4"},
{"code": "90732", "title": "PCV20", "fee": "290.00"},
{"code": "90716", "title": "VARICELLA VIRUS VACCINE LIVE",
"fee": "180.00"},
{"code": "90460", "title": "IMMUNIZATION ADMIN", "checked": False,
"fee": "0.00"}],
dob="07/01/2020", age_sex=" 6Y, M")
page.evaluate("() => { window.feeScheduleOkRechecksExisting = true; }")
result = vac.apply(page, "C1", _live(page))
assert result.changed is True, result
assert [c["code"] for c in result.changes] == ["90460"], result.changes
change = result.changes[0]
assert change["added"] is False and change["grid_changed"] is True, change
# And flagged: a failed add that moved the grid is never "clean" (D2).
assert result.review == ("90460 could not be added cleanly — check the "
"CPT grid by hand"), result.review
assert _rows_for(page, "90461") == [], "90461 must not be attempted"
text = vac.describe(result)
assert "FAILED to add 90460" in text and "CHECK BY HAND" in text, text
# both states of the line, so the operator sees exactly what moved
assert "90460 x1 (fee 0.00, unchecked)" in text, text
assert "90460 x1 (fee 25.00, checked)" in text, text
# --- nothing raised mid-add may lose a line already on the form ---------------
@contextlib.contextmanager
def _patched(module, name, replacement):
real = getattr(module, name)
setattr(module, name, replacement)
try:
yield real
finally:
setattr(module, name, real)
@case
def apply_second_add_raising_keeps_the_first_and_reports_both(page):
_fresh(page)
real_add = claim_form.add_cpt_row
def add_that_times_out_on_90472(page_, code):
if code != "90472":
return real_add(page_, code)
# The picker is open when the timeout hits, as it would be live.
page_.locator(sel.SEL_CPT_ADD_BTN).first.click()
raise TimeoutError("Locator.click: Timeout 10000ms exceeded (simulated)")
with _patched(claim_form, "add_cpt_row", add_that_times_out_on_90472):
results = run_all(page, "9113000", _live(page))
assert [r.condition_name for r in results] == ["vaccine_admin_codes"], \
"a raise inside the second add must not drop the whole result"
by_code = {c["code"]: c for c in results[0].changes}
assert by_code["90471"]["added"] is True, by_code
assert by_code["90472"]["added"] is False, by_code
assert "raised" in by_code["90472"]["error"], by_code
# Unit D review, finding 3: the missing 90472 makes it a Review row.
assert results[0].review.startswith("90472 could not be added"), \
results[0].review
assert len(_rows_for(page, "90471")) == 1
assert not page.locator(sel.SEL_FEE_SCHEDULE_CPT_SEARCH).first.is_visible(), \
"the picker the failed add left open must be closed"
text = vac.describe(results[0])
assert "Added 90471 x1" in text and "FAILED to add 90472" in text, text
@case
def apply_units_write_raising_still_reports_the_line_it_added(page):
_fresh(page)
page.evaluate("() => { window.feeScheduleNewLineUnits = '0'; }")
def units_that_time_out(*args, **kwargs):
raise TimeoutError("Locator.fill: Timeout 10000ms exceeded (simulated)")
with _patched(claim_form, "set_cpt_units", units_that_time_out):
results = run_all(page, "9113000", _live(page))
assert [r.condition_name for r in results] == ["vaccine_admin_codes"], results
by_code = {c["code"]: c for c in results[0].changes}
assert by_code["90472"]["added"] is True, by_code
assert by_code["90472"]["units"] == "0", \
"the report shows what the line really reads — still 0 units"
assert "raised" in by_code["90472"]["error"], by_code
text = vac.describe(results[0])
assert "Added 90472 x0" in text and "CHECK" in text, text
# --- the Fee Schedule picker is never left open --------------------------------
@case
def apply_ok_that_keeps_the_picker_open_closes_it_and_adds_nothing(page):
# Slow (~15s): add_cpt_row() waits out its own 10s for the picker to
# hide before deciding OK did nothing.
_fresh(page)
_seed(page, _ADULT_ONE)
page.evaluate("() => { window.feeScheduleOkKeepsOpen = true; }")
result = vac.apply(page, "9113000", _live(page))
assert result.changed is False, result
assert _rows_for(page, "90471") == []
assert not page.locator(sel.SEL_FEE_SCHEDULE_CPT_SEARCH).first.is_visible(), \
"a picker left up would block the claim form's own Cancel"
@case
def add_cpt_row_closes_the_picker_when_a_step_raises(page):
# Slow (~10s): a disabled OK makes Playwright's click time out, with
# the picker open — it must be closed before the error goes on up.
_fresh(page)
page.evaluate("() => { document.getElementById('claimFeeSchOkBtn')"
".disabled = true; }")
try:
claim_form.add_cpt_row(page, "90471")
except Exception:
pass
else:
raise AssertionError("the OK click timeout must still be raised")
assert not page.locator(sel.SEL_FEE_SCHEDULE_CPT_SEARCH).first.is_visible()
# --- the fee read back is the re-priced one -----------------------------------
@case
def apply_waits_for_an_async_units_reprice(page):
_fresh(page)
page.evaluate("() => { window.unitsRepriceDelayMs = 600; "
"window.feeScheduleNewLineUnits = '0'; }")
result = vac.apply(page, "9113000", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert by_code["90472"]["billed_fee"] == "20.00", \
("the 0.00 fee read straight after the blur is stale", by_code)
assert by_code["90472"]["error"] is None, by_code
@case
def apply_flags_a_fee_that_never_reprices(page):
_fresh(page)
page.evaluate("() => { window.unitsNoReprice = true; "
"window.feeScheduleNewLineUnits = '0'; }")
result = vac.apply(page, "9113000", _live(page))
by_code = {c["code"]: c for c in result.changes}
assert by_code["90472"]["units"] == "1", by_code
assert "re-priced" in (by_code["90472"]["error"] or ""), by_code
assert "CHECK" in vac.describe(result)
# --- the professional/HCFA screen ---------------------------------------------
def _hcfa_with_one_vaccine(page):
page.goto(HCFA_FIXTURE.as_uri())
page.evaluate("""(title) => {
const row = document.getElementById('CPTROW_1');
row.querySelector('[data-fieldname="claimCPTCode"]').value = '90734';
row.querySelector('[data-fieldname="claimCPTCode"]').closest('td')
.setAttribute('title', title);
// The live screen's DOB bind (MM/DD/YYYY, read on 9109000 and
// 9119000) is not part of the fixture; a made-up adult DOB.
const dob = document.createElement('span');
dob.setAttribute('ng-bind', 'PatientInfo.dob');
dob.textContent = '01/15/1980';
document.body.appendChild(dob);
}""", _TDAP)
@case
def hcfa_screen_vaccine_claim_fires_on_the_payer_from_the_insurances_grid(page):
# hcfa_claim.html is a United Health Care (Commercial) claim — covered
# by document #18. This used to be pinned as a gap: extract() read no
# insurance on this screen, so the payer gate always said no.
_hcfa_with_one_vaccine(page)
data = _live(page)
assert [r["code"] for r in vac.checked_vaccine_rows(data["cpt"])] == ["90734"]
assert data["insurance"][0]["Name"] == "United Health Care", data["insurance"]
assert vac.detect("9103000", data) is True
@case
def hcfa_screen_with_no_payer_row_still_blames_the_read(page):
_hcfa_with_one_vaccine(page)
page.evaluate("() => document.querySelector("
"'#billingClaimTbl8 tbody').innerHTML = ''")
data = _live(page)
assert data["insurance"] == [], data["insurance"]
out = io.StringIO()
with contextlib.redirect_stdout(out):
assert vac.detect("9103000", data) is False
assert "no primary payer name was read" in out.getvalue(), \
("the log must blame the read, not payer_groups.json", out.getvalue())
@case
def run_all_fires_only_this_condition_on_the_fixture(page):
_fresh(page)
data = _live(page)
results = run_all(page, "9113000", data)
assert [r.condition_name for r in results] == ["vaccine_admin_codes"], results
# =============================================================================
# What the Charge Summary says (final review, 2026-10-05)
# =============================================================================
def _change(code, added):
return {"code": code, "added": added, "units": 1, "wanted_units": 1,
"billed_fee": "10.00", "error": "" if added else "not found",
"grid_changed": None if added else True}
@case
def summary_comment_says_which_admin_code_was_added_and_which_was_not():
"""
The fixed "( vaccine admin code added )" read "added" next to the
review reason saying the code could NOT be added.
"""
sc = vac.summary_comment
mk = lambda *c: ConditionResult("vaccine_admin_codes", True, list(c))
assert sc(mk(_change("90471", True), _change("90472", True))) == \
"CPT Code Missing (vaccine admin code 90471 added; 90472 added)"
assert sc(mk(_change("90471", False))) == \
"CPT Code Missing (vaccine admin code 90471 NOT added — add by hand)"
assert sc(mk(_change("90471", True), _change("90472", False))) == (
"CPT Code Missing (vaccine admin code 90471 added; 90472 NOT added "
"— add by hand)")
@case
def the_charge_summary_row_no_longer_says_added_for_a_failed_add():
"""End to end through charge_summary.claim_outcome, both cases."""
from ecw_bot.core import charge_summary as cs
for changes, review in (
([_change("90471", False)],
"90471 could not be added cleanly — check the CPT grid by hand"),
([_change("90471", True), _change("90472", False)],
"90472 could not be added cleanly — check the CPT grid by hand")):
result = ConditionResult("vaccine_admin_codes", True, changes,
review=review)
data = {"cpt": [{"code": "90686"}], "icd": [{"code": "Z23"}],
"progress_notes": {"opened": "frame", "sections": {}},
"_conditions": {
"fired": ["vaccine_admin_codes"], "saved": False,
"failed": [],
"review": [{"name": "vaccine_admin_codes",
"reason": review}],
"comments": {"vaccine_admin_codes":
vac.summary_comment(result)}}}
o = cs.claim_outcome(True, data)
assert o["Category"] == "Review", o
assert "vaccine admin code added" not in o["Comments"], o
assert "NOT added — add by hand" in o["Comments"], o
@case
def a_live_grid_that_reads_empty_after_a_full_first_read_is_declined():
"""
Final review, 2026-10-05: detect() found billed vaccines in the first
read, but the live re-read came back empty — declined, not "Nothing to
add" (none(), which the summary reads as Pass).
"""
from ecw_bot.conditions.base import CPT_GRID_NOT_READ
orig = (claim_form.open_cpt_hcpcs_tab, claim_form.extract)
claim_form.open_cpt_hcpcs_tab = lambda page: True
claim_form.extract = lambda page: {"cpt": []}
try:
with contextlib.redirect_stdout(io.StringIO()):
result = vac.apply(None, "9131000",
{"cpt": [_row("90686", "Flu vaccine")]})
finally:
claim_form.open_cpt_hcpcs_tab, claim_form.extract = orig
assert result == ConditionResult.declined("vaccine_admin_codes",
CPT_GRID_NOT_READ), result
def _run_cases() -> int:
if not FIXTURE.exists():
print(f" FAIL fixture missing: {FIXTURE}")
return 1
try:
from playwright.sync_api import sync_playwright
except ImportError:
print(" SKIP playwright is not installed")
return 0
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:
from ecw_bot import settings as _cfg
# 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.
orig = _cfg.SAVE_CORRECTIONS
_cfg.SAVE_CORRECTIONS = True
try:
return _run_cases()
finally:
_cfg.SAVE_CORRECTIONS = orig
if __name__ == "__main__":
sys.exit(main())