feat(sp41): CARC-aware filter — CO-45/26/129 excluded, PI-16/OA-18 reviewed
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
"""CARC-aware filter.
|
||||||
|
|
||||||
|
EXCLUDED = contractual / not recoverable / not a denial-of-payment in the
|
||||||
|
narrow sense (charge exceeds fee schedule, prior to coverage, etc.).
|
||||||
|
REVIEW = operator must decide (claim/service lacks info, non-covered
|
||||||
|
charges, duplicate, etc.). Anything else falls through to REBILL.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class CarcDecision(str, Enum):
|
||||||
|
EXCLUDED = "EXCLUDED"
|
||||||
|
REVIEW = "REVIEW"
|
||||||
|
REBILL = "REBILL"
|
||||||
|
|
||||||
|
|
||||||
|
# These CARCs are NOT recoverable denials. Do not rebill.
|
||||||
|
EXCLUDED_CARCS: frozenset[str] = frozenset({
|
||||||
|
"CO-45", # charge exceeds fee schedule / contractual obligation
|
||||||
|
"CO-26", # expenses incurred prior to coverage
|
||||||
|
"CO-129", # prior processing information; forward to next payer
|
||||||
|
})
|
||||||
|
|
||||||
|
# These CARCs need human review before rebill.
|
||||||
|
REVIEW_CARCS: frozenset[str] = frozenset({
|
||||||
|
"PI-16", # claim/service lacks information
|
||||||
|
"PI-96", # non-covered charges
|
||||||
|
"PI-15", # authorization / certification absent
|
||||||
|
"PI-4", # procedure not paid separately
|
||||||
|
"PI-110", # billing date predates service date
|
||||||
|
"OA-18", # exact duplicate (resubmit noise)
|
||||||
|
"OA-23", # impact of prior payer adjudication
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def decide_carc(reasons: tuple[str, ...] | list[str]) -> CarcDecision:
|
||||||
|
"""Pick the strongest action: EXCLUDED > REVIEW > REBILL."""
|
||||||
|
if any(r in EXCLUDED_CARCS for r in reasons):
|
||||||
|
return CarcDecision.EXCLUDED
|
||||||
|
if any(r in REVIEW_CARCS for r in reasons):
|
||||||
|
return CarcDecision.REVIEW
|
||||||
|
return CarcDecision.REBILL
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
"""CARC-aware filter for Pipeline A.
|
||||||
|
|
||||||
|
Contractual / non-recoverable denials (CO-45, CO-26, CO-129) must be
|
||||||
|
excluded from rebill. CARCs that need operator review (PI-16, PI-96,
|
||||||
|
PI-15, PI-4, PI-110, OA-18, OA-23) must be surfaced as 'REVIEW' so the
|
||||||
|
operator can decide.
|
||||||
|
"""
|
||||||
|
from cyclone.rebill.carc_filter import (
|
||||||
|
CarcDecision,
|
||||||
|
decide_carc,
|
||||||
|
EXCLUDED_CARCS,
|
||||||
|
REVIEW_CARCS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_co45_is_excluded():
|
||||||
|
assert decide_carc(("CO-45",)) == CarcDecision.EXCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
def test_co26_is_excluded():
|
||||||
|
assert decide_carc(("CO-26",)) == CarcDecision.EXCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
def test_co129_is_excluded():
|
||||||
|
assert decide_carc(("CO-129",)) == CarcDecision.EXCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
def test_pi16_is_review():
|
||||||
|
assert decide_carc(("PI-16",)) == CarcDecision.REVIEW
|
||||||
|
|
||||||
|
|
||||||
|
def test_o18_is_review():
|
||||||
|
"""OA-18 is the duplicate noise — surface for review, don't auto-rebill."""
|
||||||
|
assert decide_carc(("OA-18",)) == CarcDecision.REVIEW
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_carc_is_rebill():
|
||||||
|
assert decide_carc(()) == CarcDecision.REBILL
|
||||||
|
|
||||||
|
|
||||||
|
def test_mixed_excluded_wins():
|
||||||
|
"""If any CARC is excluded, the whole service is excluded."""
|
||||||
|
assert decide_carc(("PI-16", "CO-45")) == CarcDecision.EXCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
def test_sets_have_expected_members():
|
||||||
|
assert "CO-45" in EXCLUDED_CARCS
|
||||||
|
assert "PI-16" in REVIEW_CARCS
|
||||||
|
assert "OA-18" in REVIEW_CARCS
|
||||||
Reference in New Issue
Block a user