feat(ops): 整改工单去重 — 已有活跃工单时升级优先级而非重复创建
- InspectionRectificationServiceImpl 先查区域活跃保洁工单: 排队中(PENDING/QUEUED)→升级一级优先级;已派发/已到达→静默跳过 - OpsOrderMapper 新增 selectActiveCleanOrder,使用枚举替代硬编码终态 - InspectionAsyncHandler 清理归属判定注释代码,替换为 TODO 标记 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 实现
|
||||
* <p>
|
||||
* 逻辑与客流阈值触发一致:
|
||||
* 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<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<OpsOrderDO> {
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询区域内保洁类型的活跃工单(非终态,不限触发来源)
|
||||
*
|
||||
* @param areaId 区域ID
|
||||
* @return 最近创建的活跃保洁工单,不存在返回 null
|
||||
*/
|
||||
default OpsOrderDO selectActiveCleanOrder(Long areaId) {
|
||||
return selectOne(new LambdaQueryWrapperX<OpsOrderDO>()
|
||||
.eq(OpsOrderDO::getAreaId, areaId)
|
||||
.eq(OpsOrderDO::getOrderType, "CLEAN")
|
||||
.notIn(OpsOrderDO::getStatus,
|
||||
WorkOrderStatusEnum.COMPLETED.getStatus(),
|
||||
WorkOrderStatusEnum.CANCELLED.getStatus())
|
||||
.orderByDesc(OpsOrderDO::getCreateTime)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
// ==================== 统计聚合查询 ====================
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user