feat(backend): add FastAPI backend — procurement, inventory domain, Casdoor auth, PM arrival endpoints

This commit is contained in:
ali_mohaghegh
2026-08-25 19:08:14 +03:30
parent c8a9b66395
commit 170aed66ea
67 changed files with 9774 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
"""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)}