from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from ..db import get_session from ..dependencies import AuthUser, get_current_user from ..models import Job, JobItem, JobStatus, JobType from ..schemas import JobItemOut, JobListResponse, JobOut router = APIRouter(prefix="/api/v1/jobs", tags=["jobs"]) @router.get("", response_model=JobListResponse) async def list_jobs( status_filter: Optional[JobStatus] = None, job_type: Optional[JobType] = None, offset: int = 0, limit: int = 20, session: AsyncSession = Depends(get_session), auth_user: AuthUser = Depends(get_current_user), ) -> JobListResponse: query = select(Job).order_by(Job.created_at.desc()) if auth_user.role_name != "ADMIN": query = query.where(Job.created_for_customer == auth_user.customer_id) if status_filter: query = query.where(Job.status == status_filter) if job_type: query = query.where(Job.job_type == job_type) total_query = select(func.count()).select_from(query.subquery()) total = await session.scalar(total_query) jobs = (await session.scalars(query.offset(offset).limit(limit))).all() return JobListResponse(items=[JobOut.model_validate(j) for j in jobs], total=total or len(jobs)) @router.get("/{job_uuid}", response_model=JobOut) async def get_job_detail( job_uuid: str, session: AsyncSession = Depends(get_session), auth_user: AuthUser = Depends(get_current_user), ) -> JobOut: job = await session.scalar(select(Job).where(Job.job_uuid == job_uuid)) if not job: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Job not found") if auth_user.role_name != "ADMIN" and job.created_for_customer != auth_user.customer_id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden") return JobOut.model_validate(job) @router.get("/{job_uuid}/items", response_model=List[JobItemOut]) async def list_job_items( job_uuid: str, session: AsyncSession = Depends(get_session), auth_user: AuthUser = Depends(get_current_user), ) -> List[JobItemOut]: job = await session.scalar(select(Job).where(Job.job_uuid == job_uuid)) if not job: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Job not found") if auth_user.role_name != "ADMIN" and job.created_for_customer != auth_user.customer_id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden") items = ( await session.scalars( select(JobItem) .where(JobItem.job_id == job.id) .options(selectinload(JobItem.instance)) .order_by(JobItem.id.asc()) ) ).all() return [JobItemOut.model_validate(i) for i in items]