|
|
@@ -0,0 +1,379 @@
|
|
|
+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.framework.web.service.SysPermissionService;
|
|
|
+import com.ygtx.gxt.domain.*;
|
|
|
+import com.ygtx.gxt.service.IGxtOrderScoreService;
|
|
|
+import com.ygtx.gxt.service.IGxtRepairOrderFlowService;
|
|
|
+import com.ygtx.gxt.service.IGxtRepairOrderService;
|
|
|
+import com.ygtx.gxt.service.IGxtWorkOrderFlowService;
|
|
|
+import com.ygtx.gxt.service.IGxtWorkOrderService;
|
|
|
+import com.ygtx.system.mapper.SysUserMapper;
|
|
|
+import com.ygtx.system.service.ISysConfigService;
|
|
|
+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.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 工单自动终评任务
|
|
|
+ * 每小时执行,对复评超过24小时但未终评的维修工单和维保工单进行自动终评
|
|
|
+ *
|
|
|
+ * @author ouyj
|
|
|
+ * @date 2026-01-23
|
|
|
+ */
|
|
|
+@EnableScheduling
|
|
|
+@Component("orderScoreAutoFinalTask")
|
|
|
+public class OrderScoreAutoFinalTask {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(OrderScoreAutoFinalTask.class);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtRepairOrderService repairOrderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtRepairOrderFlowService repairOrderFlowService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtWorkOrderService workOrderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtWorkOrderFlowService workOrderFlowService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGxtOrderScoreService orderScoreService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysUserMapper userMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysPermissionService permissionService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysConfigService configService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每小时执行定时任务
|
|
|
+ * 查找复评超过24小时但未终评的维修工单和维保工单,并进行自动终评
|
|
|
+ */
|
|
|
+ public void autoFinalOrders() {
|
|
|
+ log.info("开始执行工单自动终评任务");
|
|
|
+
|
|
|
+ // 设置系统用户上下文
|
|
|
+ setSystemUserContext();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 处理维修工单的自动终评
|
|
|
+ processRepairOrders();
|
|
|
+
|
|
|
+ // 处理维保工单的自动终评
|
|
|
+ processWorkOrders();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("执行工单自动终评任务时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理维修工单的自动终评
|
|
|
+ */
|
|
|
+ private void processRepairOrders() {
|
|
|
+ try {
|
|
|
+ // 构造查询条件:待终评状态的工单
|
|
|
+ GxtRepairOrder queryOrder = new GxtRepairOrder();
|
|
|
+ queryOrder.setScoringStatus("to_final"); // 待终评状态
|
|
|
+ List<GxtRepairOrder> orders = repairOrderService.selectGxtRepairOrderList(queryOrder);
|
|
|
+
|
|
|
+ int finalCount = 0;
|
|
|
+ for (GxtRepairOrder order : orders) {
|
|
|
+ // 检查是否满足自动终评条件(复评超过24小时)
|
|
|
+ //if (shouldAutoFinalRepairOrder(order)) {
|
|
|
+ // 执行自动终评操作
|
|
|
+ autoFinalRepairOrder(order);
|
|
|
+ finalCount++;
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("维修工单自动终评任务执行完成,共处理 {} 个工单", finalCount);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理维修工单自动终评时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理维保工单的自动终评
|
|
|
+ */
|
|
|
+ private void processWorkOrders() {
|
|
|
+ try {
|
|
|
+ // 构造查询条件:待终评状态的维保工单
|
|
|
+ GxtWorkOrder queryOrder = new GxtWorkOrder();
|
|
|
+ queryOrder.setScoringStatus("to_final"); // 待终评状态
|
|
|
+ List<GxtWorkOrder> orders = workOrderService.selectGxtWorkOrderList(queryOrder);
|
|
|
+
|
|
|
+ int finalCount = 0;
|
|
|
+ for (GxtWorkOrder order : orders) {
|
|
|
+ // 检查是否满足自动终评条件(复评超过24小时)
|
|
|
+ //if (shouldAutoFinalWorkOrder(order)) {
|
|
|
+ // 执行自动终评操作
|
|
|
+ autoFinalWorkOrder(order);
|
|
|
+ finalCount++;
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("维保工单自动终评任务执行完成,共处理 {} 个工单", finalCount);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理维保工单自动终评时发生异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断维修工单是否满足自动终评条件
|
|
|
+ * 条件:处于待终评状态且超过配置的小时数,默认24小时
|
|
|
+ *
|
|
|
+ * @param order 维修工单
|
|
|
+ * @return 是否满足自动终评条件
|
|
|
+ */
|
|
|
+ private boolean shouldAutoFinalRepairOrder(GxtRepairOrder order) {
|
|
|
+ Date toFinalStatusTime = null;
|
|
|
+
|
|
|
+ // 通过查询工单流转记录获取进入待终评状态的时间
|
|
|
+ GxtRepairOrderFlow flowQuery = new GxtRepairOrderFlow();
|
|
|
+ flowQuery.setOrderId(order.getId());
|
|
|
+ flowQuery.setActionType("reviewRating");
|
|
|
+ List<GxtRepairOrderFlow> flows = repairOrderFlowService.selectGxtRepairOrderFlowList(flowQuery);
|
|
|
+
|
|
|
+ if (!flows.isEmpty()) {
|
|
|
+ // 获取最后一次进入待终评状态的时间
|
|
|
+ toFinalStatusTime = flows.get(flows.size() - 1).getActionTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toFinalStatusTime == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从配置中获取终评超时小时数,如果配置为空则默认24小时
|
|
|
+ String hoursStr = configService.selectConfigByKey("gxt.orderScore.autoFinalHours");
|
|
|
+ int finalHours = 24; // 默认24小时
|
|
|
+ if (hoursStr != null && !hoursStr.trim().isEmpty()) {
|
|
|
+ try {
|
|
|
+ finalHours = Integer.parseInt(hoursStr.trim());
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("配置的自动终评小时数不是有效数字,使用默认值24小时: {}", hoursStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查进入待终评状态的时间是否已超过配置的小时数
|
|
|
+ Date now = DateUtils.getNowDate();
|
|
|
+ Date finalTimeThreshold = DateUtils.addHours(toFinalStatusTime, finalHours);
|
|
|
+
|
|
|
+ return now.after(finalTimeThreshold);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断维保工单是否满足自动终评条件
|
|
|
+ * 条件:处于待终评状态且超过配置的小时数,默认24小时
|
|
|
+ *
|
|
|
+ * @param order 维保工单
|
|
|
+ * @return 是否满足自动终评条件
|
|
|
+ */
|
|
|
+ private boolean shouldAutoFinalWorkOrder(GxtWorkOrder order) {
|
|
|
+ Date toFinalStatusTime = null;
|
|
|
+
|
|
|
+ // 通过查询工单流转记录获取进入待终评状态的时间
|
|
|
+ GxtWorkOrderFlow flowQuery = new GxtWorkOrderFlow();
|
|
|
+ flowQuery.setOrderId(order.getId());
|
|
|
+ flowQuery.setActionType("reviewRating");
|
|
|
+ List<GxtWorkOrderFlow> flows = workOrderFlowService.selectGxtWorkOrderFlowList(flowQuery);
|
|
|
+
|
|
|
+ if (!flows.isEmpty()) {
|
|
|
+ // 获取最后一次进入待终评状态的时间
|
|
|
+ toFinalStatusTime = flows.get(flows.size() - 1).getActionTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toFinalStatusTime == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从配置中获取终评超时小时数,如果配置为空则默认24小时
|
|
|
+ String hoursStr = configService.selectConfigByKey("gxt.orderScore.autoFinalHours");
|
|
|
+ int finalHours = 24; // 默认24小时
|
|
|
+ if (hoursStr != null && !hoursStr.trim().isEmpty()) {
|
|
|
+ try {
|
|
|
+ finalHours = Integer.parseInt(hoursStr.trim());
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("配置的自动终评小时数不是有效数字,使用默认值24小时: {}", hoursStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查进入待终评状态的时间是否已超过配置的小时数
|
|
|
+ Date now = DateUtils.getNowDate();
|
|
|
+ Date finalTimeThreshold = DateUtils.addHours(toFinalStatusTime, finalHours);
|
|
|
+
|
|
|
+ return now.after(finalTimeThreshold);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对维修工单进行自动终评操作
|
|
|
+ *
|
|
|
+ * @param order 需要终评的工单
|
|
|
+ */
|
|
|
+ private void autoFinalRepairOrder(GxtRepairOrder order) {
|
|
|
+ try {
|
|
|
+ // 获取工单的人员评分信息
|
|
|
+ List<GxtRepairOrderPerson> orderPersons = repairOrderService.selectRepairOrderPersonListByOrderId(order.getId());
|
|
|
+
|
|
|
+ // 创建评分信息对象
|
|
|
+ OrderScoreInfo orderScoreInfo = new OrderScoreInfo();
|
|
|
+ orderScoreInfo.setId(order.getId());
|
|
|
+ orderScoreInfo.setOrderType(1); // 维修工单
|
|
|
+ orderScoreInfo.setWorkOrderProjectNo(order.getWorkOrderProjectNo());
|
|
|
+
|
|
|
+ // 复制原工单的评分状态和类型信息
|
|
|
+ //orderScoreInfo.setMaintenanceType(order.getMaintenanceType());
|
|
|
+ orderScoreInfo.setFinalCoefficient(order.getFinalCoefficient() != null ? order.getFinalCoefficient() : BigDecimal.ONE); // 系数设为1
|
|
|
+
|
|
|
+ // 如果有重启时间,这可能影响最终的状态
|
|
|
+ //orderScoreInfo.setRestartTime(order.getRestartTime());
|
|
|
+
|
|
|
+ // 设置人员评分列表
|
|
|
+ if (orderPersons != null && !orderPersons.isEmpty()) {
|
|
|
+ List<OrderScorePerson> scorePersons = orderPersons.stream().map(person -> {
|
|
|
+ OrderScorePerson scorePerson = new OrderScorePerson();
|
|
|
+ scorePerson.setId(person.getId());
|
|
|
+ scorePerson.setUserId(person.getUserId());
|
|
|
+ scorePerson.setNickName(person.getNickName());
|
|
|
+
|
|
|
+ // 使用复评分作为终评分和总评分
|
|
|
+ Double reviewScore = person.getReviewScore();
|
|
|
+ scorePerson.setFinalScore(reviewScore);
|
|
|
+
|
|
|
+ Double totalScore = (person.getTotalScore() != null) ? person.getTotalScore() : reviewScore;
|
|
|
+ scorePerson.setTotalScore(totalScore != null ? totalScore : 0.0);
|
|
|
+
|
|
|
+ // 保留原有的运行得分和停机扣分
|
|
|
+ scorePerson.setRunScore(person.getRunScore());
|
|
|
+ scorePerson.setStopScore(person.getStopScore());
|
|
|
+
|
|
|
+ return scorePerson;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ orderScoreInfo.setScorePersonList(scorePersons);
|
|
|
+ } else {
|
|
|
+ // 如果没有人员评分信息,则创建一个空列表,避免空指针异常
|
|
|
+ orderScoreInfo.setScorePersonList(new ArrayList<>());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用现有的终评方法
|
|
|
+ int result = orderScoreService.finalEvaluation(orderScoreInfo);
|
|
|
+
|
|
|
+ if (result > 0) {
|
|
|
+ log.info("工单 {} 已成功自动终评", order.getWorkOrderProjectNo());
|
|
|
+ } else {
|
|
|
+ log.warn("工单 {} 自动终评失败", order.getWorkOrderProjectNo());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("自动终评工单 {} 时发生异常", order.getWorkOrderProjectNo(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对维保工单进行自动终评操作
|
|
|
+ *
|
|
|
+ * @param order 需要终评的工单
|
|
|
+ */
|
|
|
+ private void autoFinalWorkOrder(GxtWorkOrder order) {
|
|
|
+ try {
|
|
|
+ // 获取工单的人员评分信息
|
|
|
+ List<GxtWorkOrderPerson> orderPersons = workOrderService.selectWorkOrderPersonListByOrderId(order.getId());
|
|
|
+
|
|
|
+ // 创建评分信息对象
|
|
|
+ OrderScoreInfo orderScoreInfo = new OrderScoreInfo();
|
|
|
+ orderScoreInfo.setId(order.getId());
|
|
|
+ orderScoreInfo.setOrderType(2); // 维保工单
|
|
|
+ orderScoreInfo.setWorkOrderProjectNo(order.getWorkOrderProjectNo());
|
|
|
+
|
|
|
+ // 复制原工单的评分状态和类型信息
|
|
|
+ //orderScoreInfo.setInspectionType(order.getInspectionType());
|
|
|
+ //orderScoreInfo.setItemCompletionFactor(order.getItemCompletionFactor()); // 系数设为1
|
|
|
+
|
|
|
+ // 如果有重启时间,这可能影响最终的状态
|
|
|
+ //orderScoreInfo.setRestartTime(order.getRestartTime());
|
|
|
+
|
|
|
+ // 设置人员评分列表
|
|
|
+ if (orderPersons != null && !orderPersons.isEmpty()) {
|
|
|
+ List<OrderScorePerson> scorePersons = orderPersons.stream().map(person -> {
|
|
|
+ OrderScorePerson scorePerson = new OrderScorePerson();
|
|
|
+ scorePerson.setId(person.getId());
|
|
|
+ scorePerson.setUserId(person.getUserId());
|
|
|
+ scorePerson.setNickName(person.getNickName());
|
|
|
+
|
|
|
+ // 使用复评分作为终评分和总评分
|
|
|
+ Double reviewScore = person.getReviewScore();
|
|
|
+ scorePerson.setFinalScore(reviewScore);
|
|
|
+
|
|
|
+ Double totalScore = (person.getTotalScore() != null) ? person.getTotalScore() : reviewScore;
|
|
|
+ scorePerson.setTotalScore(totalScore != null ? totalScore : 0.0);
|
|
|
+
|
|
|
+ // 保留原有的运行得分和停机扣分
|
|
|
+ scorePerson.setRunScore(person.getRunScore());
|
|
|
+ scorePerson.setStopScore(person.getStopScore());
|
|
|
+
|
|
|
+ return scorePerson;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ orderScoreInfo.setScorePersonList(scorePersons);
|
|
|
+ } else {
|
|
|
+ // 如果没有人员评分信息,则创建一个空列表,避免空指针异常
|
|
|
+ orderScoreInfo.setScorePersonList(new ArrayList<>());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用现有的终评方法
|
|
|
+ int result = orderScoreService.finalEvaluation(orderScoreInfo);
|
|
|
+
|
|
|
+ if (result > 0) {
|
|
|
+ log.info("工单 {} 已成功自动终评", order.getWorkOrderProjectNo());
|
|
|
+ } else {
|
|
|
+ log.warn("工单 {} 自动终评失败", order.getWorkOrderProjectNo());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("自动终评工单 {} 时发生异常", order.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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|