from __future__ import annotations import uuid from fastapi import APIRouter, Depends, HTTPException, Response, status from sqlalchemy.ext.asyncio import AsyncSession from cpv3.infrastructure.auth import get_current_user from cpv3.db.session import get_db from cpv3.modules.jobs.schemas import ( JobCreate, JobEventCreate, JobEventRead, JobEventUpdate, JobRead, JobUpdate, ) from cpv3.modules.jobs.service import JobService from cpv3.modules.tasks.service import TaskService from cpv3.modules.users.models import User jobs_router = APIRouter(prefix="/api/jobs", tags=["jobs"]) events_router = APIRouter(prefix="/api/jobs", tags=["events"]) @jobs_router.get("/jobs/", response_model=list[JobRead]) async def list_jobs_endpoint( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> list[JobRead]: service = JobService(db) jobs = await service.list_jobs(requester=current_user) return [JobRead.model_validate(j) for j in jobs] @jobs_router.post("/jobs/", response_model=JobRead, status_code=status.HTTP_201_CREATED) async def create_job_endpoint( body: JobCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobRead: service = JobService(db) job = await service.create_job(requester=current_user, data=body) return JobRead.model_validate(job) @jobs_router.get("/jobs/{job_id}/", response_model=JobRead) async def retrieve_job_endpoint( job_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobRead: service = JobService(db) job = await service.get_job(job_id) if job is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") if not current_user.is_staff and job.user_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Доступ запрещён") return JobRead.model_validate(job) @jobs_router.patch("/jobs/{job_id}/", response_model=JobRead) async def patch_job_endpoint( job_id: uuid.UUID, body: JobUpdate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobRead: service = JobService(db) job = await service.get_job(job_id) if job is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") if not current_user.is_staff and job.user_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Доступ запрещён") if body.status == "CANCELLED": task_service = TaskService(db) job = await task_service.cancel_job(job) return JobRead.model_validate(job) job = await service.update_job(job, body) return JobRead.model_validate(job) @jobs_router.delete("/jobs/{job_id}/", status_code=status.HTTP_204_NO_CONTENT) async def delete_job_endpoint( job_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> Response: service = JobService(db) job = await service.get_job(job_id) if job is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") if not current_user.is_staff and job.user_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Доступ запрещён") await service.deactivate_job(job) return Response(status_code=status.HTTP_204_NO_CONTENT) @events_router.get("/events/", response_model=list[JobEventRead]) async def list_events_endpoint( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> list[JobEventRead]: _ = current_user service = JobService(db) events = await service.list_job_events() return [JobEventRead.model_validate(e) for e in events] @events_router.post("/events/", response_model=JobEventRead, status_code=status.HTTP_201_CREATED) async def create_event_endpoint( body: JobEventCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobEventRead: _ = current_user service = JobService(db) event = await service.create_job_event(body) return JobEventRead.model_validate(event) @events_router.get("/events/{event_id}/", response_model=JobEventRead) async def retrieve_event_endpoint( event_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobEventRead: _ = current_user service = JobService(db) event = await service.get_job_event(event_id) if event is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") return JobEventRead.model_validate(event) @events_router.patch("/events/{event_id}/", response_model=JobEventRead) async def patch_event_endpoint( event_id: uuid.UUID, body: JobEventUpdate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> JobEventRead: _ = current_user service = JobService(db) event = await service.get_job_event(event_id) if event is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") event = await service.update_job_event(event, body) return JobEventRead.model_validate(event) @events_router.delete("/events/{event_id}/", status_code=status.HTTP_204_NO_CONTENT) async def delete_event_endpoint( event_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> Response: _ = current_user service = JobService(db) event = await service.get_job_event(event_id) if event is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Не найдено") await service.deactivate_job_event(event) return Response(status_code=status.HTTP_204_NO_CONTENT)