chore: 【ops】工单基础Service
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package com.viewsh.module.ops.service.order;
|
||||
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.module.ops.dal.dataobject.dto.*;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
import com.viewsh.module.ops.enums.OperatorTypeEnum;
|
||||
|
||||
/**
|
||||
* 通用工单服务
|
||||
* 职责:
|
||||
* 1. 工单CRUD基础操作
|
||||
* 2. 工单状态转换(调用状态机)
|
||||
* 3. 工单分页查询
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
public interface OpsOrderService {
|
||||
|
||||
/**
|
||||
* 创建工单(通用方法)
|
||||
*
|
||||
* @param createReq 创建请求
|
||||
* @return 工单ID
|
||||
*/
|
||||
Long createOrder(OpsOrderCreateReqDTO createReq);
|
||||
|
||||
/**
|
||||
* 更新工单
|
||||
*
|
||||
* @param updateReq 更新请求
|
||||
*/
|
||||
void updateOrder(OpsOrderUpdateReqDTO updateReq);
|
||||
|
||||
/**
|
||||
* 删除工单
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
*/
|
||||
void deleteOrder(Long orderId);
|
||||
|
||||
/**
|
||||
* 查询工单详情
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @return 工单对象
|
||||
*/
|
||||
OpsOrderDO getOrder(Long orderId);
|
||||
|
||||
/**
|
||||
* 分页查询工单
|
||||
*
|
||||
* @param pageReq 分页请求
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<OpsOrderDO> getOrderPage(OpsOrderPageReqDTO pageReq);
|
||||
|
||||
/**
|
||||
* 分配工单(状态转换:PENDING -> ASSIGNED)
|
||||
*
|
||||
* @param assignReq 分配请求
|
||||
* @param operatorType 操作人类型
|
||||
* @param operatorId 操作人ID
|
||||
*/
|
||||
void assignOrder(OpsOrderAssignReqDTO assignReq, OperatorTypeEnum operatorType, Long operatorId);
|
||||
|
||||
/**
|
||||
* 接单(状态转换:ASSIGNED -> ARRIVED)
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param userId 保洁员ID
|
||||
*/
|
||||
void acceptOrder(Long orderId, Long userId);
|
||||
|
||||
/**
|
||||
* 完成工单(状态转换:ARRIVED -> COMPLETED)
|
||||
*
|
||||
* @param completeReq 完成请求
|
||||
* @param userId 执行人ID
|
||||
*/
|
||||
void completeOrder(OpsOrderCompleteReqDTO completeReq, Long userId);
|
||||
|
||||
/**
|
||||
* 暂停工单(状态转换:ARRIVED -> PAUSED)
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param userId 保洁员ID
|
||||
* @param reason 暂停原因
|
||||
*/
|
||||
void pauseOrder(Long orderId, Long userId, String reason);
|
||||
|
||||
/**
|
||||
* 恢复工单(状态转换:PAUSED -> ARRIVED)
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param userId 保洁员ID
|
||||
*/
|
||||
void resumeOrder(Long orderId, Long userId);
|
||||
|
||||
/**
|
||||
* 取消工单
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param reason 取消原因
|
||||
* @param operatorType 操作人类型
|
||||
* @param operatorId 操作人ID
|
||||
*/
|
||||
void cancelOrder(Long orderId, String reason, OperatorTypeEnum operatorType, Long operatorId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.viewsh.module.ops.service.order;
|
||||
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.framework.common.util.object.BeanUtils;
|
||||
import com.viewsh.module.ops.dal.dataobject.dto.*;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
|
||||
import com.viewsh.module.ops.enums.OperatorTypeEnum;
|
||||
import com.viewsh.module.ops.enums.PriorityEnum;
|
||||
import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
|
||||
import com.viewsh.module.ops.service.fsm.OrderStateMachine;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通用工单服务实现
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OpsOrderServiceImpl implements OpsOrderService {
|
||||
|
||||
@Resource
|
||||
private OpsOrderMapper opsOrderMapper;
|
||||
|
||||
@Resource
|
||||
private OrderStateMachine orderStateMachine;
|
||||
|
||||
private static final DateTimeFormatter ORDER_CODE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createOrder(OpsOrderCreateReqDTO createReq) {
|
||||
// 1. 构建工单对象
|
||||
OpsOrderDO order = BeanUtils.toBean(createReq, OpsOrderDO.class);
|
||||
|
||||
// 2. 设置默认值
|
||||
if (order.getPriority() == null) {
|
||||
order.setPriority(PriorityEnum.P2.getPriority());
|
||||
}
|
||||
if (order.getStatus() == null) {
|
||||
order.setStatus(WorkOrderStatusEnum.PENDING.getStatus());
|
||||
}
|
||||
if (order.getSourceType() == null) {
|
||||
order.setSourceType("MANUAL");
|
||||
}
|
||||
|
||||
// 3. 生成工单编号
|
||||
order.setOrderCode(generateOrderCode());
|
||||
|
||||
// 4. 插入数据库
|
||||
opsOrderMapper.insert(order);
|
||||
|
||||
// 5. 记录创建事件
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.PENDING,
|
||||
OperatorTypeEnum.SYSTEM,
|
||||
null,
|
||||
"创建工单"
|
||||
);
|
||||
|
||||
log.info("创建工单成功: orderId={}, orderCode={}, title={}",
|
||||
order.getId(), order.getOrderCode(), order.getTitle());
|
||||
|
||||
return order.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateOrder(OpsOrderUpdateReqDTO updateReq) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO existingOrder = opsOrderMapper.selectById(updateReq.getId());
|
||||
if (existingOrder == null) {
|
||||
throw new RuntimeException("工单不存在: " + updateReq.getId());
|
||||
}
|
||||
|
||||
// 2. 更新允许修改的字段
|
||||
OpsOrderDO updateObj = new OpsOrderDO();
|
||||
updateObj.setId(updateReq.getId());
|
||||
if (updateReq.getTitle() != null) {
|
||||
updateObj.setTitle(updateReq.getTitle());
|
||||
}
|
||||
if (updateReq.getDescription() != null) {
|
||||
updateObj.setDescription(updateReq.getDescription());
|
||||
}
|
||||
if (updateReq.getPriority() != null) {
|
||||
updateObj.setPriority(updateReq.getPriority());
|
||||
}
|
||||
if (updateReq.getUrgentReason() != null) {
|
||||
updateObj.setUrgentReason(updateReq.getUrgentReason());
|
||||
}
|
||||
|
||||
// 3. 执行更新
|
||||
opsOrderMapper.updateById(updateObj);
|
||||
|
||||
log.info("更新工单成功: orderId={}", updateReq.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteOrder(Long orderId) {
|
||||
// 1. 校验工单状态
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
|
||||
// 2. 只能删除待分配或已取消的工单
|
||||
if (!WorkOrderStatusEnum.PENDING.getStatus().equals(order.getStatus()) &&
|
||||
!WorkOrderStatusEnum.CANCELLED.getStatus().equals(order.getStatus())) {
|
||||
throw new RuntimeException("只能删除待分配或已取消的工单");
|
||||
}
|
||||
|
||||
// 3. 执行删除
|
||||
opsOrderMapper.deleteById(orderId);
|
||||
|
||||
log.info("删除工单成功: orderId={}", orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpsOrderDO getOrder(Long orderId) {
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<OpsOrderDO> getOrderPage(OpsOrderPageReqDTO pageReq) {
|
||||
// TODO: 实现分页查询
|
||||
// 需要在OpsOrderMapper中添加分页查询方法
|
||||
// 或者使用MyBatis Plus的原生分页
|
||||
throw new UnsupportedOperationException("分页查询功能待实现");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void assignOrder(OpsOrderAssignReqDTO assignReq, OperatorTypeEnum operatorType, Long operatorId) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(assignReq.getOrderId());
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + assignReq.getOrderId());
|
||||
}
|
||||
|
||||
// 2. 设置执行人
|
||||
order.setAssigneeId(assignReq.getAssigneeId());
|
||||
|
||||
// 3. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.DISPATCHED,
|
||||
operatorType,
|
||||
operatorId,
|
||||
assignReq.getRemark()
|
||||
);
|
||||
|
||||
log.info("分配工单成功: orderId={}, assigneeId={}", assignReq.getOrderId(), assignReq.getAssigneeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void acceptOrder(Long orderId, Long userId) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
|
||||
// 2. 校验:只有分配给的执行人才能接单
|
||||
if (!userId.equals(order.getAssigneeId())) {
|
||||
throw new RuntimeException("无权接单,该工单未分配给您");
|
||||
}
|
||||
|
||||
// 3. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.ARRIVED,
|
||||
OperatorTypeEnum.CLEANER,
|
||||
userId,
|
||||
"保洁员接单"
|
||||
);
|
||||
|
||||
log.info("接单成功: orderId={}, userId={}", orderId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void completeOrder(OpsOrderCompleteReqDTO completeReq, Long userId) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(completeReq.getOrderId());
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + completeReq.getOrderId());
|
||||
}
|
||||
|
||||
// 2. 校验:只有执行人才能完成工单
|
||||
if (!userId.equals(order.getAssigneeId())) {
|
||||
throw new RuntimeException("无权完成工单,您不是该工单的执行人");
|
||||
}
|
||||
|
||||
// 3. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.COMPLETED,
|
||||
OperatorTypeEnum.CLEANER,
|
||||
userId,
|
||||
completeReq.getRemark()
|
||||
);
|
||||
|
||||
log.info("完成工单成功: orderId={}, userId={}", completeReq.getOrderId(), userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void pauseOrder(Long orderId, Long userId, String reason) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
|
||||
// 2. 校验:只有执行人才能暂停工单
|
||||
if (!userId.equals(order.getAssigneeId())) {
|
||||
throw new RuntimeException("无权暂停工单,您不是该工单的执行人");
|
||||
}
|
||||
|
||||
// 3. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.PAUSED,
|
||||
OperatorTypeEnum.CLEANER,
|
||||
userId,
|
||||
reason
|
||||
);
|
||||
|
||||
log.info("暂停工单成功: orderId={}, userId={}, reason={}", orderId, userId, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void resumeOrder(Long orderId, Long userId) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
|
||||
// 2. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.ARRIVED,
|
||||
OperatorTypeEnum.CLEANER,
|
||||
userId,
|
||||
"恢复工单"
|
||||
);
|
||||
|
||||
log.info("恢复工单成功: orderId={}, userId={}", orderId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void cancelOrder(Long orderId, String reason, OperatorTypeEnum operatorType, Long operatorId) {
|
||||
// 1. 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new RuntimeException("工单不存在: " + orderId);
|
||||
}
|
||||
|
||||
// 2. 校验:已完成的工单不能取消
|
||||
if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) {
|
||||
throw new RuntimeException("已完成的工单不能取消");
|
||||
}
|
||||
|
||||
// 3. 通过状态机执行状态转换
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
WorkOrderStatusEnum.CANCELLED,
|
||||
operatorType,
|
||||
operatorId,
|
||||
reason
|
||||
);
|
||||
|
||||
log.info("取消工单成功: orderId={}, reason={}", orderId, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成工单编号
|
||||
* 格式:WO + yyyyMMddHHmmss + 3位随机数
|
||||
* 示例:WO20250104143025123
|
||||
*/
|
||||
private String generateOrderCode() {
|
||||
String timestamp = LocalDateTime.now().format(ORDER_CODE_FORMATTER);
|
||||
int random = (int) (Math.random() * 1000);
|
||||
return String.format("WO%s%03d", timestamp, random);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user