feat(sp7): remit detail includes serviceLinePayments + claimLevelAdjustments
This commit is contained in:
@@ -760,6 +760,28 @@ def to_ui_remittance_with_adjustments(
|
|||||||
return base
|
return base
|
||||||
|
|
||||||
|
|
||||||
|
def _svc_to_wire_dict(svc) -> dict:
|
||||||
|
"""Project an ORM ``ServiceLinePayment`` to the wire format used by
|
||||||
|
the remit drawer's ``serviceLinePayments`` array.
|
||||||
|
|
||||||
|
Mirrors the shape produced by the line-reconciliation endpoint so
|
||||||
|
the UI can render the same components from either source.
|
||||||
|
"""
|
||||||
|
import json as _json
|
||||||
|
return {
|
||||||
|
"id": svc.id,
|
||||||
|
"line_number": svc.line_number,
|
||||||
|
"procedure_qualifier": svc.procedure_qualifier,
|
||||||
|
"procedure_code": svc.procedure_code,
|
||||||
|
"modifiers": _json.loads(svc.modifiers_json or "[]"),
|
||||||
|
"charge": str(Decimal(str(svc.charge))),
|
||||||
|
"payment": str(Decimal(str(svc.payment))),
|
||||||
|
"units": str(Decimal(str(svc.units))) if svc.units is not None else None,
|
||||||
|
"unit_type": svc.unit_type,
|
||||||
|
"service_date": svc.service_date.isoformat() if svc.service_date else None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def to_ui_provider(
|
def to_ui_provider(
|
||||||
*,
|
*,
|
||||||
npi: str,
|
npi: str,
|
||||||
@@ -1188,6 +1210,11 @@ class CycloneStore:
|
|||||||
and labels each via :mod:`cyclone.parsers.cas_codes`. Returns
|
and labels each via :mod:`cyclone.parsers.cas_codes`. Returns
|
||||||
``None`` when the remittance is not found so the API layer can
|
``None`` when the remittance is not found so the API layer can
|
||||||
map that to a 404.
|
map that to a 404.
|
||||||
|
|
||||||
|
SP7: also returns the per-line SVC composites
|
||||||
|
(``serviceLinePayments``) and the CLP-level (claim-level) CAS
|
||||||
|
bucket (``claimLevelAdjustments``) so the remit drawer can show
|
||||||
|
per-line payments + adjustments without a second fetch.
|
||||||
"""
|
"""
|
||||||
with db.SessionLocal()() as s:
|
with db.SessionLocal()() as s:
|
||||||
row = s.get(Remittance, remittance_id)
|
row = s.get(Remittance, remittance_id)
|
||||||
@@ -1203,12 +1230,39 @@ class CycloneStore:
|
|||||||
)
|
)
|
||||||
if parsed_at is not None and parsed_at.tzinfo is None:
|
if parsed_at is not None and parsed_at.tzinfo is None:
|
||||||
parsed_at = parsed_at.replace(tzinfo=timezone.utc)
|
parsed_at = parsed_at.replace(tzinfo=timezone.utc)
|
||||||
return to_ui_remittance_with_adjustments(
|
body = to_ui_remittance_with_adjustments(
|
||||||
row,
|
row,
|
||||||
batch_id=row.batch_id,
|
batch_id=row.batch_id,
|
||||||
parsed_at=parsed_at,
|
parsed_at=parsed_at,
|
||||||
cas_rows=cas_rows,
|
cas_rows=cas_rows,
|
||||||
)
|
)
|
||||||
|
# SP7: per-line SVC composites + claim-level CAS bucket.
|
||||||
|
from cyclone.db import ServiceLinePayment as SLP
|
||||||
|
slps = (
|
||||||
|
s.query(SLP)
|
||||||
|
.filter(SLP.remittance_id == remittance_id)
|
||||||
|
.order_by(SLP.line_number)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
body["serviceLinePayments"] = [
|
||||||
|
_svc_to_wire_dict(svc) for svc in slps
|
||||||
|
]
|
||||||
|
body["claimLevelAdjustments"] = [
|
||||||
|
{
|
||||||
|
"id": c.id,
|
||||||
|
"group_code": c.group_code,
|
||||||
|
"reason_code": c.reason_code,
|
||||||
|
"amount": str(Decimal(str(c.amount))),
|
||||||
|
"quantity": (
|
||||||
|
str(Decimal(str(c.quantity)))
|
||||||
|
if c.quantity is not None
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
}
|
||||||
|
for c in cas_rows
|
||||||
|
if c.service_line_payment_id is None
|
||||||
|
]
|
||||||
|
return body
|
||||||
|
|
||||||
def get_claim_detail(self, claim_id: str) -> dict | None:
|
def get_claim_detail(self, claim_id: str) -> dict | None:
|
||||||
"""Return the SP4 detail-drawer shape for one claim, or ``None``.
|
"""Return the SP4 detail-drawer shape for one claim, or ``None``.
|
||||||
|
|||||||
Reference in New Issue
Block a user