feat(backend): parse-835 JSON response includes reconciliation summary
This commit is contained in:
@@ -303,6 +303,40 @@ def _has_835_validation_errors(result: ParseResult835) -> bool:
|
||||
return result.validation is not None and not result.validation.passed
|
||||
|
||||
|
||||
def _reconciliation_summary_for_batch(batch_id: str) -> dict:
|
||||
"""Return ``{matched, unmatched_claims, unmatched_remittances, skipped}`` for a batch.
|
||||
|
||||
Reads from the DB after ``store.add()`` has already triggered T10
|
||||
reconciliation synchronously (via ``_run_reconcile``). Counts are
|
||||
observed at this moment; a subsequent manual match/unmatch will not
|
||||
be reflected until the next request.
|
||||
|
||||
``skipped`` is reserved for future use — the T10 orchestrator tracks
|
||||
skipped claims internally but does not surface a queryable count.
|
||||
"""
|
||||
from sqlalchemy import func, select
|
||||
from cyclone import db
|
||||
from cyclone.db import Match, Remittance
|
||||
|
||||
with db.SessionLocal()() as s:
|
||||
matched = s.execute(
|
||||
select(func.count(Match.id)).where(
|
||||
Match.remittance_id.in_(
|
||||
select(Remittance.id).where(Remittance.batch_id == batch_id)
|
||||
)
|
||||
)
|
||||
).scalar_one()
|
||||
|
||||
# Pull unmatched via the store (small result set; cheap).
|
||||
unmatched = store.list_unmatched(kind="both")
|
||||
return {
|
||||
"matched": matched,
|
||||
"unmatched_claims": len(unmatched["claims"]),
|
||||
"unmatched_remittances": len(unmatched["remittances"]),
|
||||
"skipped": 0, # reserved — T10 does not persist a skipped count
|
||||
}
|
||||
|
||||
|
||||
@app.post("/api/parse-835")
|
||||
async def parse_835_endpoint(
|
||||
request: Request,
|
||||
@@ -384,7 +418,9 @@ async def parse_835_endpoint(
|
||||
store.add(rec)
|
||||
|
||||
if _client_wants_json(request):
|
||||
return JSONResponse(content=json.loads(result.model_dump_json()))
|
||||
body = json.loads(result.model_dump_json())
|
||||
body["reconciliation"] = _reconciliation_summary_for_batch(rec.id)
|
||||
return JSONResponse(content=body)
|
||||
|
||||
# Default: NDJSON stream.
|
||||
return StreamingResponse(
|
||||
|
||||
Reference in New Issue
Block a user