from typing import Literal from fastapi import APIRouter, Depends, HTTPException, Query from psycopg import AsyncConnection from pydantic import BaseModel, Field from mm_api.db import get_conn from mm_api.dependencies import current_user import mm_api.services.official as svc import mm_api.services.permission as perm_svc router = APIRouter(tags=["officials"]) async def _require_profile_perm(action: str, user: dict, conn: AsyncConnection): if not await perm_svc.can(conn, user["id"], action, "profile", is_admin=True): raise HTTPException(403, "Yetersiz yetki") class PersonCreate(BaseModel): first_name: str = Field(..., min_length=1, max_length=100) last_name: str = Field(..., min_length=1, max_length=100) birth_year: int | None = Field(None, ge=1900, le=2010) class PersonUpdate(BaseModel): first_name: str | None = Field(None, min_length=1, max_length=100) last_name: str | None = Field(None, min_length=1, max_length=100) birth_year: int | None = Field(None, ge=1900, le=2010) class ElectionCreate(BaseModel): name: str = Field(..., min_length=2, max_length=200) held_at: str # YYYY-MM-DD type: Literal["genel", "yerel", "cumhurbaskanligi", "referandum"] class OfficialCreate(BaseModel): person_id: int unit_id: int title: str = Field(..., min_length=2, max_length=200) started_at: str # YYYY-MM-DD election_id: int | None = None class OfficialClose(BaseModel): ended_at: str # YYYY-MM-DD # --- Persons --- @router.get("/persons") async def list_persons( q: str | None = Query(None), limit: int = Query(20, ge=1, le=100), offset: int = Query(0, ge=0), conn: AsyncConnection = Depends(get_conn), ): return await svc.list_persons(conn, q, limit, offset) @router.get("/persons/{person_id}") async def get_person( person_id: int, conn: AsyncConnection = Depends(get_conn), ): person = await svc.get_person(conn, person_id) if not person: raise HTTPException(404, "Kişi bulunamadı") officials = await svc.get_person_officials(conn, person_id) return {**person, "officials": officials} @router.post("/persons", status_code=201) async def create_person( data: PersonCreate, user: dict = Depends(current_user), conn: AsyncConnection = Depends(get_conn), ): await _require_profile_perm("create", user, conn) return await svc.create_person(conn, data.first_name, data.last_name, data.birth_year) @router.patch("/persons/{person_id}") async def update_person( person_id: int, data: PersonUpdate, user: dict = Depends(current_user), conn: AsyncConnection = Depends(get_conn), ): await _require_profile_perm("update", user, conn) person = await svc.get_person(conn, person_id) if not person: raise HTTPException(404, "Kişi bulunamadı") try: return await svc.update_person(conn, person_id, data.first_name, data.last_name, data.birth_year) except ValueError as e: raise HTTPException(400, str(e)) # --- Elections --- @router.get("/elections") async def list_elections(conn: AsyncConnection = Depends(get_conn)): return await svc.list_elections(conn) @router.post("/elections", status_code=201) async def create_election( data: ElectionCreate, user: dict = Depends(current_user), conn: AsyncConnection = Depends(get_conn), ): await _require_profile_perm("create", user, conn) return await svc.create_election(conn, data.name, data.held_at, data.type) # --- Officials --- @router.get("/officials") async def list_officials( person_id: int | None = Query(None), unit_id: int | None = Query(None), active_only: bool = Query(False), limit: int = Query(20, ge=1, le=100), offset: int = Query(0, ge=0), conn: AsyncConnection = Depends(get_conn), ): return await svc.list_officials(conn, person_id, unit_id, active_only, limit, offset) @router.get("/officials/{official_id}") async def get_official( official_id: int, conn: AsyncConnection = Depends(get_conn), ): official = await svc.get_official(conn, official_id) if not official: raise HTTPException(404, "Yetkili kaydı bulunamadı") stats = await svc.get_official_stats(conn, official_id) return {**official, "stats": stats} @router.post("/officials", status_code=201) async def create_official( data: OfficialCreate, user: dict = Depends(current_user), conn: AsyncConnection = Depends(get_conn), ): await _require_profile_perm("create", user, conn) try: return await svc.create_official(conn, data.person_id, data.unit_id, data.title, data.started_at, data.election_id) except ValueError as e: raise HTTPException(400, str(e)) @router.post("/officials/{official_id}/close") async def close_official( official_id: int, data: OfficialClose, user: dict = Depends(current_user), conn: AsyncConnection = Depends(get_conn), ): await _require_profile_perm("update", user, conn) try: return await svc.close_official(conn, official_id, data.ended_at) except ValueError as e: raise HTTPException(400, str(e))