|
|
@@ -0,0 +1,423 @@
|
|
|
+package org.dromara.order.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import org.dromara.common.core.utils.MapstructUtils;
|
|
|
+import org.dromara.common.core.utils.StringUtils;
|
|
|
+import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
+import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlowLink;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlowNodeLink;
|
|
|
+import org.dromara.order.domain.bo.OrderCustomerFlowLinkBo;
|
|
|
+import org.dromara.order.service.IOrderCustomerFlowLinkService;
|
|
|
+import org.dromara.order.service.IOrderCustomerFlowNodeLinkService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.dromara.order.domain.bo.OrderCustomerFlowBo;
|
|
|
+import org.dromara.order.domain.bo.OrderCustomerFlowSaveBo;
|
|
|
+import org.dromara.order.domain.bo.OrderCustomerFlowNodeBo;
|
|
|
+import org.dromara.order.domain.bo.OrderCustomerFlowNodeLinkBo;
|
|
|
+import org.dromara.order.domain.vo.OrderCustomerFlowVo;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlow;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlowNode;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlowLink;
|
|
|
+import org.dromara.order.domain.OrderCustomerFlowNodeLink;
|
|
|
+import org.dromara.order.mapper.OrderCustomerFlowMapper;
|
|
|
+import org.dromara.order.mapper.OrderCustomerFlowNodeMapper;
|
|
|
+import org.dromara.order.service.IOrderCustomerFlowService;
|
|
|
+import org.dromara.order.service.IOrderCustomerFlowNodeService;
|
|
|
+
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Objects;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 客户订单流程Service业务层处理
|
|
|
+ *
|
|
|
+ * @author LionLi
|
|
|
+ * @date 2026-02-25
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Service
|
|
|
+public class OrderCustomerFlowServiceImpl extends ServiceImpl<OrderCustomerFlowMapper, OrderCustomerFlow> implements IOrderCustomerFlowService {
|
|
|
+
|
|
|
+ private final OrderCustomerFlowMapper baseMapper;
|
|
|
+
|
|
|
+ private final IOrderCustomerFlowNodeService nodeService;
|
|
|
+
|
|
|
+ private final IOrderCustomerFlowLinkService linkService;
|
|
|
+
|
|
|
+ private final IOrderCustomerFlowNodeLinkService nodeLinkService;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询客户订单流程
|
|
|
+ *
|
|
|
+ * @param id 主键
|
|
|
+ * @return 客户订单流程
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public OrderCustomerFlowVo queryById(Long id){
|
|
|
+ OrderCustomerFlowVo orderCustomerFlowVo = baseMapper.selectVoById(id);
|
|
|
+ List<OrderCustomerFlowNode> orderCustomerFlowNodes = nodeService.list(Wrappers.lambdaQuery(OrderCustomerFlowNode.class).eq(OrderCustomerFlowNode::getFlowId, orderCustomerFlowVo.getId()));
|
|
|
+ orderCustomerFlowVo.setFlowNodes(orderCustomerFlowNodes);
|
|
|
+ return orderCustomerFlowVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询客户订单流程列表
|
|
|
+ *
|
|
|
+ * @param bo 查询条件
|
|
|
+ * @param pageQuery 分页参数
|
|
|
+ * @return 客户订单流程分页列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public TableDataInfo<OrderCustomerFlowVo> queryPageList(OrderCustomerFlowBo bo, PageQuery pageQuery) {
|
|
|
+ LambdaQueryWrapper<OrderCustomerFlow> lqw = buildQueryWrapper(bo);
|
|
|
+ Page<OrderCustomerFlowVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
|
|
+ return TableDataInfo.build(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询符合条件的客户订单流程列表
|
|
|
+ *
|
|
|
+ * @param bo 查询条件
|
|
|
+ * @return 客户订单流程列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<OrderCustomerFlowVo> queryList(OrderCustomerFlowBo bo) {
|
|
|
+ LambdaQueryWrapper<OrderCustomerFlow> lqw = buildQueryWrapper(bo);
|
|
|
+ return baseMapper.selectVoList(lqw);
|
|
|
+ }
|
|
|
+
|
|
|
+ private LambdaQueryWrapper<OrderCustomerFlow> buildQueryWrapper(OrderCustomerFlowBo bo) {
|
|
|
+ Map<String, Object> params = bo.getParams();
|
|
|
+ LambdaQueryWrapper<OrderCustomerFlow> lqw = Wrappers.lambdaQuery();
|
|
|
+ lqw.like(StringUtils.isNotBlank(bo.getFlowName()), OrderCustomerFlow::getFlowName, bo.getFlowName());
|
|
|
+ lqw.eq(bo.getCustomerId() != null, OrderCustomerFlow::getCustomerId, bo.getCustomerId());
|
|
|
+ lqw.eq(bo.getUserId() != null, OrderCustomerFlow::getUserId, bo.getUserId());
|
|
|
+ lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OrderCustomerFlow::getStatus, bo.getStatus());
|
|
|
+ lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), OrderCustomerFlow::getPlatformCode, bo.getPlatformCode());
|
|
|
+ lqw.orderByDesc(OrderCustomerFlow::getUpdateTime);
|
|
|
+ return lqw;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增客户订单流程
|
|
|
+ *
|
|
|
+ * @param bo 客户订单流程
|
|
|
+ * @return 是否新增成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean insertByBo(OrderCustomerFlowBo bo) {
|
|
|
+ OrderCustomerFlow add = MapstructUtils.convert(bo, OrderCustomerFlow.class);
|
|
|
+ validEntityBeforeSave(add);
|
|
|
+ boolean flag = baseMapper.insert(add) > 0;
|
|
|
+ if (flag) {
|
|
|
+ bo.setId(add.getId());
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修改客户订单流程
|
|
|
+ *
|
|
|
+ * @param bo 客户订单流程
|
|
|
+ * @return 是否修改成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean updateByBo(OrderCustomerFlowBo bo) {
|
|
|
+ OrderCustomerFlow update = MapstructUtils.convert(bo, OrderCustomerFlow.class);
|
|
|
+ validEntityBeforeSave(update);
|
|
|
+ return baseMapper.updateById(update) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存前的数据校验
|
|
|
+ */
|
|
|
+ private void validEntityBeforeSave(OrderCustomerFlow entity){
|
|
|
+ //TODO 做一些数据校验,如唯一约束
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存编辑客户订单流程(包括流程和节点)
|
|
|
+ *
|
|
|
+ * @param bo 客户订单流程保存对象
|
|
|
+ * @return 是否保存成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Boolean saveFlowWithNodes(OrderCustomerFlowSaveBo bo) {
|
|
|
+ if (bo == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean isNew = bo.getId() == null || bo.getId() <= 0;
|
|
|
+
|
|
|
+ // 1. 保存或更新流程主表
|
|
|
+ OrderCustomerFlowBo flowBo = new OrderCustomerFlowBo();
|
|
|
+ flowBo.setId(bo.getId());
|
|
|
+ flowBo.setFlowName(bo.getFlowName());
|
|
|
+ flowBo.setCustomerId(bo.getCustomerId());
|
|
|
+ flowBo.setUserId(bo.getUserId());
|
|
|
+ flowBo.setStatus(bo.getStatus());
|
|
|
+ flowBo.setRemark(bo.getRemark());
|
|
|
+
|
|
|
+ boolean flowSuccess;
|
|
|
+ if (isNew) {
|
|
|
+ flowSuccess = this.insertByBo(flowBo);
|
|
|
+ if (flowSuccess) {
|
|
|
+ bo.setId(flowBo.getId()); // 回填ID
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ flowSuccess = this.updateByBo(flowBo);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Long flowId = flowBo.getId();
|
|
|
+
|
|
|
+ // 2. 处理节点信息
|
|
|
+ List<OrderCustomerFlowNodeBo> nodeBos = bo.getFlowNodes();
|
|
|
+ if (nodeBos != null && !nodeBos.isEmpty()) {
|
|
|
+ // 如果是更新操作,先删除原有的节点
|
|
|
+ if (!isNew) {
|
|
|
+ LambdaQueryWrapper<OrderCustomerFlowNode> deleteWrapper = Wrappers.lambdaQuery();
|
|
|
+ deleteWrapper.eq(OrderCustomerFlowNode::getFlowId, flowId);
|
|
|
+ nodeService.remove(deleteWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量插入新节点
|
|
|
+ for (OrderCustomerFlowNodeBo nodeBo : nodeBos) {
|
|
|
+ nodeBo.setFlowId(flowId);
|
|
|
+ nodeService.insertByBo(nodeBo);
|
|
|
+ }
|
|
|
+ } else if (!isNew) {
|
|
|
+ // 如果是更新且没有提供节点,则删除原有节点
|
|
|
+ LambdaQueryWrapper<OrderCustomerFlowNode> deleteWrapper = Wrappers.lambdaQuery();
|
|
|
+ deleteWrapper.eq(OrderCustomerFlowNode::getFlowId, flowId);
|
|
|
+ nodeService.remove(deleteWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验并批量删除客户订单流程信息
|
|
|
+ *
|
|
|
+ * @param ids 待删除的主键集合
|
|
|
+ * @param isValid 是否进行有效性校验
|
|
|
+ * @return 是否删除成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
+ if(isValid){
|
|
|
+ //TODO 做一些业务上的校验,判断是否需要校验
|
|
|
+ }
|
|
|
+ return baseMapper.deleteByIds(ids) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化订单流程
|
|
|
+ *
|
|
|
+ * @param orderId 订单ID
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void initOrderFlow(Long orderId) {
|
|
|
+ //查询默认开启的流程
|
|
|
+ OrderCustomerFlow flow = baseMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<OrderCustomerFlow>().eq(OrderCustomerFlow::getStatus, "0")
|
|
|
+ .orderByDesc(OrderCustomerFlow::getUpdateTime)
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ if (flow == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //查询流程节点
|
|
|
+ List<OrderCustomerFlowNode> orderCustomerFlowNodes = nodeService.list(
|
|
|
+ new LambdaQueryWrapper<OrderCustomerFlowNode>().eq(OrderCustomerFlowNode::getFlowId, flow.getId())
|
|
|
+ );
|
|
|
+ if (ObjectUtil.isEmpty(orderCustomerFlowNodes)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ Long firstNodeId = null;
|
|
|
+ //先初始化流程节点
|
|
|
+ for (OrderCustomerFlowNode orderCustomerFlowNode : orderCustomerFlowNodes) {
|
|
|
+ OrderCustomerFlowNodeLink nodeLink = BeanUtil.toBean(orderCustomerFlowNode, OrderCustomerFlowNodeLink.class);
|
|
|
+ nodeLink.setId(null);
|
|
|
+ nodeLink.setOrderId(orderId);
|
|
|
+ nodeLink.setFlowId(flow.getId());
|
|
|
+ nodeLinkService.save(nodeLink);
|
|
|
+ if (orderCustomerFlowNode.getNodeType() == 0){
|
|
|
+ firstNodeId = nodeLink.getId();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ OrderCustomerFlowLink flowLink = new OrderCustomerFlowLink();
|
|
|
+ flowLink.setOrderId(orderId);
|
|
|
+ flowLink.setFlowId(flow.getId());
|
|
|
+ flowLink.setNodeId(firstNodeId);
|
|
|
+ linkService.save(flowLink);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 审核订单流程
|
|
|
+ *
|
|
|
+ * @param bo 审核信息
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void auditOrderFlow(OrderCustomerFlowLinkBo bo) {
|
|
|
+ // 参数校验
|
|
|
+ if (bo == null || bo.getOrderId() == null || bo.getNodeId() == null || bo.getReviewStatus() == null) {
|
|
|
+ throw new IllegalArgumentException("审核参数不完整");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 查询当前流程链接信息
|
|
|
+ OrderCustomerFlowLink currentLink = linkService.getOne(
|
|
|
+ new LambdaQueryWrapper<OrderCustomerFlowLink>()
|
|
|
+ .eq(OrderCustomerFlowLink::getOrderId, bo.getOrderId())
|
|
|
+ .eq(OrderCustomerFlowLink::getNodeId, bo.getNodeId())
|
|
|
+ );
|
|
|
+
|
|
|
+ if (currentLink == null) {
|
|
|
+ throw new RuntimeException("未找到对应的流程节点信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询当前节点链接信息
|
|
|
+ OrderCustomerFlowNodeLink currentNodeLink = nodeLinkService.getOne(
|
|
|
+ new LambdaQueryWrapper<OrderCustomerFlowNodeLink>()
|
|
|
+ .eq(OrderCustomerFlowNodeLink::getOrderId, bo.getOrderId())
|
|
|
+ .eq(OrderCustomerFlowNodeLink::getId, bo.getNodeId())
|
|
|
+ );
|
|
|
+
|
|
|
+ if (currentNodeLink == null) {
|
|
|
+ throw new RuntimeException("未找到对应的节点链接信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 直接更新节点链接表的审核状态
|
|
|
+ OrderCustomerFlowNodeLink updateNodeLink = new OrderCustomerFlowNodeLink();
|
|
|
+ updateNodeLink.setId(currentNodeLink.getId());
|
|
|
+ updateNodeLink.setReviewStatus(bo.getReviewStatus());
|
|
|
+ updateNodeLink.setReason(bo.getReason());
|
|
|
+ updateNodeLink.setRemark(bo.getRemark());
|
|
|
+
|
|
|
+ boolean nodeUpdateSuccess = nodeLinkService.updateById(updateNodeLink);
|
|
|
+ if (!nodeUpdateSuccess) {
|
|
|
+ throw new RuntimeException("更新节点审核状态失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 根据审核结果处理流程流转
|
|
|
+ if (bo.getReviewStatus() == 1) { // 审核通过
|
|
|
+ handleAuditPass(bo, currentLink, currentNodeLink);
|
|
|
+ } else if (bo.getReviewStatus() == 2) { // 审核驳回
|
|
|
+ handleAuditReject(bo, currentLink, currentNodeLink);
|
|
|
+ } else {
|
|
|
+ throw new IllegalArgumentException("无效的审核状态");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 更新流程链接表的当前节点信息
|
|
|
+ OrderCustomerFlowLink updateLink = new OrderCustomerFlowLink();
|
|
|
+ updateLink.setId(currentLink.getId());
|
|
|
+ updateLink.setReviewStatus(bo.getReviewStatus());
|
|
|
+ updateLink.setReason(bo.getReason());
|
|
|
+ updateLink.setRemark(bo.getRemark());
|
|
|
+
|
|
|
+ linkService.updateById(updateLink);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理审核通过逻辑
|
|
|
+ */
|
|
|
+ private void handleAuditPass(OrderCustomerFlowLinkBo bo, OrderCustomerFlowLink currentLink, OrderCustomerFlowNodeLink currentNodeLink) {
|
|
|
+ Long orderId = currentLink.getOrderId();
|
|
|
+
|
|
|
+ // 查询流程的所有节点,按排序字段排列
|
|
|
+ List<OrderCustomerFlowNodeLink> flowNodes = nodeLinkService.list(
|
|
|
+ new LambdaQueryWrapper<OrderCustomerFlowNodeLink>()
|
|
|
+ .eq(OrderCustomerFlowNodeLink::getOrderId, orderId)
|
|
|
+ .orderByAsc(OrderCustomerFlowNodeLink::getSort)
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (ObjectUtil.isEmpty(flowNodes)) {
|
|
|
+ throw new RuntimeException("流程节点配置异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 找到当前节点在流程中的位置
|
|
|
+ // 注意:这里应该通过nodeId而不是直接比较id
|
|
|
+ int currentIndex = -1;
|
|
|
+ for (int i = 0; i < flowNodes.size(); i++) {
|
|
|
+ if (flowNodes.get(i).getId().equals(currentLink.getNodeId())) {
|
|
|
+ currentIndex = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (currentIndex == -1) {
|
|
|
+ throw new RuntimeException("无法定位当前节点在流程中的位置");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将当前节点的链接信息更新
|
|
|
+ OrderCustomerFlowNodeLink node = flowNodes.get(currentIndex);
|
|
|
+ node.setReviewStatus(1L); // 待审核状态
|
|
|
+ nodeLinkService.updateById(node);
|
|
|
+
|
|
|
+ // 如果不是最后一个节点,移动到下一个节点
|
|
|
+ if (currentIndex < flowNodes.size() - 1) {
|
|
|
+
|
|
|
+ // 更新流程链接表指向新的节点
|
|
|
+ OrderCustomerFlowNodeLink nextNode = flowNodes.get(currentIndex + 1);
|
|
|
+
|
|
|
+ OrderCustomerFlowLink updateLink = new OrderCustomerFlowLink();
|
|
|
+ updateLink.setId(currentLink.getId());
|
|
|
+ updateLink.setNodeId(nextNode.getId());
|
|
|
+ updateLink.setHandlerId(nextNode.getHandlerId());
|
|
|
+ updateLink.setReviewStatus(0L); // 待审核
|
|
|
+
|
|
|
+ linkService.updateById(updateLink);
|
|
|
+ } else {
|
|
|
+ // 已经是最后一个节点,流程结束
|
|
|
+ OrderCustomerFlowLink updateLink = new OrderCustomerFlowLink();
|
|
|
+ updateLink.setId(currentLink.getId());
|
|
|
+ updateLink.setReviewStatus(1L); // 流程完成
|
|
|
+
|
|
|
+ linkService.updateById(updateLink);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理审核驳回逻辑
|
|
|
+ */
|
|
|
+ private void handleAuditReject(OrderCustomerFlowLinkBo bo, OrderCustomerFlowLink currentLink, OrderCustomerFlowNodeLink currentNodeLink) {
|
|
|
+ Long orderId = currentLink.getOrderId();
|
|
|
+ Long nodeId = currentLink.getNodeId();
|
|
|
+ linkService.update(Wrappers.lambdaUpdate(OrderCustomerFlowLink.class)
|
|
|
+ .set(OrderCustomerFlowLink::getReviewStatus, 2L)
|
|
|
+ .set(OrderCustomerFlowLink::getReason, bo.getReason())
|
|
|
+ .eq(OrderCustomerFlowLink::getOrderId, orderId)
|
|
|
+ .eq(OrderCustomerFlowLink::getNodeId, nodeId)
|
|
|
+ );
|
|
|
+ nodeLinkService.update(Wrappers.lambdaUpdate(OrderCustomerFlowNodeLink.class)
|
|
|
+ .set(OrderCustomerFlowNodeLink::getReviewStatus, 2L)
|
|
|
+ .set(OrderCustomerFlowNodeLink::getReason, bo.getReason())
|
|
|
+ .eq(OrderCustomerFlowNodeLink::getId, currentNodeLink.getId())
|
|
|
+ );
|
|
|
+ // 驳回时保持在当前节点,但可以记录驳回信息
|
|
|
+ // 这里可以根据业务需求决定是否需要特殊的驳回处理逻辑
|
|
|
+ // 比如:驳回到指定节点、重新提交等
|
|
|
+
|
|
|
+ log.info("订单{}的节点{}被驳回,驳回原因:{}",
|
|
|
+ currentLink.getOrderId(), currentLink.getNodeId(), bo.getReason());
|
|
|
+ }
|
|
|
+}
|