zioinfo-mail/docs/work_timetable.md
DESKTOP-TKLFCPR\ython e228faabf5 feat(itsm): G-1~G-12 확장 기능 + 하네스/봇/설치스크립트 구현
G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현
G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건)
G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST)
G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직
G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트
G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트
G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API
G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트
G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트
G-10: core/push_notify.py + routers/push.py + PushSubscription 모델
G-11: approvals 다중승인 (위임/서명/기한초과/마감연장)
G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh

하네스: guardia-orchestrator 확장기능 Phase 반영
봇명령어: /sr /status /license /bulk 슬래시 명령어 추가
설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:18:52 +09:00

10 KiB

[Specification] 작업 타임테이블 + Excel 다운로드

SM 운영, 정기점검, PM, SR 기반 작업 등 모든 수행 이력을 타임테이블로 관리하고
Excel 파일로 다운로드하는 기능 명세.


1. 타임테이블 개요

1.1. 목적

목적 설명
작업 이력 관리 정기점검·PM·SR·장애대응 모든 작업을 단일 화면에서 통합 관리
감사 자료 제출 기관·감사원 요청 시 Excel로 즉시 제출 가능한 형태 유지
PM 보고 자료 월간/분기 활동 보고서 자동 생성 기반 데이터
작업 표준화 수행 명령어·쉘 스크립트를 기록해 재사용 가능하도록 관리

1.2. 작업 유형

work_type 한글명 설명
REGULAR_CHECK 정기점검 월간·분기·반기·연간 계획된 점검
PM 예방 정비 하드웨어 교체, 패치 적용, 취약점 조치
SR SR 기반 작업 ITSM SR과 연계된 작업
ADHOC 수시점검 비정기 확인, 고객 요청 확인
DEPLOY 배포 작업 소스 배포, 설정 변경
EMERGENCY 긴급 대응 장애 복구, 긴급 조치

2. 데이터 모델

2.1. 주요 컬럼 상세

컬럼 타입 필수 설명
timetable_id BIGINT PK
work_type VARCHAR(30) 작업 유형
title VARCHAR(200) 작업 제목 (예: 2025 Q1 정기점검 - 기획재정부)
inst_id VARCHAR(20) 대상 기관
server_id VARCHAR(30) 대상 서버 (복수면 JSON)
sr_id VARCHAR(30) 연계 SR ID
script_id BIGINT 사용 쉘 스크립트 ID
scheduled_at TIMESTAMP 처리 예정 일시
started_at TIMESTAMP 실제 시작 일시
completed_at TIMESTAMP 완료 일시
content TEXT 처리 내용 (무엇을, 어떻게, 왜)
command_or_shell TEXT 실행한 명령어 또는 쉘 이름
result TEXT 처리 결과 (성공/실패 내용)
result_status VARCHAR(20) PENDING / SUCCESS / FAILED / PARTIAL
assignee VARCHAR(50) 담당 엔지니어 사번
reviewer VARCHAR(50) PM/검토자 사번
attachments JSONB 첨부파일 목록

3. API 엔드포인트

메서드 URL 권한 설명
GET /api/timetable ADMIN, PM, ENGINEER 타임테이블 목록 (필터링 지원)
GET /api/timetable/{id} ADMIN, PM, ENGINEER 상세 조회
POST /api/timetable ENGINEER, PM, ADMIN 새 작업 등록
PATCH /api/timetable/{id} ENGINEER, PM, ADMIN 수정
DELETE /api/timetable/{id} ADMIN 삭제
GET /api/timetable/export/excel ADMIN, PM Excel 다운로드
GET /api/timetable/stats ADMIN, PM 기간별 통계

3.1. 목록 조회 쿼리 파라미터

GET /api/timetable
  ?inst_code=MOF          # 기관 필터
  &work_type=REGULAR_CHECK # 작업 유형 필터
  &result_status=SUCCESS  # 결과 상태 필터
  &assignee=EMP-0101     # 담당자 필터
  &date_from=2025-01-01  # 시작일
  &date_to=2025-03-31    # 종료일
  &keyword=점검           # 제목/내용 검색
  &skip=0&limit=50

3.2. Excel 다운로드 쿼리 파라미터

GET /api/timetable/export/excel
  ?inst_code=MOF
  &date_from=2025-01-01
  &date_to=2025-03-31
  &work_type=REGULAR_CHECK

응답: Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
파일명: GUARDiA_작업이력_MOF_20250101_20250331.xlsx


4. Excel 파일 구조

openpyxl 라이브러리 사용 (on-premise, 외부 API 호출 없음)

4.1. 시트 구성

시트 내용
작업이력 전체 타임테이블 데이터
통계요약 작업 유형별·결과별 집계
서버현황 대상 서버 목록 (민감정보 제외)

4.2. 작업이력 시트 컬럼

# 컬럼명 데이터
A 번호 순번
B 작업유형 정기점검 / PM / SR작업 / 수시점검
C 제목 work timetable title
D 기관명 inst_name
E 대상서버 server_id (hostname)
F 처리예정일시 scheduled_at
G 시작일시 started_at
H 완료일시 completed_at
I 소요시간(분) completed_at - started_at
J 처리내용 content
K 명령어/쉘 command_or_shell
L 처리결과 result
M 결과상태 SUCCESS / FAILED / PARTIAL
N 담당자 assignee 이름
O 검토자 reviewer 이름
P SR번호 sr_id
Q 비고 note

4.3. 스타일 규칙

# 헤더 스타일
header_fill = PatternFill("solid", fgColor="1E3A5F")  # 네이비
header_font = Font(name="맑은 고딕", bold=True, color="FFFFFF", size=11)
header_align = Alignment(horizontal="center", vertical="center")

# 데이터 행 교대 색상
row_fill_even = PatternFill("solid", fgColor="F2F6FA")
row_fill_odd  = None  # 흰색

# 결과 상태 강조 색상
status_colors = {
    "SUCCESS":  "C6EFCE",  # 연초록
    "FAILED":   "FFC7CE",  # 연빨강
    "PARTIAL":  "FFEB9C",  # 연노랑
    "PENDING":  "F4F4F4",  # 연회색
}

5. 프론트엔드 화면 구성

5.1. 타임테이블 뷰 (view-timetable)

┌─────────────────────────────────────────────────────────┐
│ 📅 작업 타임테이블         [+ 작업 등록]  [📥 Excel]    │
├─────────────────────────────────────────────────────────┤
│ [기관▼] [작업유형▼] [결과▼] [날짜범위] [담당자] [검색]  │
├─────────────────────────────────────────────────────────┤
│ 날짜/시간         │ 유형      │ 제목            │ 기관   │
│                   │           │                 │        │
│ 2025-03-15 14:00  │ 정기점검  │ 1분기 정기점검  │ MOF    │
│                   │           │ - 기획재정부    │ ✅완료  │
│                   │           │                 │        │
│ 2025-03-20 09:00  │ SR작업    │ SR-20250320-001 │ MOIS   │
│                   │           │ WAS 재기동      │ ⚠일부  │
└───────────────────────────────────────────────────────--┘

5.2. 신규 등록 모달

┌─ 작업 등록 ──────────────────────────────────────────┐
│ 작업유형 [정기점검 ▼]          기관 [MOF ▼]          │
│ 제목 [___________________________________]           │
│ 대상서버 [MOF-WAS-01 ▼]       SR연계 [선택 ▼]        │
│ 처리예정 [2025-03-15] [14:00]                         │
│                                                       │
│ 처리내용                                              │
│ [──────────────────────────────────────────]         │
│ [                                          ]         │
│                                                       │
│ 명령어/쉘 스크립트                                    │
│ [쉘 선택 ▼]   또는 직접 입력                          │
│ [──────────────────────────────────────────]         │
│                                                       │
│ 처리결과   [___________________________]              │
│ 결과상태   [완료 ✅ / 부분완료 ⚠ / 실패 ❌]           │
│ 담당자     [김엔지니어 ▼]  검토자 [이PM ▼]           │
│                                                       │
│                      [취소]  [저장]                   │
└───────────────────────────────────────────────────────┘

6. Excel 생성 코드 구조 (서버측)

# routers/timetable.py
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from fastapi.responses import StreamingResponse
import io

@router.get("/export/excel")
async def export_excel(
    inst_code: str | None = Query(None),
    date_from: date | None = Query(None),
    date_to: date | None = Query(None),
    work_type: str | None = Query(None),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    # 1. 데이터 조회
    rows = await _fetch_timetable(db, inst_code, date_from, date_to, work_type)

    # 2. Workbook 생성
    wb = Workbook()
    ws = wb.active
    ws.title = "작업이력"

    # 3. 헤더 작성
    headers = ["번호", "작업유형", "제목", "기관명", "대상서버",
               "처리예정", "시작", "완료", "소요(분)",
               "처리내용", "명령어/쉘", "처리결과", "결과상태",
               "담당자", "검토자", "SR번호", "비고"]
    _write_header(ws, headers)

    # 4. 데이터 작성
    for i, row in enumerate(rows, start=2):
        _write_row(ws, i, row)

    # 5. 통계 시트 추가
    _add_stats_sheet(wb, rows)

    # 6. StreamingResponse 반환
    buf = io.BytesIO()
    wb.save(buf)
    buf.seek(0)
    filename = f"GUARDiA_작업이력_{inst_code or 'ALL'}_{date.today():%Y%m%d}.xlsx"
    return StreamingResponse(
        buf,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": f"attachment; filename*=UTF-8''{filename}"}
    )

7. 의존성

openpyxl>=3.1.0   # Excel 생성 (on-premise, 외부 API 없음)

requirements.txt에 추가:

openpyxl==3.1.2