5.1 KiB
5.1 KiB
设计师绩效排行榜扣分逻辑说明
一、当前实现逻辑(数据分析页面)
数据分析页面的设计师绩效排行榜使用的是 AnalyticsService.getDesignerPerformance 方法,扣分逻辑如下:
1. 延误扣分计算公式
扣分 = 任务积分 × 延误小时数 × 扣分比例(默认1%)
限制条件:
- 扣分不能超过任务积分
- 如果计算结果超过任务积分,则扣分 = 任务积分
扣分比例:
- 默认值:1%(即
BigDecimal.ONE) - 可以从部门配置中获取(
DesignerTargetScore.deductionRate) - 三级部门继承二级部门的配置
2. 进度未更新扣分
除了延误扣分,还会加上进度未更新扣分:
- 从
progress_deduction_log表中查询当月的进度未更新扣分总额 - 进度未更新扣分 + 延误扣分 = 总扣分
3. 净积分计算
净积分 = 获得积分 - 总扣分
如果净积分 < 0,则净积分 = 0
二、需求文档中的扣分规则(DelayPenaltyService)
需求文档中定义的延误扣分规则(在 DelayPenaltyService 中实现,但当前数据分析页面未使用):
| 延误程度 | 延误时长 | 扣分规则 | 示例 |
|---|---|---|---|
| 轻微延误 | < 2小时 | 每小时扣2分 | 延误1.5小时 → 扣3分 |
| 一般延误 | 2-8小时 | 每小时扣3分 | 延误5小时 → 扣15分 |
| 严重延误 | 8-24小时 | 每小时扣5分 | 延误10小时 → 扣50分 |
| 重大延误 | > 24小时 | 基础50分+每天10分 | 延误2天 → 扣70分 |
三、"若兰"被扣10分的情况分析
从图片数据看:
- 获得积分:10分
- 延误扣分:10分
- 净积分:0分
可能的原因:
-
情况A:延误扣分达到上限
- 如果任务积分是10分,延误时间较长
- 按照公式:
10分 × 延误小时数 × 1% = 10分 - 或者计算结果超过10分,被限制为10分
-
情况B:延误扣分 + 进度未更新扣分 = 10分
- 延误扣分 + 进度未更新扣分 = 10分
- 例如:延误扣分5分 + 进度未更新扣分5分 = 10分
四、代码位置
当前使用的扣分逻辑:
- 文件:
backend/src/main/java/com/designhub/service/AnalyticsService.java - 方法:
getDesignerPerformance(第535行) - 扣分计算:第680-698行(延误扣分)+ 第701-718行(进度未更新扣分)
- 扣分比例获取:
getDeductionRate(第1146行)
需求文档中的扣分逻辑(未在数据分析页面使用):
- 文件:
backend/src/main/java/com/designhub/service/DelayPenaltyService.java - 方法:
calculateDelayPenalty(第36行) - 规则:按延误等级和固定扣分规则
五、建议复核的问题
-
数据分析页面应该使用哪套扣分规则?
- 当前实现:按百分比扣分(任务积分 × 延误小时数 × 扣分比例)
- 需求文档:按延误等级固定扣分(轻微/一般/严重/重大)
-
扣分比例默认值是否合理?
- 当前默认:1%
- 如果任务积分100分,延误10小时,扣分 = 100 × 10 × 1% = 10分
- 如果任务积分10分,延误100小时,扣分 = min(10 × 100 × 1%, 10) = 10分
-
进度未更新扣分是否应该计入?
- 当前实现:计入总扣分
- 是否需要单独显示?
-
是否需要使用 DelayPenaltyRecord 表的数据?
- 当前实现:直接从任务表计算,不使用 DelayPenaltyRecord
- 需求文档中有 DelayPenaltyRecord 表的设计,但数据分析页面未使用
六、相关代码片段
当前扣分计算逻辑(AnalyticsService.java 第680-698行):
// 计算延误扣分(如果超时完成)
if (task.getDeadline() != null && task.getActualEndTime() != null
&& task.getActualEndTime().isAfter(task.getDeadline())) {
// 计算延误小时数
long overdueHours = Duration.between(task.getDeadline(), task.getActualEndTime()).toHours();
if (overdueHours > 0 && taskScore.compareTo(BigDecimal.ZERO) > 0) {
// 扣分 = 任务积分 * 延误小时数 * 扣分比例
BigDecimal taskDeduction = taskScore
.multiply(BigDecimal.valueOf(overdueHours))
.multiply(deductionRate)
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
// 扣分不能超过任务积分
if (taskDeduction.compareTo(taskScore) > 0) {
taskDeduction = taskScore;
}
deductionScore = deductionScore.add(taskDeduction);
}
}
需求文档中的扣分规则(DelayPenaltyService.java 第56-72行):
if (delayHours < 2) {
// 轻微延误:每小时扣2分
delayLevel = "light";
penaltyScore = (int) Math.ceil(delayHours * 2.0);
} else if (delayHours < 8) {
// 一般延误:每小时扣3分
delayLevel = "general";
penaltyScore = (int) Math.ceil(delayHours * 3.0);
} else if (delayHours < 24) {
// 严重延误:每小时扣5分
delayLevel = "severe";
penaltyScore = (int) Math.ceil(delayHours * 5.0);
} else {
// 重大延误:基础50分+每天10分
delayLevel = "major";
penaltyScore = 50 + (int) delayDays * 10;
}