"""Users — profile + role assignment (v2.6, Casdoor-backed). GET /users/me — the caller's profile: role, PM's project, display name. PATCH /users/{id} — assign role (admin only). """ from fastapi import APIRouter, Depends from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.auth import UserContext, get_current_user, require_role from app.db.engine import get_db from app.models.procurement import Project, User from app.schemas.procurement import UserRoleUpdate from app.utils.errors import NotFoundError from app.utils.serialization import to_iso router = APIRouter(prefix="/users", tags=["users"]) USER_ROLE_LABELS = { "pm": "مدیر پروژه", "procurement_manager": "مدیر تدارکات", "admin": "ادمین", } def user_to_dict(user: User, project: Project | None = None) -> dict: return { "id": str(user.id), "casdoor_id": user.casdoor_id, "first_name": user.first_name, "last_name": user.last_name, "phone": user.phone, "role": user.role, "role_label": USER_ROLE_LABELS.get(user.role) if user.role else None, "project_id": str(project.id) if project else None, "project_name": project.name if project else None, "created_at": to_iso(user.created_at), } @router.get("/me") async def me(ctx: UserContext = Depends(get_current_user), db: AsyncSession = Depends(get_db)): project = await db.scalar(select(Project).where(Project.pm_user_id == ctx.user.id)) if ctx.role == "pm" else None return {"data": user_to_dict(ctx.user, project)} @router.patch("/{user_id}") async def update_user_role( user_id, payload: UserRoleUpdate, _: UserContext = Depends(require_role("admin")), db: AsyncSession = Depends(get_db), ): user = await db.get(User, user_id) if user is None: raise NotFoundError("کاربر یافت نشد") user.role = payload.role await db.flush() project = await db.scalar(select(Project).where(Project.pm_user_id == user.id)) if user.role == "pm" else None return {"data": user_to_dict(user, project)}