feat: tkuser 통합 관리 서비스 + 전체 시스템 SSO 쿠키 인증 통합

- tkuser 서비스 신규 추가 (API + Web)
  - 사용자/권한/프로젝트/부서/작업자/작업장/설비/작업/휴가 통합 관리
  - 작업장 탭: 공장→작업장 드릴다운 네비게이션 + 구역지도 클릭 연동
  - 작업 탭: 공정(work_types)→작업(tasks) 계층 관리
  - 휴가 탭: 유형 관리 + 연차 배정(근로기준법 자동계산)
- 전 시스템 SSO 쿠키 인증으로 통합 (.technicalkorea.net 공유)
- System 2: 작업 이슈 리포트 기능 강화
- System 3: tkuser API 연동, 페이지 권한 체계 적용
- docker-compose에 tkuser-api, tkuser-web 서비스 추가
- ARCHITECTURE.md, DEPLOYMENT.md 문서 작성

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-02-12 13:45:52 +09:00
parent 6495b8af32
commit 733bb0cb35
96 changed files with 9721 additions and 825 deletions

View File

@@ -1,10 +1,12 @@
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi import APIRouter, Depends, HTTPException, Query, Request
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, User, Project, ReviewStatus, DisposalReasonType
from database.models import Issue, User, ReviewStatus, DisposalReasonType
from utils.tkuser_client import get_token_from_request
import utils.tkuser_client as tkuser_client
from database.schemas import (
InboxIssue, IssueDisposalRequest, IssueReviewRequest,
IssueStatusUpdateRequest, ModificationLogEntry, ManagementUpdateRequest
@@ -123,6 +125,7 @@ async def dispose_issue(
async def review_issue(
issue_id: int,
review_request: IssueReviewRequest,
request: Request,
current_user: User = Depends(get_current_user), # 수신함 권한이 있는 사용자
db: Session = Depends(get_db)
):
@@ -157,9 +160,10 @@ async def review_issue(
# 프로젝트 변경
if review_request.project_id is not None and review_request.project_id != issue.project_id:
# 프로젝트 존재 확인
# 프로젝트 존재 확인 (tkuser API)
if review_request.project_id != 0: # 0은 프로젝트 없음을 의미
project = db.query(Project).filter(Project.id == review_request.project_id).first()
token = get_token_from_request(request)
project = await tkuser_client.get_project(token, review_request.project_id)
if not project:
raise HTTPException(status_code=400, detail="존재하지 않는 프로젝트입니다.")
@@ -264,12 +268,11 @@ async def update_issue_status(
# 진행 중 또는 완료 상태로 변경 시 프로젝트별 순번 자동 할당
if status_request.review_status in [ReviewStatus.in_progress, ReviewStatus.completed]:
if not issue.project_sequence_no:
from sqlalchemy import text
result = db.execute(
text("SELECT generate_project_sequence_no(:project_id)"),
{"project_id": issue.project_id}
)
issue.project_sequence_no = result.scalar()
from sqlalchemy import func
max_seq = db.query(func.coalesce(func.max(Issue.project_sequence_no), 0)).filter(
Issue.project_id == issue.project_id
).scalar()
issue.project_sequence_no = max_seq + 1
# 완료 사진 업로드 처리
if status_request.completion_photo and status_request.review_status == ReviewStatus.completed: