主管交接(ReviewerTransferService)

考核進行中,主管突發離職/異動時,保留已完成評分記錄,只更換 ExamParticipant 配置欄位。與原有「更換主管(清空重來)」並存為兩種模式。

核心原則

  1. 歷史記錄不改ExamRecord.ReviewerName 永遠保留原主管名(簡打的分就是簡打的,歷史帳面不動)
  2. 只換配置:更新 ExamParticipant.Reviewer1/Reviewer2/Approver1..5 欄位
  3. 草稿清除:進行中該關卡的草稿刪除,新主管接手重評
  4. Shift 遞補:無接替主管時,後面關卡往前搬、TotalReviewSteps -= 1,已過該關的員工不動

分類處理邏輯(per 員工)

員工狀態處理方式
CurrentStep > 離職主管 Step(已過關)配置換名(若指定新人),原 ExamRecord 保留;若 Shift 則不動(已過無需遞補)
CurrentStep == 離職主管 Step(進行中)清草稿,新人接手重評 or 執行 Shift
CurrentStep < 離職主管 Step(尚未到)單純換名 or 執行 Shift
Status == "Completed"不動

API

POST /api/hr/participants/batch-transfer-reviewers

{
  "participantIds": [1, 2, 3],
  "role": "Reviewer2",
  "newReviewerName": "林○○",      // null 或 "" = 無接替(Shift)
  "dryRun": true,                   // true = 只預覽不寫入
  "hrPassword": "..."               // 受保護部門需要
}

回傳 TransferPreviewResult

  • recordPreserved:已過該關卡,配置換名、Record 保留的筆數
  • draftCleared:正在該關卡,草稿清除的筆數
  • notReached:尚未到,配置換名
  • completed:已完成跳過
  • shifted:執行 Shift 的筆數(含 draftCleared + notReached 的子集)
  • skipped:因狀態無法處理(e.g., 已過關但要 Shift)
  • details:每位員工的詳細處理結果

前端 UI(人員管理頁)

HR 工作流程:

  1. 篩選器(初核/複核/審核主管 + 公司/部門/單位)找出離職主管負責的員工
  2. 批次勾選人員
  3. 點「批次調整主管」→ Dialog 開啟
  4. 選「處理模式」:
    • 保留已完成評分記錄(主管交接) — 預設,呼叫新 API
    • 清空重評(原行為) — 呼叫原 batch-reviewers API
  5. 保留模式下選「交接角色」+ 「接手主管」或勾選「無接替」
  6. 點「預覽影響」→ 顯示分類計數
  7. 確認後點「確認執行交接」

接手主管候選名單

transferCandidates所有考核清單員工去重 + 現有主管合併,不限於已擔任主管者(解決新人接手場景)。

雙向連動篩選

人員管理頁的篩選器(公司/部門/虛擬部門/單位/初核/複核/審核主管)互相連動:選任何一個都會縮減其他下拉的選項範圍,共用 managerMatches predicate 實作。

考核表單歷程顯示交接

ReviewHistoryCard 每一關比較 ExamRecord.ReviewerName 與當前 ExamParticipant.ReviewerX 配置:

  • 不一致 → 顯示琥珀色註記「ℹ 主管已交接,後續退回將由 XX 接手」
  • 考慮 isMergedReviewer:merged 時 Step 1 合併、Approver 索引位移

不支援的場景(簡化)

  • 跨週期批次:active period 同時只有一個,不需要
  • 反遞補(Shift 後找到新人恢復):40 天週期內用不到,HR 手動重建即可
  • SkippedSteps:直接用 Shift 取代,不需要「跳過」標記欄位

稽核

新增 audit action:ReviewerTransfer,記錄操作 HR、角色、接手人/shift、分類計數。