fix(sales): register GET /{sale_id} last so /settings /customers /past /discounts resolve

The 1-segment parametric route was swallowing the literal GET routes (int-parse 422,
silently masked before). Moved it after all literals.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-06-23 17:38:16 +10:00
parent bf08cd9b35
commit 5673ee125d

View File

@ -151,12 +151,6 @@ async def _load_sale(db, sale_id):
return s, items, cust
@router.get("/{sale_id}")
async def sale_detail(sale_id: int, ident=Depends(require_token), db=Depends(get_db)):
s, items, cust = await _load_sale(db, sale_id)
return {"sale": s, "items": items, "customer": cust}
@router.get("/{sale_id}/receipt")
async def sale_receipt(sale_id: int, ident=Depends(require_token), db=Depends(get_db)):
"""Rendered receipt HTML (for the print window) + the customer's email if on file."""
@ -335,3 +329,11 @@ async def past_sales(q: str = Query(""), ident=Depends(require_token), db=Depend
{where} ORDER BY s.sale_date DESC NULLS LAST LIMIT 100
"""), params)
return {"sales": [dict(r) for r in rows.mappings()]}
# Parametric catch-all LAST so it doesn't swallow /settings, /customers, /past, /discounts
# (FastAPI matches by registration order; "/{sale_id}" regex matches any single segment).
@router.get("/{sale_id}")
async def sale_detail(sale_id: int, ident=Depends(require_token), db=Depends(get_db)):
s, items, cust = await _load_sale(db, sale_id)
return {"sale": s, "items": items, "customer": cust}