diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionAsyncHandler.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionAsyncHandler.java index cc739f8..b8cda87 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionAsyncHandler.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionAsyncHandler.java @@ -27,18 +27,13 @@ public class InspectionAsyncHandler { */ @Async("ops-task-executor") public void handleFailedInspection(Long recordId, Long areaId) { - // 1. 归属判定 - try { - inspectionAttributionService.determineAttribution(recordId, areaId); - } catch (Exception e) { - log.error("[handleFailedInspection] 归属判定异常: recordId={}, areaId={}", recordId, areaId, e); - } + // 1. TODO 归属判定:待评分体系完善后启用 inspectionAttributionService.determineAttribution() - // 2. 创建整改工单(不论归属判定结果,不合格即需整改) + // 2. 整改工单:已有活跃工单则升级优先级,否则新建 try { inspectionRectificationService.createRectificationOrder(recordId, areaId); } catch (Exception e) { - log.error("[handleFailedInspection] 整改工单创建异常: recordId={}, areaId={}", recordId, areaId, e); + log.error("[handleFailedInspection] 整改工单处理异常: recordId={}, areaId={}", recordId, areaId, e); } } diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRectificationServiceImpl.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRectificationServiceImpl.java index 26312c8..5d975b6 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRectificationServiceImpl.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRectificationServiceImpl.java @@ -1,49 +1,113 @@ package com.viewsh.module.ops.environment.service.inspection; import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO; +import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; import com.viewsh.module.ops.dal.mysql.area.OpsBusAreaMapper; +import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper; import com.viewsh.module.ops.environment.service.cleanorder.dto.CleanOrderAutoCreateReqDTO; import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionRecordDO; import com.viewsh.module.ops.environment.dal.mysql.inspection.OpsInspectionRecordMapper; import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderService; import com.viewsh.module.ops.enums.PriorityEnum; import com.viewsh.module.ops.enums.SourceTypeEnum; +import com.viewsh.module.ops.enums.WorkOrderStatusEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.util.Set; + /** * 巡检整改工单 Service 实现 + *

+ * 逻辑与客流阈值触发一致: + * 1. 查该区域有无活跃保洁工单(非终态) + * 2. 有排队中工单(PENDING/QUEUED)→ 升级优先级一级 + * 3. 有已派发/已到达工单 → 保洁员已在处理中,不重复创建 + * 4. 无活跃工单 → 新建整改工单 */ @Service @Validated @Slf4j public class InspectionRectificationServiceImpl implements InspectionRectificationService { - /** 默认整改工单预计时长(分钟) */ private static final int DEFAULT_RECTIFICATION_DURATION_MINUTES = 30; + /** 可升级优先级的状态集合(仅排队中,尚未派发) */ + private static final Set UPGRADABLE_STATUSES = Set.of( + WorkOrderStatusEnum.PENDING.getStatus(), + WorkOrderStatusEnum.QUEUED.getStatus() + ); + @Resource private CleanOrderService cleanOrderService; @Resource private OpsBusAreaMapper opsBusAreaMapper; + @Resource + private OpsOrderMapper opsOrderMapper; + @Resource private OpsInspectionRecordMapper inspectionRecordMapper; @Override @Transactional(rollbackFor = Exception.class) public Long createRectificationOrder(Long recordId, Long areaId) { - // 1. 获取区域信息 + // 1. 查该区域活跃保洁工单 + OpsOrderDO activeOrder = opsOrderMapper.selectActiveCleanOrder(areaId); + + if (activeOrder != null) { + return handleExistingOrder(activeOrder, recordId, areaId); + } + + // 2. 无活跃工单 → 新建整改工单 + return createNewOrder(recordId, areaId); + } + + /** + * 已有活跃工单:排队中则升级优先级,已派发/已到达则静默 + */ + private Long handleExistingOrder(OpsOrderDO activeOrder, Long recordId, Long areaId) { + Long orderId = activeOrder.getId(); + String status = activeOrder.getStatus(); + + if (UPGRADABLE_STATUSES.contains(status)) { + // 排队中 → 升级优先级一级 + PriorityEnum result = cleanOrderService.upgradeOneLevelPriority( + orderId, "巡检不合格自动升级"); + + if (result != null) { + log.info("[createRectificationOrder] 已有工单优先级升级: recordId={}, orderId={}, newPriority={}", + recordId, orderId, result); + } else { + log.info("[createRectificationOrder] 已有工单已是P0封顶: recordId={}, orderId={}", + recordId, orderId); + } + } else { + // 已派发/已确认/已到达 → 保洁员已在处理中 + log.info("[createRectificationOrder] 区域{}保洁员已在处理中(状态:{}),不重复创建: recordId={}, orderId={}", + areaId, status, recordId, orderId); + } + + // 回写关联工单ID + updateGeneratedOrderId(recordId, orderId); + return orderId; + } + + /** + * 新建整改工单 + */ + private Long createNewOrder(Long recordId, Long areaId) { + // 获取区域信息 OpsBusAreaDO area = opsBusAreaMapper.selectById(areaId); String areaName = (area != null) ? area.getAreaName() : "未知区域"; int expectedDuration = (area != null && area.getStandardDuration() != null) ? area.getStandardDuration() : DEFAULT_RECTIFICATION_DURATION_MINUTES; - // 2. 构建整改工单请求 + // 构建请求 CleanOrderAutoCreateReqDTO createReq = new CleanOrderAutoCreateReqDTO(); createReq.setOrderType("CLEAN"); createReq.setSourceType(SourceTypeEnum.INSPECTION.getType()); @@ -55,18 +119,21 @@ public class InspectionRectificationServiceImpl implements InspectionRectificati createReq.setCleaningType("SPOT"); createReq.setDifficultyLevel(3); - // 3. 调用现有工单引擎创建工单 + // 创建工单 Long orderId = cleanOrderService.createAutoCleanOrder(createReq); log.info("[createRectificationOrder] 整改工单创建成功: recordId={}, areaId={}, orderId={}", recordId, areaId, orderId); - // 4. 回写 generated_order_id 到巡检记录 + // 回写关联工单ID + updateGeneratedOrderId(recordId, orderId); + return orderId; + } + + private void updateGeneratedOrderId(Long recordId, Long orderId) { OpsInspectionRecordDO update = new OpsInspectionRecordDO(); update.setId(recordId); update.setGeneratedOrderId(orderId); inspectionRecordMapper.updateById(update); - - return orderId; } } diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/workorder/OpsOrderMapper.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/workorder/OpsOrderMapper.java index c64d919..f1454b9 100644 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/workorder/OpsOrderMapper.java +++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/workorder/OpsOrderMapper.java @@ -4,6 +4,7 @@ import com.viewsh.framework.mybatis.core.mapper.BaseMapperX; import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX; import com.viewsh.module.ops.controller.admin.workorder.vo.statistics.*; import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; +import com.viewsh.module.ops.enums.WorkOrderStatusEnum; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -74,6 +75,23 @@ public interface OpsOrderMapper extends BaseMapperX { .last("LIMIT 1")); } + /** + * 查询区域内保洁类型的活跃工单(非终态,不限触发来源) + * + * @param areaId 区域ID + * @return 最近创建的活跃保洁工单,不存在返回 null + */ + default OpsOrderDO selectActiveCleanOrder(Long areaId) { + return selectOne(new LambdaQueryWrapperX() + .eq(OpsOrderDO::getAreaId, areaId) + .eq(OpsOrderDO::getOrderType, "CLEAN") + .notIn(OpsOrderDO::getStatus, + WorkOrderStatusEnum.COMPLETED.getStatus(), + WorkOrderStatusEnum.CANCELLED.getStatus()) + .orderByDesc(OpsOrderDO::getCreateTime) + .last("LIMIT 1")); + } + // ==================== 统计聚合查询 ==================== /**