FR-148 · 設計文件 · 2026-10-18(D1~D16 全數定案)

一張任務卡走完「開始 → 1 → 2 → 3 → 結案」

關卡是任務裡面的事;BPMN 流程圖一顆方塊一筆任務,不動圖

管理員在系統設定建幾個任務關卡樣板(只是關卡骨架:名稱、說明、順序,不設負責人);PM 在規劃頁替任務選樣板、每一關各派部門+人員(可多人);任務卡上多一條關卡進度,按鈕跟著「你是不是當下那關的人」變(送審/核可/退回),每換一關通知下一關的人;走完最後一關才呼叫既有的「完成任務」讓流程往下走。出廠預設是零關的「無關卡」=現狀,沒設定的客戶什麼都不會變。

D1~D16 全數定案(D3 作廢) 6 張實作卡,畫面先出 不動 BPMN 引擎、不動流程圖 動 jedi-flow-engine(任務表加兩欄) 陷阱:待辦清單的 view 只讀原指派表

狀態:設計定案(D1~D16),待開卡|日期:2026-10-18 討論稿(含四方案比較、被排除選項):discussion.html|雛形:prototype/index.html 開發 branch:三個 repo 目前都在 feature/FR-139(開工前 runner 自己 git branch --show-current 確認,不對就停下問)

🔴 這份是設計決策,不是現況。 內文的行號停在 2026-10-18 定稿當時,實作改動的結果不回頭改寫這裡——現況看實作完成後的 FINAL-SPEC.md。

路徑慣例:BE 路徑相對 compliance-manager-be/;pkg/ 代表 ~/Projects/Jedicogy/module/jedi-python-package/;FE 路徑相對 compliance-manager-fe/。

變更紀錄

日期 變更 對應
2026-10-18 初版設計定案:D1~D15、資料模型、六卡拆分、端到端驗收 FR-148
2026-10-18 §5.7/D7 改「任務建立時套公司預設」:runner 實查「啟動稽核」在任務做完之後,原設計的掛點不成立;決策者裁 A CM-2885
2026-10-18 新增 D16 退回只到上一關;§5.4 退回彈窗、§5.6 樣板編輯彈窗改版(Steps 預覽、名稱說明分兩列、關卡表不放開始/結案) 決策者裁示
2026-10-18 內建零關樣板改名「無關卡」 決策者裁示

1. 需求背景與端到端流程

1.1 一句話

一個任務要經過「交證據 → 主管審 → 顧問審」時,是同一張卡依序交給不同的人,不是三張卡。

1.2 要解的問題

現在任務只有「未開始/進行中/已完成」三態。想讓一個任務經過主管、顧問兩道審核,只能在流程圖畫三個方塊——而流程圖的規則是一個方塊=一筆任務(FR-112 定的,證據、留言、問卷、執行紀錄全掛在那一筆上),於是變成三張卡:證據在第一張、主管在第二張看不到證據、顧問在第三張看不到前兩張的留言。

1.3 給非工程讀者的三個名詞

  • 任務關卡樣板:系統設定裡的一份關卡清單,例如「標準三關:執行人交證據、主管審核、顧問審核」。只有關卡的名稱與順序,不寫誰負責。
  • 關卡:任務走到的某一站。畫面上長「開始 → 1 → 2 → 3 → 結案」,開始與結案只是兩個端點,中間的數字才是關卡。
  • 零關:一關都沒有的樣板(內建的「無關卡」),就是今天的做法——指派人員按完成就結束。

1.4 端到端流程

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
    participant AD as 管理員
    participant PM as 專案管理者
    participant EX as 執行人(第 1 關)
    participant MG as 主管(第 2 關)
    participant CS as 顧問(第 3 關)
    participant BE as 後端
    participant WF as BPMN 引擎(不改)
    AD->>BE: 系統設定建樣板「標準三關」
    PM->>BE: 規劃頁替任務選樣板(複製一份到任務)+每關派部門/人員
    Note over WF: 專案啟動,方塊實體化成進行中(既有)
    BE-->>EX: 通知(既有 notify_user_todo_job,收件人=第 1 關)
    EX->>BE: 上傳證據、按「送審」
    BE->>BE: 目前關卡 1→2、寫歷程
    BE-->>MG: 通知「待你處理」
    MG->>BE: 看同一張卡的證據與留言,退回到第 1 關+理由
    BE->>BE: 目前關卡 2→1、寫歷程
    BE-->>EX: 通知「被退回」+理由
    EX->>BE: 補證據、再送審
    MG->>BE: 核可
    BE-->>CS: 通知
    CS->>BE: 核可並結案
    BE->>WF: complete_job()(既有)
    WF->>WF: 下一方塊實體化、通知其執行人(既有)
圖 1 — 一張卡從套樣板到結案(含退回)

2. 分工概述(30 秒版)

整案一句話:任務身上帶一份從樣板複製來的關卡清單+每關一組人,同一張卡依序換手,走完最後一關才讓流程往下;出廠預設零關=現狀。

卡 做什麼 產出 決策者檢查法
① 任務卡關卡進度+送審/核可/退回+歷程 任務卡標頭多關卡進度、狀態標籤右邊多時鐘圖示開歷程彈窗、底部按鈕跟著當下那關的人變、每換一關寄信 五張新表+任務兩欄的 migration、推進/退回 service 與三支端點、FE 三個子元件 對照 雛形頁 1:DEV 手灌一個三關任務,用三個帳號各登入一次走送審→核可→核可並結案,歷程三筆、每步下一關的人收到信;主管退回時執行人收到信且卡回第 1 關
② 待辦任務頁 第 2 關以後的人也看得到任務;多「目前關卡」欄、「待我處理」段 vw_user_job_queue 併入關卡指派表、待辦查詢加兩欄一條件、FE 欄與段 對照 雛形頁 2:主管帳號登入,「待我處理」看得到等他審的那筆;執行人帳號看到被退回的那筆
③ 系統設定「任務關卡樣板設定」 清單+編輯 dialog(版型同專案列表);建/改/刪樣板;內建「無關卡」 CRUD 端點、能力點、FE 清單頁與 dialog、ui_routes 選單 對照 雛形頁 4:新增一個兩關樣板、改順序、設預設,重開頁面還在;「無關卡」刪除鈕是灰的
④ 規劃頁選樣板+每關指派+套用到其他任務 任務表單的「部門+人員」兩格換成一行摘要+「設定」;彈窗內選樣板、每關一組部門→人員、套用到其他任務;開始後樣板鎖、人可改 套樣板端點、每關指派端點、批次套用端點、FE 摘要列與彈窗子元件 對照 雛形頁 3:選「標準三關」、三關各派人、存檔重開還在;已開始任務換不了樣板但能換人,新加的人(若是當下那關)收到信
⑤ 啟動預設、退回重開、批次推進、啟動前提醒 專案啟動時沒選樣板的任務帶公司預設;管理員退回重開時回第 1 關;批次完成改成推進當下那一關;啟動前軟提醒加「有關卡沒派人」 啟動掛點、兩處重開 hook、批次完成改寫、PlanningReadinessChecker 加一項 已結案任務退回重開 → 回第 1 關、執行人收到信;待辦勾三筆按批次完成,三筆各前進一關;有關卡沒派人時按啟動會跳確認視窗列出
⑥ 任務配置 Excel 對齊 指派/部門兩欄改為第 1 關;加唯讀「任務關卡」摘要欄;填寫說明加一句 job_import_service.py、task_guidance_workbook 填寫說明、JobImportDialog.vue 預覽加唯讀欄 匯出一份含三關任務的檔,看到摘要欄;改第 1 關的人匯入,第 2、3 關的人不變

依賴:① 是地基(表與 service),先做;②③ 只依賴 ①,可平行;④ 依賴 ①③;⑤ 依賴 ①④;⑥ 依賴 ①④。卡的排序以「決策者何時看得到畫面」為準——① 做完就能用 DEV 手灌資料看到任務卡走完整條。

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
    C1[① 任務卡關卡進度<br/>表+service+任務卡] --> C2[② 待辦任務頁]
    C1 --> C3[③ 任務關卡樣板設定]
    C3 --> C4[④ 規劃頁選樣板<br/>每關指派]
    C4 --> C5[⑤ 啟動預設/退回重開<br/>批次推進/啟動提醒]
    C4 --> C6[⑥ 任務配置 Excel]
圖 2 — 六張卡的依賴

3. 決策定案(D1~D16)

# 定案 理由 被排除
D1 樣板不設負責人;每關由誰做是 PM 在規劃頁指派,跟現在指派任務人員同一套操作(部門→人員),每關可多人。第 1 關=原本的指派人員 樣板是公司層範本、誰做是專案的事;沿用現有操作 樣板上填專案角色、跑到那關查角色——多一層間接,PM 看不出某關是誰
D2 畫面呈現「開始 → 1 → 2 → … → 結案」,開始/結案只是端點,不存資料、不編號、沒有人與按鈕 讓流程看起來完整;零關就是「開始 → 結案」,一眼看得出是直通 —
D3 作廢(D1 後不需系統找部門主管) — —
D4 同一關多人時,任一人核可或退回就算數;歷程記是誰 全部都要簽=會簽,要多一層「已簽幾個」,第一版不做 會簽
D5 任務開始後樣板不能換、關卡結構不能改,但每關的人可以改(D15 放寬);系統改樣板不影響已套用的任務(任務拿的是複製品) 避免「主管正在審、第 2 關被刪」;換人不改結構、常見(請假、換顧問) 開始後全鎖——沒派齊的關卡會卡死無人能補
D6 退回不清證據,執行人在原有證據上補 證據本來可以多筆,歷程記退回理由 標記「上一輪」證據
D7 系統出廠內建零關樣板「無關卡」並設為公司預設(seed migration 寫入;不可刪、不可改名、不可加關)。任務建立時沒選樣板就帶公司預設(三個建立點;不在啟動稽核套,見 §5.7);已在跑的舊專案不回頭套 預設=現狀,沒設定的客戶什麼都不會變;管理員自己改預設才會變 「標準三關」當預設
D8 待辦頁批次完成:推進每筆當下那一關(第 1 關=送審、審核關=核可、零關=完成);只有當下那關有你的任務勾得到;退回仍要逐筆 執行人一次交十筆、主管一次核可十筆都常見;批次沒有理由欄 審核關不能批次
D9 問卷任務第一版不能套樣板,維持問卷自己的審核(待審核/待補充說明、approval_required、is_approver) 一起併要動 jedi-survey 發版+FE 12 檔 一次併
D10 資源庫任務範本不預設樣板 FR-147 剛做完那頁 —
D11 樣板建在系統層(帶 tenant_id),各專案在規劃頁自己決定哪些任務套哪一個、可「套用到其他任務」 公司建一次、全部專案能選;放系統層或專案層工作量相同 專案層——每個新專案要重建
D12 不做單一任務微調關卡(加減關、改名);要不同關卡就套不同樣板(不審=零關的「無關卡」) 微調讓「這個任務走哪套」無從追查 任務層微調
D13 規劃頁「任務配置」Excel 只管第 1 關:指派人員/參與部門兩欄=第 1 關;加一欄唯讀「任務關卡」摘要;第 2 關以後與樣板不進 Excel 關數不一,攤成欄會大半空格且欄位會跑;審核關通常固定幾人,彈窗設就夠 每關攤成欄
D14 改善計畫(POA&M)任務不套樣板,改善計畫頁與其 Excel 不動 稽核後才產生、走另一條流程 —
D15 啟動前「有關卡沒派人」是軟提醒,併入既有 PlanningReadinessChecker(按確認仍可啟動);搭配 D5 放寬讓開始後還能補人 與既有啟動檢查做法一致;硬擋會讓 PM 為一個顧問還沒定就整個專案動不了 硬擋
D16 退回只能退回上一關,第 1 關不能退;樣板不設退回目標。規則由後端算,存的 back_to_seqs 不採用(舊樣板與進行中任務一併適用) 每關各勾「可退到哪幾關」設定太複雜,實務上幾乎都是退給上一手 每關自訂可退回的關卡

用詞:系統設定選單「任務關卡樣板設定」、每筆「任務關卡樣板」、任務卡上那條「關卡進度」、每一站「關卡」。「流程」只留給 BPMN 流程圖。


4. 現況接入點盤點

元件 現況(2026-10-18 核對) 本案動作
任務狀態 JobStatus pkg/jedi-flow-engine/jedi_flow_engine/common/enum/job_code.py:TODO/PROCESSING/COMPLETED/CANCEL 不動。關卡在 PROCESSING 期間換手
任務表 compliance.job_executions ORM 在 pkg/jedi-flow-engine/jedi_flow_engine/infra/models/job_execution.py;FR-137/FR-140 已加週期、期限欄 加 review_step_no、review_template_id 兩欄(ORM 同步改套件,走 path dependency)
完成任務 api/flow_engine/routes/flow_engine_route.py:42 → workflow_execution_service.complete_job()(:623)把下一方塊實體化並 notify_user_todo_job 有關卡且未到最後一關時,此端點要擋(否則繞過關卡);推進 service 走到最後一關時由 BE 呼叫它
批次完成 app/flow_control/service/job_batch_complete_service.py:43 batch_complete(210 行) D8:有關卡的任務改走推進當下那一關
退回重開 app/flow_engine/service/job_reopen.py:10 reopen_job_execution(24 行);app/flow_control/service/job_restart_service.py:63 restart_from_first_station(週期重跑) 兩處結束時把目前關卡重設為第 1 關、寫一筆歷程
通知 workflow_execution_service.py:1209 notify_user_todo_job(job_id, assignees=None):只在任務 PROCESSING 時寄;沒給 assignees 就查 task_assignees 換關時把該關的人當 assignees 傳入;不新開管線
換人通知 job_service.py:503 _notify_newly_added_assignees:比對新舊名單,只寄給新加的人 每關換人比照:只寄新加的人、且只在該關是當下那關時寄
指派表 compliance.task_assignees pkg/jedi-task-platform/jedi_task_platform/participant/infra/model/task_assignee.py:is_approver(問卷審查人員專用)、role 不動。第 1 關=這張表;第 2 關以後另存新表
🔴 待辦清單 app/readmodel/service/my_jobs_app_service.py:51 → infra/readmodel/tasks/my_grc_jobs_query.py → view public.vw_user_job_queue(scripts/sql/view/vw_user_job_queue.sql,FROM compliance.task_assignees) view 要併入關卡指派表,不然第 2 關以後的人看不到任務
啟動前檢查 pkg/jedi-compliance-audit/jedi_compliance_audit/app/service/planning_readiness_checker.py(128 行)兩項軟提醒;接線 di_containers/flow_control/flow_control_containers.py:699;由 oscal_stage_handlers.py LaunchAuditOnCompleteHandler 呼叫,force 放行 加第三項「有任務的關卡沒派人」;動 jedi-compliance-audit 套件
規劃頁任務表單 FE src/components/grc/planning/AoTaskForm.vue(749 行,接近 800 上限):部門 MultiSelect(:436)→ 人員 MultiSelect 依部門篩(:443,usersInDepts/keepAssigneesInDepts);問卷任務多一排審核者開關(:448) 非問卷任務的部門+人員兩格換成摘要列+「設定」;彈窗另開子元件
任務卡 FE src/components/grc/JobExecutionDrawer.vue(2,344 行,已超標);標頭 JobDrawerHeader 關卡進度、歷程圖示+彈窗、動作區各開子元件,抽屜只插幾行
待辦頁 FE src/views/project/MyTasksView.vue(760 行) 加欄與段
任務配置 Excel app/flow_control/service/job_import_service.py(492 行):前九欄共用(task_guidance_workbook.py)+任務類型/指派人員/參與部門/設備;JobImportDialog.vue(443 行) D13
系統設定頁慣例 FE src/views/ 下 notify-config、system-menu-manage 等;版型參考 src/views/project/ProjectListView.vue(標題列+搜尋+表格卡+編輯 dialog) 新頁照專案列表版型

5. 詳細設計

5.1 資料模型

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
erDiagram
    review_step_templates ||--o{ review_step_template_items : "一個樣板多關"
    job_executions ||--o{ job_review_steps : "套樣板時複製"
    job_review_steps ||--o{ job_review_step_assignees : "每關的人(可多人)"
    job_executions ||--o{ job_review_step_logs : "每次推進/退回"
    review_step_templates {
        int id PK
        string uid
        int tenant_id "RLS"
        string name
        text description
        bool is_default "公司預設,每租戶最多一筆"
        bool is_builtin "內建無關卡"
    }
    review_step_template_items {
        int id PK
        int template_id FK
        int seq "1 起算"
        string name
        text description
        int[] back_to_seqs "退回目標,固定為上一關(D16)"
    }
    job_executions {
        int review_step_no "目前第幾關;NULL=零關"
        int review_template_id "來源樣板,只記錄"
    }
    job_review_steps {
        int id PK
        int job_execution_id FK
        int seq "1 起算"
        string name
        text description
        int[] back_to_seqs
    }
    job_review_step_assignees {
        int job_execution_id FK
        int seq "2 起算;第 1 關用 task_assignees"
        int user_id
        int org_unit_id "部門,可空"
    }
    job_review_step_logs {
        int id PK
        int job_execution_id FK
        int seq "在哪一關"
        string action "submit / approve / reject / reopen"
        int to_seq "退回到哪關"
        int user_id
        text note
        timestamptz created_at
    }
圖 3 — 新表與任務表

要點:

  • 表名用 review_step_*(程式識別),中文介面叫「任務關卡」。全部放 compliance schema。
  • review_step_no 為 NULL=零關(直通),行為與現況完全相同;非 NULL 時 1..N 是目前所在關卡,走完最後一關核可時呼叫 complete_job、欄位停在 N。
  • 第 1 關的人=task_assignees(原指派人員,含問卷的 is_approver 不動);第 2 關以後存 job_review_step_assignees。所以零關任務、問卷任務完全不碰新表。
  • 部門:第 1 關的部門沿用既有任務部門關聯(job_execution_org_unit);第 2 關以後的部門存在 job_review_step_assignees.org_unit_id(同一關選多部門時,每個「人×部門」一列;只選部門沒選人不算已指派)。
  • is_default:每租戶最多一筆,用部分唯一索引 WHERE is_default 保證。內建「無關卡」由 seed migration 為每個租戶寫一筆並設為預設;is_builtin=true 的不可刪、不可改名、不可加關。
  • RLS:review_step_templates 帶 tenant_id,FOR ALL 條件「超管或 app_tenant_allowed_for_session(tenant_id)」;其餘四張無租戶欄,跟隨父表(review_step_template_items 跟隨樣板、三張 job_* 跟隨 job_executions 所屬專案),並加進 test/security/database/test_project_scoped_tables_rls.py 清單。每張表 GRANT ... TO cm_app + sequence 權限。
  • 新表 ORM:樣板兩張放主專案 infra/;任務三張跟 job_executions 同層(主專案 infra/flow_control/,不放套件——套件只加兩個欄位,避免把關卡業務塞進流程引擎套件)。

5.2 推進與退回(核心 service)

新開 app/flow_control/service/review_step_service.py(不塞進已近千行的既有 service):

方法 誰能叫 做什麼
submit(job_uid) 第 1 關的人(task_assignees) 目前關卡 1→2;寫歷程 submit;通知第 2 關的人
approve(job_uid, note) 當下那關的人 若不是最後一關:關卡 +1、寫歷程、通知下一關;若是最後一關:寫歷程 approve、呼叫 workflow_execution_service.complete_job()
reject(job_uid, to_seq, note) 當下那關的人;note 必填;to_seq 必須在該關 back_to_seqs 內 關卡改成 to_seq、寫歷程 reject、通知 to_seq 那關的人
reset_to_first(job_execution) 內部(重開 hook 呼叫) 關卡回 1、寫歷程 reopen;caller 在 @transaction 內

規則:

  • 守門在 app service:先 resolve 任務 → 專案,assert_project_participant;再判「你是否在當下那關的名單」,不是就 ForbiddenError(新錯誤碼 GRC_403070 起)。
  • 任務不是 PROCESSING、或零關任務呼叫 submit/approve/reject → PreconditionFailedError(GRC_412070 起)。
  • 同一關多人任一人動作即算數(D4);併發時用條件式 UPDATE(WHERE review_step_no = :expected),更新 0 列就回 ConflictError(GRC_409048 起),避免兩人同時核可推進兩格。
  • 既有完成端點要擋:complete_job 進入點對「有關卡且 review_step_no 不是最後一關」的任務拋錯;推進 service 自己呼叫時帶內部旗標放行。否則前端舊按鈕或批次完成能繞過關卡。
  • 通知:呼叫 notify_user_todo_job(job_id, assignees=<該關的人>);文案沿用既有「待你處理」,被退回時多帶理由(若既有通知不支援理由欄,第一版只寄既有文案,理由看歷程)。

端點(api/flow_control/routes/ 新檔):

  • POST /grc/jobs/<job_uid>/review-steps/submit
  • POST /grc/jobs/<job_uid>/review-steps/approve body {note}
  • POST /grc/jobs/<job_uid>/review-steps/reject body {to_seq, note}
  • GET /grc/jobs/<job_uid>/review-steps → {template_name, current_seq, steps:[{seq, name, description, back_to_seqs, assignees:[{user_uid, name, dept_name}]}], logs:[{created_at, seq, step_name, action, to_seq, user_name, note}]}(歷程的人名照「審計欄位回傳規範」在 app service 批次轉 nickname)

5.3 任務卡(FE)

  • JobExecutionDrawer.vue 已超標,只插三行:在 JobDrawerHeader 下掛 <JobReviewStepBar>;標頭狀態標籤右邊掛時鐘圖示按鈕(角標筆數),點開 <JobReviewHistoryDialog>;描述區上方掛 <JobReviewActionBox>。底部原「完成任務」按鈕:有關卡時換成 <JobReviewActions>(送審/核可/核可並結案/退回)。
  • 關卡進度:開始、結案為虛線端點圖示(play/flag),中間數字節點下方列該關的人;當下那關高亮,若含目前使用者加「待你處理」小標。不能出現水平捲軸(節點依內容寬、連線吃剩餘空間)。
  • 退回 dialog:退回目標固定為上一關(D16)+理由必填。
  • 零關任務:關卡進度只畫「開始 → 結案」,按鈕維持「完成任務」,其餘不變。問卷任務:不顯示關卡進度。
  • UI 禁令:不准左側粗色邊框。字級、配色走 dark-card 與全站 token,不自訂字型。

5.4 待辦清單(view 與 FE)

  • vw_user_job_queue 改為 task_assignees UNION job_review_step_assignees 兩個來源(後者 user_id 帶出同欄位、is_approver=false),並多帶 review_step_no、review_step_name、review_step_count、is_current_step_assignee(這位使用者是否在當下那關)。改 view 時整支 CREATE OR REPLACE、欄位只加在尾端(FR-140 先例 scripts/sql/2026-10-15-fr140-job-executions-due-at.sql:111 的 GRANT 要重下)。
  • 同一使用者同時在兩關(例如第 1 關又是第 3 關)不得重複列,view 要 DISTINCT ON 任務。
  • 「待我處理」=job_status = PROCESSING AND is_current_step_assignee(零關任務:在 task_assignees 即算)。
  • FE MyTasksView.vue:狀態欄右邊加「目前關卡」(2/3 主管審核,待你處理時橘色小標);分段加「待我處理(N)」放最前。

5.5 系統設定「任務關卡樣板設定」

  • 能力點:新增 review_step_template.manage(宣告在 core/host_capabilities.py,跑 scripts/deliverables/gen_permission_matrix.py 產 FE 常數);列表 GET 只要登入(規劃頁下拉要讀)。寫入是全站共用設定,另過 require_tenant_hq()。
  • ui_routes 一列+route_capabilities 一顆(seed migration),選單掛在系統設定底下。
  • 頁面照 ProjectListView.vue:標題列(名稱+「共 N 筆樣板」)+右邊「新增任務關卡樣板」;搜尋框+重設;表格欄:樣板名稱(內建者加「系統內建」標)/說明/關卡數/公司預設/已套用任務數/操作(鉛筆、垃圾桶)。不放關卡預覽。點一列或新增開編輯 dialog,表單由上而下單欄排列:樣板名稱、說明(多行)、公司預設勾選、關卡預覽(PrimeVue Steps,開始/結案用圖示、中間關卡編號對齊關卡表)、關卡表(只列實際關卡:編號、名稱、說明、上下移、刪;不列開始/結案,沒有退回設定)。
  • 刪除:已套用的任務不受影響(拿的是複製品);內建者刪除鈕停用。

5.6 規劃頁

  • AoTaskForm.vue 只剩 51 行額度:非問卷任務的「部門+人員」兩格整段換成 <TaskReviewStepSummary>(一行:樣板名、關數、「N 關已指派、M 關未指派 ⚠」+「設定」按鈕;已開始顯示「檢視/換人」);問卷任務維持原兩格與審核者開關。

  • 彈窗 <TaskReviewStepDialog>:樣板下拉(含零關)→ 關卡預覽 → 每關一列「部門 MultiSelect → 人員 MultiSelect(依部門篩,重用 usersInDepts/keepAssigneesInDepts)」,第 1 關標「=原本的指派人員」;零關只有一列;左下「套用到其他任務」、右下取消/儲存。

  • 換樣板:同位置已派的人保留,多出來的關空著;少掉的關的人刪除。

  • 任務開始後:樣板下拉與關卡結構唯讀,人仍可改(D5)。

  • 換人時的通知(比照現況:notify_user_todo_job 只在任務進行中才寄;job_service.py:355 先記舊名單、:503 _notify_newly_added_assignees 只寄新加的人):

    換人的是哪一關 寄給誰
    任務還沒啟動 不寄;啟動時寄給第 1 關當下的名單
    任務進行中,換當下那關 只寄新加的人
    任務進行中,換還沒走到的關 不寄;走到那關時寄給那時的名單
    任務進行中,換已走過的關 不寄;之後被退回到那關時寄給那關當下的名單

    例:第 2 關原本派雷門,雷門離職改派阿好——不論何時改,信只會在輪到第 2 關時寄給阿好。被移除的人不收任何通知(現況也沒有),第一版不做移除通知。

  • 套用到其他任務:比照流程圖「套用到其他任務」動線(flow_apply_to_tasks_service.py 的候選列法:同專案同輪),只列未開始、非問卷任務;套的是樣板(人保留同位置,新關空著)。

  • 端點:PUT /grc/jobs/<job_uid>/review-steps(body {template_uid, steps_assignees:[{seq, dept_uids, user_uids}]})、POST /grc/jobs/review-steps/apply(body {template_uid, job_uids})。守門:專案 manager。

5.7 啟動、重開、批次、啟動前提醒

  • 帶公司預設:任務建立的當下就套(決策者 2026-10-18 裁 A)——三個建立點:專案成立產生任務(prep_job_generation_service.py)、規劃頁新增任務(job_service.create_job)、覆核輪產生任務(reverify_inheritance_service)。只對「非問卷、還沒有 job_review_steps」的任務套;公司預設是零關就什麼都不做;舊專案不回頭套。不在「啟動稽核」套:啟動稽核是規劃階段結束、任務都做完才按的(它的既有前置就是「證據任務未完成」提醒),那時套關卡沒意義。排除 B「PM 按開始執行任務才套」:套上時第 2 關以後都沒人、一送審就卡住,且要改任務平台的啟動掛鉤。
  • 重開:reopen_job_execution 與 restart_from_first_station 結束時,對有關卡的任務呼叫 review_step_service.reset_to_first。
  • 批次完成:job_batch_complete_service.batch_complete 對有關卡的任務改呼叫 submit/approve(當下那關有你才處理,否則計入 skipped 並回原因)。
  • 啟動前提醒:PlanningReadinessChecker 加 WARN_REVIEW_STEPS_UNASSIGNED = "review_steps_unassigned",context {count, jobs:[{uid, name, missing_seqs}]};FE 確認視窗的提醒清單加一種文案(i18n key 同 code)。檢查要讀主專案的新表 → 用注入的查詢介面,不讓套件 import 主專案。

5.8 任務配置 Excel(D13)

  • 匯出:EXTRA_COLUMNS 尾端加一欄「任務關卡」(唯讀灰底),值例:「標準三關(3 關,2 關已指派)」/「無關卡」;「指派人員」「參與部門」欄標頭不改字(相容舊檔),填寫說明頁加一句「多關卡任務:指派人員/參與部門是第 1 關(執行人);審核關卡的人員請到規劃頁設定」。
  • 匯入:讀到第 1 關,寫回 task_assignees 的邏輯不變;新欄不讀;舊檔沒有這欄照樣能匯入(欄位對應依位置,新欄放最後)。任務已開始時換第 1 關的人照舊放行。
  • JobImportDialog.vue 預覽表加唯讀欄。

6. 拆分(6 張實作卡)

卡 範圍 依賴 驗收
① 地基+任務卡 migration(五表兩欄、RLS、GRANT、內建樣板 seed)、ORM(套件兩欄+主專案新表)、review_step_service、四支端點、既有完成端點擋關卡、FE 任務卡三個子元件 — DEV 手灌一個三關任務,三帳號走完含退回;既有完成端點對有關卡任務被擋;零關任務行為不變
② 待辦頁 vw_user_job_queue 改寫、待辦查詢、FE 欄與段 ① 第 2 關的人在待辦看得到;「待我處理」正確;同人兩關不重複
③ 樣板設定頁 CRUD 端點、能力點、ui_routes、FE 清單+dialog ① 建/改/刪/設預設;內建不可刪
④ 規劃頁 套樣板/每關指派/套用到其他任務端點、FE 摘要列+彈窗;開始後可換人並通知 ①③ 對照雛形頁 3
⑤ 啟動/重開/批次/提醒 啟動帶預設、兩處重開 hook、批次完成、PlanningReadinessChecker(動 jedi-compliance-audit) ①④ 見 §2 表
⑥ 任務配置 Excel 匯出欄、填寫說明、匯入預覽 ①④ 見 §2 表

套件異動:① 動 jedi-flow-engine(job_executions 兩欄 ORM)、⑤ 動 jedi-compliance-audit(readiness checker)。都走 path dependency(pyproject.toml 已是 path 形式),不發版;發版時機等決策者。


7. 端到端驗收

  1. 裝好不設定:所有任務零關,規劃頁摘要寫「無關卡」,任務卡只有「開始 → 結案」,按鈕「完成任務」——與上線前完全相同。
  2. 系統設定建「標準三關」,規劃頁替一個任務套上、三關各派一人,啟動專案。
  3. 執行人收到信、上傳證據、送審 → 主管收到信、在待辦「待我處理」看到、打開看得到證據與留言、退回 → 執行人收到信、卡回第 1 關 → 再送審 → 主管核可 → 顧問核可並結案 → 流程往下一個任務走。
  4. 時鐘圖示的歷程彈窗有五筆。
  5. 任務進行中,PM 把第 2 關換人:只有新加的人收到信(若第 2 關是當下那關);樣板下拉是鎖的。
  6. 有關卡沒派人時啟動專案:確認視窗列出「有幾個任務的關卡沒派人」,按確定仍可啟動。
  7. 管理員退回重開一個已結案任務:回第 1 關、歷程多一筆 reopen。
  8. 待辦勾三筆(一筆第 1 關、一筆審核關、一筆零關)按批次完成:各前進一格。
  9. 匯出任務配置 Excel:多「任務關卡」唯讀欄;改第 1 關的人匯入,其他關的人不變;用上線前匯出的舊檔匯入仍成功。
  10. 問卷任務、改善計畫任務:完全不受影響。

回歸範圍:既有完成任務、批次完成、退回重開、週期重跑、待辦清單、任務配置 Excel 匯入匯出、啟動稽核。


8. 這份文件的定位

你想知道 看這份
為什麼不用 BPMN、四個方案怎麼比 討論稿
畫面長怎樣 雛形
為什麼這樣決定、要做哪些 本頁
做完的現況 FINAL-SPEC.md(實作完成後產出)