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

381 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
r"""
conditions/medicare_pps_code.py — document #25: a PPS Payer's UB claim must
carry the PPS Code its billed Qualifying Codes map to on the client's
Medicare G code crosswalk (G0466–G0470; operator, 2026-10-23, spec EEWA-34).
python tests\test_conditions_medicare_pps_code.py
Terms (GLOSSARY.md): PPS Code, Qualifying Code, PPS Payer. Claim numbers
here are made up.
"""
import io
import sys
import pathlib
import inspect
import contextlib
ROOT = pathlib.Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "src"))
from ecw_bot.conditions import medicare_pps_code as pps # noqa: E402
CASES = []
def case(fn):
CASES.append(fn)
return fn
def _quiet(fn, *a, **k):
with contextlib.redirect_stdout(io.StringIO()) as out:
result = fn(*a, **k)
return result, out.getvalue()
def _row(code, billed=True, fee="120.00"):
return {"code": code, "billed": billed, "billed_fee": fee, "units": "1"}
def _data(codes, payer="Medicare", screen="ub"):
cpt = [c if isinstance(c, dict) else _row(c) for c in codes]
return {"cpt": cpt, "screen": screen,
"insurance": [{"Name": payer}] if payer is not None else []}
# ── decisions (no browser) ───────────────────────────────────────────────────
@case
def an_office_visit_without_its_pps_code_is_detected():
fired, _ = _quiet(pps.detect, "C1", _data(["99213"]))
assert fired is True
def _adds(data):
return [pps_code for pps_code, _ in pps.decide(data)["add"]]
@case
def each_visit_kind_maps_to_its_pps_code():
for codes, want in ((["99203"], "G0466"), (["92002"], "G0466"),
(["99341"], "G0466H"), (["99213"], "G0467"),
(["Q0091"], "G0467"), (["99309"], "G0467NH"),
(["99318"], "G0467NH"), (["99348"], "G0467H"),
(["99336"], "G0467"), (["G0439"], "G0468")):
assert _adds(_data(codes)) == [want], (codes, pps.decide(_data(codes)))
assert pps.decide(_data(["99203"]))["add"] == [("G0466", ["99203"])]
@case
def an_awv_or_ippe_takes_g0468_even_with_an_office_visit():
assert _adds(_data(["99213", "G0438"])) == ["G0468"]
@case
def the_right_pps_code_already_billed_needs_nothing():
for codes in (["99213", "G0467"], ["99203", "G0466"],
["99309", "G0467NH"], ["G0439", "G0468"]):
data = _data(codes)
fired, _ = _quiet(pps.detect, "C1", data)
assert fired is False, codes
assert pps.needs_review("C1", data) is None, codes
@case
def a_code_that_does_not_end_billed_does_not_qualify():
assert _adds(_data([_row("99213", billed=False, fee="0.00")])) == []
assert _adds(_data([_row("99213", fee="0.00")])) == []
assert _adds(_data(["36415"])) == [], "not on the crosswalk"
def _review(codes, **kw):
data = _data(codes, **kw)
fired, _ = _quiet(pps.detect, "C1", data)
assert fired is False, (codes, pps.decide(data))
return pps.needs_review("C1", data) or ""
@case
def codes_on_both_lists_only_are_review_new_or_established():
for codes in (["G0444"], ["97802"], ["G0444", "G0101"]):
why = _review(codes)
assert "new or established" in why and "G0466" in why \
and "G0467" in why and codes[0] in why, (codes, why)
@case
def a_code_on_one_list_settles_the_ones_on_both():
assert _adds(_data(["99213", "G0444"])) == ["G0467"]
assert pps.decide(_data(["99213", "G0444"]))["add"] == \
[("G0467", ["99213"])]
@case
def conflicting_visit_codes_are_review_and_nothing_is_added():
for codes, a, b in ((["99203", "99213"], "G0466", "G0467"),
(["99213", "99348"], "G0467", "G0467H")):
why = _review(codes)
assert "conflicting" in why and a in why and b in why, (codes, why)
assert _adds(_data(codes)) == [], codes
@case
def conflicting_codes_stay_review_with_one_of_their_pps_codes_billed():
why = _review(["99203", "99213", "G0467"])
assert "conflicting" in why and "G0466" in why, why
@case
def a_different_pps_code_billed_is_review_and_not_changed():
why = _review(["99203", "G0467"])
assert "G0467 billed" in why and "G0466" in why, why
@case
def a_different_pps_code_next_to_the_right_one_is_review_too():
why = _review(["99213", "G0467", "G0466"])
assert "G0466 billed" in why and "crosswalk says G0467" in why, why
why = _review(["G0439", "G0468", "G0467"])
assert "G0467 billed" in why and "crosswalk says G0468" in why, why
@case
def mental_health_is_review_until_the_client_rules():
why = _review(["90834"])
assert "G0469 or G0470" in why and "90834" in why, why
for billed in ("G0469", "G0470"):
data = _data(["90834", billed])
assert pps.needs_review("C1", data) is None, billed
@case
def hcfa_is_review_by_hand_and_dental_is_skipped():
why = _review(["99213"], screen="hcfa")
assert "by hand" in why and "PPS" in why and "G0467" in why, why
why = _review(["99213", "G0467"], screen="hcfa")
assert "hcfa" in why and "99213" in why and "by hand" in why, \
"the wrong form is caught with the PPS code there too"
assert _review(["36415"], screen="hcfa") == "", "no Qualifying Code"
data = _data(["99213"], screen="dental")
assert _quiet(pps.detect, "C1", data)[0] is False
assert pps.needs_review("C1", data) is None
@case
def g0468_on_a_payer_whose_history_is_never_checked_is_review():
"""Operator, 2026-10-23: the Cigna plans are Commercial for #27–#29,
so their preventive visit history is never read — Review, not an add.
On Medicare #27–#29 reads it first, so the claim still fires."""
for payer in ("Cigna Healthspring", "Cigna Health Spring/ Bravo"):
why = _review(["G0439"], payer=payer)
assert "G0468 not added" in why and "history not checked" in why \
and "G0439" in why, (payer, why)
assert _adds(_data(["G0439"])) == ["G0468"]
@case
def only_pps_payers_by_their_exact_names_cigna_healthspring_included():
for payer in ("Medicare", "Medicare-Novitas", "HCFA Medicare Novitas",
"Humana Medicare", "Devoted MCR UB", "Cigna Healthspring",
"Cigna Health Spring/ Bravo", " medicare "):
fired, _ = _quiet(pps.detect, "C1", _data(["99213"], payer=payer))
assert fired is True, payer
for payer in ("Medicaid", "Cigna Medicare Access Plan", "Devoted",
"Humana Claims", "", None):
data = _data(["99213"], payer=payer)
fired, _ = _quiet(pps.detect, "C1", data)
assert fired is False, payer
assert pps.needs_review("C1", data) is None, payer
# ── apply (browser) ─────────────────────────────────────────────────────────
FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "vaccine_claim.html"
from ecw_bot import settings as cfg # noqa: E402
from ecw_bot.conditions.base import ConditionResult # noqa: E402
from ecw_bot.pages import claim_form # noqa: E402
_VISIT = [{"code": "99213", "title": "OFFICE VISIT EST LEVEL 3", "fee": "120.00"}]
def _fresh(page, rows, payer="Medicare"):
page.goto(FIXTURE.as_uri())
page.evaluate("rows => window.seedCptRows(rows)", rows)
data = claim_form.extract(page)
data["insurance"] = [{"Name": payer}]
return data
def _rows_for(page, code):
return [r for r in claim_form.extract(page)["cpt"] if r["code"] == code]
@case
def verify_adds_nothing_and_says_which_pps_code_to_add_by_hand(page):
data = _fresh(page, _VISIT)
saved = cfg.SAVE_CORRECTIONS
cfg.SAVE_CORRECTIONS = False
try:
result, _ = _quiet(pps.apply, page, "C1", data)
finally:
cfg.SAVE_CORRECTIONS = saved
assert isinstance(result, ConditionResult)
assert result.changed is False, result
assert "G0467" in result.review and "99213" in result.review \
and "by hand" in result.review, result.review
assert _rows_for(page, "G0467") == []
@case
def live_write_adds_the_pps_code_once_with_units_1(page):
result, out = _quiet(pps.apply, page, "C1", _fresh(page, _VISIT))
assert result.changed is True and result.review == "", (result, out)
added = _rows_for(page, "G0467")
assert len(added) == 1 and added[0]["units"] == "1", added
assert len(claim_form.extract(page)["cpt"]) == 2, "nothing else changed"
assert pps.summary_comment(result) == \
"CPT Code Missing (PPS code G0467 added (99213))", \
pps.summary_comment(result)
text = pps.describe(result)
assert "G0467" in text and "99213" in text and "Added" in text, text
@case
def a_pps_code_the_picker_cannot_find_is_review_add_by_hand(page):
data = _fresh(page, [{"code": "99348", "title": "HOME VISIT EST",
"fee": "130.00"}])
result, _ = _quiet(pps.apply, page, "C1", data)
assert result.changed is False, result
assert "G0467H could not be added" in result.review \
and "99348" in result.review, result.review
assert _rows_for(page, "G0467H") == []
from ecw_bot.conditions import CONDITIONS # noqa: E402
from ecw_bot.conditions.base import run_all # noqa: E402
from ecw_bot.core import charge_summary as cs # noqa: E402
def _outcome(page, data, live_write):
data["progress_notes"] = {"opened": "modal", "text": "Office visit."}
saved = cfg.SAVE_CORRECTIONS
cfg.SAVE_CORRECTIONS = live_write
try:
report = {}
results, out = _quiet(run_all, page, "C1", data, report=report)
finally:
cfg.SAVE_CORRECTIONS = saved
data["_conditions"] = {"fired": [r.condition_name for r in results],
"saved": False, "failed": report["failed"],
"review": report["review"],
"comments": report["comments"]}
return cs.claim_outcome(True, data), report, out
@case
def it_is_registered_after_the_wellness_history_and_before_priced_line_check():
names = [m.NAME for m in CONDITIONS]
i = names.index("medicare_pps_code")
assert names.index("medicare_wellness_history") < i < names.index(
"priced_line_check"), names
@case
def a_verify_run_makes_the_claim_review_naming_the_pps_code(page):
outcome, report, out = _outcome(page, _fresh(page, _VISIT), False)
assert outcome["Category"] == "Review", (outcome, out)
mine = [r for r in report["review"] if r["name"] == "medicare_pps_code"]
assert mine and "G0467" in mine[0]["reason"], report["review"]
assert "G0467" in outcome["Comments"], outcome
@case
def a_live_write_run_adds_it_and_the_claim_is_fail_saying_so(page):
outcome, report, out = _outcome(page, _fresh(page, _VISIT), True)
assert outcome["Category"] == "Fail", (outcome, out)
assert "PPS code G0467 added (99213)" in outcome["Comments"], outcome
assert not [r for r in report["review"]
if r["name"] == "medicare_pps_code"], report["review"]
assert len(_rows_for(page, "G0467")) == 1
@case
def g0468_is_held_back_when_the_wellness_history_found_a_problem(page):
awv = [{"code": "G0439", "title": "ANNUAL WELLNESS VISIT SUBSEQ",
"fee": "160.00"}]
for verdict, words in (
({"read": True, "conflicts": [
"G0439 already billed on 01/05/2026 (claim 9000001) — once "
"a year"]}, "already billed"),
({"read": False, "conflicts": []}, "history not read")):
data = _fresh(page, awv)
data["_wellness_history"] = verdict
result, _ = _quiet(pps.apply, page, "C1", data)
assert result.changed is False, (verdict, result)
assert "G0468 not added" in result.review and words in \
result.review, result.review
assert _rows_for(page, "G0468") == [], verdict
data = _fresh(page, awv)
data["_wellness_history"] = {"read": True, "conflicts": []}
result, _ = _quiet(pps.apply, page, "C1", data)
assert result.changed is True and _rows_for(page, "G0468"), result
@case
def g0468_with_no_wellness_verdict_by_apply_is_not_added(page):
"""#27–#29 raised or never reached the claim: its history is unchecked."""
data = _fresh(page, [{"code": "G0439", "title": "ANNUAL WELLNESS VISIT "
"SUBSEQ", "fee": "160.00"}])
result, _ = _quiet(pps.apply, page, "C1", data)
assert result.changed is False, result
assert "G0468 not added" in result.review, result.review
assert _rows_for(page, "G0468") == []
def _run_cases() -> int:
from playwright.sync_api import sync_playwright
failures = 0
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=True)
page = browser.new_page()
for fn in CASES:
name = fn.__name__.replace("_", " ")
try:
if len(inspect.signature(fn).parameters) == 0:
fn()
else:
fn(page)
print(f" ok {name}")
except AssertionError as exc:
print(f" FAIL {name}: {exc}")
failures += 1
except Exception as exc:
print(f" ERROR {name}: {type(exc).__name__}: {exc}")
failures += 1
browser.close()
print(f"\n{len(CASES) - failures}/{len(CASES)} passed")
return 1 if failures else 0
def main() -> int:
"""shot() writes into the operator's Screenshots\\ folder; not here.
The add cases run as LIVE-WRITE, the way a run that adds does."""
import tempfile
from ecw_bot import settings as _cfg
orig = (_cfg.SCREENSHOTS, _cfg.SAVE_CORRECTIONS)
with tempfile.TemporaryDirectory() as tmp:
_cfg.SCREENSHOTS = pathlib.Path(tmp)
_cfg.SAVE_CORRECTIONS = True
try:
return _run_cases()
finally:
_cfg.SCREENSHOTS, _cfg.SAVE_CORRECTIONS = orig
if __name__ == "__main__":
sys.exit(main())