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

460 lines
17 KiB
Python

r"""
conditions/bh_h_code_modifier.py — document #12: on a claim whose payer's
name starts with "BH", an H code line (H0001-H2037) carries no modifier;
telehealth visits are excluded (their GT stays).
python tests\test_conditions_bh_h_code_modifier.py
Uses hcfa_claim.html with an injected H code row, whose M1-M4 inputs carry
the same data-fieldnames as the fixture's own rows.
"""
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" / "hcfa_claim.html"
UB_FIXTURE = FIXTURE.with_name("ub_claim.html")
from ecw_bot.conditions import bh_h_code_modifier as bh # noqa: E402
from ecw_bot.conditions.base import 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 = []
BH = [{"Name": "BH COLORADO ACCESS"}]
MEDICAID = [{"Name": "APM2 Medicaid"}]
OFFICE_NOTE = {"opened": "tab", "text": "Office visit. Session Setting: Clinic."}
TELE_NOTE = {"opened": "tab", "text": "Session Setting (PoS): TeleHealth"}
def case(fn):
CASES.append(fn)
return fn
def _inject_h_row(page, code="H0023", mods=("GT", "", "", ""),
row_id="CPTROW_3"):
page.evaluate(
"""(a) => {
const tbody = document.querySelector(
'#claimCPTCodesTable8888888888888 tbody');
const last = tbody.querySelector('tr:last-child');
const tr = document.createElement('tr');
tr.id = a.rowId;
let html = '<td><input type="checkbox" ng-click="updateBillToIns(3)" checked></td>'
+ '<td><input data-fieldname="claimCPTCode" value="' + a.code + '" readonly></td>'
+ '<td><input data-fieldname="ClaimCPTPOS" type="text" value="11"></td>';
a.mods.forEach((m, i) => {
html += '<td><input data-fieldname="ClaimCPTMOD' + (i + 1)
+ '" type="text" value="' + m + '"></td>';
});
html += '<td><input data-fieldname="ClaimCPTBilledFee" value="150.00"></td>';
tr.innerHTML = html;
tbody.insertBefore(tr, last);
tr.querySelectorAll('[data-fieldname^="ClaimCPTMOD"]').forEach(el =>
el.addEventListener('blur', () => { el.dataset.blurred = '1'; }));
}""", {"code": code, "mods": list(mods), "rowId": row_id})
def _mods(page, index):
row = page.locator(sel.SEL_CPT_ROWS).nth(index)
return [row.locator(s).first.input_value() for s in sel.SEL_CPT_MOD]
def _data(page, ins=BH, note=OFFICE_NOTE):
data = claim_form.extract(page)
data["insurance"] = ins
# The fixture's Z13.31 would fire depression_dx_pointer in run_all, and
# the injected row has no ICD inputs for it to read.
data["icd"] = []
if note is not None:
data["progress_notes"] = note
return data
# ── detect ───────────────────────────────────────────────────────────────────
def _cpt(code="H0023", mod1="GT", mod2=""):
return [{"code": "99213", "mod1": "25"},
{"code": code, "mod1": mod1, "mod2": mod2}]
@case
def detect_true_for_a_bh_payer_h_code_with_a_modifier():
for payer in ("BH COLORADO ACCESS", "BH ROCKY MTN HEALTH 2022",
"BH ROCKY MOUNTAIN HEALTH PLANS", " bh rock mtn ub "):
data = {"insurance": [{"Name": payer}], "cpt": _cpt(),
"progress_notes": OFFICE_NOTE}
assert bh.detect("C1", data) is True, payer
@case
def detect_true_when_only_a_later_modifier_is_set():
data = {"insurance": BH, "cpt": _cpt(mod1="", mod2="HO"),
"progress_notes": OFFICE_NOTE}
assert bh.detect("C1", data) is True
def _billed_h(billed=True, fee="150.00", mod1="GT"):
return [{"code": "99213", "billed": True, "billed_fee": "210.00"},
{"code": "H0023", "mod1": mod1, "billed": billed,
"billed_fee": fee}]
@case
def detect_true_for_a_billed_h_code_on_a_non_bh_payer():
"""
Operator, 2026-10-12: an H code is billed to BH payers only; on any
other payer it is unchecked and zeroed — telehealth or not, modifier
or not.
"""
for payer in ("Carelon Behavioral Health, Inc", "APM2 Medicaid",
"HCFA Medicare", "Rocky Mountain Health Prime"):
for note in (OFFICE_NOTE, TELE_NOTE):
for mod1 in ("GT", ""):
data = {"insurance": [{"Name": payer}],
"cpt": _billed_h(mod1=mod1), "progress_notes": note}
assert bh.detect("C1", data) is True, (payer, note, mod1)
@case
def detect_true_for_a_non_bh_ub_h_line_with_a_fee_and_no_checkbox():
data = {"insurance": MEDICAID, "cpt": _billed_h(billed=None)}
assert bh.detect("C1", data) is True
@case
def detect_false_for_a_non_bh_h_code_already_unchecked_and_zeroed():
for billed, fee in ((False, "150.00"), (None, "0.00"), (True, "0.00")):
data = {"insurance": MEDICAID, "cpt": _billed_h(billed, fee)}
assert bh.detect("C1", data) is False, (billed, fee)
@case
def detect_false_when_the_payer_was_not_read():
for ins in ([{"Name": ""}], []):
data = {"insurance": ins, "cpt": _billed_h()}
assert bh.detect("C1", data) is False, ins
@case
def detect_false_when_the_h_code_has_no_modifier():
data = {"insurance": BH, "cpt": _cpt(mod1=""),
"progress_notes": OFFICE_NOTE}
assert bh.detect("C1", data) is False
@case
def detect_false_for_codes_that_only_start_with_h():
"""Only H0001-H2037 style codes: 'H' plus four digits."""
for code in ("HCG", "H00231", "H002"):
data = {"insurance": BH, "cpt": _cpt(code=code),
"progress_notes": OFFICE_NOTE}
assert bh.detect("C1", data) is False, code
@case
def detect_false_on_a_telehealth_visit():
data = {"insurance": BH, "cpt": _cpt(), "progress_notes": TELE_NOTE}
assert bh.detect("C1", data) is False
@case
def detect_true_when_the_note_was_not_read():
"""Unknown telehealth: it fires, and apply() sends it to Review."""
for note in (None, {"opened": "disabled"}, {"opened": "absent"},
{"opened": "tab", "error": "boom"}):
data = {"insurance": BH, "cpt": _cpt()}
if note is not None:
data["progress_notes"] = note
assert bh.detect("C1", data) is True, note
# ── apply ────────────────────────────────────────────────────────────────────
@case
def apply_clears_every_modifier_on_the_h_code_row_only(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "HO", "", ""))
other_before = [_mods(page, i) for i in (0, 1, 2)]
result = bh.apply(page, "C1", _data(page))
assert result.changed is True, result
assert result.review == "", result.review
assert result.changes == [{"row": 3, "code": "H0023",
"before": ["GT", "HO", "", ""],
"after": ["", "", "", ""], "ok": True}], \
result.changes
assert _mods(page, 3) == ["", "", "", ""]
assert [_mods(page, i) for i in (0, 1, 2)] == other_before, \
"non-H-code rows must be left exactly as they were"
row = page.locator(sel.SEL_CPT_ROWS).nth(3)
assert row.locator(sel.SEL_CPT_MOD1).first.get_attribute("data-blurred") == "1", \
"M1 must be blurred so eCW's updateCPTMod commits the change"
@case
def an_empty_live_grid_declines_instead_of_passing(page):
"""Review finding 2 (2026-10-12): the grid did not re-render."""
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
data = _data(page)
page.evaluate("""() => document.querySelectorAll('tr[id^="CPTROW_"]')
.forEach(tr => tr.remove())""")
result = bh.apply(page, "C1", data)
assert result.changed is False
assert result.review == bh.CPT_GRID_NOT_READ, result.review
@case
def a_fee_eCW_reprices_after_the_modifier_change_is_recorded(page):
"""Review finding 4: eCW re-prices the line on the modifier's blur."""
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
page.evaluate("""() => {
const tr = document.getElementById('CPTROW_3');
const fee = tr.querySelector('[data-fieldname="ClaimCPTBilledFee"]');
tr.querySelector('[data-fieldname="ClaimCPTMOD1"]').addEventListener(
'blur', () => setTimeout(() => { fee.value = '120.00'; }, 300));
}""")
result = bh.apply(page, "C1", _data(page))
assert result.changes[0]["fee"] == {"before": "150.00",
"after": "120.00"}, result.changes
text = bh.describe(result)
assert "150.00" in text and "120.00" in text, text
@case
def a_partial_note_counts_as_not_read_on_a_bh_payer(page):
"""
Review, 2026-10-12: a note whose sections never settled may be missing
the telehealth line, so GT must not be removed on its word.
"""
partial = dict(OFFICE_NOTE, partial=True, partial_sections=0)
assert bh.detect("C1", {"insurance": BH, "cpt": _cpt(),
"progress_notes": partial}) is True
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
result = bh.apply(page, "C1", _data(page, note=partial))
assert result.changed is False
assert result.review == bh.NOTE_NOT_READ, result.review
assert _mods(page, 3)[0] == "GT"
@case
def a_modifier_eCW_puts_back_after_the_blur_is_not_removed(page):
"""
The read-back is judged after eCW has had time to react, not straight
after the blur: here the modifier comes back 300 ms later.
"""
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
page.evaluate("""() => {
const m1 = document.getElementById('CPTROW_3')
.querySelector('[data-fieldname="ClaimCPTMOD1"]');
m1.addEventListener('blur', () =>
setTimeout(() => { m1.value = 'GT'; }, 300));
}""")
result = bh.apply(page, "C1", _data(page))
assert result.changes[0]["ok"] is False, result.changes
assert result.review == bh.NOT_REMOVED, result.review
assert "STILL SET" in bh.describe(result)
assert "NOT removed" in bh.summary_comment(result), \
bh.summary_comment(result)
@case
def apply_on_the_ub_form_clears_and_blurs_every_set_modifier(page):
"""The UB screen's own ids (uBClaimModN), M2 seeded as well as M1."""
page.goto(UB_FIXTURE.as_uri())
page.evaluate("""() => {
const tr = document.querySelectorAll('tr[id^="CPTROW_"]')[0];
const m2 = tr.querySelector('[id^="uBClaimMod2"]');
m2.value = 'HO';
for (const el of tr.querySelectorAll('[id^="uBClaimMod"]'))
el.addEventListener('blur', () => { el.dataset.blurred = '1'; });
}""")
data = _data(page)
assert data["cpt"][0]["code"] == "H0023"
result = bh.apply(page, "C1", data)
assert result.changes and result.changes[0]["before"][:2] == ["GT", "HO"], \
result.changes
assert result.changes[0]["ok"] is True
assert _mods(page, 0) == ["", "", "", ""]
tr = page.locator(sel.SEL_CPT_ROWS).nth(0)
for n in (1, 2):
assert tr.locator(f'[id^="uBClaimMod{n}"]').first \
.get_attribute("data-blurred") == "1", f"M{n} not blurred"
@case
def apply_sends_an_unread_note_to_review_and_changes_nothing(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "", "", ""))
result = bh.apply(page, "C1", _data(page, note={"opened": "disabled"}))
assert result.changed is False
assert result.review == bh.NOTE_NOT_READ, result.review
assert _mods(page, 3) == ["GT", "", "", ""]
@case
def apply_is_a_no_op_when_the_h_code_has_no_modifier(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("", "", "", ""))
result = bh.apply(page, "C1", _data(page))
assert result.changed is False and result.review == "", result
@case
def describe_names_the_code_and_the_removed_modifiers(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "HO", "", ""))
text = bh.describe(bh.apply(page, "C1", _data(page)))
assert "H0023" in text and "GT" in text and "HO" in text, text
@case
def run_all_on_a_bh_office_visit_fires_this_condition(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "", "", ""))
report = {}
results = run_all(page, "C1", _data(page), report=report)
assert "bh_h_code_modifier" in report["fired"], report
assert "bh_h_code_modifier" in [r.condition_name for r in results], results
assert _mods(page, 3) == ["", "", "", ""]
def _h_row_state(page, index=3):
row = page.locator(sel.SEL_CPT_ROWS).nth(index)
return (row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked(),
row.locator(sel.SEL_CPT_BILLED_FEE).first.input_value())
@case
def apply_on_a_non_bh_payer_unchecks_and_zeroes_the_h_code_only(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "", "", ""))
others = [_h_row_state(page, i) for i in (0, 1, 2)]
result = bh.apply(page, "C1", _data(page, ins=MEDICAID, note=TELE_NOTE))
assert result.changed is True and result.review == "", result
assert result.changes == [{"row": 3, "code": "H0023", "unchecked": True,
"fee": {"before": "150.00",
"after": "0.00"}}], result.changes
assert _h_row_state(page) == (False, "0.00")
assert _mods(page, 3) == ["GT", "", "", ""], "modifier is not this path's"
assert [_h_row_state(page, i) for i in (0, 1, 2)] == others
@case
def apply_on_a_non_bh_payer_with_an_unread_note_still_unchecks(page):
"""Telehealth does not matter off a BH payer, so the note does not."""
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
result = bh.apply(page, "C1",
_data(page, ins=MEDICAID, note={"opened": "disabled"}))
assert result.changed is True, result
assert _h_row_state(page) == (False, "0.00")
@case
def apply_on_a_non_bh_payer_with_an_empty_live_grid_declines(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
data = _data(page, ins=MEDICAID)
page.evaluate("""() => document.querySelectorAll('tr[id^="CPTROW_"]')
.forEach(tr => tr.remove())""")
result = bh.apply(page, "C1", data)
assert result.changed is False
assert result.review == bh.CPT_GRID_NOT_READ, result.review
@case
def summary_comment_and_describe_follow_the_path_taken(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
off = bh.apply(page, "C1", _data(page, ins=MEDICAID))
assert bh.summary_comment(off) == ("H code not billed to a non-BH payer "
"(unchecked and fee zeroed)"), \
bh.summary_comment(off)
# UB, no Assign-To-Patient checkbox: only the fee moved (option A).
fee_only = bh.ConditionResult(
condition_name=bh.NAME, changed=True,
changes=[{"row": 0, "code": "H0023",
"fee": {"before": "74.00", "after": "0.00"}}])
assert bh.summary_comment(fee_only) == ("H code not billed to a non-BH "
"payer (fee zeroed)"), \
bh.summary_comment(fee_only)
text = bh.describe(off)
assert "H0023" in text and "150.00" in text and "non-BH" in text, text
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
on = bh.apply(page, "C1", _data(page))
assert bh.summary_comment(on) == bh.MODIFIER_COMMENT, \
bh.summary_comment(on)
@case
def run_all_on_a_non_bh_payer_leaves_the_h_code_unchecked_at_zero(page):
"""priced_line_check (last) must not re-check it: its fee is 0.00."""
page.goto(FIXTURE.as_uri())
_inject_h_row(page)
report = {}
run_all(page, "C1", _data(page, ins=MEDICAID), report=report)
assert "bh_h_code_modifier" in report["fired"], report
assert _h_row_state(page) == (False, "0.00")
@case
def run_all_on_a_bh_telehealth_visit_keeps_gt(page):
page.goto(FIXTURE.as_uri())
_inject_h_row(page, mods=("GT", "", "", ""))
report = {}
run_all(page, "C1", _data(page, note=TELE_NOTE), report=report)
assert "bh_h_code_modifier" not in report["fired"], report
assert _mods(page, 3)[0] == "GT"
def main() -> 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
if __name__ == "__main__":
sys.exit(main())