2025-12-10 12:02:17 +08:00

73 lines
2.8 KiB
Python

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]