77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
"""Visit-to-835 reconciliation on (member_id, procedure, DOS)."""
|
|
from datetime import date
|
|
from decimal import Decimal
|
|
from cyclone.rebill.reconcile import (
|
|
VisitRow,
|
|
SvcRow,
|
|
ReconcileOutcome,
|
|
reconcile_visits_to_835,
|
|
OutcomeCategory,
|
|
)
|
|
|
|
|
|
def _v(date, member, proc, amt):
|
|
return VisitRow(date=date, member_id=member, procedure=proc, billed=Decimal(amt))
|
|
|
|
|
|
def _s(date, member, proc, chg, paid, status="1"):
|
|
return SvcRow(
|
|
src_file="x.835", claim_id="c1", member_id=member, status=status,
|
|
procedure=proc, modifiers="", charge=Decimal(chg), paid=Decimal(paid),
|
|
units=Decimal("0"), svc_date=date, cas_reasons=(), pay_date=None,
|
|
)
|
|
|
|
|
|
def test_visit_paid_when_any_svc_paid_within_tolerance():
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "2.32")]
|
|
svcs = [_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "2.30")]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.PAID
|
|
assert out[0].unpaid == Decimal("0")
|
|
|
|
|
|
def test_visit_paid_when_one_svc_paid_others_denied_duplicate():
|
|
"""OA-18 on duplicates is noise; paid SVC wins."""
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "2.32")]
|
|
svcs = [
|
|
_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "2.30", "1"),
|
|
_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "0.00", "4"),
|
|
_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "0.00", "4"),
|
|
]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.PAID
|
|
|
|
|
|
def test_visit_denied_when_all_svc_denied():
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "2.32")]
|
|
svcs = [
|
|
_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "0.00", "4"),
|
|
_s(date(2026, 1, 18), "J813715", "T1019", "2.32", "0.00", "4"),
|
|
]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.DENIED
|
|
assert out[0].unpaid == Decimal("2.32")
|
|
|
|
|
|
def test_visit_not_in_835_when_no_svc_match():
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "2.32")]
|
|
svcs = [_s(date(2026, 1, 19), "J813715", "T1019", "2.32", "2.30")]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.NOT_IN_835
|
|
assert out[0].unpaid == Decimal("2.32")
|
|
|
|
|
|
def test_partial_when_total_paid_below_95pct_of_billed():
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "10.00")]
|
|
svcs = [_s(date(2026, 1, 18), "J813715", "T1019", "10.00", "4.00")]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.PARTIAL
|
|
assert out[0].unpaid == Decimal("6.00")
|
|
|
|
|
|
def test_different_member_does_not_match():
|
|
visits = [_v(date(2026, 1, 18), "J813715", "T1019", "2.32")]
|
|
svcs = [_s(date(2026, 1, 18), "OTHERMEMBER", "T1019", "2.32", "2.30")]
|
|
out = reconcile_visits_to_835(visits, svcs)
|
|
assert out[0].category == OutcomeCategory.NOT_IN_835
|