feat(sp7): persist ServiceLinePayment + link CAS rows on 835 ingest

This commit is contained in:
Tyler
2026-06-20 19:27:24 -06:00
parent 0dd6d39424
commit 8442bf91ce
2 changed files with 236 additions and 3 deletions
+68 -3
View File
@@ -259,6 +259,69 @@ def _cas_adjustment_row(adj, remittance_id: str) -> "db.CasAdjustment":
)
def _persist_835_remit(session, cp: "ClaimPayment", remittance_id: str) -> None:
"""SP7: persist ServiceLinePayment + CAS rows for one CLP composite.
For each 835 SVC composite in ``cp.service_payments``:
- insert a ServiceLinePayment row (line_number, procedure, modifiers,
charge, payment, units, service_date).
- flush to populate slp.id.
- insert each per-SVC CAS adjustment with ``service_line_payment_id``
set to slp.id.
For CLP-level CAS adjustments (``cp.claim_adjustments``, a future
extension; not produced by today's 835 parser but allowed by the spec):
- insert CAS rows with ``service_line_payment_id IS NULL``.
The caller controls the transaction; this function does not commit.
The 835 ingest site calls this after ``_remittance_835_row`` is
flushed so the FK target is populated.
"""
import json as _json
from cyclone.db import ServiceLinePayment, CasAdjustment
for svc in cp.service_payments:
slp = ServiceLinePayment(
remittance_id=remittance_id,
line_number=svc.line_number,
procedure_qualifier=svc.procedure_qualifier,
procedure_code=svc.procedure_code,
modifiers_json=_json.dumps(svc.modifiers or []),
charge=Decimal(str(svc.charge)),
payment=Decimal(str(svc.payment)),
units=Decimal(str(svc.units)) if svc.units is not None else None,
unit_type=svc.unit_type,
service_date=svc.service_date,
ref_benefit_plan=svc.ref_benefit_plan,
)
session.add(slp)
session.flush() # populate slp.id for the FK below
for adj in svc.adjustments:
quantity = getattr(adj, "quantity", None)
session.add(CasAdjustment(
remittance_id=remittance_id,
group_code=adj.group_code,
reason_code=adj.reason_code,
amount=Decimal(str(adj.amount)),
quantity=Decimal(str(quantity)) if quantity is not None else None,
service_line_payment_id=slp.id,
))
# CLP-level CAS (no SVC composite to attach to). Today's parser does
# not produce these; the branch is forward-compatible.
for adj in getattr(cp, "claim_adjustments", []) or []:
quantity = getattr(adj, "quantity", None)
session.add(CasAdjustment(
remittance_id=remittance_id,
group_code=adj.group_code,
reason_code=adj.reason_code,
amount=Decimal(str(adj.amount)),
quantity=Decimal(str(quantity)) if quantity is not None else None,
service_line_payment_id=None,
))
# ---------------------------------------------------------------------------
# UI mappers: ORM rows → simpler UI types.
# ---------------------------------------------------------------------------
@@ -905,9 +968,11 @@ class CycloneStore:
# this the CasAdjustment inserts below would reference an
# unset id and violate the FK.
s.flush()
for svc in cp.service_payments:
for adj in svc.adjustments:
s.add(_cas_adjustment_row(adj, remit_row.id))
# SP7: persist per-line ServiceLinePayment + linked
# SVC-level CAS rows + claim-level CAS bucket. Replaces
# the previous per-SVC CAS insert loop so the
# service_line_payment_id FK is set correctly.
_persist_835_remit(s, cp, remit_row.id)
s.add(ActivityEvent(
ts=record.parsed_at,
kind="remit_received",