from datetime import datetime, timezone from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db, get_current_user from app.models.user import User from app.models.project import Project from app.models.generation_record import GenerationRecord from app.schemas.project import ProjectCreate, ProjectOut from app.services.resource_accounting_service import soft_delete_generation_record_resources from app.utils.id_gen import generate_id router = APIRouter(prefix="/projects", tags=["projects"]) @router.get("", response_model=list[ProjectOut]) async def list_projects( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(Project) .where( Project.user_id == current_user.id, Project.deleted_at.is_(None), ) .order_by(Project.created_at.desc()) ) return result.scalars().all() @router.post("", response_model=ProjectOut) async def create_project( req: ProjectCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): project = Project( id=generate_id(), user_id=current_user.id, name=req.name, industry=req.industry, ) db.add(project) await db.flush() return project @router.delete("/{project_id}") async def delete_project( project_id: str, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(Project).where( Project.id == project_id, Project.user_id == current_user.id, Project.deleted_at.is_(None), ) ) project = result.scalar_one_or_none() if not project: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="项目不存在") generating_count = ( await db.execute( select(func.count(GenerationRecord.id)).where( GenerationRecord.project_id == project_id, GenerationRecord.user_id == current_user.id, GenerationRecord.status == "generating", GenerationRecord.deleted_at.is_(None), ) ) ).scalar() or 0 if generating_count > 0: raise HTTPException(status_code=400, detail="当前项目下存在生成中任务,暂不能删除") records_result = await db.execute( select(GenerationRecord).where( GenerationRecord.project_id == project_id, GenerationRecord.user_id == current_user.id, GenerationRecord.deleted_at.is_(None), ) ) records = list(records_result.scalars().all()) record_ids = [record.id for record in records] now = datetime.now(timezone.utc) project.deleted_at = now for record in records: record.deleted_at = now freed_size_bytes = await soft_delete_generation_record_resources( db, record_ids, deleted_at=now, ) await db.flush() return { "message": "ok", "project_id": project_id, "deleted": True, "deleted_records": len(record_ids), "freed_size_bytes": freed_size_bytes, }