feat(backend): 835 ERA parser with BPR/CLP/SVC balancing, CO Medicaid config, CLI, and FastAPI route

This commit is contained in:
Tyler
2026-06-19 17:01:57 -06:00
parent 3dff38045a
commit 8ea951f436
18 changed files with 2413 additions and 26 deletions
+171
View File
@@ -0,0 +1,171 @@
"""Tests for the 835 ERA Pydantic models."""
import json
from datetime import date
from decimal import Decimal
from cyclone.parsers.models import Address, BatchSummary, Envelope
from cyclone.parsers.models_835 import (
ClaimAdjustment,
ClaimPayment,
FinancialInfo,
ParseResult835,
Payer835,
Payee835,
ReassociationTrace,
ServicePayment,
claim_status_label,
)
def _build_result() -> ParseResult835:
return ParseResult835(
envelope=Envelope(
sender_id="COMEDASSISTPROG",
receiver_id="TPID001",
control_number="991102984",
transaction_date=date(2026, 6, 17),
implementation_guide="005010X221A1",
),
financial_info=FinancialInfo(
handling_code="C",
paid_amount=Decimal("85.00"),
credit_debit_flag="C",
payment_method="ACH",
payer_tax_id="81-1725341",
payment_date=date(2026, 6, 17),
),
trace=ReassociationTrace(
trace_type_code="1",
trace_number="991102984",
originating_company_id="TPID001",
payer_id="81-1725341",
),
payer=Payer835(
name="CO_TXIX",
id="7912900843",
contact_url="hcpf.colorado.gov",
address=Address(line1="PO BOX 11000", city="DENVER", state="CO", zip="802110000"),
),
payee=Payee835(
name="TOC, Inc.",
npi="1881068062",
address=Address(line1="1100 East Main St", line2="Suite A", city="Montrose", state="CO", zip="814014063"),
),
claims=[
ClaimPayment(
payer_claim_control_number="CLM001",
status_code="1",
status_label="Processed as Primary",
total_charge=Decimal("100.00"),
total_paid=Decimal("85.00"),
patient_responsibility=Decimal("15.00"),
claim_filing_indicator="MC",
original_claim_id="CLM001",
facility_type="12",
frequency_code="1",
per_diem_covered_days=None,
ref_benefit_plan=None,
service_payments=[
ServicePayment(
line_number=1,
procedure_qualifier="HC",
procedure_code="S5130",
modifiers=["U2"],
charge=Decimal("60.00"),
payment=Decimal("50.00"),
units=Decimal("7.73"),
unit_type="UN",
service_date=date(2026, 6, 2),
adjustments=[
ClaimAdjustment(group_code="CO", reason_code="45", amount=Decimal("10.00"), quantity=None),
],
ref_benefit_plan=None,
),
],
raw_segments=[["CLP", "CLM001", "1", "100.00", "85.00"]],
)
],
summary=BatchSummary(
input_file="f",
control_number="991102984",
transaction_date=date(2026, 6, 17),
total_claims=1,
passed=1,
failed=0,
),
)
def test_financial_info_decimal_paid_amount():
f = FinancialInfo(handling_code="C", paid_amount=Decimal("85.00"), credit_debit_flag="C")
assert f.paid_amount == Decimal("85.00")
assert f.payer_tax_id is None
assert f.payment_date is None
def test_reassociation_trace_required():
t = ReassociationTrace(trace_type_code="1", trace_number="X", originating_company_id="Y")
assert t.payer_id is None
def test_payer835_optional_fields():
p = Payer835(name="X")
assert p.id is None
assert p.address is None
assert p.contact_url is None
def test_payee835_required_npi():
p = Payee835(name="TOC", npi="1881068062")
assert p.npi == "1881068062"
def test_claim_adjustment_quantity_optional():
a = ClaimAdjustment(group_code="CO", reason_code="45", amount=Decimal("10.00"))
assert a.quantity is None
def test_service_payment_modifiers_default_empty():
sp = ServicePayment(
line_number=1,
procedure_qualifier="HC",
procedure_code="99213",
charge=Decimal("100.00"),
payment=Decimal("85.00"),
)
assert sp.modifiers == []
assert sp.adjustments == []
def test_claim_payment_status_label_decoded():
c = ClaimPayment(
payer_claim_control_number="X",
status_code="1",
total_charge=Decimal("100"),
total_paid=Decimal("85"),
)
assert c.status_label == "Processed as Primary"
assert claim_status_label("4") == "Denied"
assert claim_status_label("25") == "Predetermination Pricing Only"
assert claim_status_label("99") is None # unknown → None
def test_parse_result835_date_serializes_to_iso():
r = _build_result()
blob = r.model_dump()
assert blob["envelope"]["transaction_date"] == "2026-06-17"
assert blob["financial_info"]["payment_date"] == "2026-06-17"
assert blob["claims"][0]["service_payments"][0]["service_date"] == "2026-06-02"
def test_parse_result835_full_round_trip():
r = _build_result()
blob = json.loads(r.model_dump_json())
assert blob["envelope"]["control_number"] == "991102984"
assert blob["payer"]["name"] == "CO_TXIX"
assert blob["payee"]["npi"] == "1881068062"
assert blob["claims"][0]["payer_claim_control_number"] == "CLM001"
# Round-trip back to a model
r2 = ParseResult835.model_validate(blob)
assert r2.claims[0].total_paid == Decimal("85.00")
assert r2.payer.contact_url == "hcpf.colorado.gov"