"""Endpoints для проектов.""" import logging from typing import Any from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, desc from app.core.database import get_db from app.core.security import get_current_user from app.schemas.project import ProjectCreate, ProjectUpdate, ProjectResponse from app.models.user import User from app.models.project import Project logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/projects", tags=["projects"]) @router.post("", response_model=ProjectResponse) async def create_project(data: ProjectCreate, db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)): """Создать новый проект.""" project = Project( client_id=user["id"], title=data.title, description=data.description, category=data.category, required_skills=data.required_skills, budget_min=data.budget_min, budget_max=data.budget_max, deadline=data.deadline, ) db.add(project) await db.commit() await db.refresh(project) return ProjectResponse( id=str(project.id), title=project.title, description=project.description, category=project.category, required_skills=project.required_skills, budget_min=float(project.budget_min) if project.budget_min else None, budget_max=float(project.budget_max) if project.budget_max else None, status=project.status, deadline=str(project.deadline) if project.deadline else None, created_at=str(project.created_at), updated_at=str(project.updated_at), ) @router.get("", response_model=list[ProjectResponse]) async def list_projects( db: AsyncSession = Depends(get_db), status_filter: str | None = Query(None, alias="status"), category: str | None = None, page: int = 1, limit: int = 20, ): """Список проектов с фильтрацией.""" stmt = select(Project) if status_filter: stmt = stmt.where(Project.status == status_filter) if category: stmt = stmt.where(Project.category == category) stmt = stmt.order_by(desc(Project.created_at)).offset((page - 1) * limit).limit(limit) result = await db.execute(stmt) projects = result.scalars().all() return [ProjectResponse( id=str(p.id), title=p.title, description=p.description, category=p.category, required_skills=p.required_skills, budget_min=float(p.budget_min) if p.budget_min else None, budget_max=float(p.budget_max) if p.budget_max else None, status=p.status, deadline=str(p.deadline) if p.deadline else None, created_at=str(p.created_at), updated_at=str(p.updated_at), ) for p in projects] @router.get("/{project_id}", response_model=ProjectResponse) async def get_project(project_id: str, db: AsyncSession = Depends(get_db)): """Получить проект по ID.""" result = await db.execute(select(Project).where(Project.id == project_id)) project = result.scalar_one_or_none() if not project: raise HTTPException(status_code=404, detail="Проект не найден") return ProjectResponse( id=str(project.id), title=project.title, description=project.description, category=project.category, required_skills=project.required_skills, budget_min=float(project.budget_min) if project.budget_min else None, budget_max=float(project.budget_max) if project.budget_max else None, status=project.status, deadline=str(project.deadline) if project.deadline else None, created_at=str(project.created_at), updated_at=str(project.updated_at), ) @router.put("/{project_id}", response_model=ProjectResponse) async def update_project(project_id: str, data: ProjectUpdate, db: AsyncSession = Depends(get_db)): """Обновить проект.""" result = await db.execute(select(Project).where(Project.id == project_id)) project = result.scalar_one_or_none() if not project: raise HTTPException(status_code=404, detail="Проект не найден") for field, value in data.model_dump(exclude_unset=True).items(): setattr(project, field, value) await db.commit() await db.refresh(project) return ProjectResponse( id=str(project.id), title=project.title, description=project.description, category=project.category, required_skills=project.required_skills, budget_min=float(project.budget_min) if project.budget_min else None, budget_max=float(project.budget_max) if project.budget_max else None, status=project.status, deadline=str(project.deadline) if project.deadline else None, created_at=str(project.created_at), updated_at=str(project.updated_at), )