from __future__ import annotations from fastapi import APIRouter, Body, Depends from typing import Any from app.api.v1.endpoints.platform import ok, fail from app.db.platform_store import get_platform_store from app.core.auth import get_current_user, is_admin router = APIRouter(prefix="/approvals", tags=["approval"]) @router.get("/templates") def list_templates(current_user: dict = Depends(get_current_user)) -> dict[str, Any]: return ok(get_platform_store().approval_templates()) @router.post("/templates") def create_template(payload: dict[str, Any] = Body(...), current_user: dict = Depends(get_current_user)) -> dict[str, Any]: if not is_admin(current_user): raise fail(403, "admin permission required") if not payload.get("name"): raise fail(400, "name 必填") return ok(get_platform_store().create_approval_template(payload)) @router.get("/templates/{template_id}") def get_template(template_id: str) -> dict[str, Any]: try: return ok(get_platform_store().approval_template(template_id)) except KeyError: raise fail(404, "template not found") @router.put("/templates/{template_id}") def update_template(template_id: str, payload: dict[str, Any] = Body(...), current_user: dict = Depends(get_current_user)) -> dict[str, Any]: if not is_admin(current_user): raise fail(403, "admin permission required") try: return ok(get_platform_store().update_approval_template(template_id, payload)) except KeyError: raise fail(404, "template not found") @router.delete("/templates/{template_id}") def delete_template(template_id: str, current_user: dict = Depends(get_current_user)) -> dict[str, Any]: if not is_admin(current_user): raise fail(403, "admin permission required") try: return ok(get_platform_store().delete_approval_template(template_id)) except KeyError: raise fail(404, "template not found") @router.get("") def list_instances(status: str | None = None, current_user: dict = Depends(get_current_user)) -> dict[str, Any]: items = get_platform_store().approval_instances(status=status) return ok(items if is_admin(current_user) else [item for item in items if item.get("applicant_id") == current_user.get("id")]) @router.post("") def create_instance(payload: dict[str, Any] = Body(...), current_user: dict = Depends(get_current_user)) -> dict[str, Any]: payload["applicant_id"] = current_user.get("id") for field in ("resource_type", "resource_id"): if not payload.get(field): raise fail(400, f"{field} 必填") try: return ok(get_platform_store().create_approval_instance(payload)) except KeyError: raise fail(404, "template not found") @router.get("/{instance_id}") def get_instance(instance_id: str, current_user: dict = Depends(get_current_user)) -> dict[str, Any]: try: item = get_platform_store().approval_instance(instance_id) if not is_admin(current_user) and item.get("applicant_id") != current_user.get("id"): raise fail(403, "no permission to access approval") return ok(item) except KeyError: raise fail(404, "instance not found") @router.post("/{instance_id}/steps/{step_index}/decision") def decide( instance_id: str, step_index: int, payload: dict[str, Any] = Body(...), ) -> dict[str, Any]: if not payload.get("approver_id"): raise fail(400, "approver_id 必填") try: return ok( get_platform_store().decide_approval_step( instance_id, step_index, approver_id=payload["approver_id"], approved=bool(payload.get("approved", False)), comment=payload.get("comment"), ) ) except (KeyError, ValueError) as e: raise fail(400, str(e))