"""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