Files
Hyungi Ahn 550633b89d feat: 3-System 분리 프로젝트 초기 코드 작성
TK-FB(공장관리+신고)와 M-Project(부적합관리)를 3개 독립 시스템으로
분리하기 위한 전체 코드 구조 작성.
- SSO 인증 서비스 (bcrypt + pbkdf2 이중 해시 지원)
- System 1: 공장관리 (TK-FB 기반, 신고 코드 제거)
- System 2: 신고 (TK-FB에서 workIssue 코드 추출)
- System 3: 부적합관리 (M-Project 기반)
- Gateway 포털 (path-based 라우팅)
- 통합 docker-compose.yml 및 배포 스크립트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:40:11 +09:00

213 lines
8.0 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, DailyReportStats
)
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
}
@router.get("/stats", response_model=DailyReportStats)
async def get_management_stats(
project_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="관리함 접근 권한이 없습니다.")
# 해당 프로젝트의 관리함 이슈들 조회
issues = db.query(Issue).filter(
Issue.project_id == project_id,
Issue.review_status.in_([ReviewStatus.in_progress, ReviewStatus.completed])
).all()
# 통계 계산
stats = DailyReportStats()
today = datetime.now().date()
for issue in issues:
stats.total_count += 1
if issue.review_status == ReviewStatus.in_progress:
stats.management_count += 1
# 지연 여부 확인
if issue.expected_completion_date and issue.expected_completion_date < today:
stats.delayed_count += 1
elif issue.review_status == ReviewStatus.completed:
stats.completed_count += 1
return stats