fix: 按完成时间归属月度积分
确保主任务/子任务的月度积分按完成时间入账,并补充修正脚本。
This commit is contained in:
parent
96e8040af5
commit
67b8cb7991
@ -1,6 +1,5 @@
|
||||
package com.designhub.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.designhub.entity.Department;
|
||||
import com.designhub.entity.DeptMonthlyScore;
|
||||
import com.designhub.mapper.DepartmentMapper;
|
||||
@ -26,13 +25,13 @@ public class DeptMonthlyScoreService {
|
||||
private final DepartmentMapper departmentMapper;
|
||||
|
||||
/**
|
||||
* 获取或创建当月积分记录
|
||||
* 获取或创建指定月份积分记录(基于完成时间)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DeptMonthlyScore getOrCreateCurrentMonth(Long deptId) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
int year = now.getYear();
|
||||
int month = now.getMonthValue();
|
||||
public DeptMonthlyScore getOrCreateMonth(Long deptId, LocalDateTime scoreTime) {
|
||||
LocalDateTime targetTime = scoreTime != null ? scoreTime : LocalDateTime.now();
|
||||
int year = targetTime.getYear();
|
||||
int month = targetTime.getMonthValue();
|
||||
|
||||
DeptMonthlyScore record = deptMonthlyScoreMapper.getByDeptAndMonth(deptId, year, month);
|
||||
if (record == null) {
|
||||
@ -53,20 +52,28 @@ public class DeptMonthlyScoreService {
|
||||
record.setCompletedTaskCount(0);
|
||||
record.setDelayedTaskCount(0);
|
||||
record.setTotalDelayHours(BigDecimal.ZERO);
|
||||
record.setCreateTime(now);
|
||||
record.setUpdateTime(now);
|
||||
record.setCreateTime(targetTime);
|
||||
record.setUpdateTime(targetTime);
|
||||
|
||||
deptMonthlyScoreMapper.insert(record);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或创建当月积分记录
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DeptMonthlyScore getOrCreateCurrentMonth(Long deptId) {
|
||||
return getOrCreateMonth(deptId, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加部门获得积分(任务完成时调用)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addEarnedScore(Long deptId, BigDecimal score, boolean isDelayed, BigDecimal delayHours) {
|
||||
DeptMonthlyScore record = getOrCreateCurrentMonth(deptId);
|
||||
public void addEarnedScore(Long deptId, BigDecimal score, boolean isDelayed, BigDecimal delayHours, LocalDateTime scoreTime) {
|
||||
DeptMonthlyScore record = getOrCreateMonth(deptId, scoreTime);
|
||||
|
||||
// 增加获得积分
|
||||
record.setEarnedScore(record.getEarnedScore().add(score));
|
||||
@ -87,12 +94,20 @@ public class DeptMonthlyScoreService {
|
||||
deptMonthlyScoreMapper.updateById(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加部门获得积分(兼容旧调用,使用当前时间)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addEarnedScore(Long deptId, BigDecimal score, boolean isDelayed, BigDecimal delayHours) {
|
||||
addEarnedScore(deptId, score, isDelayed, delayHours, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加部门扣除积分(延误扣分时调用)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addDeductedScore(Long deptId, BigDecimal deductedScore) {
|
||||
DeptMonthlyScore record = getOrCreateCurrentMonth(deptId);
|
||||
public void addDeductedScore(Long deptId, BigDecimal deductedScore, LocalDateTime scoreTime) {
|
||||
DeptMonthlyScore record = getOrCreateMonth(deptId, scoreTime);
|
||||
|
||||
record.setDeductedScore(record.getDeductedScore().add(deductedScore));
|
||||
// 重新计算净积分
|
||||
@ -102,12 +117,20 @@ public class DeptMonthlyScoreService {
|
||||
deptMonthlyScoreMapper.updateById(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加部门扣除积分(兼容旧调用,使用当前时间)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addDeductedScore(Long deptId, BigDecimal deductedScore) {
|
||||
addDeductedScore(deptId, deductedScore, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 扣除部门获得积分(删除已完成任务时调用,用于回退积分)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deductEarnedScore(Long deptId, BigDecimal score) {
|
||||
DeptMonthlyScore record = getOrCreateCurrentMonth(deptId);
|
||||
public void deductEarnedScore(Long deptId, BigDecimal score, LocalDateTime scoreTime) {
|
||||
DeptMonthlyScore record = getOrCreateMonth(deptId, scoreTime);
|
||||
|
||||
// 扣除获得积分(不能小于0)
|
||||
BigDecimal newEarnedScore = record.getEarnedScore().subtract(score);
|
||||
@ -131,6 +154,14 @@ public class DeptMonthlyScoreService {
|
||||
log.info("已扣除部门月度积分: deptId={}, score={}, newEarnedScore={}", deptId, score, newEarnedScore);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扣除部门获得积分(兼容旧调用,使用当前时间)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deductEarnedScore(Long deptId, BigDecimal score) {
|
||||
deductEarnedScore(deptId, score, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门当月积分
|
||||
*/
|
||||
|
||||
@ -818,7 +818,8 @@ public class TaskItemService {
|
||||
item.getReceiverDeptId(),
|
||||
item.getTotalScore(),
|
||||
isDelayed,
|
||||
delayHours
|
||||
delayHours,
|
||||
item.getCompleteTime()
|
||||
);
|
||||
|
||||
log.info("🎉 子任务 {} 积分已发放: deptId={}, score={}, isDelayed={}, delayHours={}",
|
||||
|
||||
@ -3684,15 +3684,16 @@ public class TaskService {
|
||||
if (task.getReceiverDeptId() != null) {
|
||||
try {
|
||||
deptMonthlyScoreService.addEarnedScore(
|
||||
task.getReceiverDeptId(),
|
||||
task.getReceiverDeptId(),
|
||||
task.getScoreReward() != null ? task.getScoreReward() : BigDecimal.ZERO,
|
||||
isDelayed,
|
||||
delayHours
|
||||
delayHours,
|
||||
completeTime
|
||||
);
|
||||
|
||||
// 如果有延误扣分,单独记录扣除
|
||||
if (deductedScore.compareTo(BigDecimal.ZERO) > 0) {
|
||||
deptMonthlyScoreService.addDeductedScore(task.getReceiverDeptId(), deductedScore);
|
||||
deptMonthlyScoreService.addDeductedScore(task.getReceiverDeptId(), deductedScore, completeTime);
|
||||
}
|
||||
|
||||
log.info("更新部门月度积分: deptId={}, earned={}, deducted={}",
|
||||
@ -4275,7 +4276,11 @@ public class TaskService {
|
||||
log.info("已回退主任务积分: deptId={}, score={}", task.getReceiverDeptId(), task.getScoreReward());
|
||||
|
||||
// 回退部门月度积分统计
|
||||
deptMonthlyScoreService.deductEarnedScore(task.getReceiverDeptId(), task.getScoreReward());
|
||||
deptMonthlyScoreService.deductEarnedScore(
|
||||
task.getReceiverDeptId(),
|
||||
task.getScoreReward(),
|
||||
task.getCompleteTime()
|
||||
);
|
||||
log.info("已回退部门月度积分: deptId={}, score={}", task.getReceiverDeptId(), task.getScoreReward());
|
||||
} else {
|
||||
log.warn("部门积分池不存在,跳过主任务积分回退: deptId={}", task.getReceiverDeptId());
|
||||
@ -4304,7 +4309,11 @@ public class TaskService {
|
||||
item.getItemNo(), item.getReceiverDeptId(), item.getTotalScore());
|
||||
|
||||
// 回退部门月度积分统计
|
||||
deptMonthlyScoreService.deductEarnedScore(item.getReceiverDeptId(), item.getTotalScore());
|
||||
deptMonthlyScoreService.deductEarnedScore(
|
||||
item.getReceiverDeptId(),
|
||||
item.getTotalScore(),
|
||||
item.getCompleteTime()
|
||||
);
|
||||
} else {
|
||||
log.warn("部门积分池不存在,跳过子任务积分回退: itemNo={}, deptId={}", item.getItemNo(), item.getReceiverDeptId());
|
||||
}
|
||||
|
||||
54
database/repair_monthly_scores.sql
Normal file
54
database/repair_monthly_scores.sql
Normal file
@ -0,0 +1,54 @@
|
||||
-- 按完成时间修正部门月度积分(earned_score / completed_task_count)
|
||||
-- 注意:本脚本不会修改 deducted_score / 延误统计,仅重算 earned_score 与 net_score
|
||||
|
||||
-- 1) 设定需要修正的年月
|
||||
SET @year = 2026;
|
||||
SET @month = 2;
|
||||
SET @start = STR_TO_DATE(CONCAT(@year, '-', LPAD(@month, 2, '0'), '-01 00:00:00'), '%Y-%m-%d %H:%i:%s');
|
||||
SET @end = DATE_ADD(@start, INTERVAL 1 MONTH);
|
||||
|
||||
-- 2) 汇总该月完成的主任务/子任务积分(主任务排除流水线任务)
|
||||
CREATE TEMPORARY TABLE tmp_monthly_earned AS
|
||||
SELECT dept_id, SUM(score) AS earned_score, COUNT(*) AS completed_task_count
|
||||
FROM (
|
||||
SELECT t.receiver_dept_id AS dept_id, t.score_reward AS score
|
||||
FROM task t
|
||||
WHERE t.status = 'completed'
|
||||
AND t.receiver_dept_id IS NOT NULL
|
||||
AND t.score_reward IS NOT NULL
|
||||
AND t.score_reward > 0
|
||||
AND (t.is_pipeline IS NULL OR t.is_pipeline = 0)
|
||||
AND t.complete_time >= @start AND t.complete_time < @end
|
||||
UNION ALL
|
||||
SELECT ti.receiver_dept_id AS dept_id, ti.total_score AS score
|
||||
FROM task_item ti
|
||||
WHERE ti.status = 'completed'
|
||||
AND ti.receiver_dept_id IS NOT NULL
|
||||
AND ti.total_score IS NOT NULL
|
||||
AND ti.total_score > 0
|
||||
AND ti.complete_time >= @start AND ti.complete_time < @end
|
||||
) u
|
||||
GROUP BY dept_id;
|
||||
|
||||
-- 3) 更新已有记录
|
||||
UPDATE dept_monthly_score d
|
||||
JOIN tmp_monthly_earned e
|
||||
ON d.dept_id = e.dept_id AND d.year = @year AND d.month = @month
|
||||
SET d.earned_score = e.earned_score,
|
||||
d.completed_task_count = e.completed_task_count,
|
||||
d.net_score = e.earned_score - d.deducted_score,
|
||||
d.update_time = NOW();
|
||||
|
||||
-- 4) 插入缺失记录
|
||||
INSERT INTO dept_monthly_score
|
||||
(dept_id, dept_name, year, month, earned_score, deducted_score, net_score,
|
||||
completed_task_count, delayed_task_count, total_delay_hours, create_time, update_time)
|
||||
SELECT e.dept_id, dept.dept_name, @year, @month, e.earned_score, 0,
|
||||
e.earned_score, e.completed_task_count, 0, 0, NOW(), NOW()
|
||||
FROM tmp_monthly_earned e
|
||||
JOIN department dept ON dept.id = e.dept_id
|
||||
LEFT JOIN dept_monthly_score d
|
||||
ON d.dept_id = e.dept_id AND d.year = @year AND d.month = @month
|
||||
WHERE d.id IS NULL;
|
||||
|
||||
DROP TEMPORARY TABLE tmp_monthly_earned;
|
||||
Loading…
x
Reference in New Issue
Block a user