feat(ops): 手动派单遵循执行人忙碌状态,忙碌时入队等待
ManualOrderActionFacade.dispatch: - 新增 strategy.isAssigneeIdle() 判断,空闲→DISPATCHED,忙碌→QUEUED - 不再无条件直接派发 OrderBusinessStrategy: - 新增 isAssigneeIdle() 默认方法,默认返回 true CleanOrderBusinessStrategy: - isAssigneeIdle 通过 BadgeDeviceStatusService.isBusy() 判断设备忙碌 SecurityOrderBusinessStrategy: - isAssigneeIdle 通过 UserDispatchStatusService.isIdle() 判断人员忙碌 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,12 @@ public class CleanOrderBusinessStrategy implements OrderBusinessStrategy {
|
||||
return WorkOrderTypeEnum.CLEAN.getType().equals(businessType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssigneeIdle(DispatchOrderCommand cmd, OpsOrderDO order) {
|
||||
BadgeDeviceStatusDTO badge = badgeDeviceStatusService.getBadgeStatus(cmd.getAssigneeId());
|
||||
return badge != null && !badge.isBusy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDispatch(DispatchOrderCommand cmd, OpsOrderDO order) {
|
||||
if (cmd.getAssigneeId() == null) {
|
||||
|
||||
@@ -68,10 +68,14 @@ public class ManualOrderActionFacade {
|
||||
OrderBusinessStrategy strategy = resolveStrategy(cmd.getBusinessType());
|
||||
strategy.validateDispatch(cmd, order);
|
||||
|
||||
// 3. 状态变更
|
||||
// 3. 判断执行人是否空闲,决定目标状态
|
||||
boolean idle = strategy.isAssigneeIdle(cmd, order);
|
||||
WorkOrderStatusEnum targetStatus = idle ? WorkOrderStatusEnum.DISPATCHED : WorkOrderStatusEnum.QUEUED;
|
||||
|
||||
// 4. 状态变更
|
||||
OrderTransitionRequest request = OrderTransitionRequest.builder()
|
||||
.orderId(cmd.getOrderId())
|
||||
.targetStatus(WorkOrderStatusEnum.DISPATCHED)
|
||||
.targetStatus(targetStatus)
|
||||
.assigneeId(cmd.getAssigneeId())
|
||||
.assigneeName(cmd.getAssigneeName())
|
||||
.assigneePhone(cmd.getAssigneePhone())
|
||||
@@ -85,18 +89,19 @@ public class ManualOrderActionFacade {
|
||||
throw new IllegalStateException("手动派单失败: " + result.getMessage());
|
||||
}
|
||||
|
||||
// 4. 更新主表执行人(只更新 assignee 字段,避免覆盖状态机已写入的 status)
|
||||
// 5. 更新主表执行人(只更新 assignee 字段,避免覆盖状态机已写入的 status)
|
||||
OpsOrderDO assigneeUpdate = new OpsOrderDO();
|
||||
assigneeUpdate.setId(cmd.getOrderId());
|
||||
assigneeUpdate.setAssigneeId(cmd.getAssigneeId());
|
||||
assigneeUpdate.setAssigneeName(cmd.getAssigneeName());
|
||||
opsOrderMapper.updateById(assigneeUpdate);
|
||||
|
||||
// 5. 条线后置
|
||||
// 6. 条线后置
|
||||
// 注:业务日志由生命周期事件 → 条线 EventListener 统一记录,此处不重复写
|
||||
strategy.afterDispatch(cmd, order);
|
||||
|
||||
log.info("[ManualOrderActionFacade] 手动派单完成: orderId={}, assigneeId={}", cmd.getOrderId(), cmd.getAssigneeId());
|
||||
log.info("[ManualOrderActionFacade] 手动派单完成: orderId={}, assigneeId={}, targetStatus={}",
|
||||
cmd.getOrderId(), cmd.getAssigneeId(), targetStatus);
|
||||
}
|
||||
|
||||
// ==================== 手动升级优先级 ====================
|
||||
|
||||
@@ -20,6 +20,20 @@ public interface OrderBusinessStrategy {
|
||||
*/
|
||||
boolean supports(String businessType);
|
||||
|
||||
// ==================== 派单决策 ====================
|
||||
|
||||
/**
|
||||
* 判断执行人是否空闲,决定手动派单的目标状态。
|
||||
* <p>
|
||||
* 空闲返回 true → DISPATCHED(直接派发);
|
||||
* 忙碌返回 false → QUEUED(入队等待)。
|
||||
* <p>
|
||||
* 默认返回 true(直接派发),条线按需覆写。
|
||||
*/
|
||||
default boolean isAssigneeIdle(DispatchOrderCommand cmd, OpsOrderDO order) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 前置校验 ====================
|
||||
|
||||
default void validateDispatch(DispatchOrderCommand cmd, OpsOrderDO order) {}
|
||||
|
||||
@@ -8,13 +8,11 @@ import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
|
||||
import com.viewsh.module.ops.enums.WorkOrderTypeEnum;
|
||||
import com.viewsh.module.ops.security.dal.dataobject.area.OpsAreaSecurityUserDO;
|
||||
import com.viewsh.module.ops.security.dal.mysql.area.OpsAreaSecurityUserMapper;
|
||||
import com.viewsh.module.ops.service.dispatch.UserDispatchStatusService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.viewsh.module.ops.enums.ErrorCodeConstants.SECURITY_ASSIGNEE_NOT_BOUND_TO_AREA;
|
||||
|
||||
/**
|
||||
* 安保条线策略
|
||||
* <p>
|
||||
@@ -32,11 +30,19 @@ public class SecurityOrderBusinessStrategy implements OrderBusinessStrategy {
|
||||
@Resource
|
||||
private OrderQueueService orderQueueService;
|
||||
|
||||
@Resource
|
||||
private UserDispatchStatusService userDispatchStatusService;
|
||||
|
||||
@Override
|
||||
public boolean supports(String businessType) {
|
||||
return WorkOrderTypeEnum.SECURITY.getType().equals(businessType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssigneeIdle(DispatchOrderCommand cmd, OpsOrderDO order) {
|
||||
return userDispatchStatusService.isIdle(cmd.getAssigneeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDispatch(DispatchOrderCommand cmd, OpsOrderDO order) {
|
||||
// 尝试从区域绑定记录回填姓名(不做区域限制,允许跨区域派单)
|
||||
|
||||
Reference in New Issue
Block a user