주요 변경사항: - 비활성화된 프로젝트 관리 기능 추가 * 프로젝트 관리 페이지에 접을 수 있는 비활성 프로젝트 섹션 추가 * 비활성화된 프로젝트 복구 기능 제공 * 업로드 시에는 활성 프로젝트만 표시되도록 API 호출 분리 - 헤더 비밀번호 변경 기능 완전 구현 * CommonHeader.js에 완전한 비밀번호 변경 모달 구현 * ESC 키 지원, 실시간 유효성 검사, 토스트 메시지 추가 * 중복 코드 제거 및 통일된 함수 호출 구조 - 수신함 수정 내용 표시 문제 해결 * description 우선 표시로 최신 수정 내용 반영 * 관리함에서 final_description/final_category 업데이트 로직 추가 - 현황판 날짜 그룹화 개선 * 업로드일 기준에서 관리함 진입일(reviewed_at) 기준으로 변경 * Invalid Date 오류 해결 - 프로젝트 관리 페이지 JavaScript 오류 수정 * 중복 변수 선언 및 함수 참조 오류 해결 * 페이지 초기화 로직 개선 기술적 개선: - API 호출 최적화 (active_only 매개변수 명시적 전달) - 프론트엔드 표시 우선순위 통일 (description || final_description) - 백엔드 final_* 필드 업데이트 로직 추가
175 lines
6.7 KiB
Python
175 lines
6.7 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from datetime import datetime
|
|
from typing import List
|
|
|
|
from database.database import get_db
|
|
from database.models import Issue, User, ReviewStatus
|
|
from database.schemas import (
|
|
ManagementUpdateRequest, AdditionalInfoUpdateRequest, Issue as IssueSchema
|
|
)
|
|
from routers.auth import get_current_user
|
|
from routers.page_permissions import check_page_access
|
|
|
|
router = APIRouter(prefix="/api/management", tags=["management"])
|
|
|
|
@router.get("/", response_model=List[IssueSchema])
|
|
async def get_management_issues(
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
관리함 - 진행 중 및 완료된 부적합 목록 조회
|
|
"""
|
|
# 관리함 페이지 권한 확인
|
|
if not check_page_access(current_user.id, 'issues_management', db):
|
|
raise HTTPException(status_code=403, detail="관리함 접근 권한이 없습니다.")
|
|
|
|
# 진행 중 또는 완료된 이슈들 조회
|
|
issues = db.query(Issue).filter(
|
|
Issue.review_status.in_([ReviewStatus.in_progress, ReviewStatus.completed])
|
|
).order_by(Issue.reviewed_at.desc()).all()
|
|
|
|
return issues
|
|
|
|
@router.put("/{issue_id}")
|
|
async def update_issue(
|
|
issue_id: int,
|
|
update_request: ManagementUpdateRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
관리함에서 이슈 정보 업데이트
|
|
"""
|
|
# 관리함 페이지 권한 확인
|
|
if not 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="부적합을 찾을 수 없습니다.")
|
|
|
|
# 진행 중 또는 완료 대기 상태인지 확인
|
|
if issue.review_status not in [ReviewStatus.in_progress]:
|
|
raise HTTPException(status_code=400, detail="진행 중 상태의 부적합만 수정할 수 있습니다.")
|
|
|
|
# 업데이트할 데이터 처리
|
|
update_data = update_request.dict(exclude_unset=True)
|
|
|
|
for field, value in update_data.items():
|
|
if field == 'completion_photo' and value:
|
|
# 완료 사진 Base64 처리
|
|
from services.file_service import save_base64_image
|
|
try:
|
|
print(f"🔍 완료 사진 처리 시작 - 데이터 길이: {len(value)}")
|
|
print(f"🔍 Base64 데이터 시작 부분: {value[:100]}...")
|
|
photo_path = save_base64_image(value, "completion_")
|
|
if photo_path:
|
|
issue.completion_photo_path = photo_path
|
|
print(f"✅ 완료 사진 저장 성공: {photo_path}")
|
|
else:
|
|
print("❌ 완료 사진 저장 실패: photo_path가 None")
|
|
except Exception as e:
|
|
print(f"❌ 완료 사진 저장 실패: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
continue
|
|
elif field == 'final_description' and value:
|
|
# final_description 업데이트 시 description도 함께 업데이트
|
|
issue.final_description = value
|
|
issue.description = value
|
|
print(f"✅ final_description 및 description 업데이트: {value[:50]}...")
|
|
continue
|
|
elif field == 'final_category' and value:
|
|
# final_category 업데이트 시 category도 함께 업데이트
|
|
issue.final_category = value
|
|
issue.category = value
|
|
print(f"✅ final_category 및 category 업데이트: {value}")
|
|
continue
|
|
elif field == 'expected_completion_date' and value:
|
|
# 날짜 필드 처리
|
|
if not value.endswith('T00:00:00'):
|
|
value = value + 'T00:00:00'
|
|
setattr(issue, field, value)
|
|
|
|
db.commit()
|
|
db.refresh(issue)
|
|
|
|
return {
|
|
"message": "이슈가 성공적으로 업데이트되었습니다.",
|
|
"issue_id": issue.id,
|
|
"updated_at": datetime.now()
|
|
}
|
|
|
|
@router.put("/{issue_id}/additional-info")
|
|
async def update_additional_info(
|
|
issue_id: int,
|
|
additional_info: AdditionalInfoUpdateRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
추가 정보 업데이트 (원인부서, 해당자 상세, 원인 상세)
|
|
"""
|
|
# 관리함 페이지 권한 확인
|
|
if not 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="부적합을 찾을 수 없습니다.")
|
|
|
|
# 진행 중 상태인지 확인
|
|
if issue.review_status != ReviewStatus.in_progress:
|
|
raise HTTPException(status_code=400, detail="진행 중 상태의 부적합만 추가 정보를 입력할 수 있습니다.")
|
|
|
|
# 추가 정보 업데이트
|
|
update_data = additional_info.dict(exclude_unset=True)
|
|
|
|
for field, value in update_data.items():
|
|
setattr(issue, field, value)
|
|
|
|
# 추가 정보 입력 시간 및 입력자 기록
|
|
issue.additional_info_updated_at = datetime.now()
|
|
issue.additional_info_updated_by_id = current_user.id
|
|
|
|
db.commit()
|
|
db.refresh(issue)
|
|
|
|
return {
|
|
"message": "추가 정보가 성공적으로 업데이트되었습니다.",
|
|
"issue_id": issue.id,
|
|
"updated_at": issue.additional_info_updated_at,
|
|
"updated_by": current_user.username
|
|
}
|
|
|
|
@router.get("/{issue_id}/additional-info")
|
|
async def get_additional_info(
|
|
issue_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""
|
|
추가 정보 조회
|
|
"""
|
|
# 관리함 페이지 권한 확인
|
|
if not 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="부적합을 찾을 수 없습니다.")
|
|
|
|
return {
|
|
"issue_id": issue.id,
|
|
"cause_department": issue.cause_department.value if issue.cause_department else None,
|
|
"responsible_person_detail": issue.responsible_person_detail,
|
|
"cause_detail": issue.cause_detail,
|
|
"additional_info_updated_at": issue.additional_info_updated_at,
|
|
"additional_info_updated_by_id": issue.additional_info_updated_by_id
|
|
}
|