""" 간단한 리비전 관리 API - 리비전 세션 생성 및 관리 - 자재 비교 및 변경사항 처리 """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from sqlalchemy import text from typing import List, Optional, Dict, Any from datetime import datetime from pydantic import BaseModel from ..database import get_db from ..auth.middleware import get_current_user from ..services.revision_session_service import RevisionSessionService from ..services.revision_comparison_service import RevisionComparisonService router = APIRouter(prefix="/revision-management", tags=["revision-management"]) class RevisionSessionCreate(BaseModel): job_no: str current_file_id: int previous_file_id: int @router.post("/sessions") async def create_revision_session( session_data: RevisionSessionCreate, current_user: dict = Depends(get_current_user), db: Session = Depends(get_db) ): """리비전 세션 생성""" try: session_service = RevisionSessionService(db) # 실제 DB에 세션 생성 result = session_service.create_revision_session( job_no=session_data.job_no, current_file_id=session_data.current_file_id, previous_file_id=session_data.previous_file_id, username=current_user.get("username") ) return { "success": True, "data": result, "message": "리비전 세션이 생성되었습니다." } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 세션 생성 실패: {str(e)}") @router.get("/sessions/{session_id}") async def get_session_status( session_id: int, db: Session = Depends(get_db) ): """세션 상태 조회""" try: session_service = RevisionSessionService(db) # 실제 DB에서 세션 상태 조회 result = session_service.get_session_status(session_id) return { "success": True, "data": result } except Exception as e: raise HTTPException(status_code=500, detail=f"세션 상태 조회 실패: {str(e)}") @router.get("/sessions/{session_id}/summary") async def get_revision_summary( session_id: int, db: Session = Depends(get_db) ): """리비전 요약 조회""" try: comparison_service = RevisionComparisonService(db) # 세션의 모든 변경사항 조회 changes = comparison_service.get_session_changes(session_id) # 요약 통계 계산 summary = { "session_id": session_id, "total_changes": len(changes), "new_materials": len([c for c in changes if c['change_type'] == 'added']), "changed_materials": len([c for c in changes if c['change_type'] == 'quantity_changed']), "removed_materials": len([c for c in changes if c['change_type'] == 'removed']), "categories": {} } # 카테고리별 통계 for change in changes: category = change['category'] if category not in summary["categories"]: summary["categories"][category] = { "total_changes": 0, "added": 0, "changed": 0, "removed": 0 } summary["categories"][category]["total_changes"] += 1 if change['change_type'] == 'added': summary["categories"][category]["added"] += 1 elif change['change_type'] == 'quantity_changed': summary["categories"][category]["changed"] += 1 elif change['change_type'] == 'removed': summary["categories"][category]["removed"] += 1 return { "success": True, "data": summary } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 요약 조회 실패: {str(e)}") @router.post("/sessions/{session_id}/compare/{category}") async def compare_category( session_id: int, category: str, db: Session = Depends(get_db) ): """카테고리별 자재 비교""" try: # 세션 정보 조회 session_service = RevisionSessionService(db) session_status = session_service.get_session_status(session_id) session_info = session_status["session_info"] # 자재 비교 수행 comparison_service = RevisionComparisonService(db) result = comparison_service.compare_materials_by_category( current_file_id=session_info["current_file_id"], previous_file_id=session_info["previous_file_id"], category=category, session_id=session_id ) return { "success": True, "data": result } except Exception as e: raise HTTPException(status_code=500, detail=f"카테고리 비교 실패: {str(e)}") @router.get("/history/{job_no}") async def get_revision_history( job_no: str, db: Session = Depends(get_db) ): """리비전 히스토리 조회""" try: session_service = RevisionSessionService(db) # 실제 DB에서 리비전 히스토리 조회 history = session_service.get_job_revision_history(job_no) return { "success": True, "data": { "job_no": job_no, "history": history } } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 히스토리 조회 실패: {str(e)}") # 세션 변경사항 조회 @router.get("/sessions/{session_id}/changes") async def get_session_changes( session_id: int, category: Optional[str] = Query(None), db: Session = Depends(get_db) ): """세션의 변경사항 조회""" try: comparison_service = RevisionComparisonService(db) # 세션의 변경사항 조회 changes = comparison_service.get_session_changes(session_id, category) return { "success": True, "data": { "changes": changes, "total_count": len(changes) } } except Exception as e: raise HTTPException(status_code=500, detail=f"세션 변경사항 조회 실패: {str(e)}") # 리비전 액션 처리 @router.post("/changes/{change_id}/process") async def process_revision_action( change_id: int, action_data: Dict[str, Any], current_user: dict = Depends(get_current_user), db: Session = Depends(get_db) ): """리비전 액션 처리""" try: comparison_service = RevisionComparisonService(db) # 액션 처리 result = comparison_service.process_revision_action( change_id=change_id, action=action_data.get("action"), username=current_user.get("username"), notes=action_data.get("notes") ) return { "success": True, "data": result } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 액션 처리 실패: {str(e)}") # 세션 완료 @router.post("/sessions/{session_id}/complete") async def complete_revision_session( session_id: int, current_user: dict = Depends(get_current_user), db: Session = Depends(get_db) ): """리비전 세션 완료""" try: session_service = RevisionSessionService(db) # 세션 완료 처리 result = session_service.complete_session( session_id=session_id, username=current_user.get("username") ) return { "success": True, "data": result } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 세션 완료 실패: {str(e)}") # 세션 취소 @router.post("/sessions/{session_id}/cancel") async def cancel_revision_session( session_id: int, reason: Optional[str] = Query(None), current_user: dict = Depends(get_current_user), db: Session = Depends(get_db) ): """리비전 세션 취소""" try: session_service = RevisionSessionService(db) # 세션 취소 처리 result = session_service.cancel_session( session_id=session_id, username=current_user.get("username"), reason=reason ) return { "success": True, "data": {"cancelled": result} } except Exception as e: raise HTTPException(status_code=500, detail=f"리비전 세션 취소 실패: {str(e)}") @router.get("/categories") async def get_supported_categories(): """지원 카테고리 목록 조회""" try: categories = [ {"key": "PIPE", "name": "배관", "description": "파이프 및 배관 자재"}, {"key": "FITTING", "name": "피팅", "description": "배관 연결 부품"}, {"key": "FLANGE", "name": "플랜지", "description": "플랜지 및 연결 부품"}, {"key": "VALVE", "name": "밸브", "description": "각종 밸브류"}, {"key": "GASKET", "name": "가스켓", "description": "씰링 부품"}, {"key": "BOLT", "name": "볼트", "description": "체결 부품"}, {"key": "SUPPORT", "name": "서포트", "description": "지지대 및 구조물"}, {"key": "SPECIAL", "name": "특수자재", "description": "특수 목적 자재"}, {"key": "UNCLASSIFIED", "name": "미분류", "description": "분류되지 않은 자재"} ] return { "success": True, "data": { "categories": categories } } except Exception as e: raise HTTPException(status_code=500, detail=f"지원 카테고리 조회 실패: {str(e)}") @router.get("/actions") async def get_supported_actions(): """지원 액션 목록 조회""" try: actions = [ {"key": "new_material", "name": "신규 자재", "description": "새로 추가된 자재"}, {"key": "additional_purchase", "name": "추가 구매", "description": "구매된 자재의 수량 증가"}, {"key": "inventory_transfer", "name": "재고 이관", "description": "구매된 자재의 수량 감소 또는 제거"}, {"key": "purchase_cancel", "name": "구매 취소", "description": "미구매 자재의 제거"}, {"key": "quantity_update", "name": "수량 업데이트", "description": "미구매 자재의 수량 변경"}, {"key": "maintain", "name": "유지", "description": "변경사항 없음"} ] return { "success": True, "data": { "actions": actions } } except Exception as e: raise HTTPException(status_code=500, detail=f"지원 액션 조회 실패: {str(e)}")