184 lines
6.3 KiB
Java
184 lines
6.3 KiB
Java
package com.designhub.service;
|
||
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.designhub.entity.DelayPenaltyRecord;
|
||
import com.designhub.entity.DelayPenaltyRule;
|
||
import com.designhub.mapper.DelayPenaltyRecordMapper;
|
||
import com.designhub.mapper.DelayPenaltyRuleMapper;
|
||
import lombok.RequiredArgsConstructor;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
|
||
import java.time.LocalDateTime;
|
||
import java.time.temporal.ChronoUnit;
|
||
import java.util.List;
|
||
|
||
/**
|
||
* 延误扣分Service
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
@RequiredArgsConstructor
|
||
public class DelayPenaltyService {
|
||
|
||
private final DelayPenaltyRecordMapper delayPenaltyRecordMapper;
|
||
private final DelayPenaltyRuleMapper delayPenaltyRuleMapper;
|
||
|
||
/**
|
||
* 计算延误扣分
|
||
* 根据需求文档的规则:
|
||
* - 轻微延误(< 2小时):每小时扣2分
|
||
* - 一般延误(2-8小时):每小时扣3分
|
||
* - 严重延误(8-24小时):每小时扣5分
|
||
* - 重大延误(> 24小时):基础50分+每天10分
|
||
*/
|
||
public DelayPenaltyRecord calculateDelayPenalty(Long taskId, Long designerId,
|
||
LocalDateTime deadline,
|
||
LocalDateTime actualTime) {
|
||
if (deadline == null || actualTime == null) {
|
||
return null;
|
||
}
|
||
|
||
// 如果实际时间早于截止时间,未延误
|
||
if (actualTime.isBefore(deadline) || actualTime.isEqual(deadline)) {
|
||
return null;
|
||
}
|
||
|
||
// 计算延误小时数
|
||
long delayHours = ChronoUnit.HOURS.between(deadline, actualTime);
|
||
long delayDays = ChronoUnit.DAYS.between(deadline, actualTime);
|
||
|
||
// 确定延误等级和扣分
|
||
String delayLevel;
|
||
Integer penaltyScore;
|
||
|
||
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;
|
||
}
|
||
|
||
// 创建延误扣分记录
|
||
DelayPenaltyRecord record = new DelayPenaltyRecord();
|
||
record.setTaskId(taskId);
|
||
record.setDesignerId(designerId);
|
||
record.setDelayDays((int) delayDays);
|
||
record.setDelayHours(delayHours);
|
||
record.setDelayLevel(delayLevel);
|
||
record.setPenaltyScore(penaltyScore);
|
||
record.setOriginalDeadline(deadline);
|
||
record.setActualTime(actualTime);
|
||
record.setStatus("confirmed");
|
||
|
||
log.info("计算延误扣分: taskId={}, designerId={}, delayHours={}, delayLevel={}, penaltyScore={}",
|
||
taskId, designerId, delayHours, delayLevel, penaltyScore);
|
||
|
||
return record;
|
||
}
|
||
|
||
/**
|
||
* 保存延误扣分记录
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public DelayPenaltyRecord saveDelayPenaltyRecord(DelayPenaltyRecord record) {
|
||
if (record == null) {
|
||
return null;
|
||
}
|
||
delayPenaltyRecordMapper.insert(record);
|
||
log.info("保存延误扣分记录: recordId={}, taskId={}, penaltyScore={}",
|
||
record.getId(), record.getTaskId(), record.getPenaltyScore());
|
||
return record;
|
||
}
|
||
|
||
/**
|
||
* 根据任务ID查询延误记录
|
||
*/
|
||
public List<DelayPenaltyRecord> getDelayRecordsByTaskId(Long taskId) {
|
||
return delayPenaltyRecordMapper.findByTaskId(taskId);
|
||
}
|
||
|
||
/**
|
||
* 根据设计师ID查询延误记录
|
||
*/
|
||
public List<DelayPenaltyRecord> getDelayRecordsByDesignerId(Long designerId) {
|
||
return delayPenaltyRecordMapper.findByDesignerId(designerId);
|
||
}
|
||
|
||
/**
|
||
* 统计设计师的延误扣分总数
|
||
*/
|
||
public Integer getTotalPenaltyScoreByDesignerId(Long designerId) {
|
||
Integer total = delayPenaltyRecordMapper.sumPenaltyScoreByDesignerId(designerId);
|
||
return total != null ? total : 0;
|
||
}
|
||
|
||
/**
|
||
* 申诉延误扣分
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void appealDelayPenalty(Long recordId, Long designerId, String appealReason) {
|
||
DelayPenaltyRecord record = delayPenaltyRecordMapper.selectById(recordId);
|
||
if (record == null) {
|
||
throw new RuntimeException("延误扣分记录不存在");
|
||
}
|
||
|
||
if (!record.getDesignerId().equals(designerId)) {
|
||
throw new RuntimeException("无权申诉此记录");
|
||
}
|
||
|
||
if (!"confirmed".equals(record.getStatus())) {
|
||
throw new RuntimeException("该记录已申诉或已处理");
|
||
}
|
||
|
||
record.setStatus("appealed");
|
||
record.setAppealReason(appealReason);
|
||
record.setAppealTime(LocalDateTime.now());
|
||
delayPenaltyRecordMapper.updateById(record);
|
||
|
||
log.info("设计师申诉延误扣分: recordId={}, designerId={}, reason={}",
|
||
recordId, designerId, appealReason);
|
||
}
|
||
|
||
/**
|
||
* 管理员审批申诉
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void approveAppeal(Long recordId, Long approverId, Boolean approved, String appealResult) {
|
||
DelayPenaltyRecord record = delayPenaltyRecordMapper.selectById(recordId);
|
||
if (record == null) {
|
||
throw new RuntimeException("延误扣分记录不存在");
|
||
}
|
||
|
||
if (!"appealed".equals(record.getStatus())) {
|
||
throw new RuntimeException("该记录不是申诉状态");
|
||
}
|
||
|
||
if (approved) {
|
||
record.setStatus("approved");
|
||
} else {
|
||
record.setStatus("rejected");
|
||
}
|
||
record.setAppealResult(appealResult);
|
||
record.setApproverId(approverId);
|
||
record.setApproveTime(LocalDateTime.now());
|
||
delayPenaltyRecordMapper.updateById(record);
|
||
|
||
log.info("管理员审批申诉: recordId={}, approverId={}, approved={}",
|
||
recordId, approverId, approved);
|
||
}
|
||
}
|
||
|