fix(permissions+seed): add /api/reconciliation routes and shape billing_provider.address as dict

Two bugs surfaced as 403/500 storms in the live UI:

1. PERMISSIONS matrix only had '/api/reconcile' as a prefix but the
   client hits '/api/reconciliation/*' (dashboard reconciliation tab,
   manual match endpoint). Every call returned 403 even for admin.
   Add ('GET', '/api/reconciliation') and ('POST', '/api/reconciliation')
   alongside the existing /api/reconcile entries.

2. The seed CLI built billing_provider.address as a flat string but
   to_ui_claim_detail._address_to_ui expects {line1,line2,city,state,zip},
   so opening any seeded claim in the detail drawer threw
   'str object has no attribute get' → 500. Build the dict from the
   provider fields instead.
This commit is contained in:
Nora
2026-06-22 17:54:39 -06:00
parent add6e982a4
commit 0c81968d0c
2 changed files with 13 additions and 4 deletions
+2
View File
@@ -43,6 +43,7 @@ PERMISSIONS: dict[tuple[str, str], set[Role]] = {
("GET", "/api/inbox/lanes"): ALL_ROLES,
("GET", "/api/inbox/export.csv"): ALL_ROLES,
("GET", "/api/reconcile"): ALL_ROLES,
("GET", "/api/reconciliation"): ALL_ROLES,
("GET", "/api/audit-log"): ADMIN_ONLY,
# Write endpoints (admin + user, no viewer).
@@ -53,6 +54,7 @@ PERMISSIONS: dict[tuple[str, str], set[Role]] = {
("POST", "/api/inbox/rejected"): WRITE_ROLES,
("POST", "/api/inbox/payer-rejected"): WRITE_ROLES,
("POST", "/api/reconcile"): WRITE_ROLES,
("POST", "/api/reconciliation"): WRITE_ROLES,
("POST", "/api/resubmit"): WRITE_ROLES,
("POST", "/api/acks"): WRITE_ROLES,
+11 -4
View File
@@ -243,10 +243,17 @@ def _build_seed_rows(
"npi": provider["npi"],
"name": provider["name"],
"tax_id": provider["tax_id"],
"address": provider["address"],
"city": provider["city"],
"state": provider["state"],
"zip": provider["zip"],
# 837 parser produces ``address`` as a structured dict so
# the claim-detail drawer can render line1/line2/city/state/zip.
# A flat string here crashes ``_address_to_ui`` with
# ``AttributeError: 'str' object has no attribute 'get'``.
"address": {
"line1": provider["address"],
"line2": None,
"city": provider["city"],
"state": provider["state"],
"zip": provider["zip"],
},
"phone": provider["phone"],
},
"payer": {"name": payer},