r""" conditions/priced_line_check.py — the reverse half of the operator's common rule for every claim (2026-09-30): a CPT line that carries a billed fee but is unchecked gets checked. Only that direction — a checked line is never touched, and the fee is never written. python tests\test_conditions_priced_line_check.py Pure-data cases first (the shared priced-fee predicate, then detect()), then page cases against BOTH claim screens, with the same injection helpers and fixtures as test_conditions_zero_fee_uncheck.py: hcfa_claim.html, whose own rows carry the live-verified "Assign To Patient" checkbox, and ub_claim.html, whose own rows carry a plain checkbox with no ng-click at all — so on the UB form a UB-style row is injected with the checkbox vaccine_claim.html's rows use, and the fixture's own rows stand in for a row whose checkbox state is unknown. hcfa_claim.html's own G8510 (CPTROW_2) sits UNCHECKED at 65.00 — the 9103000 shape depression_dx_pointer re-includes, and exactly the line this rule checks. Cases about some other line call `_neutralise_fixture_g8510()` first, so that line cannot answer for them. The run_all() cases are the point of registering this LAST. Each exclusion condition — j2930_j2001_update (J2001), dummy_codes (DCONS), medicare_telehealth ("other primary CPT codes") and depression_dx_pointer's duplicate step — starts from an original grid where the line it excludes is UNCHECKED but still PRICED. That line must end unchecked at 0.00, its checkbox never clicked, and no result may report a check on it: the check/uncheck toggle claim 9131000 showed between two steps of one condition, here between two conditions. One contrast case runs this condition FIRST instead, to prove that order is what prevents it. Live evidence: 0 of the 39 saved claim snapshots had an unchecked priced line — this is rare — and exactly one had a checked zero-fee line (85018 at 0.00, zero_fee_uncheck's half). """ 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" / "hcfa_claim.html" UB_FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "ub_claim.html" VACCINE_FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "vaccine_claim.html" from ecw_bot import conditions # noqa: E402 from ecw_bot.conditions import priced_line_check as plc # noqa: E402 from ecw_bot.conditions import (bh_h_code_modifier, # noqa: E402 dental_dummy_codes, dental_payer_check, depression_dx_pointer, dummy_codes, injection_admin_code, medicare_pps_code, j2930_j2001_update, lab_codes, medicaid_uncheck_cpts, t1017_non_billable, medicare_billing_screening, medicare_telehealth, medicare_vaccine_a6, medicare_wellness_history, medicaid_pregnancy_th, telehealth, vaccine_admin_codes, vaccine_z23_pointer, zero_fee_uncheck) from ecw_bot.conditions.base import ( # noqa: E402 CPT_TAB_NOT_CONFIRMED, ConditionResult, run_all) 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 def _cpt(code, billed=False, fee="150.00"): """One `extract()["cpt"]` row, cut down to what detect() reads.""" return {"code": code, "billed": billed, "billed_fee": fee} def _inject_row(page, code, row_id, *, screen="hcfa", checked=False, fee="150.00", has_checkbox=True, has_fee=True): """ Adds one real CPT row (a `CPTROW_` id) above the grid's trailing "*" entry row — the same helper as test_conditions_zero_fee_uncheck.py's, defaulting to this rule's shape (unchecked, priced). `screen` picks the row's own markup: * "hcfa" — hcfa_claim.html's shape: `data-fieldname` fields. * "ub" — the UB form's `uBClaim*` id prefixes, with the "Assign To Patient" checkbox vaccine_claim.html's rows carry. `has_checkbox` / `has_fee` drop the checkbox or the Billed Fee input entirely — the rows whose state is unknown, which must be left alone. """ page.evaluate( """(a) => { const n = a.rowId.replace('CPTROW_', ''); const tbody = document.querySelector(a.screen === 'ub' ? '#claimCPTCodesTable9999999999999 tbody' : '#claimCPTCodesTable8888888888888 tbody'); const entryRow = tbody.querySelector('tr:last-child'); const esc = s => String(s).replace(/&/g, '&').replace(/"/g, '"'); const box = !a.hasCheckbox ? '' : (a.screen === 'ub' ? ''; const codeInput = a.screen === 'ub' ? '' : ''; const feeInput = !a.hasFee ? '' : (a.screen === 'ub' ? '' : ''); const tr = document.createElement('tr'); tr.id = a.rowId; tr.setAttribute('ng-repeat', 'cpt in CPTCodes'); tr.innerHTML = '' + box + '' + codeInput + '' + '' + feeInput + ''; tbody.insertBefore(tr, entryRow); }""", {"code": code, "rowId": row_id, "screen": screen, "checked": checked, "fee": fee, "hasCheckbox": has_checkbox, "hasFee": has_fee}) def _inject_full_g8510_row(page, row_id, *, checked, fee, icd1="1"): """ A second G8510 on hcfa_claim.html carrying all four ICD pointer fields — depression_dx_pointer's retag step reads every one — the same helper as test_conditions_zero_fee_uncheck.py's, plus `icd1` for a copy that already carries the Z13.31 pointer ("2") alone. """ page.evaluate( """(a) => { const tbody = document.querySelector( '#claimCPTCodesTable8888888888888 tbody'); const entryRow = tbody.querySelector('tr:last-child'); const n = a.rowId.replace('CPTROW_', ''); const tr = document.createElement('tr'); tr.id = a.rowId; tr.innerHTML = '' + '' + '' + '' + '' + '' + ''; tbody.insertBefore(tr, entryRow); }""", {"rowId": row_id, "checked": checked, "fee": fee, "icd1": icd1}) def _set_row(page, row_id, *, checked=None, fee=None): """Sets one existing row's checkbox and/or Billed Fee in place.""" page.evaluate( """(a) => { const tr = document.getElementById(a.rowId); if (a.checked !== null) tr.querySelector('[ng-click*="updateBillToIns("]').checked = a.checked; if (a.fee !== null) tr.querySelector('[id^="uBClaimBillFee"], [data-fieldname="ClaimCPTBilledFee"]') .value = a.fee; }""", {"rowId": row_id, "checked": checked, "fee": fee}) def _neutralise_fixture_g8510(page): """ hcfa_claim.html's own G8510 (CPTROW_2) is unchecked at 65.00 — itself an unchecked priced line. Checked here, so a case about some other line is not answered by that one. """ _set_row(page, "CPTROW_2", checked=True) def _count_checkbox_clicks(page, row_id): """ Counts clicks on one row's "Assign To Patient" checkbox, read back as `window.clicksOn[row_id]` — the same helper the depression and zero_fee_uncheck tests use. On the live screen that click is what fires eCW's own `updateBillToIns()`, so a line that must stay excluded should never receive one at all — not merely end up unchecked again. """ page.evaluate( """(rowId) => { window.clicksOn = window.clicksOn || {}; window.clicksOn[rowId] = 0; document.querySelector('#' + rowId + ' [ng-click*="updateBillToIns("]') .addEventListener('click', () => { window.clicksOn[rowId] += 1; }); }""", row_id) def _watch_fee_writes(page): """ Counts `input`/`change` events on every Billed Fee input on the grid as `window.feeWrites` — a zero proves the fee was never written, not merely left with the same value. Call after every row has been injected. """ page.evaluate( """(s) => { window.feeWrites = 0; document.querySelectorAll('tr[id^="CPTROW_"]').forEach(tr => { tr.querySelectorAll(s).forEach(el => { el.addEventListener('input', () => { window.feeWrites += 1; }); el.addEventListener('change', () => { window.feeWrites += 1; }); }); }); }""", sel.SEL_CPT_BILLED_FEE) def _row_state(page, index): """(checked or None, fee or None) for the index-th real CPT row.""" row = page.locator(sel.SEL_CPT_ROWS).nth(index) box = row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first fee = row.locator(sel.SEL_CPT_BILLED_FEE).first return (box.is_checked() if box.count() else None, fee.input_value() if fee.count() else None) def _run_all_logged(page, claim_id, data, **kwargs): """run_all(), with everything it printed.""" out = io.StringIO() with contextlib.redirect_stdout(out): results = run_all(page, claim_id, data, **kwargs) return results, out.getvalue() def _checks_reported_on(results, row): """ Every change in `results` that reports CHECKING `row`: any change priced_line_check makes (it only ever checks), and depression's re-include step, whose change is `{"row", "code"}` alone. """ return [(r.condition_name, c) for r in results for c in r.changes if c.get("row") == row and (r.condition_name == plc.NAME or (r.condition_name == depression_dx_pointer.NAME and set(c) == {"row", "code"}))] def _assert_priced_line_check_ran_and_found_nothing(log, claim_id): """ The common case this rule is registered last for: detect() saw the excluded line priced on the claim as read, and by the time apply() looked, another condition had zeroed it. """ assert f"[COND priced_line_check {claim_id}]" in log, log assert "nothing to check" in log, log # ============================================================================= # The shared priced-fee predicate # ============================================================================= @case def is_priced_fee_reads_a_positive_amount_as_priced(): for value in ("150.00", "65", "0.01", "1,200.00", "$45.00", "$1,200.00", " 65.00 "): assert claim_form.is_priced_fee(value) is True, repr(value) @case def is_priced_fee_reads_zero_blank_non_numeric_and_negative_as_not_priced(): for value in ("", " ", None, "0", "0.00", ".00", "$0.00", "0,000.00", "N/A", "abc", "--", "0.00 USD", "-5.00", "nan", "inf"): assert claim_form.is_priced_fee(value) is False, repr(value) @case def is_priced_fee_and_is_zero_fee_never_both_hold(): # The two halves of the common rule can never both claim one line. for value in ("", None, "0", "0.00", ".00", "$0.00", "65.00", "0.01", "1,200.00", "$45.00", "N/A", "-5.00", "nan", "inf"): assert not (claim_form.is_priced_fee(value) and claim_form.is_zero_fee(value)), repr(value) # ============================================================================= # detect() # ============================================================================= @case def detect_true_for_an_unchecked_priced_line(): data = {"cpt": [_cpt("99213", billed=True, fee="210.00"), _cpt("90791", billed=False, fee="150.00")]} assert plc.detect("C1", data) is True @case def detect_true_for_a_thousands_separated_fee(): assert plc.detect("C1", {"cpt": [_cpt("J7298", fee="1,200.00")]}) is True @case def detect_true_for_a_dollar_fee(): assert plc.detect("C1", {"cpt": [_cpt("J2001", fee="$45.00")]}) is True @case def detect_false_for_an_unchecked_zero_fee_line(): # Already excluded, and correctly — the 9131000 duplicate's shape. for fee in ("0.00", "", "0", ".00", "$0.00"): assert plc.detect("C1", {"cpt": [_cpt("G8510", fee=fee)]}) is False, fee @case def detect_false_for_a_checked_priced_line(): data = {"cpt": [_cpt("99213", billed=True, fee="210.00"), _cpt("J7298", billed=True, fee="1200.00")]} assert plc.detect("C1", data) is False @case def detect_false_when_the_checkbox_state_is_unknown(): # billed None: extract() found no "Assign To Patient" checkbox on the # row. Unknown must never read as "unchecked". assert plc.detect("C1", {"cpt": [_cpt("90791", billed=None)]}) is False assert plc.detect("C1", {"cpt": [{"code": "90791", "billed_fee": "150.00"}]}) is False @case def detect_false_for_a_non_numeric_or_negative_fee(): for fee in ("N/A", "abc", "0.00 USD", "-5.00"): assert plc.detect("C1", {"cpt": [_cpt("90791", fee=fee)]}) is False, fee @case def detect_false_with_no_cpt_lines_or_no_fee_read(): assert plc.detect("C1", {"cpt": []}) is False assert plc.detect("C1", {}) is False assert plc.detect("C1", None) is False # No billed_fee key at all: nothing was read, so nothing is priced. assert plc.detect("C1", {"cpt": [{"code": "90791", "billed": False}]}) is False # ============================================================================= # apply() — the professional/HCFA screen # ============================================================================= @case def apply_checks_unchecked_priced_lines_on_the_hcfa_screen(page): """ The fixture's own G8510 (unchecked, 65.00) plus two injected lines priced the ways eCW can print a fee — "$45.00" and "1,200.00". Each is checked and reported with its fee exactly as read; the fee itself is never written. The checked 99213 and J7298 are never clicked. """ page.goto(FIXTURE.as_uri()) _inject_row(page, "85025", "CPTROW_3", fee="$45.00") _inject_row(page, "36415", "CPTROW_4", fee="1,200.00") for row_id in ("CPTROW_0", "CPTROW_1", "CPTROW_2", "CPTROW_3", "CPTROW_4"): _count_checkbox_clicks(page, row_id) _watch_fee_writes(page) result = plc.apply(page, "9103000", {}) assert isinstance(result, ConditionResult) assert result.condition_name == "priced_line_check" assert result.changed is True assert result.changes == [ {"row": 2, "code": "G8510", "fee": "65.00"}, {"row": 3, "code": "85025", "fee": "$45.00"}, {"row": 4, "code": "36415", "fee": "1,200.00"}, ], result.changes assert [_row_state(page, i) for i in range(5)] == [ (True, "210.00"), (True, "1200.00"), (True, "65.00"), (True, "$45.00"), (True, "1,200.00")] clicks = page.evaluate("window.clicksOn") assert clicks == {"CPTROW_0": 0, "CPTROW_1": 0, "CPTROW_2": 1, "CPTROW_3": 1, "CPTROW_4": 1}, clicks assert page.evaluate("window.feeWrites") == 0, "the Billed Fee was written" # A second pass has nothing left to check. assert plc.apply(page, "9103000", {}).changed is False @case def apply_leaves_zero_fee_non_numeric_and_negative_lines_alone(page): page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "85018", "CPTROW_3", fee="0.00") _inject_row(page, "85025", "CPTROW_4", fee="") _inject_row(page, "81002", "CPTROW_5", fee="N/A") _inject_row(page, "36415", "CPTROW_6", fee="-5.00") for row_id in ("CPTROW_3", "CPTROW_4", "CPTROW_5", "CPTROW_6"): _count_checkbox_clicks(page, row_id) _watch_fee_writes(page) result = plc.apply(page, "9103000", {}) assert result.changed is False, result.changes assert result.changes == [], result.changes assert [_row_state(page, i) for i in (3, 4, 5, 6)] == [ (False, "0.00"), (False, ""), (False, "N/A"), (False, "-5.00")] assert set(page.evaluate("Object.values(window.clicksOn)")) == {0}, \ page.evaluate("window.clicksOn") assert page.evaluate("window.feeWrites") == 0 @case def apply_never_touches_a_checked_line_zero_fee_or_priced(page): # A checked 0.00 line is zero_fee_uncheck's, never this rule's: only # ever checks, never unchecks. page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "85018", "CPTROW_3", checked=True, fee="0.00") for row_id in ("CPTROW_0", "CPTROW_1", "CPTROW_2", "CPTROW_3"): _count_checkbox_clicks(page, row_id) result = plc.apply(page, "9103000", {}) assert result.changed is False, result.changes assert [_row_state(page, i) for i in range(4)] == [ (True, "210.00"), (True, "1200.00"), (True, "65.00"), (True, "0.00")] assert set(page.evaluate("Object.values(window.clicksOn)")) == {0} @case def apply_leaves_an_unchecked_row_with_no_fee_input_alone(page): # No Billed Fee input at all: the fee is unknown, not priced. page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "90791", "CPTROW_3", has_fee=False) _count_checkbox_clicks(page, "CPTROW_3") result = plc.apply(page, "9103000", {}) assert result.changed is False, result.changes assert _row_state(page, 3) == (False, None) assert page.evaluate("window.clicksOn['CPTROW_3']") == 0 @case def apply_leaves_a_priced_row_with_no_checkbox_alone(page): # No "Assign To Patient" checkbox: whether it is billed is unknown. page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "90791", "CPTROW_3", has_checkbox=False) _watch_fee_writes(page) result = plc.apply(page, "9103000", {}) assert result.changed is False, result.changes assert _row_state(page, 3) == (None, "150.00") assert page.evaluate("window.feeWrites") == 0 # ============================================================================= # apply() — the UB Claim form # ============================================================================= @case def apply_checks_an_unchecked_priced_line_on_the_ub_form(page): page.goto(UB_FIXTURE.as_uri()) _inject_row(page, "90791", "CPTROW_2", screen="ub", fee="150.00") _inject_row(page, "G8510", "CPTROW_3", screen="ub", fee="0.00") _inject_row(page, "99213", "CPTROW_4", screen="ub", checked=True, fee="210.00") for row_id in ("CPTROW_2", "CPTROW_3", "CPTROW_4"): _count_checkbox_clicks(page, row_id) _watch_fee_writes(page) result = plc.apply(page, "9104000", {}) assert result.changes == [{"row": 2, "code": "90791", "fee": "150.00"}], result.changes assert _row_state(page, 2) == (True, "150.00") assert _row_state(page, 3) == (False, "0.00") assert _row_state(page, 4) == (True, "210.00") assert page.evaluate("window.clicksOn") == { "CPTROW_2": 1, "CPTROW_3": 0, "CPTROW_4": 0} assert page.evaluate("window.feeWrites") == 0, "the Billed Fee was written" @case def apply_leaves_ub_rows_without_the_assign_to_patient_checkbox_alone(page): """ ub_claim.html's own rows carry a plain checkbox with no `updateBillToIns(` ng-click — not the live-verified "Assign To Patient" box — so their billed state is unknown: one sitting unchecked at 74.00 must not be acted on. """ page.goto(UB_FIXTURE.as_uri()) page.evaluate("() => { document.getElementById('claimCPTBillToInsChk0')" ".checked = false; }") result = plc.apply(page, "9104000", {}) assert result.changed is False, result.changes assert page.locator("#claimCPTBillToInsChk0").is_checked() is False assert page.locator("#uBClaimBillFee0").input_value() == "74.00" # ============================================================================= # apply() — no change, and a tab that cannot be confirmed # ============================================================================= @case def apply_logs_why_when_there_is_nothing_to_check(page): page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) out = io.StringIO() with contextlib.redirect_stdout(out): result = plc.apply(page, "9103000", {}) assert result == ConditionResult.none("priced_line_check"), result _assert_priced_line_check_ran_and_found_nothing(out.getvalue(), "9103000") # Only on that path — not when a line was actually checked. page.goto(FIXTURE.as_uri()) out = io.StringIO() with contextlib.redirect_stdout(out): result = plc.apply(page, "9103000", {}) assert result.changed is True, result.changes assert "nothing to check" not in out.getvalue(), out.getvalue() @case def apply_leaves_the_claim_as_read_when_the_cpt_tab_cannot_be_confirmed(page): page.goto(FIXTURE.as_uri()) def tab_that_raises(page_): raise RuntimeError("No CPT/HCPCS tab matched (simulated)") real = claim_form.open_cpt_hcpcs_tab claim_form.open_cpt_hcpcs_tab = tab_that_raises out = io.StringIO() try: with contextlib.redirect_stdout(out): result = plc.apply(page, "9103000", {}) finally: claim_form.open_cpt_hcpcs_tab = real assert result.changed is False, result.changes assert _row_state(page, 2) == (False, "65.00"), "nothing may be touched" assert "leaving the claim as read" in out.getvalue(), out.getvalue() # Declined, not none(): never checked is not clean (review item D2). assert result.review == CPT_TAB_NOT_CONFIRMED, result # ============================================================================= # describe() # ============================================================================= @case def describe_names_each_checked_line_and_its_fee(page): page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "99213", "CPTROW_3", fee="150.00") result = plc.apply(page, "9103000", {}) text = plc.describe(result) lines = text.splitlines() assert lines[0] == "Unchecked CPT line(s) with a billed fee checked:", text assert lines[1:] == [" Row 4 (99213): unchecked with billed fee 150.00 -> checked"], text @case def describe_lists_every_line_in_grid_order(): result = ConditionResult(condition_name="priced_line_check", changed=True, changes=[{"row": 0, "code": "99213", "fee": "150.00"}, {"row": 5, "code": "J7298", "fee": "1,200.00"}]) assert plc.describe(result).splitlines()[1:] == [ " Row 1 (99213): unchecked with billed fee 150.00 -> checked", " Row 6 (J7298): unchecked with billed fee 1,200.00 -> checked", ], plc.describe(result) # ============================================================================= # The registry # ============================================================================= @case def registered_last_with_zero_fee_uncheck_first(): """ zero_fee_uncheck FIRST, this LAST, every specific condition between them in its own order: an exclusion condition has always zeroed its line before this looks at the grid. """ assert conditions.CONDITIONS[0] is zero_fee_uncheck, conditions.CONDITIONS assert conditions.CONDITIONS[-1] is plc, conditions.CONDITIONS assert conditions.CONDITIONS == [ zero_fee_uncheck, telehealth, medicare_telehealth, depression_dx_pointer, j2930_j2001_update, dummy_codes, dental_dummy_codes, dental_payer_check, medicaid_uncheck_cpts, lab_codes, t1017_non_billable, medicare_billing_screening, medicare_vaccine_a6, medicare_wellness_history, medicaid_pregnancy_th, bh_h_code_modifier, vaccine_z23_pointer, vaccine_admin_codes, injection_admin_code, medicare_pps_code, plc, ], conditions.CONDITIONS assert conditions.BY_NAME["priced_line_check"] is plc assert plc.NAME == "priced_line_check" # ============================================================================= # run_all() against the REAL registry — the positive cases # ============================================================================= @case def run_all_checks_an_unrelated_priced_line_and_reports_it(page): """ 99213 unchecked at 150.00 on the claim as read, no other condition's business: priced_line_check alone fires, and the line ends checked with its fee untouched. `icd` is left out of the data on purpose: the fixture carries Z13.31, which would fire depression_dx_pointer on its own account. """ page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _set_row(page, "CPTROW_0", checked=False, fee="150.00") _count_checkbox_clicks(page, "CPTROW_0") data = {"cpt": claim_form.extract(page)["cpt"]} results = run_all(page, "9103000", data) assert [r.condition_name for r in results] == ["priced_line_check"], results assert results[0].changes == [{"row": 0, "code": "99213", "fee": "150.00"}], \ results[0].changes assert _row_state(page, 0) == (True, "150.00") assert page.evaluate("window.clicksOn['CPTROW_0']") == 1 @case def run_all_fires_both_halves_of_the_common_rule_on_one_claim(page): # A checked 0.00 line and an unchecked priced one: each half takes its # own line, and neither touches the other's. page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "85018", "CPTROW_3", checked=True, fee="0.00") _inject_row(page, "90791", "CPTROW_4", checked=False, fee="150.00") _count_checkbox_clicks(page, "CPTROW_3") _count_checkbox_clicks(page, "CPTROW_4") data = {"cpt": claim_form.extract(page)["cpt"]} results = run_all(page, "9103000", data) assert [r.condition_name for r in results] == \ ["zero_fee_uncheck", "priced_line_check"], results assert results[0].changes == [{"row": 3, "code": "85018", "fee": "0.00"}] assert results[1].changes == [{"row": 4, "code": "90791", "fee": "150.00"}] assert (_row_state(page, 3), _row_state(page, 4)) == \ ((False, "0.00"), (True, "150.00")) assert page.evaluate("window.clicksOn") == {"CPTROW_3": 1, "CPTROW_4": 1} @case def run_all_leaves_claim_9131000_alone(page): """ Live claim 9131000 (Logs\\run_20260929_161613.log), already correct: the first G8510 checked at 65.00 and tagged Z13.31 alone, a later G8510 unchecked at 0.00. Nothing may change — not even with this rule in the registry: the 0.00 copy is not priced, and nobody clicks it. """ page.goto(FIXTURE.as_uri()) page.evaluate("""() => { const set = (rowId, field, value) => { document.querySelector( '#' + rowId + ' [data-fieldname="' + field + '"]').value = value; }; set('CPTROW_0', 'ClaimCPTICD2', '3'); set('CPTROW_0', 'ClaimCPTICD3', ''); set('CPTROW_2', 'ClaimCPTICD1', '2'); }""") _neutralise_fixture_g8510(page) _inject_full_g8510_row(page, "CPTROW_3", checked=False, fee="0.00", icd1="2") _count_checkbox_clicks(page, "CPTROW_3") results = run_all(page, "9131000", claim_form.extract(page)) assert results == [], results assert _row_state(page, 3) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_3']") == 0 # ============================================================================= # run_all() against the REAL registry — NO TOGGLE on an excluded line # ============================================================================= @case def run_all_does_not_toggle_an_unchecked_priced_j2001(page): """ J2001 unchecked but still at 45.00 on the claim as read. priced_line_check's detect() fires on it; j2930_j2001_update zeroes its fee (no click — it is already unchecked); priced_line_check, running last, finds it at 0.00 and checks nothing. """ page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "J2001", "CPTROW_3", checked=False, fee="45.00") _count_checkbox_clicks(page, "CPTROW_3") data = {"cpt": claim_form.extract(page)["cpt"]} assert plc.detect("9103000", data) is True assert j2930_j2001_update.detect("9103000", data) is True results, log = _run_all_logged(page, "9103000", data) assert [r.condition_name for r in results] == ["j2930_j2001_update"], results assert results[0].changes == [{"row": 3, "code": "J2001", "fee": {"before": "45.00", "after": "0.00"}}], \ results[0].changes assert _checks_reported_on(results, 3) == [], results assert _row_state(page, 3) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_3']") == 0, \ "J2001's checkbox was clicked — updateBillToIns() would fire" _assert_priced_line_check_ran_and_found_nothing(log, "9103000") @case def run_all_does_not_toggle_an_unchecked_priced_dcons(page): page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "DCONS", "CPTROW_3", checked=False, fee="45.00") _count_checkbox_clicks(page, "CPTROW_3") data = {"cpt": claim_form.extract(page)["cpt"]} assert plc.detect("9121000", data) is True assert dummy_codes.detect("9121000", data) is True results, log = _run_all_logged(page, "9121000", data) assert [r.condition_name for r in results] == ["dummy_codes"], results assert results[0].changes == [{"row": 3, "code": "DCONS", "fee": {"before": "45.00", "after": "0.00"}}], \ results[0].changes assert _checks_reported_on(results, 3) == [], results assert _row_state(page, 3) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_3']") == 0, \ "DCONS's checkbox was clicked — updateBillToIns() would fire" _assert_priced_line_check_ran_and_found_nothing(log, "9121000") _MEDICARE_DATA = { "progress_notes": {"text": "Session Setting (PoS): TeleHealth"}, "insurance": [{"Name": "Humana Medicare"}], } @case def run_all_does_not_toggle_a_medicare_telehealth_other_line(page): """ Document #22's "Other Primary CPT codes need to be unchecked and change the fee amount as Zero", on the fixture's own G8510 — already unchecked but still at 65.00, exactly an excluded-but-priced line. G2025 is added through the fixture's Fee Schedule picker, every other line is zeroed, and priced_line_check leaves G8510 excluded. Data shaped the way test_conditions_medicare_telehealth.py's `_MEDICARE_DATA` is, plus the CPT grid as read. """ page.goto(FIXTURE.as_uri()) _count_checkbox_clicks(page, "CPTROW_2") data = dict(_MEDICARE_DATA, cpt=claim_form.extract(page)["cpt"]) assert plc.detect("9103000", data) is True assert medicare_telehealth.detect("9103000", data) is True results, log = _run_all_logged(page, "9103000", data) assert [r.condition_name for r in results] == ["medicare_telehealth"], results g8510 = [c for c in results[0].changes if c.get("row") == 2] assert g8510 == [{"row": 2, "code": "G8510", "fee": {"before": "65.00", "after": "0.00"}, # Unit E (2026-10-05): every change also carries the # audio/video evidence describe() shows. "signal": "telehealth", "mode": "video", "mode_phrase": ""}], results[0].changes assert _checks_reported_on(results, 2) == [], results assert _row_state(page, 2) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_2']") == 0, \ "G8510's checkbox was clicked — updateBillToIns() would fire" _assert_priced_line_check_ran_and_found_nothing(log, "9103000") # G2025, the one line #22 keeps billed, is still billed. last = page.locator(sel.SEL_CPT_ROWS).last assert last.locator(sel.SEL_CPT_CODE).first.input_value() == "G2025" assert last.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is True @case def pinned_needs_ruling_g2025_unconfirmed_other_line_gets_checked(page): """ PINNED, NEEDS A RULING (review finding, 2026-09-30) — the one normal, non-raising path running last does NOT protect. When G2025 cannot be confirmed (here: ub_claim.html, where the Fee Schedule picker flow has no evidence), medicare_telehealth deliberately leaves every other CPT row as read "for review". An "other" line sitting unchecked but priced is then checked by this rule, last — billing a line document #22 says must be excluded, against medicare_telehealth's own log line. Leaving it for review instead is beyond rulings A/B/C. """ page.goto(UB_FIXTURE.as_uri()) _inject_row(page, "99214", "CPTROW_7", screen="ub", checked=False, fee="65.00") data = dict(_MEDICARE_DATA, cpt=claim_form.extract(page)["cpt"]) results, log = _run_all_logged(page, "9120000", data) names = [r.condition_name for r in results] # The fixture's H0023 is billed to Medicare, not a BH payer: #12 # unchecks and zeroes it (operator, 2026-10-12). assert names == ["medicare_telehealth", "bh_h_code_modifier", "priced_line_check"], results assert results[1].changes == [{"row": 0, "code": "H0023", "fee": {"before": "74.00", "after": "0.00"}}], \ results[1].changes assert "Could not confirm G2025" in log, log assert [c for c in results[0].changes if "fee" in c] == [], results[0].changes assert [(c["code"], c["fee"]) for c in results[2].changes] == \ [("99214", "65.00")], ("today: the other line is checked", results[2].changes) @case def run_all_does_not_toggle_an_unchecked_priced_duplicate_g8510(page): """ depression_dx_pointer's duplicate step: the first G8510 checked at 65.00 is the one kept, and a later G8510 sits unchecked but still at 75.00. The duplicate step zeroes its fee (no click — already unchecked); priced_line_check, last, finds it at 0.00. """ page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_full_g8510_row(page, "CPTROW_3", checked=False, fee="75.00") _count_checkbox_clicks(page, "CPTROW_3") data = claim_form.extract(page) assert plc.detect("9103000", data) is True assert depression_dx_pointer.detect("9103000", data) is True results, log = _run_all_logged(page, "9103000", data) assert [r.condition_name for r in results] == ["depression_dx_pointer"], results duplicate = [c for c in results[0].changes if "before" not in c] assert duplicate == [{"row": 3, "code": "G8510", "fee": {"before": "75.00", "after": "0.00"}}], \ results[0].changes assert _checks_reported_on(results, 3) == [], results assert _row_state(page, 2) == (True, "65.00"), "the kept G8510 stays billed" assert _row_state(page, 3) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_3']") == 0, \ "the duplicate's checkbox was clicked — updateBillToIns() would fire" _assert_priced_line_check_ran_and_found_nothing(log, "9103000") @case def run_all_checks_the_unrelated_line_but_never_the_excluded_one(page): # Both on one claim: 99213 unchecked at 150.00 (checked) and J2001 # unchecked at 45.00 (excluded) — the rule tells them apart only by # running after j2930_j2001_update has zeroed J2001. page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _set_row(page, "CPTROW_0", checked=False, fee="150.00") _inject_row(page, "J2001", "CPTROW_3", checked=False, fee="45.00") _count_checkbox_clicks(page, "CPTROW_0") _count_checkbox_clicks(page, "CPTROW_3") data = {"cpt": claim_form.extract(page)["cpt"]} results = run_all(page, "9103000", data) assert [r.condition_name for r in results] == \ ["j2930_j2001_update", "priced_line_check"], results assert results[1].changes == [{"row": 0, "code": "99213", "fee": "150.00"}], \ results[1].changes assert _checks_reported_on(results, 3) == [], results assert (_row_state(page, 0), _row_state(page, 3)) == \ ((True, "150.00"), (False, "0.00")) assert page.evaluate("window.clicksOn") == {"CPTROW_0": 1, "CPTROW_3": 0} @case def run_all_with_this_rule_first_would_toggle_j2001(page): """ The contrast that is WHY this is registered last: the same claim as `run_all_does_not_toggle_an_unchecked_priced_j2001`, with this rule moved ahead of j2930_j2001_update. It checks J2001, and J2001's own condition unchecks it straight after — the same end state, reached by two clicks on a line that must stay out and two contradictory changes in the review box. """ page.goto(FIXTURE.as_uri()) _neutralise_fixture_g8510(page) _inject_row(page, "J2001", "CPTROW_3", checked=False, fee="45.00") _count_checkbox_clicks(page, "CPTROW_3") data = {"cpt": claim_form.extract(page)["cpt"]} results = run_all(page, "9103000", data, conditions=[plc, j2930_j2001_update]) assert [r.condition_name for r in results] == \ ["priced_line_check", "j2930_j2001_update"], results assert results[0].changes == [{"row": 3, "code": "J2001", "fee": "45.00"}] assert results[1].changes == [{"row": 3, "code": "J2001", "unchecked": True, "fee": {"before": "45.00", "after": "0.00"}}] assert _row_state(page, 3) == (False, "0.00") assert page.evaluate("window.clicksOn['CPTROW_3']") == 2, "the toggle" # ============================================================================= # run_all() — a KNOWN GAP where this rule meets vaccine_admin_codes' own # pre-read decision, PINNED pending an operator ruling. Not the settled end # state; see priced_line_check.py's module docstring. # ============================================================================= _TDAP = "TETANUS DIPHTHERIA TOXOIDS AND ACELLULAR PERTUSSIS VACC" _ADMIN_1ST = "IMMUNIZATION ADMIN SINGLE OR COMBINATION" @case def run_all_pins_the_vaccine_gap_for_an_unchecked_priced_admin_line(page): """ PINNED KNOWN GAP, pending an operator ruling — the mirror image of the checked-zero-fee admin line zero_fee_uncheck used to open (fixed 2026-09-30). vaccine_admin_codes decides on the claim as read, where the 90471 is UNCHECKED — so "no admin billed", and it adds a new 90471. This rule then runs last and checks the old 90471, still at 30.00: two admin lines billed for one vaccine. None of the 39 snapshots has this shape (none has an unchecked priced line at all). Fixing it means vaccine_admin_codes counting an unchecked priced admin line as billed — another condition's behaviour, not ruled on. """ page.goto(VACCINE_FIXTURE.as_uri()) page.evaluate("rows => window.seedCptRows(rows)", [ {"code": "99396", "title": "PREVENTIVE VISIT EST AGE 40-64", "fee": "250.00"}, {"code": "90734", "title": _TDAP, "fee": "60.00", "icd1": "2"}, {"code": "90471", "title": _ADMIN_1ST, "fee": "30.00", "checked": False}, ]) results = run_all(page, "9113000", claim_form.extract(page)) assert [r.condition_name for r in results] == \ ["vaccine_admin_codes", "priced_line_check"], results assert results[1].changes == [{"row": 2, "code": "90471", "fee": "30.00"}] grid = [(r["code"], r["billed"], r["billed_fee"]) for r in claim_form.extract(page)["cpt"]] assert grid == [("99396", True, "250.00"), ("90734", True, "60.00"), ("90471", True, "30.00"), ("90471", True, "30.00")], \ ("today: two 90471 lines billed", grid) def _run_cases() -> int: for fixture in (FIXTURE, UB_FIXTURE, VACCINE_FIXTURE): 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())