from fastapi import APIRouter, Depends, Form, HTTPException, Request from fastapi.responses import RedirectResponse from anode_client import anode_request from auth import get_current_user from templating import templates router = APIRouter() def fetch_organisationseinheiten(organization_id: str) -> list[dict]: result = anode_request("GET", f"/api/v1/organizations/{organization_id}/organisationseinheiten") return result.get("organisationseinheiten", []) if result.get("success") else [] def find_oe_in_organization(oe_id: str, organization_id: str) -> dict | None: """ Besitz-Validierung analog zu find_device_in_organization() in routers/geraete.py (siehe ADR-0011): eine oe_id aus der URL wird nur akzeptiert, wenn sie tatsächlich in der OE-Liste der eigenen Organisation auftaucht. """ for oe in fetch_organisationseinheiten(organization_id): if oe["id"] == oe_id: return oe return None @router.get("/struktur") def struktur_ansicht(request: Request, user=Depends(get_current_user)): oes = fetch_organisationseinheiten(user.organization_id) return templates.TemplateResponse( request, "struktur.html", {"user": user, "organisationseinheiten": oes} ) @router.post("/struktur") def oe_anlegen( name: str = Form(...), parent_id: str = Form(default=""), user=Depends(get_current_user), ): anode_request( "POST", f"/api/v1/organizations/{user.organization_id}/organisationseinheiten", json={"name": name, "parent_id": parent_id or None}, ) return RedirectResponse("/struktur", status_code=303) @router.get("/struktur/{oe_id}/umbenennen") def oe_umbenennen_form(request: Request, oe_id: str, user=Depends(get_current_user)): oe = find_oe_in_organization(oe_id, user.organization_id) if oe is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") return templates.TemplateResponse(request, "struktur_umbenennen.html", {"user": user, "oe": oe}) @router.post("/struktur/{oe_id}/umbenennen") def oe_umbenennen(oe_id: str, name: str = Form(...), user=Depends(get_current_user)): oe = find_oe_in_organization(oe_id, user.organization_id) if oe is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") anode_request( "PATCH", f"/api/v1/organisationseinheiten/{oe_id}", json={"name": name, "parent_id": oe["parent_id"]}, ) return RedirectResponse("/struktur", status_code=303) @router.get("/struktur/{oe_id}/loeschen") def oe_loeschen_form(request: Request, oe_id: str, user=Depends(get_current_user)): oe = find_oe_in_organization(oe_id, user.organization_id) if oe is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") return templates.TemplateResponse(request, "struktur_loeschen.html", {"user": user, "oe": oe, "fehler": None}) @router.post("/struktur/{oe_id}/loeschen") def oe_loeschen(request: Request, oe_id: str, user=Depends(get_current_user)): oe = find_oe_in_organization(oe_id, user.organization_id) if oe is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") result = anode_request("DELETE", f"/api/v1/organisationseinheiten/{oe_id}") if not result.get("success"): return templates.TemplateResponse( request, "struktur_loeschen.html", {"user": user, "oe": oe, "fehler": result.get("message")} ) return RedirectResponse("/struktur", status_code=303) @router.get("/struktur/{oe_id}/merkmale") def oe_merkmale_ansicht(request: Request, oe_id: str, user=Depends(get_current_user)): oe = find_oe_in_organization(oe_id, user.organization_id) if oe is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") result = anode_request("GET", f"/api/v1/organisationseinheiten/{oe_id}/merkmale") merkmale = result.get("merkmale", []) if result.get("success") else [] kategorien: dict[str, list[dict]] = {} for eintrag in merkmale: kategorie_name = eintrag["kategorie"]["name"] if eintrag["kategorie"] else "Ohne Kategorie" kategorien.setdefault(kategorie_name, []).append(eintrag) return templates.TemplateResponse( request, "struktur_merkmale.html", {"user": user, "oe": oe, "kategorien": kategorien} ) @router.post("/struktur/{oe_id}/merkmale/{merkmal_key}/select") def oe_merkmal_select(oe_id: str, merkmal_key: str, user=Depends(get_current_user)): if find_oe_in_organization(oe_id, user.organization_id) is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") anode_request("POST", f"/api/v1/organisationseinheiten/{oe_id}/merkmale/{merkmal_key}/select") return RedirectResponse(f"/struktur/{oe_id}/merkmale", status_code=303) @router.post("/struktur/{oe_id}/merkmale/{merkmal_key}/deselect") def oe_merkmal_deselect(oe_id: str, merkmal_key: str, user=Depends(get_current_user)): if find_oe_in_organization(oe_id, user.organization_id) is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") anode_request("POST", f"/api/v1/organisationseinheiten/{oe_id}/merkmale/{merkmal_key}/deselect") return RedirectResponse(f"/struktur/{oe_id}/merkmale", status_code=303) @router.post("/struktur/{oe_id}/merkmale/{merkmal_key}/unset") def oe_merkmal_unset(oe_id: str, merkmal_key: str, user=Depends(get_current_user)): if find_oe_in_organization(oe_id, user.organization_id) is None: raise HTTPException(status_code=404, detail="OE wurde nicht gefunden.") anode_request("POST", f"/api/v1/organisationseinheiten/{oe_id}/merkmale/{merkmal_key}/unset") return RedirectResponse(f"/struktur/{oe_id}/merkmale", status_code=303)