from __future__ import annotations from typing import Annotated from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status from app.api.deps import CurrentUserContext, get_current_user from app.db.session import get_session_factory from app.schemas.attachment_association_job import ( AttachmentAssociationJobCreate, AttachmentAssociationJobRead, ) from app.schemas.common import ErrorResponse from app.services.attachment_association_jobs import ( create_attachment_association_job, get_attachment_association_job, run_attachment_association_job, ) router = APIRouter(prefix="/reimbursements/attachment-association-jobs") CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)] @router.post( "", response_model=AttachmentAssociationJobRead, status_code=status.HTTP_202_ACCEPTED, summary="创建附件自动关联后台任务", description="根据已 OCR 入票据夹的 receipt_id,在后台自动匹配并归集到报销草稿。", responses={ status.HTTP_400_BAD_REQUEST: { "model": ErrorResponse, "description": "请求缺少可关联票据。", }, }, ) def create_attachment_association_job_endpoint( payload: AttachmentAssociationJobCreate, background_tasks: BackgroundTasks, current_user: CurrentUser, ) -> AttachmentAssociationJobRead: try: job = create_attachment_association_job(payload, current_user) except ValueError as exc: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc background_tasks.add_task( run_attachment_association_job, job.job_id, current_user, get_session_factory(), ) return job @router.get( "/{job_id}", response_model=AttachmentAssociationJobRead, summary="查询附件自动关联后台任务", description="用于前端会话恢复后按 job_id 查询任务状态。", responses={ status.HTTP_404_NOT_FOUND: { "model": ErrorResponse, "description": "任务不存在或当前用户无权查看。", }, }, ) def get_attachment_association_job_endpoint( job_id: str, current_user: CurrentUser, ) -> AttachmentAssociationJobRead: job = get_attachment_association_job(job_id, current_user) if job is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="附件关联任务不存在或已失效。") return job