CC4 sub1: add missing v2 listing/discovery endpoints + fix kategorizirani SQL
- GET /api/v2/klubovi (v2 alias for /api/klubovi listing) - GET /api/v2/savezi (v2 alias for /api/savezi listing) - GET /api/v2/sport[/] (namespace discovery index) - FIX /api/v2/kategorizirani/list (column alias used in WHERE -> 500 -> 200) Source audit: _audit/audit_20260505_023639/errors.json Smoke (anon+auth+public): 200 OK on all five endpoints. Backup: _backups/r3_cc4/pgz_sport_v2_router.py.bak.1777962063
This commit is contained in:
+75
-1
@@ -3087,7 +3087,7 @@ import json
|
||||
# ═══ HOO KATEGORIZIRANI SPORTAŠI ═══
|
||||
@router.get("/kategorizirani/list")
|
||||
def list_kategorizirani(kategorija: Optional[str] = None, sport: Optional[str] = None):
|
||||
where = ["c.kategorija_hoo AS hoo_kategorija IS NOT NULL"]; params = []
|
||||
where = ["c.hoo_kategorija IS NOT NULL"]; params = []
|
||||
if kategorija: where.append("c.hoo_kategorija=%s"); params.append(kategorija)
|
||||
if sport: where.append("LOWER(c.sport)=LOWER(%s)"); params.append(sport)
|
||||
sql = f"""SELECT c.id, c.ime, c.prezime, c.hoo_kategorija, c.sport,
|
||||
@@ -5348,3 +5348,77 @@ def graph_3d_iframe(min_orgs: int = 2, top_n: int = 100, sport: str = ""):
|
||||
return f.read()
|
||||
return "<h1>3D iframe not found</h1>"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# CC4-Sub1 (05.05.2026) — fill audit gaps: /api/v2/{klubovi,savezi,sport/}
|
||||
# Author: cc4-sub1@rinet.one
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@router.get("/klubovi")
|
||||
def v2_klubovi_list(q: Optional[str] = None, savez_id: Optional[int] = None,
|
||||
sport: Optional[str] = None, grad: Optional[str] = None,
|
||||
limit: int = 500):
|
||||
"""v2 alias for /api/klubovi — minimal listing for portal/CRM panels."""
|
||||
where = ["aktivan"]
|
||||
params: List[Any] = []
|
||||
if q:
|
||||
where.append("(naziv ILIKE %s OR oib ILIKE %s OR sport ILIKE %s)")
|
||||
params.extend([f"%{q}%", f"%{q}%", f"%{q}%"])
|
||||
if savez_id:
|
||||
where.append("savez_id=%s"); params.append(savez_id)
|
||||
if sport:
|
||||
where.append("sport ILIKE %s"); params.append(f"%{sport}%")
|
||||
if grad:
|
||||
where.append("grad ILIKE %s"); params.append(f"%{grad}%")
|
||||
params.append(max(1, min(limit, 2000)))
|
||||
sql = f"""SELECT id, naziv, oib, sport, grad, savez_id,
|
||||
region, broj_clanova, predsjednik, email, telefon, web
|
||||
FROM pgz_sport.klubovi
|
||||
WHERE {' AND '.join(where)}
|
||||
ORDER BY naziv COLLATE "hr-HR-x-icu"
|
||||
LIMIT %s"""
|
||||
rows = db_query(sql, params)
|
||||
return {"ok": True, "count": len(rows), "rows": rows}
|
||||
|
||||
|
||||
@router.get("/savezi")
|
||||
def v2_savezi_list(q: Optional[str] = None, razina: Optional[str] = None,
|
||||
sport: Optional[str] = None, limit: int = 500):
|
||||
"""v2 alias for /api/savezi — minimal listing."""
|
||||
where = ["aktivan"]
|
||||
params: List[Any] = []
|
||||
if q:
|
||||
where.append("(naziv ILIKE %s OR sport ILIKE %s)")
|
||||
params.extend([f"%{q}%", f"%{q}%"])
|
||||
if razina:
|
||||
where.append("razina = %s"); params.append(razina)
|
||||
if sport:
|
||||
where.append("sport ILIKE %s"); params.append(f"%{sport}%")
|
||||
params.append(max(1, min(limit, 2000)))
|
||||
sql = f"""SELECT id, naziv, sport, razina, sjediste_zupanija,
|
||||
godina_osnutka, predsjednik, email, web,
|
||||
(SELECT COUNT(*) FROM pgz_sport.klubovi WHERE savez_id=s.id) AS broj_klubova
|
||||
FROM pgz_sport.savezi s
|
||||
WHERE {' AND '.join(where)}
|
||||
ORDER BY naziv COLLATE "hr-HR-x-icu"
|
||||
LIMIT %s"""
|
||||
rows = db_query(sql, params)
|
||||
return {"ok": True, "count": len(rows), "rows": rows}
|
||||
|
||||
|
||||
@router.get("/sport")
|
||||
@router.get("/sport/")
|
||||
def v2_sport_index():
|
||||
"""v2 sport index — discovery endpoint listing sport-related sub-routes."""
|
||||
return {
|
||||
"ok": True,
|
||||
"service": "pgz_sport v2 sport namespace",
|
||||
"endpoints": {
|
||||
"GET /api/v2/sport/svi/stats": "all-sports aggregate stats",
|
||||
"GET /api/v2/sport/{sport_naziv}/pregled": "drill-down per-sport view",
|
||||
"POST /api/v2/sport/ask": "RAG sport agent (Q&A)",
|
||||
"POST /api/v2/sport/lawyer": "RAG legal/regulation agent",
|
||||
"GET /api/v2/sport/objekti": "sport facilities listing",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user