|
|
@@ -0,0 +1,676 @@
|
|
|
+package com.ygtx.gxt.task;
|
|
|
+
|
|
|
+import com.ygtx.common.core.domain.entity.SysUser;
|
|
|
+import com.ygtx.common.core.domain.model.LoginUser;
|
|
|
+import com.ygtx.common.utils.DateUtils;
|
|
|
+import com.ygtx.common.utils.SecurityUtils;
|
|
|
+import com.ygtx.common.utils.spring.SpringUtils;
|
|
|
+import com.ygtx.framework.web.service.SysPermissionService;
|
|
|
+import com.ygtx.gxt.domain.*;
|
|
|
+import com.ygtx.gxt.mapper.GxtRepairOrderMapper;
|
|
|
+import com.ygtx.gxt.mapper.GxtWorkOrderMapper;
|
|
|
+import com.ygtx.gxt.service.IGxtEquipmentService;
|
|
|
+import com.ygtx.gxt.service.IGxtMonthScoreService;
|
|
|
+import com.ygtx.gxt.service.IGxtRepairOrderService;
|
|
|
+import com.ygtx.gxt.service.IGxtSafeOperationRewardService;
|
|
|
+import com.ygtx.gxt.service.IGxtUserScoreService;
|
|
|
+import com.ygtx.gxt.service.IGxtWorkOrderService;
|
|
|
+import com.ygtx.system.mapper.SysUserMapper;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.scheduling.annotation.EnableScheduling;
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
|
+import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 设备连续安全运行奖励任务
|
|
|
+ * 每天0点执行一次,对符合安全运行天数的设备进行奖励分值发放
|
|
|
+ *
|
|
|
+ * @author ouyj
|
|
|
+ * @date 2026-01-08
|
|
|
+ */
|
|
|
+@EnableScheduling
|
|
|
+@Component("equipmentSafeOperationRewardTask")
|
|
|
+public class EquipmentSafeOperationRewardTask {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(EquipmentSafeOperationRewardTask.class);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtEquipmentService equipmentService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtRepairOrderService repairOrderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtWorkOrderService workOrderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtSafeOperationRewardService safeOperationRewardService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtMonthScoreService monthScoreService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtUserScoreService userScoreService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysUserMapper userMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysPermissionService permissionService;
|
|
|
+
|
|
|
+ // 限制每次查询的最大工单数量,防止数据量过大导致性能问题
|
|
|
+ private static final int MAX_ORDERS_PER_QUERY = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每天凌晨0点执行定时任务
|
|
|
+ * 循环设备表GxtEquipment,计算连续安全运行奖励
|
|
|
+ */
|
|
|
+ //@Scheduled(cron = "0 0 0 * * ?") // 每天凌晨0点执行一次
|
|
|
+ public void processSafeOperationRewards() {
|
|
|
+ log.info("开始执行设备连续安全运行奖励任务");
|
|
|
+
|
|
|
+ // 设置系统用户上下文
|
|
|
+ setSystemUserContext();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询所有设备
|
|
|
+ GxtEquipment equipmentQuery = new GxtEquipment();
|
|
|
+ List<GxtEquipment> equipments = equipmentService.selectGxtEquipmentList(equipmentQuery);
|
|
|
+
|
|
|
+ int processedCount = 0;
|
|
|
+ for (GxtEquipment equipment : equipments) {
|
|
|
+ try {
|
|
|
+ processEquipmentSafeOperationReward(equipment);
|
|
|
+ processedCount++;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理设备 {} 连续安全运行奖励时发生异常", equipment.getEquipmentCode(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("设备连续安全运行奖励任务执行完成,共处理 {} 个设备", processedCount);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("执行设备连续安全运行奖励任务时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理单个设备的连续安全运行奖励
|
|
|
+ *
|
|
|
+ * @param equipment 设备信息
|
|
|
+ */
|
|
|
+ private void processEquipmentSafeOperationReward(GxtEquipment equipment) {
|
|
|
+ log.debug("开始处理设备 {} 的连续安全运行奖励", equipment.getEquipmentCode());
|
|
|
+
|
|
|
+ /* // 第一次查询:查询workOrderStatus为archived的工单,按restartTime降序排序
|
|
|
+ List<GxtRepairOrder> archivedRepairOrders = repairOrderService.selectGxtRepairOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "archived", false, "restartTime", MAX_ORDERS_PER_QUERY);
|
|
|
+
|
|
|
+ List<GxtWorkOrder> archivedWorkOrders = workOrderService.selectGxtWorkOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "archived", false, "restartTime", MAX_ORDERS_PER_QUERY);*/
|
|
|
+
|
|
|
+ // 第一次查询:查询workOrderStatus不等于invalid的工单,按restartTime降序排序
|
|
|
+ List<GxtRepairOrder> archivedRepairOrders = repairOrderService.selectGxtRepairOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "invalid", true, "restartTime", MAX_ORDERS_PER_QUERY);
|
|
|
+
|
|
|
+ List<GxtWorkOrder> archivedWorkOrders = workOrderService.selectGxtWorkOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "invalid", true, "restartTime", MAX_ORDERS_PER_QUERY);
|
|
|
+
|
|
|
+ // 第二次查询:维修工单workOrderStatus不等于invalid,按occurTime降序排序;维保工单workOrderStatus不等于invalid,按pauseTime降序排序
|
|
|
+ List<GxtRepairOrder> activeRepairOrders = repairOrderService.selectGxtRepairOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "invalid", true, "occurTime", MAX_ORDERS_PER_QUERY);
|
|
|
+
|
|
|
+ List<GxtWorkOrder> activeWorkOrders = workOrderService.selectGxtWorkOrderByDeviceIdWithCondition(
|
|
|
+ equipment.getEquipmentId(), "invalid", true, "pauseTime", MAX_ORDERS_PER_QUERY);
|
|
|
+
|
|
|
+ // 合并两次查询的结果,一次性处理所有数据,找出关键时间点和相关工单
|
|
|
+ ProcessedTimeData processedData = processTimeData(archivedRepairOrders, archivedWorkOrders, activeRepairOrders, activeWorkOrders);
|
|
|
+
|
|
|
+ if (processedData.latestRestartTime == null) {
|
|
|
+ log.debug("设备 {} 未找到任何restartTime数据,跳过处理", equipment.getEquipmentCode());
|
|
|
+ return; // 必须最少能找到任意的GxtRepairOrder或者GxtWorkOrder当中的其中一个,否则数据不完整,不用再继续后面的步骤
|
|
|
+ }
|
|
|
+
|
|
|
+ /*if (processedData.latestOccurOrPauseTime == null) {
|
|
|
+ log.debug("设备 {} 未找到任何occurTime或pauseTime数据,跳过处理", equipment.getEquipmentCode());
|
|
|
+ return; // 必须最少能找到任意的GxtRepairOrder或者GxtWorkOrder当中的其中一个,否则数据不完整,不用再继续后面的步骤
|
|
|
+ }*/
|
|
|
+
|
|
|
+ // 检查是否在安全运行中
|
|
|
+ if (processedData.latestOccurOrPauseTime != null && processedData.latestRestartTime.before(processedData.latestOccurOrPauseTime)) {
|
|
|
+ log.debug("设备 {} 的最新occurTime/pauseTime({})比restartTime({})晚,不在安全运行中",
|
|
|
+ equipment.getEquipmentCode(), processedData.latestOccurOrPauseTime, processedData.latestRestartTime);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算安全运行天数
|
|
|
+ int daysBetween = DateUtils.differentDaysByMillisecond(DateUtils.getNowDate(), processedData.latestRestartTime);
|
|
|
+ if (daysBetween <= 0) {
|
|
|
+ log.debug("设备 {} 安全运行天数为 {} 天,无需奖励", equipment.getEquipmentCode(), daysBetween);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取奖励配置
|
|
|
+ GxtSafeOperationReward rewardQuery = new GxtSafeOperationReward();
|
|
|
+ rewardQuery.setStatus(0);
|
|
|
+ List<GxtSafeOperationReward> rewardConfigs = safeOperationRewardService.selectGxtSafeOperationRewardList(rewardQuery);
|
|
|
+ if (rewardConfigs.isEmpty()) {
|
|
|
+ log.warn("未找到任何启用的安全运行奖励配置");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按照safeDuration升序排序
|
|
|
+ rewardConfigs.sort(Comparator.comparingInt(GxtSafeOperationReward::getSafeDuration));
|
|
|
+
|
|
|
+ // 获取对应的奖励配置
|
|
|
+ GxtSafeOperationReward applicableReward = getApplicableRewardConfig(rewardConfigs, daysBetween);
|
|
|
+ if (applicableReward == null) {
|
|
|
+ log.debug("设备 {} 运行天数 {} 未找到对应的安全运行奖励配置", equipment.getEquipmentCode(), daysBetween);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用预处理的数据进行奖励处理
|
|
|
+ if (processedData.relatedRepairOrder != null) {
|
|
|
+ // 如果对应的工单是GxtRepairOrder,则获取的是unplannedMaintenanceScore的值
|
|
|
+ BigDecimal rewardScore = applicableReward.getUnplannedMaintenanceScore();
|
|
|
+ if (rewardScore != null && rewardScore.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ log.info("设备 {} 安全运行 {} 天,奖励维修工单 {} 维修奖励分值 {}",
|
|
|
+ equipment.getEquipmentCode(), daysBetween, processedData.relatedRepairOrder.getWorkOrderProjectNo(), rewardScore);
|
|
|
+
|
|
|
+ // 然后在获取这个工单所对应的人员数据,对这些人员进行加分操作
|
|
|
+ updatePersonRunScoreForRepairOrder(processedData.relatedRepairOrder, rewardScore);
|
|
|
+ // 更新月度统计数据
|
|
|
+ updateMonthlyScoreDataForRunScore(processedData.relatedRepairOrder, rewardScore);
|
|
|
+ }
|
|
|
+ } else if (processedData.relatedWorkOrder != null) {
|
|
|
+ // 如果对应的工单是GxtWorkOrder,则获取的是plannedMaintenanceScore的值
|
|
|
+ BigDecimal rewardScore = applicableReward.getPlannedMaintenanceScore();
|
|
|
+ if (rewardScore != null && rewardScore.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ log.info("设备 {} 安全运行 {} 天,奖励维保工单 {} 计划检修奖励分值 {}",
|
|
|
+ equipment.getEquipmentCode(), daysBetween, processedData.relatedWorkOrder.getWorkOrderProjectNo(), rewardScore);
|
|
|
+
|
|
|
+ // 然后在获取这个工单所对应的人员数据,对这些人员进行加分操作
|
|
|
+ updatePersonRunScoreForWorkOrder(processedData.relatedWorkOrder, rewardScore);
|
|
|
+ // 更新月度统计数据
|
|
|
+ updateMonthlyScoreDataForRunScore(processedData.relatedWorkOrder, rewardScore);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.warn("设备 {} 未找到对应的工单信息", equipment.getEquipmentCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新月度统计数据以反映运行得分奖励
|
|
|
+ *
|
|
|
+ * @param repairOrder 维修工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updateMonthlyScoreDataForRunScore(GxtRepairOrder repairOrder, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ // 使用当前日期所在的月份(因为奖励是在当前时间发放的)
|
|
|
+ SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM");
|
|
|
+ String monthPeriod = sdf.format(new Date());
|
|
|
+
|
|
|
+ // 获取场站ID
|
|
|
+ Long deptId = repairOrder.getPcsStationPid();
|
|
|
+
|
|
|
+ // 获取月度统计信息
|
|
|
+ GxtMonthScore queryScore = new GxtMonthScore();
|
|
|
+ queryScore.setDeptId(deptId);
|
|
|
+ queryScore.setMonthPeriod(monthPeriod);
|
|
|
+ List<GxtMonthScore> scoreList = monthScoreService.selectGxtMonthScoreList(queryScore);
|
|
|
+ GxtMonthScore monthScore = null;
|
|
|
+ if (!scoreList.isEmpty()) {
|
|
|
+ monthScore = scoreList.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (monthScore == null) {
|
|
|
+ // 如果没有月度统计记录,创建新的记录
|
|
|
+ monthScore = new GxtMonthScore();
|
|
|
+ monthScore.setDeptId(deptId);
|
|
|
+ monthScore.setMonthPeriod(monthPeriod);
|
|
|
+ monthScore.setStatus(0); // 初始状态
|
|
|
+ monthScore.setPersionId(SecurityUtils.getUserId());
|
|
|
+ monthScore.setCreateBy(SecurityUtils.getUsername());
|
|
|
+ monthScore.setCreateTime(new Date());
|
|
|
+ monthScoreService.insertGxtMonthScore(monthScore);
|
|
|
+
|
|
|
+ // 重新查询刚插入的记录
|
|
|
+ scoreList = monthScoreService.selectGxtMonthScoreList(queryScore);
|
|
|
+ if (!scoreList.isEmpty()) {
|
|
|
+ monthScore = scoreList.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (monthScore != null) {
|
|
|
+ // 更新用户评分统计
|
|
|
+ updateUserScoresForRunScore(monthScore, repairOrder, rewardScore);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维修工单 {} 的月度统计数据时发生异常", repairOrder.getWorkOrderProjectNo(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新月度统计数据以反映运行得分奖励
|
|
|
+ *
|
|
|
+ * @param workOrder 维保工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updateMonthlyScoreDataForRunScore(GxtWorkOrder workOrder, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ // 使用当前日期所在的月份(因为奖励是在当前时间发放的)
|
|
|
+ java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM");
|
|
|
+ String monthPeriod = sdf.format(new Date());
|
|
|
+
|
|
|
+ // 获取场站ID
|
|
|
+ Long deptId = workOrder.getPcsStationPid();
|
|
|
+
|
|
|
+ // 获取月度统计信息
|
|
|
+ GxtMonthScore queryScore = new GxtMonthScore();
|
|
|
+ queryScore.setDeptId(deptId);
|
|
|
+ queryScore.setMonthPeriod(monthPeriod);
|
|
|
+ List<GxtMonthScore> scoreList = monthScoreService.selectGxtMonthScoreList(queryScore);
|
|
|
+ GxtMonthScore monthScore = null;
|
|
|
+ if (!scoreList.isEmpty()) {
|
|
|
+ monthScore = scoreList.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (monthScore == null) {
|
|
|
+ // 如果没有月度统计记录,创建新的记录
|
|
|
+ monthScore = new GxtMonthScore();
|
|
|
+ monthScore.setDeptId(deptId);
|
|
|
+ monthScore.setMonthPeriod(monthPeriod);
|
|
|
+ monthScore.setStatus(0); // 初始状态
|
|
|
+ monthScore.setPersionId(SecurityUtils.getUserId());
|
|
|
+ monthScore.setCreateBy(SecurityUtils.getUsername());
|
|
|
+ monthScore.setCreateTime(new Date());
|
|
|
+ monthScoreService.insertGxtMonthScore(monthScore);
|
|
|
+
|
|
|
+ // 重新查询刚插入的记录
|
|
|
+ scoreList = monthScoreService.selectGxtMonthScoreList(queryScore);
|
|
|
+ if (!scoreList.isEmpty()) {
|
|
|
+ monthScore = scoreList.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (monthScore != null) {
|
|
|
+ // 更新用户评分统计
|
|
|
+ updateUserScoresForRunScore(monthScore, workOrder, rewardScore);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维保工单 {} 的月度统计数据时发生异常", workOrder.getWorkOrderProjectNo(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新用户评分统计以反映运行得分奖励
|
|
|
+ *
|
|
|
+ * @param monthScore 月度统计信息
|
|
|
+ * @param order 维修工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updateUserScoresForRunScore(GxtMonthScore monthScore, GxtRepairOrder order, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ List<GxtRepairOrderPerson> persons = order.getRepairOrderPersonList();
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ // 如果工单中的人员列表为空,尝试从数据库查询
|
|
|
+ persons = repairOrderService.selectRepairOrderPersonListByOrderId(order.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (persons != null) {
|
|
|
+ for (GxtRepairOrderPerson person : persons) {
|
|
|
+ Long userId = person.getUserId();
|
|
|
+ SysUser sysUser = userMapper.selectUserById(userId);
|
|
|
+
|
|
|
+ // 使用userName、monthPeriod、monthScoreId精确查询用户评分记录
|
|
|
+ GxtUserScore userScoreQuery = new GxtUserScore();
|
|
|
+ userScoreQuery.setUserName(sysUser.getUserName());
|
|
|
+ userScoreQuery.setMonthPeriod(monthScore.getMonthPeriod());
|
|
|
+ userScoreQuery.setMonthScoreId(monthScore.getId());
|
|
|
+ List<GxtUserScore> userScores = userScoreService.selectGxtUserScoreList(userScoreQuery);
|
|
|
+
|
|
|
+ if (!userScores.isEmpty()) {
|
|
|
+ // 找到现有记录,直接更新
|
|
|
+ GxtUserScore userScore = userScores.get(0);
|
|
|
+ BigDecimal currentRepairTotal = (userScore.getRepairTotalScore() != null) ?
|
|
|
+ userScore.getRepairTotalScore() : BigDecimal.ZERO;
|
|
|
+
|
|
|
+ BigDecimal newRepairScore = currentRepairTotal.add(rewardScore);
|
|
|
+ userScore.setRepairTotalScore(newRepairScore);
|
|
|
+
|
|
|
+ // 更新最终评分
|
|
|
+ BigDecimal maintenanceScore = (userScore.getMaintenanceTotalScore() != null) ?
|
|
|
+ userScore.getMaintenanceTotalScore() : BigDecimal.ZERO;
|
|
|
+
|
|
|
+ BigDecimal finalScore = maintenanceScore.add(newRepairScore);
|
|
|
+ userScore.setFinalScore(finalScore);
|
|
|
+ userScore.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ userScore.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ userScoreService.updateGxtUserScore(userScore);
|
|
|
+
|
|
|
+ log.debug("更新用户 {} 月度统计得分: {} -> {}", person.getNickName(), currentRepairTotal, newRepairScore);
|
|
|
+ } else {
|
|
|
+ // 没有找到记录,创建新记录
|
|
|
+ GxtUserScore newUserScore = new GxtUserScore();
|
|
|
+ newUserScore.setMonthScoreId(monthScore.getId());
|
|
|
+ newUserScore.setUserName(sysUser.getUserName());
|
|
|
+ newUserScore.setNickName(person.getNickName());
|
|
|
+ newUserScore.setMonthPeriod(monthScore.getMonthPeriod());
|
|
|
+
|
|
|
+ // 设置维修工单得分
|
|
|
+ BigDecimal repairScore = rewardScore;
|
|
|
+ newUserScore.setRepairTotalScore(rewardScore);
|
|
|
+
|
|
|
+ // 维保得分默认为0
|
|
|
+ newUserScore.setMaintenanceTotalScore(BigDecimal.ZERO);
|
|
|
+ newUserScore.setFinalScore(rewardScore);
|
|
|
+ newUserScore.setStatus(0);
|
|
|
+ newUserScore.setCreateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ newUserScore.setCreateTime(new Date());
|
|
|
+ // 插入新记录
|
|
|
+ userScoreService.insertGxtUserScore(newUserScore);
|
|
|
+
|
|
|
+ log.debug("创建用户 {} 月度统计得分: {}", person.getNickName(), repairScore);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维修工单人员月度统计数据时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新用户评分统计以反映运行得分奖励
|
|
|
+ *
|
|
|
+ * @param monthScore 月度统计信息
|
|
|
+ * @param order 维保工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updateUserScoresForRunScore(GxtMonthScore monthScore, GxtWorkOrder order, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ List<GxtWorkOrderPerson> persons = order.getWorkOrderPersonList();
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ // 如果工单中的人员列表为空,尝试从数据库查询
|
|
|
+ persons = workOrderService.selectWorkOrderPersonListByOrderId(order.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (persons != null) {
|
|
|
+ for (GxtWorkOrderPerson person : persons) {
|
|
|
+ Long userId = person.getUserId();
|
|
|
+ SysUser sysUser = userMapper.selectUserById(userId);
|
|
|
+
|
|
|
+ // 使用userName、monthPeriod、monthScoreId精确查询用户评分记录
|
|
|
+ GxtUserScore userScoreQuery = new GxtUserScore();
|
|
|
+ userScoreQuery.setUserName(sysUser.getUserName());
|
|
|
+ userScoreQuery.setMonthPeriod(monthScore.getMonthPeriod());
|
|
|
+ userScoreQuery.setMonthScoreId(monthScore.getId());
|
|
|
+ List<GxtUserScore> userScores = userScoreService.selectGxtUserScoreList(userScoreQuery);
|
|
|
+
|
|
|
+ if (!userScores.isEmpty()) {
|
|
|
+ // 找到现有记录,直接更新
|
|
|
+ GxtUserScore userScore = userScores.get(0);
|
|
|
+ BigDecimal currentMaintenanceTotal = (userScore.getMaintenanceTotalScore() != null) ?
|
|
|
+ userScore.getMaintenanceTotalScore() : BigDecimal.ZERO;
|
|
|
+
|
|
|
+ BigDecimal newMaintenanceScore = currentMaintenanceTotal.add(rewardScore);
|
|
|
+ userScore.setMaintenanceTotalScore(newMaintenanceScore);
|
|
|
+
|
|
|
+ // 更新最终评分
|
|
|
+ BigDecimal repairScore = (userScore.getRepairTotalScore() != null) ?
|
|
|
+ userScore.getRepairTotalScore() : BigDecimal.ZERO;
|
|
|
+
|
|
|
+ BigDecimal finalScore = repairScore.add(newMaintenanceScore);
|
|
|
+ userScore.setFinalScore(finalScore);
|
|
|
+ userScore.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ userScore.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ userScoreService.updateGxtUserScore(userScore);
|
|
|
+
|
|
|
+ log.debug("更新用户 {} 月度统计得分: {} -> {}", person.getNickName(), currentMaintenanceTotal, newMaintenanceScore);
|
|
|
+ } else {
|
|
|
+ // 没有找到记录,创建新记录
|
|
|
+ GxtUserScore newUserScore = new GxtUserScore();
|
|
|
+ newUserScore.setMonthScoreId(monthScore.getId());
|
|
|
+ newUserScore.setUserName(sysUser.getUserName());
|
|
|
+ newUserScore.setNickName(person.getNickName());
|
|
|
+ newUserScore.setMonthPeriod(monthScore.getMonthPeriod());
|
|
|
+
|
|
|
+ // 设置维保工单得分
|
|
|
+ BigDecimal maintenanceScore = rewardScore;
|
|
|
+ newUserScore.setMaintenanceTotalScore(maintenanceScore);
|
|
|
+
|
|
|
+ // 维修得分默认为0
|
|
|
+ newUserScore.setRepairTotalScore(BigDecimal.ZERO);
|
|
|
+ newUserScore.setFinalScore(maintenanceScore);
|
|
|
+ newUserScore.setStatus(0);
|
|
|
+ newUserScore.setCreateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ newUserScore.setCreateTime(new Date());
|
|
|
+ // 插入新记录
|
|
|
+ userScoreService.insertGxtUserScore(newUserScore);
|
|
|
+
|
|
|
+ log.debug("创建用户 {} 月度统计得分: {}", person.getNickName(), maintenanceScore);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维保工单人员月度统计数据时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理时间数据,一次性计算所有必要的时间点和相关工单
|
|
|
+ */
|
|
|
+ private ProcessedTimeData processTimeData(List<GxtRepairOrder> archivedRepairOrders, List<GxtWorkOrder> archivedWorkOrders,
|
|
|
+ List<GxtRepairOrder> activeRepairOrders, List<GxtWorkOrder> activeWorkOrders) {
|
|
|
+ ProcessedTimeData data = new ProcessedTimeData();
|
|
|
+
|
|
|
+ // 获取最新的restartTime数据和对应的工单(从归档工单中查找)
|
|
|
+ // 由于查询时已按restartTime降序排序,所以取第一个非空元素即可
|
|
|
+ if (!archivedRepairOrders.isEmpty()) {
|
|
|
+ GxtRepairOrder firstOrder = archivedRepairOrders.get(0);
|
|
|
+ if (firstOrder.getRestartTime() != null) {
|
|
|
+ data.latestRestartTime = firstOrder.getRestartTime();
|
|
|
+ data.relatedRepairOrder = firstOrder; // 记录相关维修工单
|
|
|
+ data.relatedWorkOrder = null; // 清除可能之前设置的维保工单
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!archivedWorkOrders.isEmpty()) {
|
|
|
+ GxtWorkOrder firstOrder = archivedWorkOrders.get(0);
|
|
|
+ if (firstOrder.getRestartTime() != null &&
|
|
|
+ (data.latestRestartTime == null || firstOrder.getRestartTime().after(data.latestRestartTime))) {
|
|
|
+ data.latestRestartTime = firstOrder.getRestartTime();
|
|
|
+ data.relatedWorkOrder = firstOrder; // 记录相关维保工单
|
|
|
+ data.relatedRepairOrder = null; // 清除可能之前设置的维修工单
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取最新的occurTime或pauseTime数据(从活动工单中查找)
|
|
|
+ // 由于查询时已按相应时间字段降序排序,所以取第一个非空元素即可
|
|
|
+ if (!activeRepairOrders.isEmpty()) {
|
|
|
+ GxtRepairOrder firstOrder = activeRepairOrders.get(0);
|
|
|
+ if (firstOrder.getOccurTime() != null) {
|
|
|
+ data.latestOccurOrPauseTime = firstOrder.getOccurTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!activeWorkOrders.isEmpty()) {
|
|
|
+ GxtWorkOrder firstOrder = activeWorkOrders.get(0);
|
|
|
+ if (firstOrder.getPauseTime() != null &&
|
|
|
+ (data.latestOccurOrPauseTime == null || firstOrder.getPauseTime().after(data.latestOccurOrPauseTime))) {
|
|
|
+ data.latestOccurOrPauseTime = firstOrder.getPauseTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据安全运行天数获取适用的奖励配置
|
|
|
+ *
|
|
|
+ * @param rewardConfigs 奖励配置列表
|
|
|
+ * @param daysBetween 安全运行天数
|
|
|
+ * @return 适用的奖励配置
|
|
|
+ */
|
|
|
+ private GxtSafeOperationReward getApplicableRewardConfig(List<GxtSafeOperationReward> rewardConfigs, int daysBetween) {
|
|
|
+ GxtSafeOperationReward applicableReward = null;
|
|
|
+
|
|
|
+ for (GxtSafeOperationReward config : rewardConfigs) {
|
|
|
+ if (config.getSafeDuration() <= daysBetween) {
|
|
|
+ applicableReward = config;
|
|
|
+ } else {
|
|
|
+ // 因为已经按safeDuration升序排序,所以第一个大于daysBetween的配置就是边界
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return applicableReward;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 为维修工单人员更新运行得分
|
|
|
+ *
|
|
|
+ * @param repairOrder 维修工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updatePersonRunScoreForRepairOrder(GxtRepairOrder repairOrder, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ List<GxtRepairOrderPerson> persons = repairOrder.getRepairOrderPersonList();
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ // 如果工单中的人员列表为空,尝试从数据库查询
|
|
|
+ persons = repairOrderService.selectRepairOrderPersonListByOrderId(repairOrder.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ log.warn("维修工单 {} 没有找到相关人员", repairOrder.getWorkOrderProjectNo());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<GxtRepairOrderPerson> updatedPersons = new ArrayList<>();
|
|
|
+ for (GxtRepairOrderPerson person : persons) {
|
|
|
+ Double currentRunScore = person.getRunScore();
|
|
|
+ Double newRunScore = (currentRunScore != null ? currentRunScore : 0.0) + rewardScore.doubleValue();
|
|
|
+
|
|
|
+ GxtRepairOrderPerson updatedPerson = new GxtRepairOrderPerson();
|
|
|
+ updatedPerson.setId(person.getId());
|
|
|
+ updatedPerson.setRunScore(newRunScore);
|
|
|
+ updatedPerson.setScore(person.getScore() != null ? person.getScore().add(rewardScore) : rewardScore);
|
|
|
+ updatedPerson.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ updatedPerson.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ updatedPersons.add(updatedPerson);
|
|
|
+
|
|
|
+ log.debug("维修工单 {} 人员 {} 运行得分更新: {} -> {}",
|
|
|
+ repairOrder.getWorkOrderProjectNo(), person.getNickName(), currentRunScore, newRunScore );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量更新人员得分
|
|
|
+ int result = repairOrderService.updateRepairOrderPersonList(updatedPersons);
|
|
|
+ log.info("维修工单 {} 共更新 {} 名人员的运行得分和总得分", repairOrder.getWorkOrderProjectNo(), updatedPersons.size());
|
|
|
+
|
|
|
+ /*double totalScore = persons.stream()
|
|
|
+ .mapToDouble(person -> person.getTotalScore() != null ? person.getTotalScore() : 0.0)
|
|
|
+ .sum();
|
|
|
+ repairOrder.setScore(new BigDecimal(String.valueOf(totalScore)));
|
|
|
+
|
|
|
+ repairOrderService.updateGxtRepairOrderForScore(repairOrder);*/
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维修工单 {} 人员运行得分时发生异常", repairOrder.getWorkOrderProjectNo(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 为维保工单人员更新运行得分
|
|
|
+ *
|
|
|
+ * @param workOrder 维保工单
|
|
|
+ * @param rewardScore 奖励分数
|
|
|
+ */
|
|
|
+ private void updatePersonRunScoreForWorkOrder(GxtWorkOrder workOrder, BigDecimal rewardScore) {
|
|
|
+ try {
|
|
|
+ List<GxtWorkOrderPerson> persons = workOrder.getWorkOrderPersonList();
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ // 如果工单中的人员列表为空,尝试从数据库查询
|
|
|
+ persons = workOrderService.selectWorkOrderPersonListByOrderId(workOrder.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (persons == null || persons.isEmpty()) {
|
|
|
+ log.warn("维保工单 {} 没有找到相关人员", workOrder.getWorkOrderProjectNo());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<GxtWorkOrderPerson> updatedPersons = new ArrayList<>();
|
|
|
+ for (GxtWorkOrderPerson person : persons) {
|
|
|
+ Double currentRunScore = person.getRunScore();
|
|
|
+ Double newRunScore = (currentRunScore != null ? currentRunScore : 0.0) + rewardScore.doubleValue();
|
|
|
+
|
|
|
+ GxtWorkOrderPerson updatedPerson = new GxtWorkOrderPerson();
|
|
|
+ updatedPerson.setId(person.getId());
|
|
|
+ updatedPerson.setRunScore(newRunScore);
|
|
|
+ updatedPerson.setScore(person.getScore() != null ? person.getScore().add(rewardScore) : rewardScore);
|
|
|
+ updatedPerson.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserName());
|
|
|
+ updatedPerson.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ updatedPersons.add(updatedPerson);
|
|
|
+
|
|
|
+ log.debug("维保工单 {} 人员 {} 运行得分更新: {} -> {}",
|
|
|
+ workOrder.getWorkOrderProjectNo(), person.getNickName(), currentRunScore, newRunScore);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量更新人员得分
|
|
|
+ int result = workOrderService.updateWorkOrderPersonList(updatedPersons);
|
|
|
+ log.info("维保工单 {} 共更新 {} 名人员的运行得分和总得分", workOrder.getWorkOrderProjectNo(), updatedPersons.size());
|
|
|
+
|
|
|
+ /*double totalScore = persons.stream()
|
|
|
+ .mapToDouble(person -> person.getTotalScore() != null ? person.getTotalScore() : 0.0)
|
|
|
+ .sum();
|
|
|
+ workOrder.setScore(new BigDecimal(String.valueOf(totalScore)));
|
|
|
+
|
|
|
+ workOrderService.updateGxtWorkOrderForScore(workOrder);*/
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新维保工单 {} 人员运行得分时发生异常", workOrder.getWorkOrderProjectNo(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置系统用户上下文,用于自动操作
|
|
|
+ */
|
|
|
+ private void setSystemUserContext() {
|
|
|
+ try {
|
|
|
+ // 获取admin用户信息
|
|
|
+ SysUser userAdmin = userMapper.selectUserByUserName("admin");
|
|
|
+ if (userAdmin != null) {
|
|
|
+ Set<String> permissions = permissionService.getMenuPermission(userAdmin);
|
|
|
+ LoginUser loginUser = new LoginUser(userAdmin, permissions);
|
|
|
+
|
|
|
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
|
|
+ loginUser,
|
|
|
+ null,
|
|
|
+ loginUser.getAuthorities()
|
|
|
+ );
|
|
|
+
|
|
|
+ SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("设置系统用户上下文失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 存储处理后的时间数据
|
|
|
+ */
|
|
|
+ private static class ProcessedTimeData {
|
|
|
+ Date latestRestartTime; // 最新的重启时间
|
|
|
+ Date latestOccurOrPauseTime; // 最新的故障或暂停时间
|
|
|
+ GxtRepairOrder relatedRepairOrder; // 相关的维修工单
|
|
|
+ GxtWorkOrder relatedWorkOrder; // 相关的维保工单
|
|
|
+ }
|
|
|
+}
|