"""Tests that ``CycloneStore.iter_claims`` populates ``receivedAmount`` from the matched ``Remittance.total_paid``. Before SP_Auth follow-up: every claim came back with ``receivedAmount: 0.0`` regardless of whether it had been paired with a paid remittance, so the Dashboard's "Received" KPI was always $0 even when claims had been paid and reconciled. The fix: ``iter_claims`` bulk-loads ``Remittance.total_paid`` for every matched claim id in the result set (single SQL, no N+1) and stamps the sum onto each claim dict. """ from __future__ import annotations import json from datetime import date, datetime, timezone from decimal import Decimal import pytest from cyclone import db from cyclone.db import ActivityEvent, Batch, Claim, ClaimState, Remittance from cyclone.store import store as global_store @pytest.fixture(autouse=True) def _setup(tmp_path, monkeypatch): monkeypatch.setenv("CYCLONE_DB_URL", f"sqlite:///{tmp_path}/test.db") db._reset_for_tests() db.init_db() def _make_batch(s, batch_id: str) -> None: s.add(Batch( id=batch_id, kind="837p", input_filename="seed.edi", parsed_at=datetime(2026, 6, 19, 12, 0, tzinfo=timezone.utc), totals_json={"total_claims": 3}, validation_json={"passed": True, "warnings": [], "errors": []}, raw_result_json={"_": "stub"}, )) def _make_claim(s, claim_id: str, batch_id: str, *, matched_remit_id: str | None = None) -> None: s.add(Claim( id=claim_id, batch_id=batch_id, patient_control_number=claim_id, service_date_from=date(2026, 6, 1), service_date_to=date(2026, 6, 1), charge_amount=Decimal("200.00"), provider_npi="1234567890", payer_id="SKCO0", state=ClaimState.PAID, matched_remittance_id=matched_remit_id, )) def _make_remit(s, remit_id: str, batch_id: str, *, total_paid: Decimal) -> None: s.add(Remittance( id=remit_id, batch_id=batch_id, payer_claim_control_number=remit_id, claim_id=None, status_code="1", total_charge=Decimal("200.00"), total_paid=total_paid, adjustment_amount=Decimal("0"), received_at=datetime(2026, 6, 20, 12, 0, tzinfo=timezone.utc), )) def test_iter_claims_populates_received_amount_from_matched_remittance(): """A matched claim should reflect its remittance's ``total_paid``.""" with db.SessionLocal()() as s: _make_batch(s, "b1") _make_remit(s, "r1", "b1", total_paid=Decimal("180.00")) _make_claim(s, "CLM-A", "b1", matched_remit_id="r1") s.commit() items = global_store.iter_claims(limit=10) by_id = {c["id"]: c for c in items} assert by_id["CLM-A"]["receivedAmount"] == pytest.approx(180.00) def test_iter_claims_unmatched_claim_has_zero_received(): """Claims with no matched remittance still get 0.0, not stale data.""" with db.SessionLocal()() as s: _make_batch(s, "b1") _make_claim(s, "CLM-U", "b1", matched_remit_id=None) s.commit() items = global_store.iter_claims(limit=10) by_id = {c["id"]: c for c in items} assert by_id["CLM-U"]["receivedAmount"] == 0.0 def test_iter_claims_handles_orphan_match_fk(): """A claim with a stale ``matched_remittance_id`` whose remittance row was deleted should default to 0.0 rather than blow up.""" with db.SessionLocal()() as s: _make_batch(s, "b1") _make_claim(s, "CLM-ORPHAN", "b1", matched_remit_id="r-deleted") s.commit() # No remittance row exists — the FK is dangling, which can happen # if the remittance was deleted between match and now. items = global_store.iter_claims(limit=10) by_id = {c["id"]: c for c in items} assert by_id["CLM-ORPHAN"]["receivedAmount"] == 0.0 def test_iter_claims_bulk_loads_multiple_matches_in_one_pass(): """All matched claims in a page reflect their distinct remittance totals — the bulk load must aggregate per remittance id.""" with db.SessionLocal()() as s: _make_batch(s, "b1") _make_remit(s, "r1", "b1", total_paid=Decimal("120.00")) _make_remit(s, "r2", "b1", total_paid=Decimal("175.50")) _make_remit(s, "r3", "b1", total_paid=Decimal("0")) _make_claim(s, "CLM-1", "b1", matched_remit_id="r1") _make_claim(s, "CLM-2", "b1", matched_remit_id="r2") _make_claim(s, "CLM-3", "b1", matched_remit_id="r3") _make_claim(s, "CLM-4", "b1", matched_remit_id=None) s.commit() items = global_store.iter_claims(limit=10) by_id = {c["id"]: c for c in items} assert by_id["CLM-1"]["receivedAmount"] == pytest.approx(120.00) assert by_id["CLM-2"]["receivedAmount"] == pytest.approx(175.50) assert by_id["CLM-3"]["receivedAmount"] == pytest.approx(0.0) assert by_id["CLM-4"]["receivedAmount"] == 0.0