from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List, Optional from datetime import datetime from database.database import get_db from database.models import Issue, IssueStatus, User, UserRole from database import schemas from routers.auth import get_current_user, get_current_admin from routers.page_permissions import check_page_access from services.file_service import save_base64_image, delete_file router = APIRouter(prefix="/api/issues", tags=["issues"]) @router.post("/", response_model=schemas.Issue) async def create_issue( issue: schemas.IssueCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): print(f"DEBUG: 받은 issue 데이터: {issue}") print(f"DEBUG: project_id: {issue.project_id}") # 이미지 저장 photo_path = None photo_path2 = None if issue.photo: photo_path = save_base64_image(issue.photo) if issue.photo2: photo_path2 = save_base64_image(issue.photo2) # Issue 생성 db_issue = Issue( category=issue.category, description=issue.description, photo_path=photo_path, photo_path2=photo_path2, reporter_id=current_user.id, project_id=issue.project_id, status=IssueStatus.new ) db.add(db_issue) db.commit() db.refresh(db_issue) return db_issue @router.get("/", response_model=List[schemas.Issue]) async def read_issues( skip: int = 0, limit: int = 100, status: Optional[IssueStatus] = None, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): query = db.query(Issue) # 권한별 조회 제한 if current_user.role == UserRole.admin: # 관리자는 모든 이슈 조회 가능 pass else: # 일반 사용자는 본인이 등록한 이슈만 조회 가능 query = query.filter(Issue.reporter_id == current_user.id) if status: query = query.filter(Issue.status == status) # 최신순 정렬 (report_date 기준) issues = query.order_by(Issue.report_date.desc()).offset(skip).limit(limit).all() return issues @router.get("/admin/all", response_model=List[schemas.Issue]) async def read_all_issues_admin( skip: int = 0, limit: int = 100, status: Optional[IssueStatus] = None, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """이슈 관리 권한이 있는 사용자: 모든 부적합 조회""" # 이슈 관리 페이지 권한 확인 (관리함, 폐기함 등에서 사용) from routers.page_permissions import check_page_access # 관리자이거나 이슈 관리 권한이 있는 사용자만 접근 가능 if (current_user.role != 'admin' and not check_page_access(current_user.id, 'issues_manage', db) and not check_page_access(current_user.id, 'issues_inbox', db) and not check_page_access(current_user.id, 'issues_management', db) and not check_page_access(current_user.id, 'issues_archive', db)): raise HTTPException(status_code=403, detail="이슈 관리 권한이 없습니다.") query = db.query(Issue) if status: query = query.filter(Issue.status == status) # 최신순 정렬 (report_date 기준) issues = query.order_by(Issue.report_date.desc()).offset(skip).limit(limit).all() return issues @router.get("/{issue_id}", response_model=schemas.Issue) async def read_issue( issue_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): issue = db.query(Issue).filter(Issue.id == issue_id).first() if not issue: raise HTTPException(status_code=404, detail="Issue not found") # 권한별 조회 제한 if current_user.role != UserRole.admin and issue.reporter_id != current_user.id: raise HTTPException( status_code=403, detail="본인이 등록한 부적합만 조회할 수 있습니다." ) return issue @router.put("/{issue_id}", response_model=schemas.Issue) async def update_issue( issue_id: int, issue_update: schemas.IssueUpdate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): issue = db.query(Issue).filter(Issue.id == issue_id).first() if not issue: raise HTTPException(status_code=404, detail="Issue not found") # 권한 확인 if current_user.role == UserRole.user and issue.reporter_id != current_user.id: raise HTTPException(status_code=403, detail="Not authorized to update this issue") # 업데이트 update_data = issue_update.dict(exclude_unset=True) # 첫 번째 사진이 업데이트되는 경우 처리 if "photo" in update_data: # 기존 사진 삭제 if issue.photo_path: delete_file(issue.photo_path) # 새 사진 저장 if update_data["photo"]: photo_path = save_base64_image(update_data["photo"]) update_data["photo_path"] = photo_path else: update_data["photo_path"] = None # photo 필드는 제거 (DB에는 photo_path만 저장) del update_data["photo"] # 두 번째 사진이 업데이트되는 경우 처리 if "photo2" in update_data: # 기존 사진 삭제 if issue.photo_path2: delete_file(issue.photo_path2) # 새 사진 저장 if update_data["photo2"]: photo_path2 = save_base64_image(update_data["photo2"]) update_data["photo_path2"] = photo_path2 else: update_data["photo_path2"] = None # photo2 필드는 제거 (DB에는 photo_path2만 저장) del update_data["photo2"] # work_hours가 입력되면 자동으로 상태를 complete로 변경 if "work_hours" in update_data and update_data["work_hours"] > 0: if issue.status == IssueStatus.new: update_data["status"] = IssueStatus.complete for field, value in update_data.items(): setattr(issue, field, value) db.commit() db.refresh(issue) return issue @router.delete("/{issue_id}") async def delete_issue( issue_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): issue = db.query(Issue).filter(Issue.id == issue_id).first() if not issue: raise HTTPException(status_code=404, detail="Issue not found") # 권한 확인 (관리자만 삭제 가능) if current_user.role != UserRole.admin: raise HTTPException(status_code=403, detail="Only admin can delete issues") # 이미지 파일 삭제 if issue.photo_path: delete_file(issue.photo_path) db.delete(issue) db.commit() return {"detail": "Issue deleted successfully"} @router.get("/stats/summary") async def get_issue_stats( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """이슈 통계 조회""" query = db.query(Issue) # 일반 사용자는 자신의 이슈만 if current_user.role == UserRole.user: query = query.filter(Issue.reporter_id == current_user.id) total = query.count() new = query.filter(Issue.status == IssueStatus.NEW).count() progress = query.filter(Issue.status == IssueStatus.PROGRESS).count() complete = query.filter(Issue.status == IssueStatus.COMPLETE).count() return { "total": total, "new": new, "progress": progress, "complete": complete } @router.put("/{issue_id}/management") async def update_issue_management( issue_id: int, management_update: schemas.ManagementUpdateRequest, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """ 관리함에서 이슈의 관리 관련 필드들을 업데이트합니다. """ print(f"DEBUG: Received management update for issue {issue_id}") print(f"DEBUG: Update data: {management_update}") print(f"DEBUG: Current user: {current_user.username}") # 관리함 페이지 권한 확인 if not (current_user.role == UserRole.admin or check_page_access(current_user.id, 'issues_management', db)): raise HTTPException(status_code=403, detail="관리함 접근 권한이 없습니다.") # 이슈 조회 issue = db.query(Issue).filter(Issue.id == issue_id).first() if not issue: raise HTTPException(status_code=404, detail="부적합을 찾을 수 없습니다.") print(f"DEBUG: Found issue: {issue.id}") # 관리함에서만 수정 가능한 필드들만 업데이트 update_data = management_update.dict(exclude_unset=True) print(f"DEBUG: Update data dict: {update_data}") for field, value in update_data.items(): print(f"DEBUG: Processing field {field} = {value}") if field == 'completion_photo' and value: # 완료 사진 업로드 처리 try: completion_photo_path = save_base64_image(value, "completion") setattr(issue, 'completion_photo_path', completion_photo_path) print(f"DEBUG: Saved completion photo: {completion_photo_path}") except Exception as e: print(f"DEBUG: Photo save error: {str(e)}") raise HTTPException(status_code=400, detail=f"완료 사진 저장 실패: {str(e)}") elif field != 'completion_photo': # completion_photo는 위에서 처리됨 try: setattr(issue, field, value) print(f"DEBUG: Set {field} = {value}") except Exception as e: print(f"DEBUG: Field set error for {field}: {str(e)}") raise HTTPException(status_code=400, detail=f"필드 {field} 설정 실패: {str(e)}") try: db.commit() db.refresh(issue) print(f"DEBUG: Successfully updated issue {issue.id}") except Exception as e: print(f"DEBUG: Database commit error: {str(e)}") db.rollback() raise HTTPException(status_code=500, detail=f"데이터베이스 저장 실패: {str(e)}") return { "message": "관리 정보가 업데이트되었습니다.", "issue_id": issue.id, "updated_fields": list(update_data.keys()) }