# -*- coding: utf-8 -*-
"""
사업수행계획서(.docx) — 행안부 정보화사업 산출물 표준 목차 준용.
데이터 소스: sources.py(PLANNING·IMPLEMENTATION_BACKLOG·FEATURE_BACKLOG_100 파싱).
소스 문서 갱신 시 본 스크립트 재실행만으로 결정적 재생성.
보안: 서버 IP·비밀번호·SSH·시크릿 미기재.
"""
import os
from docx import Document
from docx.shared import Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
import sources as S
from _docxutil import setup, h, para, bullets, table, NAVY, ACCENT, GREY

OUT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "사업수행계획서.docx"))
doc = Document(); setup(doc)
M = S.META
CA = WD_ALIGN_PARAGRAPH.CENTER

# ---------- 표지 ----------
for _ in range(4): doc.add_paragraph()
para(doc, f"{M['project_en']} — 사업수행계획서", size=13, color=ACCENT, align=CA, space_after=4)
p = doc.add_paragraph(); p.alignment = CA
r = p.add_run(M["title"]); r.bold = True; r.font.size = Pt(24); r.font.color.rgb = NAVY
doc.add_paragraph()
para(doc, M["std"], size=11, color=GREY, align=CA)
for _ in range(6): doc.add_paragraph()
table(doc, ["구분","내용"],
    [["문서명", M["title"]],["문서 버전", M["version"]],["작성일", M["date"]],
     ["작성 주관", M["owner"]],["발주처(수요기관)", M["client"]],
     ["사업 유형","정보시스템 구축(SI) — AI 기반 전시 운영 자동화 플랫폼"],
     ["보안 등급","대외비 — 자격증명·내부망 정보 미기재"]],
    widths=[4.5, 11.5], first_col_bold=True)
doc.add_page_break()

# ---------- 문서정보 / 개정이력 / 목차 ----------
h(doc,1,"문서 정보 및 개정 이력")
h(doc,2,"문서 정보")
table(doc, ["항목","내용"],
    [["문서 제목", M["title"]],["산출 단계","사업 착수(계획) 단계 표준 산출물"],
     ["표준 근거", M["std"]],
     ["작성 근거 문서","PLANNING v3.0 · IMPLEMENTATION_BACKLOG · FEATURE_BACKLOG_100 · GUARDIA_ALIGNMENT · SECURITY · architecture/*"],
     ["문서 관리","형상관리(Git) 하 버전 통제 — docs/deliverables/ 관리, _gen 재실행으로 재생성"]],
    widths=[4.5, 11.5], first_col_bold=True)
h(doc,2,"개정 이력")
table(doc, ["버전","일자","작성/개정자","주요 변경 내용"],
    [[M["version"], M["date"], "사업 PMO", "사업수행계획서 최초 작성(표준 목차 14장 체계)"]],
    widths=[2.0, 3.0, 3.5, 7.5])
para(doc, "※ 본 계획서는 사업 진척에 따라 형상관리 절차(14장)에 의거 개정하며, 모든 변경은 개정 이력에 기록한다.",
     size=9, italic=True, color=GREY)
h(doc,2,"목차")
for t_ in ["1. 사업 개요","2. 사업 범위","3. 추진 전략 및 개발 방법론","4. 추진 체계·조직 및 역할(R&R)",
 "5. WBS 및 마스터 일정","6. 투입 인력 및 투입 계획(M/M)","7. 품질보증 계획","8. 보안 및 개인정보보호 계획",
 "9. 시험(테스트) 계획 개요","10. 이관·교육·유지보수 계획","11. 위험(리스크) 관리","12. 의사소통·보고 체계",
 "13. 산출물 목록","14. 형상관리"]:
    pp = doc.add_paragraph(t_); pp.paragraph_format.space_after = Pt(2); pp.runs[0].font.size = Pt(10.5)
doc.add_page_break()

# ---------- 1. 사업 개요 ----------
h(doc,1,"1. 사업 개요")
h(doc,2,"1.1 추진 배경")
para(doc,"킨텍스는 총 전시면적 108,011㎡(국내 최대, 제3전시장 완공 시 약 178,000㎡)를 운영하지만, 전시 준비 실무는 여전히 "
 "표준 서식 다운로드 후 이메일·방문 제출, CAD 수작업 배치도의 육안 검수, 수기 위치표시도 기반 유틸리티 신청에 머물러 있다. "
 "참가업체 유틸리티 신청은 킨텍스 공통 플랫폼 없이 전시회별 주최자 사무국 시스템으로 파편화되어 있다.")
para(doc,"공간 데이터(배치도·도면·위치표시도)가 전부 이미지·수기로 오가며 구조화되지 않아 자동 검증·시각화·정산의 원천 데이터가 부재하고, "
 "D-150/D-30/D-25/D-7 마일스톤이 시스템화되어 있지 않으며, 시공 결과를 사전에 확인할 수단이 없다는 구조적 공백이 확인되었다.")
h(doc,2,"1.2 사업 목적")
bullets(doc,[
 "전시장 운영 전 과정(홀 배정→부스 배치→장치공사 설계→전기/조명→네트워크/유틸리티 배선→반입/반출)을 AI로 자동 설계·검증한다.",
 "AI 설계 결과를 나노바나나(이미지 생성)로 '시공 후 결과 사진'처럼 시공 전에 미리 생성하여 사진 수준 시각화를 제공한다.",
 "기획·판매·시공·운영·관람객·사후분석 전 주기를 하나의 공간 데이터·계정 체계로 통합한 베뉴 운영 플랫폼을 구축한다.",
 "AI 설계·시각화 산출물을 공사/장치 옥션(역경매)의 응찰 근거로 소비하여 설계→시각화→발주→시공 폐루프를 완성한다.",
])
h(doc,2,"1.3 비전 및 정체성")
para(doc,'비전 슬로건: "신청서를 내는 순간, 시공 후 사진을 먼저 본다."', bold=True, color=ACCENT)
para(doc,"본 시스템은 킨텍스를 기준 테넌트(#1)로 하되 코엑스 등 여타 전시관을 온보딩하는 다중 전시관 멀티테넌트 SaaS로 확장 가능한 구조로 설계한다. "
 "기능(모듈)은 전부 보존하고 그 위에 전시관 단위 데이터·권한·컨텍스트 격리 레이어를 얹는다.")
h(doc,2,"1.4 정량 목표(As-Is → To-Be)")
table(doc, ["목표 지표","현재(As-Is)","목표(To-Be)"],
    [["홀 배정 견적 회신","문의→협의→견적 수일","조건 입력 후 즉시 자동 가견적"],
     ["부스 배치도 초안","CAD 수작업 수일~수주","조건 입력 후 수 분 내 복수 안 생성"],
     ["도면 규정 검수","홀매니저 육안 검토","규정 위반 자동 플래깅 후 사람 확정"],
     ["유틸리티 위치표시도","참가업체 수기 작도","부스 좌표 클릭 → 자동 배선안·자동 견적"],
     ["시공 결과 예측","불가(외주 조감도)","표준 샷 세트 자동 생성(정면/야간/통로)"]],
    widths=[4.5, 5.5, 6.0])
h(doc,2,"1.5 기대 효과")
bullets(doc,[
 "참가업체·주최자의 의사결정 가속 및 참가업체 유치 영업 자료 확보(시공 예상 이미지 기반).",
 "규정 위반 사전 검출로 도면 반려 재작업 감소 및 홀매니저 검수 시간 단축.",
 "'현장 추가신청 불가' 유틸리티의 신청 누락 방지 — 참가업체 최대 리스크 제거.",
 "역경매 옥션을 통한 시공 발주 가격 최적화·투명화(동일 사양 위 공정 비교).",
 "공간 데이터 표준화로 자동 검증·시각화·정산·wayfinding·경영분석의 단일 원천 확보.",
])

# ---------- 2. 사업 범위 (모듈: sources.modules) ----------
h(doc,1,"2. 사업 범위")
h(doc,2,"2.1 대상 시스템 및 모듈")
para(doc,f"본 사업은 설계·시각화 코어(P0), 판매·발주·정산, 관람·참가·마케팅, 경영·콘텐츠·관리 계열의 총 {len(S.modules())}개 모듈과 "
 "공통·시스템관리 레이어(UIWS/WISE 이식)로 구성된다. (모듈 목록은 PLANNING 총괄표에서 자동 추출)")
mod_rows = [[mid, name, pri] for (mid, name, pri) in S.modules()]
table(doc, ["모듈","명칭","우선순위"], mod_rows, widths=[2.2, 11.3, 2.5])
h(doc,2,"2.2 우선순위 정의")
bullets(doc,[
 "P0 — 핵심 차별화 + 첫 상용 행사 적용 필수(부스 시공 코어 M2~M5).",
 "P1 — 운영 효율 핵심(판매·발주·정산·관람·마케팅·경영분석·관리자·공통 레이어).",
 "P2 — 확장(물류·비즈매칭·wayfinding·현장운영).",
])
h(doc,2,"2.3 범위 제외(Non-Goals)")
bullets(doc,[
 "킨텍스 임대계약의 법적 전자체결은 후속 단계 검토 — 초기에는 견적·서류 준비까지.",
 "구조계산서의 구조 안전성 최종 판정은 AI가 대신하지 않는다(규정 체크·누락 검출까지, 최종 판정은 구조기술사/킨텍스).",
 "AI 생성 시각화는 참고용이며 계약·인허가 서류로 사용 불가(워터마크·고지 강제).",
 "신규 전시관 온보딩은 마스터데이터 입력 수준까지 — 고유 규정 파서 자동 생성 제외.",
 "정밀 실내 측위(UWB/BLE 비콘)는 시설 인프라 협의 전제 — 초기에는 존-레벨 폴백.",
])

# ---------- 3. 추진 전략·방법론 ----------
h(doc,1,"3. 추진 전략 및 개발 방법론")
h(doc,2,"3.1 기본 추진 전략")
bullets(doc,[
 "공통 레이어 선행: 인증(JWT+2FA)·시스템관리·공통 업무기능을 전 도메인 모듈보다 선행 구축.",
 "코어 우선: 핵심 차별화 P0 부스 시공 코어(M2~M5)를 우선 확보하여 첫 상용 행사에 적용.",
 "단일 공간 데이터 모델: M2→M3→M4→M5가 하나의 PostGIS 지오메트리를 공유.",
 "폐루프 완성: 코어 산출물을 M15 옥션 응찰 근거로 소비하여 설계→시각화→발주→시공 종결.",
 "표준 프레임워크 준수: GUARDiA 표준(UIMS/WISE) 스택·인증·공통모듈·보안·배포를 상속하고 도메인만 확장.",
])
h(doc,2,"3.2 개발 방법론")
para(doc,"반복·점진(Iterative & Incremental) 방식. Phase A~E 단계 위에서 각 모듈은 설계→구현→모듈 완성 직후 점진 QA→통합의 짧은 반복을 수행하며, "
 "QA가 경계면·회귀·보안 불변을 검증하고 통과할 때까지 반려한다.")
ph = S.phases()
table(doc, ["단계","성격","핵심 활동"],
    [[f"Phase {p[0]}", p[1], " · ".join(t[1] for t in p[2][:3]) + (" 등" if len(p[2])>3 else "")] for p in ph],
    widths=[2.4, 4.6, 9.0])
h(doc,2,"3.3 기술 아키텍처(확정 스택)")
table(doc, ["레이어","기술","비고"],
    [["프론트엔드","React 18/19 + Vite + TypeScript","역할별 포털 번들 분리(데스크톱=설계, 모바일=현장·조회)"],
     ["백엔드","Spring Boot 3.x(Java 17) + MyBatis","REST + WebSocket(STOMP), 룰·배치/배선 엔진"],
     ["데이터베이스","PostgreSQL + PostGIS","부스 폴리곤·트렌치 포인트·배선 LineString 공간 데이터"],
     ["비동기","Redis 작업 큐","RenderJob·서류·알림 비동기 처리"],
     ["이미지 생성","나노바나나 Python 워커(사이드카)","백엔드는 큐 발행만, 생성 키는 워커 env 전용"],
     ["AI(텍스트)","Claude 기본 + 설정형 전환(AiTextRouter)","실패 시 온프레미스 모델 자동 폴백"],
     ["형상/배포","Git(Gitea)+CI/CD Webhook+systemd/nginx","무중단·헬스게이트·롤백(Fail-Safe)"]],
    widths=[2.8, 6.2, 7.0])
para(doc, f"개발 도메인은 서비스명 수준으로 {M['dev_domain']}을 사용하며, 운영 도메인은 후속 확정한다.", size=9, italic=True, color=GREY)

# ---------- 4. 추진 체계·조직·역할 ----------
h(doc,1,"4. 추진 체계·조직 및 역할(R&R)")
h(doc,2,"4.1 추진 체계")
para(doc,"발주처(킨텍스)—사업 총괄(PMO)—아키텍트 그룹—개발 그룹(공통·코어·도메인)—품질(QA)·배포(DevOps)의 계층으로 구성한다. "
 "AI 에이전트 팀(kintex-impl-orchestrator)이 각 트랙 구현을 조율하며, 기획(planner)·디자인(designer)·검증(reviewer)을 경유한다.")
h(doc,2,"4.2 조직 및 역할(R&R)")
table(doc, ["그룹","역할","주요 책임(R&R)"],
    [["거버넌스","PMO / 사업 PM","일정·범위·리스크·이해관계자 관리, 발주처 보고, 형상·품질 총괄"],
     ["아키텍트","AA(애플리케이션)","모듈 경계·레이어·API 표준·패키지·의존성 규칙"],
     ["아키텍트","SA(시스템)","확장성·HA·성능·배포 토폴로지·비기능요건(NFR)"],
     ["아키텍트","TA(기술)","기술 표준·빌드/배포·개발 표준·관측성·AiTextRouter"],
     ["아키텍트","DA(데이터)","전사 ERD·공간데이터·마스터·공통코드·BI 데이터마트"],
     ["아키텍트","NA(네트워크)","DMZ/내부망 분리·방화벽·부하분산·공개/백오피스 망 분리"],
     ["공통","공통/시스템관리 개발","인증(2FA)·시스템관리·공통 업무기능(UIWS 이식)"],
     ["코어","백엔드 개발","M1~M9 REST/WebSocket·룰 엔진·배선 엔진(PostGIS)"],
     ["코어","프론트엔드 개발","역할별 포털 화면·플로어플랜 캔버스·Before/After 뷰"],
     ["코어","DB 엔지니어","PostGIS 스키마·마이그레이션·매퍼·마스터 시드"],
     ["AI·시각화","AI 개발","배치 자동생성·규정검증 보조·매칭·서류검수·챗봇(Claude)"],
     ["AI·시각화","시각화(visualizer)","나노바나나 프롬프트·워커·워터마크 강제"],
     ["도메인","옥션/관람객/CMS/BI/관리자 개발","M15/M10/M12·M17/M16/M18 도메인 구현"],
     ["품질·배포","QA","경계면·회귀·보안 불변 점진 검증(통과까지 반려)"],
     ["품질·배포","DevOps","빌드·CI/CD·systemd/nginx·환경변수 배선"]],
    widths=[2.2, 4.0, 9.8])

# ---------- 5. WBS·마스터 일정 (sources.phases + SCHEDULE) ----------
h(doc,1,"5. WBS 및 마스터 일정")
h(doc,2,"5.1 작업 분해 구조(WBS) 개요")
para(doc,"WBS는 Phase A~E의 5개 단계와 하위 작업 패키지로 구성한다(IMPLEMENTATION_BACKLOG에서 자동 추출). "
 "상세 작업 분해·담당·의존·기간은 별첨 [WBS_및_일정.xlsx]의 'WBS' 시트에 관리한다.")
table(doc, ["Phase","작업 패키지(대표)","완료 기준(대표)"],
    [[f"{p[0]}. {p[1]}", " / ".join(t[1] for t in p[2][:3]), p[2][0][3] if p[2] else ""] for p in ph],
    widths=[3.6, 8.0, 4.4])
h(doc,2,"5.2 마스터 일정 및 마일스톤")
para(doc,"총 사업 기간은 약 28주(7개월) 기준이며, 착수 시점 확정 후 절대 일정을 확정한다(아래는 착수일 기준 상대 주차).")
table(doc, ["Phase","시작","종료","주요 마일스톤"],
    [[f"{r_[0]}. {r_[1]}", r_[2], r_[3], r_[4]] for r_ in S.SCHEDULE],
    widths=[4.2, 1.8, 1.8, 8.2])
para(doc,"※ Phase B는 Phase A와 일부 병행 착수하며, Phase B(공통 레이어) 완료가 Phase C/D 도메인 착수의 선행 전제이다.",
     size=9, italic=True, color=GREY)

# ---------- 6. 투입 인력 (sources.STAFFING) ----------
h(doc,1,"6. 투입 인력 및 투입 계획(M/M)")
h(doc,2,"6.1 투입 인력 계획")
para(doc,"역할별 투입 인력과 단계별 투입 공수(M/M)는 아래와 같다. 상세는 별첨 [WBS_및_일정.xlsx]의 '투입인력계획' 시트에 관리한다.")
table(doc, ["역할","인원(명)","등급","주 투입 Phase","투입 공수(M/M)"],
    [list(x) for x in S.STAFFING], widths=[5.5, 2.0, 2.0, 2.8, 3.7])
total_mm = sum(float(x[4]) for x in S.STAFFING)
total_head = sum(int(x[1]) for x in S.STAFFING)
para(doc, f"합계(계획): 인원 약 {total_head}명(중복 참여 포함), 총 투입 공수 약 {total_mm:.1f} M/M(추정치, 착수 시 상세 산정).",
     bold=True, size=10, color=NAVY)
h(doc,2,"6.2 투입 원칙")
bullets(doc,[
 "Phase B(공통 레이어)에 개발 인력을 선집중하여 전 도메인 기반을 조기 확보.",
 "아키텍트는 Phase A에 집중 투입 후 각 Phase 착수 시 표준 준수를 검수.",
 "QA는 전 Phase 상시 배치하여 모듈 완성 직후 점진 검증을 수행.",
])

# ---------- 7. 품질보증 ----------
h(doc,1,"7. 품질보증 계획")
h(doc,2,"7.1 품질 목표 및 기준")
bullets(doc,[
 "기능 품질: 모듈별 완료 기준(WBS) 충족, 경계면(API 응답 shape↔프론트 호출) 불일치 0.",
 "코드 품질: 표준 프레임워크·아키텍처 표준 준수, 정적 분석·코드 리뷰 통과.",
 "회귀 품질: 스모크/회귀 테스트로 기존 기능 무회귀 보장.",
 "보안 품질: 보안 불변 규칙(8장) 위반 0 — 위반 시 반려 사유.",
])
h(doc,2,"7.2 품질보증 활동")
table(doc, ["활동","시점","담당","산출"],
    [["아키텍처 정합 검증","Phase A 종료","reviewer","불일치 티켓·시정 확인"],
     ["점진 QA(모듈 완성 직후)","각 모듈 완성","QA","경계면·회귀·보안 검증 결과"],
     ["코드 리뷰","커밋/PR","개발 리드","리뷰 코멘트·조치"],
     ["스모크·회귀 테스트","배포 전","QA/DevOps","테스트 리포트"],
     ["보안 체크리스트 점검","배포·리뷰 전","QA","체크리스트 결과(8장)"]],
    widths=[4.5, 3.0, 3.0, 5.5])
h(doc,2,"7.3 품질 게이트")
para(doc,"각 Phase 종료 및 배포 직전에 품질 게이트를 두어 완료 기준·경계면 정합·보안 체크리스트·회귀 통과를 확인하고 통과 시에만 다음 단계로 진행한다.")

# ---------- 8. 보안·개인정보 ----------
h(doc,1,"8. 보안 및 개인정보보호 계획")
h(doc,2,"8.1 보안 불변 원칙")
table(doc, ["구분","원칙"],
    [["외부 API 정책","온프레미스 모델 우선. 텍스트 AI는 승인된 단일 예외 경로만, 이미지 생성은 킨텍스 고유 승인 예외(워커 전용). 그 외 외부 API 금지."],
     ["자격증명 보호","내부 IP·SSH 계정·비밀번호·해시·API 키·워커 토큰을 API 응답·로그·에러·커밋에 절대 노출 금지."],
     ["암호화 저장","admin 비밀번호는 env(AES-256-GCM 암호문)+별도 키파일로 기동 시 재시드(하드코딩 시드 금지). 저장 자격증명은 암호화 컬럼에만."],
     ["인증·권한","JWT(HS256)+2차 인증(OTP/EMAIL)+로그인 실패 잠금. 행사 단위 RBAC. 미등록 장치업체 초대·응찰 차단."],
     ["AI 이미지 워터마크","시각화 결과는 항상 워터마크·고지 포함(참고용, 계약·인허가 서류 사용 불가)."],
     ["오류 응답","스택트레이스·relation/컬럼명·내부 경로 미노출. 코드+요약 메시지만 반환."],
     ["감사 추적","관리자·인증·권한·낙찰·설계변경·개인정보 접근 등 민감 액션 감사 로그 기록(비밀값 미기재)."]],
    widths=[3.5, 12.5])
h(doc,2,"8.2 개인정보보호")
bullets(doc,[
 "관람객 배지 QR·리드캡처 데이터는 수집·이용 동의 및 보존 기간 정책을 필수 적용.",
 "리드(개인정보) 접근은 감사 로그로 전수 기록, 표시 필드는 비민감 항목으로 최소화.",
 "EDM 발송은 정보통신망법·수신 동의 규정을 준수.",
 "개인정보는 최소 수집·목적 제한·접근 통제(RBAC) 원칙을 적용.",
])
h(doc,2,"8.3 보안 체크리스트(배포·리뷰 전)")
bullets(doc,[
 "응답/로그/커밋에 IP·SSH·비번·해시·API 키·워커 토큰 노출 0(grep).",
 "AI 키(텍스트/이미지)는 env only — 코드·DB·커밋 미포함.",
 "admin 비번 하드코딩 시드 없음(env 재시드).",
 "시각화 이미지 응답에 워터마크 필드 포함.",
 "DB/서버 오류 → 요약 메시지(스택·relation 명 미노출).",
 "관리자 게이트·행사 RBAC·미등록업체 차단 동작.",
])

# ---------- 9. 시험 계획 ----------
h(doc,1,"9. 시험(테스트) 계획 개요")
h(doc,2,"9.1 시험 레벨")
table(doc, ["레벨","대상","방식"],
    [["단위 시험","서비스·매퍼·룰 엔진·배선 엔진","개발자 단위 테스트, 공간 연산(PostGIS) 정합 검증"],
     ["통합 시험","모듈 간 경계면(API↔프론트, 큐↔워커)","API 응답 shape 대조, WebSocket/큐 왕복"],
     ["시스템 시험","역할별 시나리오(주최자/참가/업체/홀매니저/관람객)","E2E 시나리오·규정 검증·시각화 워터마크 확인"],
     ["회귀·스모크","전 기능","배포 전 스모크(헬스+라우터 등록+로그인 프로브)·회귀"],
     ["보안 시험","보안 불변 규칙","자격증명 미노출·RBAC 우회·스택트레이스 차단 점검"]],
    widths=[2.6, 6.4, 7.0])
h(doc,2,"9.2 시험 원칙")
bullets(doc,[
 "각 모듈 완성 직후 QA가 점진 검증하고, 통과할 때까지 반려.",
 "공간 로직(배치·배선·규정 검증)과 시각화 워터마크 강제는 필수 검증 항목.",
 "시험 케이스·결과는 별첨 [WBS_및_일정.xlsx]의 '시험케이스' 시트와 형상관리 하 리포트로 관리.",
])

# ---------- 10. 이관·교육·유지보수 ----------
h(doc,1,"10. 이관·교육 및 유지보수 계획")
h(doc,2,"10.1 이관 계획")
bullets(doc,[
 "빌드 산출물(프론트 번들·백엔드 실행 파일·워커 서비스)과 마스터데이터·형상 이력을 발주처 운영 환경으로 이관.",
 "이관 시 무중단·헬스게이트·롤백(Fail-Safe) 배포 절차를 적용.",
 "운영 도메인·운영 환경변수 배선은 발주처 승인 하에 수행.",
])
h(doc,2,"10.2 교육 계획")
table(doc, ["대상","교육 내용","형식"],
    [["운영자/관리자","백오피스(RBAC·마스터데이터·규정 룰셋)·감사·시스템설정","운영자 지침서+실습"],
     ["킨텍스 운영팀(홀매니저)","배치 검수·규정 플래그·현장 운영 대시보드","사용자 지침서+실습"],
     ["주최자/참가업체","포털 사용(배정·설계·유틸리티·옥션·관람객)","사용자 지침서·온라인 가이드"]],
    widths=[4.0, 8.0, 4.0])
h(doc,2,"10.3 유지보수 계획")
bullets(doc,[
 "장애 대응·정기 점검·규정/요율 개정 반영(룰셋 버전 관리)을 유지보수 범위로 한다.",
 "운영 런북(헬스체크·재기동·롤백)을 기준으로 SM 운영 체계를 수립.",
 "규정·요율 연 단위 개정은 관리자 백오피스 룰셋 버전 관리로 안전 반영.",
])

# ---------- 11. 위험 관리 (sources.RISKS) ----------
h(doc,1,"11. 위험(리스크) 관리")
para(doc,"주요 리스크와 대응 방안은 아래와 같으며, 형상관리 하 리스크 대장으로 지속 관리한다.")
table(doc, ["ID","리스크","영향","대응 방안"],
    [list(x) for x in S.RISKS], widths=[1.2, 4.2, 2.6, 8.0])

# ---------- 12. 의사소통·보고 ----------
h(doc,1,"12. 의사소통·보고 체계")
table(doc, ["보고/회의","주기","참여","내용"],
    [["착수 보고","사업 착수 시","발주처·PMO","범위·일정·조직·리스크 확정"],
     ["주간 진척 보고","주 1회","PMO·개발 리드","진척·이슈·리스크·다음 주 계획"],
     ["Phase 종료 보고","각 Phase 종료","발주처·PMO","산출물·품질 게이트 결과·다음 단계"],
     ["단계별 검토회의","마일스톤","전 트랙","경계면 정합·아키텍처 준수 점검"],
     ["완료(준공) 보고","사업 종료","발주처·PMO","통합 QA 결과·이관·교육·유지보수 인계"]],
    widths=[3.6, 2.6, 3.4, 6.4])
para(doc,"긴급 이슈는 즉시 에스컬레이션하며, 모든 의사결정·변경은 형상관리(14장) 절차로 기록한다.", size=9, italic=True, color=GREY)

# ---------- 13. 산출물 목록 (sources.DELIVERABLES) ----------
h(doc,1,"13. 산출물 목록(단계별 표준 산출물)")
para(doc,"단계별 표준 산출물은 아래와 같으며, 상세 목록·형식·담당·상태는 별첨 [WBS_및_일정.xlsx]의 '산출물목록' 시트에 관리한다.")
table(doc, ["단계","산출물","형식","담당","상태"],
    [[d[0], d[1], d[2], d[3], d[4]] for d in S.DELIVERABLES],
    widths=[2.4, 6.2, 2.2, 3.0, 2.2])

# ---------- 14. 형상관리 ----------
h(doc,1,"14. 형상관리")
h(doc,2,"14.1 형상관리 원칙")
bullets(doc,[
 "모든 소스·문서·설정은 Git(Gitea) 저장소로 버전 통제하며, 변경은 커밋 이력으로 추적.",
 "산출물(계획서·설계서·시험·지침서)은 docs/deliverables/ 지정 경로에서 형상 관리.",
 "DB 스키마는 Flyway 순번 마이그레이션을 형상 권위로 하며, baseline 규율과 시드 멱등화를 준수.",
 "배포는 형상(커밋) 기준 CI/CD Webhook으로 무중단·헬스게이트·롤백 수행.",
])
h(doc,2,"14.2 형상 항목 및 절차")
table(doc, ["형상 항목","관리 방식","변경 절차"],
    [["소스코드","Git 브랜치·PR·리뷰","리뷰 승인 후 병합, 커밋 메시지 이력화"],
     ["문서/산출물","Git 버전·개정 이력","개정 이력 기록 후 갱신"],
     ["DB 스키마","Flyway 마이그레이션","신규 마이그 번호=현재 최대+1(충돌 검사)"],
     ["설정/환경변수","env 주입·시크릿 분리","키·비번은 형상에서 제외(gitignore)"],
     ["배포","CI/CD Webhook·헬스게이트","실패 시 자동 롤백"]],
    widths=[3.4, 5.6, 7.0])

doc.add_paragraph()
para(doc,"— 본 사업수행계획서는 행정안전부 정보화사업 산출물 표준 목차를 준용하여 킨텍스 자동전시시스템 구축 사업의 원본 내용으로 작성되었다. —",
     size=9, italic=True, color=GREY, align=CA)

doc.save(OUT)
print("SAVED:", OUT)
