# SSP 匯入匯出 Phase 2 — 最終 SUMMARY（2026-05-22）

## 一句話摘要

Track A（Excel 匯入 A0~A5）+ Track B（SSP 匯出 B1~B6）全部 shipped，含 DB schema 擴充、9 大資料領域匯入鉤稽、6 種格式匯出（docx/pdf/odt/json/yaml/xml）。

---

## 功能範圍

### Track A：Excel 匯入

| Phase | 功能 | 狀態 |
|-------|------|------|
| A0 / A0.1 | DB schema 擴充（3 張表 + backfill） | ✅ shipped |
| A1 | Excel 樣板設計 + 下載 | ✅ shipped |
| A2 | Excel Parser + 解析 API | ✅ shipped |
| A3 | 共用 matcher（parties / org-units 鉤稽） | ✅ shipped |
| A4 | devices / info_systems / leveraged / 控制項 / AO / 程序書 鉤稽 | ✅ shipped |
| A5 | 預覽 UI + Confirm 寫入 | ✅ shipped |

### Track B：SSP 匯出

| Phase | 功能 | 狀態 |
|-------|------|------|
| B1~B4 | DOCX generator + MF/SSP version loader + PDF/ODT | ✅ shipped |
| B5 | OSCAL JSON / XML / YAML | ✅ shipped |
| B6 | FE 匯出按鈕 + CMMC DOCX 格式升級 + bugfixes | ✅ shipped |

---

## Commit 清單（feature/ssp-import-export-phase2 vs main）

### BE（compliance-manager-be）重點 commits

| Commit | 說明 |
|--------|------|
| `c4804d7` | A0 schema 擴充 |
| `eb9fa7e` / `6deacef` | A0.1 重整補丁 |
| `b18db55`→`2b1e93c` | A1 Excel 樣板 (16 commits) |
| `f7b44ff`→`43cc206` | A2 Parser (7 commits) |
| `b011f2f`→`761fd7c` | A3 matcher (5 commits) |
| `57a9567`→`600f50a` | A4 寫入 pipeline (10 commits) |
| `535b931`→`c61ef02` | A5 BE (6 commits) + bugfix x3 |
| `062782d` | B1~B4 docx pipeline |
| `25909f2` | B5 OSCAL 格式 |
| `8df2525` | B6 DOCX 格式升級 |
| `8ee55f5` | fix: LibreOffice binary 自動偵測 |
| `43a9389` | fix: Unicode 檔名 (BE) |

### FE（compliance-manager-fe）重點 commits

| Commit | 說明 |
|--------|------|
| `e0ff8f1` / `00b6662` | A1 FE |
| `c95d02a`→`332b393` | A5 FE (5 commits) + bugfix x3 |
| `7231b6a` | B6 匯出按鈕 |
| `c21372c` | fix: Unicode 檔名 (FE) |

### jedi-oscal（套件）

| Commit | 說明 |
|--------|------|
| `afe7035`→`dbb3d7c` | A0 ORM/repo/mapper/DTO 擴充 |
| `762d8fc`→`4666091` | A0.1 重整同步 |
| `0.0.17` pin | 主專案 pyproject.toml 鎖定版本 |

---

## 升版步驟

### 前置確認

```bash
# 確認 branch 已 merge 到 main 或在 main 上
git log --oneline -3

# 確認 pyproject.toml 是 Nexus pin（不是 path dep）
grep "jedi-oscal" pyproject.toml
# 預期: jedi-oscal = "0.0.17" 或更高，不是 { path = "..." }
```

### Step 1 — DB Migration（cmmgr 帳號）

```bash
PGPASSWORD='<查 .env DB_SECRET rds_master_password>' \
psql -h <DB_HOST> -p <DB_PORT> -U cmmgr -d <DB_NAME> \
    -f scripts/sql/2026-05-22-ssp-import-export-phase2-upgrade.sql
```

> **⚠️ RENAME 不冪等**：若環境已部分執行過舊 migration，先跑確認查詢，
> 已完成的 step 手動跳過。確認方式：
> ```sql
> -- 若回傳 NULL 代表 Step 2 已跑（表已改名），可跳過 Step 2
> SELECT to_regclass('oscal.system_security_plan_system_implementations');
> ```

### Step 2 — 安裝相依套件

```bash
poetry update
# 或指定版本：poetry update jedi-oscal
```

### Step 3 — 部署 BE

```bash
# 停舊 process
lsof -ti:8000 | xargs kill -9

# 啟動
python main_socketio.py
# 或 nohup python main_socketio.py > log/app.log 2>&1 &
```

### Step 4 — 部署 FE

```bash
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
npm run build
# 或 yarn build
```

> FE 有 3 個修改檔需確保已 build：
> - `src/views/module_frame/ModuleFrameTemplateEditView.vue`
> - `src/views/project/ProjectPlanningView.vue`
> - `src/components/grc/DownloadSspBlankTemplateDialog.vue`

### Step 5 — 系統需求確認（PDF/ODT）

PDF / ODT 匯出依賴 LibreOffice：

```bash
# macOS
brew install libreoffice   # 若尚未安裝

# Linux (Debian/Ubuntu)
apt-get install libreoffice

# 自訂 binary 路徑（非標準位置）
export LIBREOFFICE_CMD=/path/to/soffice
```

### Step 6 — Smoke Test

```bash
# 取 JWT token（blsadmin / Billows@123!）
TOKEN=$(...)

# 1. Excel 樣板下載
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8000/api/1.0/module-frame/3699fc01.../ssp-template?source=module_frame&mode=filled" \
  -o test_template.xlsx

# 2. DOCX 匯出（確認中文檔名）
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8000/api/1.0/module-frame/3699fc01.../ssp-export?format=docx" \
  -OJ    # -OJ 讓 curl 用 Content-Disposition 的 filename

# 3. PDF 匯出（確認 LibreOffice 正常）
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8000/api/1.0/module-frame/3699fc01.../ssp-export?format=pdf" \
  -OJ

# 4. OSCAL JSON 匯出
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8000/api/1.0/ssp/<ssp_uid>/export?format=json" \
  -OJ
```

---

## 已知遺留項目（非阻塞）

| 項目 | 說明 | 優先級 |
|------|------|--------|
| E2E 測試 | A1/A2/A3/A4/B 全線缺 cucumber | 低（下一輪補） |
| Pending issue | `docs/issues/pending/2026-05-19-person-role-cross-domain-inconsistency.md` | 中 |
| Docx parser 對齊 | 需求文件 Q3 明確 defer，等 Phase 2 完工後處理 | 低 |
| `_resolve_ssp_id` 多版本 SSP | `get_one(profile_id=...)` 隨機取，latent issue | 低 |
| AO 無中文翻譯 | catalog 尚無 ZH 翻譯 | 低 |
| jedi-oscal 正式發版流程 | 完整 bump + Nexus push — 待 user 明確指示 | 待 user |

---

## 新增的 SQL 檔

```
scripts/sql/2026-05-18-extend-ssp-system-implementations.sql    ← A0
scripts/sql/2026-05-19-ssp-system-implementation-restructure.sql ← A0.1
scripts/sql/2026-05-19-backfill-ssp-system-implementation-items-device-id.sql
scripts/sql/2026-05-20-ssp-excel-parse-jobs.sql                 ← A2
scripts/sql/2026-05-21-ssp-excel-import-consolidated.sql        ← 舊整合入口（\ir 版）
scripts/sql/2026-05-22-ssp-import-export-phase2-upgrade.sql     ← 本次整合（單檔，升版用）
```

升版一律跑 `2026-05-22-ssp-import-export-phase2-upgrade.sql`，其餘子檔保留備查。
