""" 리비전 상태 관리 API 엔드포인트 """ from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from typing import Optional from pydantic import BaseModel from ..database import get_db from ..auth.middleware import get_current_user from ..services.revision_status_service import RevisionStatusService from ..auth.models import User from ..utils.logger import get_logger logger = get_logger(__name__) router = APIRouter(prefix="/revision-status", tags=["Revision Status"]) class CreateComparisonRequest(BaseModel): job_no: str current_file_id: int previous_file_id: int comparison_result: dict class RejectComparisonRequest(BaseModel): reason: str = "" @router.get("/{job_no}/{file_id}") async def get_revision_status( job_no: str, file_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 리비전 상태 조회 """ try: status_service = RevisionStatusService(db) revision_status = status_service.get_revision_status(job_no, file_id) if "error" in revision_status: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=revision_status["error"] ) logger.info(f"Retrieved revision status for {job_no}/{file_id}") return { "success": True, "data": revision_status, "message": "리비전 상태 조회 완료" } except HTTPException: raise except Exception as e: logger.error(f"Failed to get revision status: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"리비전 상태 조회 중 오류가 발생했습니다: {str(e)}" ) @router.get("/history/{job_no}") async def get_revision_history( job_no: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 작업의 전체 리비전 히스토리 조회 """ try: status_service = RevisionStatusService(db) history = status_service.get_revision_history(job_no) logger.info(f"Retrieved revision history for {job_no}: {len(history)} revisions") return { "success": True, "data": history, "message": "리비전 히스토리 조회 완료" } except Exception as e: logger.error(f"Failed to get revision history: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"리비전 히스토리 조회 중 오류가 발생했습니다: {str(e)}" ) @router.post("/create-comparison") async def create_comparison_record( request: CreateComparisonRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 리비전 비교 기록 생성 """ try: status_service = RevisionStatusService(db) comparison_id = status_service.create_revision_comparison_record( job_no=request.job_no, current_file_id=request.current_file_id, previous_file_id=request.previous_file_id, comparison_result=request.comparison_result, created_by=current_user.username ) logger.info(f"Created revision comparison record: {comparison_id}") return { "success": True, "data": {"comparison_id": comparison_id}, "message": "리비전 비교 기록 생성 완료" } except Exception as e: logger.error(f"Failed to create comparison record: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"비교 기록 생성 중 오류가 발생했습니다: {str(e)}" ) @router.post("/apply-comparison/{comparison_id}") async def apply_comparison( comparison_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 리비전 비교 결과 적용 """ try: status_service = RevisionStatusService(db) apply_result = status_service.apply_revision_comparison( comparison_id=comparison_id, applied_by=current_user.username ) if not apply_result["success"]: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=apply_result["error"] ) logger.info(f"Applied revision comparison: {comparison_id}") return { "success": True, "data": apply_result, "message": "리비전 비교 결과 적용 완료" } except HTTPException: raise except Exception as e: logger.error(f"Failed to apply comparison {comparison_id}: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"비교 결과 적용 중 오류가 발생했습니다: {str(e)}" ) @router.get("/pending") async def get_pending_revisions( job_no: Optional[str] = Query(None, description="특정 작업의 대기 중인 리비전만 조회"), db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 대기 중인 리비전 목록 조회 """ try: status_service = RevisionStatusService(db) pending_revisions = status_service.get_pending_revisions(job_no) logger.info(f"Retrieved {len(pending_revisions)} pending revisions") return { "success": True, "data": pending_revisions, "message": "대기 중인 리비전 조회 완료" } except Exception as e: logger.error(f"Failed to get pending revisions: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"대기 중인 리비전 조회 중 오류가 발생했습니다: {str(e)}" ) @router.post("/reject-comparison/{comparison_id}") async def reject_comparison( comparison_id: int, request: RejectComparisonRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """ 리비전 비교 결과 거부 """ try: # 비교 기록을 거부 상태로 업데이트 update_query = """ UPDATE revision_comparisons SET is_applied = false, notes = CONCAT(COALESCE(notes, ''), '\n거부됨: ', :reason, ' (by ', :rejected_by, ')') WHERE id = :comparison_id """ from ..services.database_service import DatabaseService db_service = DatabaseService(db) db_service.execute_query(update_query, { "comparison_id": comparison_id, "reason": request.reason or "사유 없음", "rejected_by": current_user.username }) db.commit() logger.info(f"Rejected revision comparison: {comparison_id}") return { "success": True, "data": {"comparison_id": comparison_id, "reason": request.reason}, "message": "리비전 비교 결과 거부 완료" } except Exception as e: logger.error(f"Failed to reject comparison {comparison_id}: {e}") db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"비교 결과 거부 중 오류가 발생했습니다: {str(e)}" )