"""Integration tests for CycloneStore.add() with 835 batches. Covers: parse-835 persist → reconcile trigger → CAS aggregation. """ from __future__ import annotations from datetime import date, datetime, timezone from decimal import Decimal import pytest from cyclone import db from cyclone.parsers.models_835 import ( ClaimPayment, ClaimAdjustment, ServicePayment, ParseResult835, Envelope, FinancialInfo, ReassociationTrace, Payer835, Payee835, BatchSummary, ) from cyclone.store import CycloneStore @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() yield db._reset_for_tests() def _make_remit_with_cas(remit_id="CLP-1", status="1", charge="124.00", paid="62.00", cas_amount="62.00"): cp = ClaimPayment( payer_claim_control_number=remit_id, status_code=status, status_label="Primary", total_charge=charge, total_paid=paid, service_payments=[ ServicePayment( line_number=1, procedure_qualifier="HC", procedure_code="99213", charge=charge, payment=paid, adjustments=[ClaimAdjustment(group_code="CO", reason_code="45", amount=cas_amount)], ), ], ) return cp def _make_835_result(claims): # NOTE: field names below follow the actual model definitions in # cyclone/parsers/models_835.py — the plan snippet (lines 2550-2566) # referenced stale field names (e.g. credit_debit/handling_code) that # no longer exist after the model was migrated. return ParseResult835( envelope=Envelope( sender_id="S", receiver_id="R", control_number="0001", transaction_date=date(2026, 6, 19), ), financial_info=FinancialInfo( handling_code="C", paid_amount=Decimal("0"), credit_debit_flag="C", payment_method=None, ), trace=ReassociationTrace( trace_type_code="1", trace_number="0001", originating_company_id="S", ), payer=Payer835(name="X", id="SKCO0"), payee=Payee835(name="Y", npi="1234567890"), claims=claims, summary=BatchSummary( input_file="era.txt", control_number="0001", transaction_date=date(2026, 6, 19), total_claims=len(claims), passed=len(claims), failed=0, ), ) def test_add_835_aggregates_cas_into_adjustment_amount(): s = CycloneStore() cp = _make_remit_with_cas() from cyclone.store import BatchRecord835 rec = BatchRecord835( id="b-1", kind="835", input_filename="era.txt", parsed_at=datetime(2026, 6, 19, tzinfo=timezone.utc), result=_make_835_result([cp]), ) s.add(rec) with db.SessionLocal()() as session: from cyclone.db import Remittance, CasAdjustment r = session.query(Remittance).first() assert r is not None assert r.adjustment_amount == 62.0 cas_rows = session.query(CasAdjustment).all() assert len(cas_rows) == 1 assert cas_rows[0].group_code == "CO" assert cas_rows[0].reason_code == "45"