批次維護:匯入匯出與文件匯出(Batch Operations)
功能群:專案管理|上層見 專案規劃頁(本頁=其 Header「批次維護」選單的三組批次作業)
事實基準:2026-07-06 從 FE / BE code 掃出;表結構對
db_schema.json、endpoint 對routes.json、欄位對 marshmallow serializer + 匯出 service 欄位定義逐條核|變更紀錄:2026-07-06 FR-047 從 project-planning.md 拆出並補匯入三步 field-level
1. 功能描述
批次維護是專案規劃頁 Header「批次維護」選單下的三組離線 Excel round-trip / 文件產出作業,供大量資料一次維護:① SSP 現況 Excel 匯出 / 匯入、② 任務配置 Excel 匯出 / 匯入、③ SSP 文件匯出(正式文件)。兩組 Excel 匯入共用同一條三步管線(匯出樣板 → 離線填 → 上傳驗證 → 線上修正重驗迴圈 → confirm 僅有效列寫入),只差 endpoint prefix;文件匯出是唯讀產出、不改資料。匯入的寫入路徑與逐筆編輯相同(現況走 現況編輯、任務走 任務配置)。
主要使用者:專案 manager(匯入寫入);匯出 / 文件產出參與者即可(唯讀)。
角色速覽(完整定義見 _overview §3):
| 角色 | 一句話 |
|---|---|
| manager | 專案經理 — 批次匯入寫入的擁有者 |
| 參與者 | auditor / viewer — 可匯出 / 產文件,不可匯入 |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | SSP 現況 Excel 匯出 | 匯出現況樣板供離線填寫(9 欄,含隱藏 statement_id) | 批次維護選單 | §6.2 |
| 2 | SSP 現況 Excel 匯入 | 上傳 → 驗證預覽 → 線上修正重驗 → 僅有效列批次寫入 | 批次維護 → dialog | UC-PP-03 |
| 3 | 任務配置 Excel 匯出 / 匯入 | 任務指派設定的批次維護,同三步驗證流程 | 批次維護 → dialog | UC-PP-06 |
| 4 | SSP 文件匯出 | 把 SSP 匯出成正式文件(docx / pdf / odt / json / yaml / xml) | 批次維護 → 匯出文件 | UC-PP-07 |
UC(§2)展開三條核心路徑:SSP 現況匯入 UC-PP-03、任務配置匯入 UC-PP-06、文件匯出 UC-PP-07(兩組匯入共用三步管線,逐欄見 §6.2)。
2. Use Case
角色速覽(同 §1)。流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-PP-03 SSP 現況批次匯入
| 項目 | 內容 |
|---|---|
| 角色 | 專案 manager |
| 前置條件 | 輪次 = planning(否則匯入按鈕 disabled) |
| 產出 / 後置條件 | 同 現況編輯
的寫入路徑批次執行;僅通過驗證的有效列寫入;檔案格式錯 →
GRC_400001 |
UC-PP-06 任務配置批次匯入 / 匯出
| 項目 | 內容 |
|---|---|
| 角色 | 專案 manager(批次維護入口) |
| 前置條件 | 輪次 = planning;本輪已有 AP(apUid)與衍生任務 |
| 產出 / 後置條件 | 同 任務配置
的寫入路徑批次執行;僅有效列寫入指派;格式錯 →
GRC_400003 |
UC-PP-07 SSP 文件匯出
| 項目 | 內容 |
|---|---|
| 角色 | 參與者即可(唯讀匯出,不改資料) |
| 前置條件 | 已定位當前輪次 SSP(planning 用 living SSP;launch-audit 後為凍結快照) |
| 產出 / 後置條件 | 無寫入;回傳所選格式的正式文件供瀏覽器下載 |
3. 權限矩陣
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 匯出樣板 / 文件 | 參與者即可 | @jwt_required()(唯讀) |
各 export route |
| SSP 現況匯入 confirm | canEdit(manager 且 planning)才顯示按鈕 |
寫入走現況 upsert 路徑(require_manager) |
ssp_control_impl_import_service.confirm_import →
現況寫入 |
| 任務配置匯入 confirm | 同上 | ⚠️ 走 job 寫入路徑(無角色守門,同 任務配置 §12) | job_import_service.confirm_import |
route 層皆
@jwt_required();SSP 現況匯入最終經require_manager,任務匯入的 job 寫入無角色守門——與逐筆編輯的守門強度一致(見各子頁)。
4. 狀態機與前置條件
承接輪次 planning gate(見 規劃頁
§4):apStatus === 'planning'
匯入按鈕才可用;文件匯出不限階段(凍結後匯出快照 SSP)。
5. UI 設計
版面骨架(批次維護選單三組作業 + 共用三步匯入管線 + 代表性 API):
📸 實機截圖(亮色模式):批次維護選單展開見 規劃頁 §5 的
planning-batch-menu.png。
狀態呈現:匯入走
dialog,上傳後顯示驗證結果表(valid_count /
error_count + 逐列
errors);有錯列可在表內修正後「重新驗證」(迴圈),僅
error_count=0 或使用者確認後才可
confirm。文件匯出直接觸發瀏覽器下載。
6. API 規格
Envelope:匯入類成功 {"status": true, "data": …};匯出 /
文件為 send_file(非 envelope,直接下載)。
6.1 總清單
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| SSP 現況 | GET /ssp/{sspUid}/control-implementations/export |
匯出現況 Excel 樣板 | §6.2 |
| SSP 現況 | POST .../control-implementations/import |
上傳 Excel + 驗證(Step 1) | §6.2 |
| SSP 現況 | POST .../control-implementations/import/validate |
線上修正後 JSON 重驗(Step 2 迴圈) | §6.2 |
| SSP 現況 | POST .../control-implementations/import/confirm |
確認 — 僅有效列批次寫入(Step 3) | §6.2 |
| 任務配置 | GET /grc/project/{uid}/ap/{apUid}/jobs/export |
匯出任務配置 Excel 樣板 | §6.2 |
| 任務配置 | POST
.../jobs/import・/import/validate・/import/confirm |
任務配置三步匯入 | §6.2 |
| 文件 | GET /ssp/{sspUid}/export?format=… |
SSP 文件匯出(6 格式) | §6.2 |
6.2 核心 endpoint
三步匯入管線兩組共用形狀(差在 endpoint prefix 與欄位):Step
1 POST .../import(multipart
file,回驗證結果)→ Step 2
POST .../import/validate(JSON
{items},前端修正後重驗,可迴圈)→ Step 3
POST .../import/confirm(JSON
{items},僅寫有效列)。上傳非 Excel 範本 → SSP
GRC_400001 / 任務 GRC_400003。
SSP 現況
— Excel 樣板欄位(control-implementations/export)
| 欄 | 標頭 | 對應欄位 | 說明 |
|---|---|---|---|
| A | (隱藏)statement_id | objective_id |
AO part_id,回寫定位用 |
| B | 控制項識別碼 | control_identifier |
如 AC.L1-3.1.1 |
| C | 控制項名稱 | control_name |
|
| D | 實作狀態 | implementation_status |
下拉驗證(5 值) |
| E | 現況描述 | implementation_description |
|
| F | 檢查項目名稱 | objective_name |
AO 名稱 |
| G | 檢查項目實作狀態 | obj_implementation_status |
下拉驗證 |
| H | 檢查項目現況描述 | obj_implementation_description |
|
| I | 參考程序書 | reference_documents |
出處:app/oscal/service/ssp_control_impl_import_service.py:10-56(欄位定義)
SSP 現況 — 三步 request / response
Step 1/2
回傳(ImportValidationResponseSchema):
| 欄位 | 型別 | 說明 |
|---|---|---|
| valid_count / error_count | int | 有效 / 錯誤列數 |
| items | array | 每列 ImportRowSchema(見下) |
item(ImportRowSchema):row(int)
/ control_identifier / control_name /
objective_id / objective_name /
task_uid / implementation_status /
implementation_description /
obj_implementation_status /
obj_implementation_description /
reference_documents /
errors[]({field, message})。
Step 2/3
request(ImportConfirmRequestSchema):{items: [ImportConfirmItemSchema]}——item
同上但不含 errors、control_identifier
required。Step 3 confirm
回傳(ImportConfirmResponseSchema):{updated_controls, updated_objectives, total, skipped_count}。出處:serializer
api/oscal/serializers/ssp/ssp_control_impl_import.py、route
api/oscal/routes/ssp/ssp_control_impl_import_route.py
任務配置 — Excel
樣板欄位(jobs/export)
標頭:任務識別碼(job_uid)/
任務名稱(job_name)/
任務類型(job_type,下拉驗證
general·survey)/
指派人員(assignees,逗號分隔
login_name)/ 參與部門(departments)/
設備(devices);另帶控制項 / AO 名稱
context
欄。出處:app/grc/service/job_import_service.py:40-44。
任務配置 — 三步 request / response
Step 1/2
回傳(JobImportValidationResponseSchema):{valid_count, error_count, items};item(JobImportRowSchema):row
/ job_uid / job_name /
control_name / ao_name / job_type
/ assignees / departments /
devices / errors[]。Step 2/3
request(JobImportConfirmRequestSchema):{items: [JobImportConfirmItemSchema]}——job_uid
/ job_type / assignees
required。confirm
回傳:{updated_count, skipped_count}。驗證含:job_uid
非空且屬本 AP、不重複;job_type 必填且有效;assignees
必填。出處:serializer
api/grc/serializers/job_import.py、service
app/grc/service/job_import_service.py:190-241
[GET] /ssp/{ssp_uid}/export?format=…
SSP 文件匯出。format ∈ docx(預設)/
pdf / odt / json /
yaml / xml(6 格式);回
send_file(Content-Disposition 帶 system_name + 作者
nickname,RFC 5987 Unicode
檔名)。無寫入。出處:api/oscal/routes/ssp/ssp_export_route.py:35-71、service
SspExportAppService.export_from_ssp_version
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/project/ProjectPlanningView.vue |
批次維護選單 + 匯出下載 + 匯入 dialog 觸發 |
SspImportDialog / JobImportDialog |
兩組匯入的三步 dialog(上傳 → 驗證表 → 修正重驗 → confirm) |
src/service/SspService.js |
exportExcel / import / validate / confirm 包裝 |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| SSP 現況匯入匯出 | api/oscal/routes/ssp/ssp_control_impl_import_route.py |
SspControlImplImportService(export_excel
/ validate_import / revalidate_items /
confirm_import) |
匯入寫入走現況 upsert(IR / statement props)+ 程序書
SspDocumentPoolService |
| 任務配置匯入匯出 | api/grc/routes/job_import_route.py |
JobImportService(同四法) |
匯入寫入走 job 更新路徑(task_assignees 等) |
| SSP 文件匯出 | api/oscal/routes/ssp/ssp_export_route.py |
SspExportAppService.export_from_ssp_version |
OSCAL → docx/pdf/… renderer |
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
匯入的寫入表與逐筆編輯完全相同(本頁不另開寫入路徑):
| 表 | 讀寫 | 說明 | 詳述 |
|---|---|---|---|
| oscal.ssp_implemented_requirements / ssp_statements | 寫 | SSP 現況匯入(同現況編輯路徑) | 現況編輯 §9.3 |
| oscal.ssp_reference_documents | 寫 | 程序書關聯(匯入的參考程序書欄) | 現況編輯 §9.3 |
| compliance.job_executions + task_assignees / org_units / devices | 寫 | 任務配置匯入(同任務配置路徑) | 任務配置 §9.3 |
| oscal.system_security_plans | 讀 | 文件匯出來源(living / 凍結快照) | GAI-SD-03 |
文件匯出唯讀;匯入 confirm 是逐筆寫入路徑的批次包裝,DB 效果與逐筆編輯一致。
10. 頁面邏輯與資料對應
三步管線 state:Step 1 上傳回
{valid_count, error_count, items[]} →
前端渲染驗證表;使用者改 item → Step 2 validate 重驗(更新
items 的 errors)→ 迴圈至可接受 → Step 3 confirm 僅寫
error_count=0 的有效列,回
{updated_*, skipped_count}。匯出:exportExcel
取 blob → URL.createObjectURL
觸發下載。錯誤對應:GRC_400001(SSP
檔格式)/ GRC_400003(任務檔格式)/ 逐列
errors[].message → 表內標紅。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| socket | 無(confirm 後前端重載樹) |
| 檔案 | 匯出 / 文件走 send_file 直接下載,不落地伺服器 |
| 共用 | 匯入寫入路徑與逐筆編輯共用(現況 / 任務) |
| 依賴 | openpyxl(Excel 讀寫 + data validation 下拉)、SSP
export renderer |
12. 邊界情況與已知坑
- 隱藏 statement_id 欄不可刪:SSP 現況樣板 A
欄是隱藏的
statement_id(AO 回寫定位鍵),使用者若在 Excel 刪欄 / 動列序會導致回寫錯位——匯入以此欄比對。 - confirm 只寫有效列:
error_count > 0時 confirm 仍可送,但只寫通過驗證的列、其餘計入skipped_count;使用者以為「全部匯入」實際跳過錯誤列,需看回傳的skipped_count。 - 任務匯入指派用 login_name
字串比對:
assignees欄是逗號分隔 login_name,匯入時字串 → user 比對;打錯名字該列報錯(errors)。 - 任務匯入無角色守門:job 寫入路徑無 BE 角色檢查(同 任務配置 §12),批次匯入亦然——靠 FE 隱藏入口。
- 文件匯出 6 格式:route 支援 docx/pdf/odt/json/yaml/xml,UI 通常只露 docx/pdf/odt;json/yaml/xml 是 OSCAL 原生格式(開發 / 交換用)。
- 匯出母體取自 v2 catalog:SSP 現況匯出的控制 / AO
母體來自
ssp.import_profile_id → profile_imports.source_catalog_id(v2 catalog 鏈),非舊 AP——框架切換後匯出內容隨之變。