GradingService

PAM 系統所有等第相關計算的單一來源。Controller 與各 fallback 一律呼叫此服務,禁止自行實作重複邏輯。

為什麼是樞紐

PAM 系統最容易出錯的地方是「計分公式散落在多處」——HrController 算一份、ReviewController 算一份、報表又算一份,遲早有一處不一致。GradingService 的設計核心就是「所有跟分數、等第、配額相關的決定都歸於一處」,新功能只能呼叫它,不能繞過它自己實作。它是整個 PAM 等第規則的 single source of truth;改公式只改這裡,所有下游服務(SettlementServiceReviewValidatorGradeReviewService)自動跟著變。

主要方法

方法用途
CalcGrade(score)分數 → 等第(特優/優等/甲等/乙等/丙等)
GradeRank(grade)等第 → 排序分數(比較大小用)
ComputeScoreC(A, B, isMerged)當次平均分數 C(合併主管→C=A;否則 (A+B)/2)
ComputeScoreD(A, B, isMerged, attendance)當次成績 D = C + 出勤扣分
ComputeAttendanceDeduction(hours)事假時數 → 扣分(每小時 -0.125)
ComputeByRate(n) / QuotaSuggestion人數 → 建議配額(餘額法,sum 永遠 = n)
GetSuggested(quota, grade)從 QuotaSuggestion 取對應等第建議數
CalcCeiling(...)等第天花板(懲處/假勤/年資 → 天花板等第 + 原因)

CalcCeiling 是最複雜的——要綜合員工的懲處紀錄、假勤異常、年資長度,按優先序回傳該員的最高可達等第與限制原因(例如「事假超過 14 天 → 上限甲等」)。詳見 等第天花板

設計原則

  1. 單一來源:HrController / ReviewController 的 CalculateGrade 與各處 fallback 一律呼叫此服務
  2. 新功能不得重寫:需要等第判定或配額計算時,一律在 GradingService 補方法
  3. 方法純函數化:盡量無副作用,輸入相同則輸出相同——便於單元測試與快取
  4. 公式變動有審計:修改 CalcGrade 區間或 ComputeAttendanceDeduction 倍率前,先在 等第規則出勤扣分 文檔對齊,避免線上計分跟法規/HR 公告不一致

反模式(嚴禁)

  • ❌ Controller 裡寫 score >= 90 ? "特優" : "優等" 之類的硬式判斷
  • ❌ 在 SQL 端用 CASE WHEN 算等第(前後端不一致)
  • ❌ 為了「特殊情境」複製一份 GradingService 改一個分支
  • ❌ 在 Hrms104Repository 或其他資料層計算分數

發現上述模式 → 立刻把該邏輯抽回 GradingService 補一個對應方法。

核心公式

C = (A + B) / 2     若 R1 ≠ R2
C = A               若 R1 = R2(合併)

D = C + 出勤扣分     // 出勤扣分 ≤ 0

詳見:等第規則出勤扣分等第天花板

誰在用 GradingService

相關概念

強連結(原文明確提及)

推斷連結(LLM 認為相關,待確認)

深入閱讀(外部資源)

← 回到 wiki