Files
M-Project/backend/routers/issues.py
hyungi 44e2fb2e44 feat: 사진 업로드 기능 개선 및 카테고리 업데이트
- 사진 2장까지 업로드 지원
- 카메라 촬영 + 갤러리 선택 분리
- 이미지 압축 및 최적화 (ImageUtils)
- iPhone .mpo 파일 JPEG 변환 지원
- 카테고리 변경: 치수불량 → 설계미스, 검사미스 추가
- KST 시간대 설정
- URL 해시 처리로 목록관리 페이지 이동 개선
- 로그인 OAuth2 form-data 형식 수정
- 업로드 속도 개선 및 프로그레스바 추가
2025-09-18 07:00:28 +09:00

184 lines
5.7 KiB
Python

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
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)
):
# 이미지 저장
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,
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 status:
query = query.filter(Issue.status == status)
issues = query.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")
# 모든 사용자가 모든 이슈를 조회 가능 (협업을 위해)
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
}