p-honggang.li
5 天以前 cda9decfde8c6b518639c5da506aa293c07f88ff
src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java
@@ -26,23 +26,35 @@
import com.webmanage.service.OrderInfoService;
import com.webmanage.service.OrderNoService;
import com.webmanage.service.MinioService;
import com.webmanage.config.WorkflowProperties;
import com.webmanage.vo.OrderAttachmentVO;
import com.webmanage.vo.OrderDetailItemVO;
import com.webmanage.vo.OrderDetailVO;
import com.webmanage.vo.OrderEvaluationVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpEntity;
import org.springframework.http.MediaType;
import org.springframework.http.HttpHeaders;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Objects;
/**
 * 订单信息Service实现类
@@ -71,6 +83,12 @@
    @Resource
    private ReportResultSubmissionMapper reportResultSubmissionMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private WorkflowProperties workflowProperties;
    @Override
    public PageResult<OrderDetailVO> getBuyerOrderPage(OrderQueryDTO queryDTO) {
@@ -167,13 +185,46 @@
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 基于workFlowType查询流程实例ID集合
        List<Object> workFlowsList = fetchWorkflowProcessInstanceIds(
            queryDTO.getWorkFlowType(),
            queryDTO.getUserId(),
            queryDTO.getDepartmentId(),
            queryDTO.getBusinessType(),
            queryDTO.getPageNum(),
            queryDTO.getPageSize()
        );
        // 如果没有任何流程ID,直接返回空分页
        if (workFlowsList == null || workFlowsList.isEmpty()) {
            return new PageResult<OrderDetailVO>(
                java.util.Collections.emptyList(),
                0L,
                queryDTO.getPageNum().longValue(),
                queryDTO.getPageSize().longValue(),
                0L
            );
        }
        List<String> workFlowIds = workFlowsList.stream()
                 .filter(item -> item instanceof Map)
                 .map(item -> (Map<?, ?>) item)
                 .map(m -> m.get("processInstanceId"))
                 .filter(Objects::nonNull)
                 .map(Object::toString)
                 .collect(Collectors.toList());
        Map<String,String> workFlowIdAndTaskIdMap = workFlowsList.stream()
                .filter(item -> item instanceof Map)
                .map(item -> (Map<?, ?>) item).collect(Collectors.toMap(m -> m.get("processInstanceId").toString(), m -> m.get("taskId").toString(),(k1,k2) -> k2));
        // 执行分页查询
        IPage<OrderInfo> result = baseMapper.selectPendingApprovalOrderPage(
            page, queryDTO.getOrderStatus(), queryDTO.getProductName(), queryDTO.getProviderName(),
            queryDTO.getOrderId(),
            queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null,
            queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null,
            queryDTO.getOrderBy(), queryDTO.getOrderDirection()
            queryDTO.getOrderBy(), queryDTO.getOrderDirection(), workFlowIds
        );
        // 将订单与详情联表封装到VO
@@ -187,6 +238,7 @@
                return item;
            }).collect(java.util.stream.Collectors.toList());
            vo.setOrderDetails(items);
            vo.setTaskId(workFlowIdAndTaskIdMap.get(vo.getWorkflowId()));
            return vo;
        }).collect(java.util.stream.Collectors.toList());
@@ -201,7 +253,7 @@
    }
    @Override
    public PageResult<OrderInfo> getPendingApprovalOrderPageWithProductConditions(OrderQueryDTO queryDTO) {
    public PageResult<OrderDetailVO> getPendingApprovalOrderPageWithProductConditions(OrderQueryDTO queryDTO) {
        // 根据产品条件查询产品ID列表
        List<String> productIds = null;
        if (StringUtils.hasText(queryDTO.getIndustryId()) || StringUtils.hasText(queryDTO.getUnitProjectId()) ||
@@ -213,7 +265,7 @@
            
            // 如果没有找到匹配的产品,直接返回空结果
            if (CollectionUtils.isEmpty(productIds)) {
                return new PageResult<OrderInfo>(
                return new PageResult<OrderDetailVO>(
                    java.util.Collections.emptyList(),
                    0L,
                    queryDTO.getPageNum().longValue(),
@@ -227,17 +279,64 @@
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 执行分页查询
        // 基于workFlowType查询流程实例ID集合
        List<?> workFlowList = fetchWorkflowProcessInstanceIds(
            queryDTO.getWorkFlowType(),
            queryDTO.getUserId(),
            queryDTO.getDepartmentId(),
            queryDTO.getBusinessType(),
            queryDTO.getPageNum(),
            queryDTO.getPageSize()
        );
        // 如果没有任何流程ID,直接返回空分页
        if (workFlowList == null || workFlowList.isEmpty()) {
            return new PageResult<OrderDetailVO>(
                    java.util.Collections.emptyList(),
                    0L,
                    queryDTO.getPageNum().longValue(),
                    queryDTO.getPageSize().longValue(),
                    0L
            );
        }
        List<String> workFlowIds = workFlowList.stream()
                        .filter(item -> item instanceof Map)
                        .map(item -> (Map<?, ?>) item)
                        .map(m -> m.get("processInstanceId"))
                        .filter(Objects::nonNull)
                        .map(Object::toString)
                        .collect(Collectors.toList());
        Map<String,String> workFlowIdAndTaskIdMap = workFlowList.stream()
                .filter(item -> item instanceof Map)
                .map(item -> (Map<?, ?>) item).collect(Collectors.toMap(m -> m.get("processInstanceId").toString(), m -> m.get("taskId").toString(),(k1,k2) -> k2));
        IPage<OrderInfo> result = baseMapper.selectPendingApprovalOrderPageWithProductConditions(
            page, queryDTO.getOrderStatus(), queryDTO.getProductName(), queryDTO.getProviderName(),
            queryDTO.getOrderId(),
            queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null,
            queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null,
            queryDTO.getOrderBy(), queryDTO.getOrderDirection(), productIds
            queryDTO.getOrderBy(), queryDTO.getOrderDirection(), productIds, workFlowIds
        );
        // 将订单与详情联表封装到VO
        List<OrderDetailVO> voList = result.getRecords().stream().map(order -> {
            OrderDetailVO vo = new OrderDetailVO();
            BeanUtils.copyProperties(order, vo);
            List<OrderDetail> details = orderDetailMapper.selectByOrderId(order.getOrderId());
            List<OrderDetailItemVO> items = details.stream().map(d -> {
                OrderDetailItemVO item = new OrderDetailItemVO();
                BeanUtils.copyProperties(d, item);
                return item;
            }).collect(java.util.stream.Collectors.toList());
            vo.setOrderDetails(items);
            vo.setTaskId(workFlowIdAndTaskIdMap.get(vo.getWorkflowId()));
            return vo;
        }).collect(java.util.stream.Collectors.toList());
        // 构建返回结果
        return new PageResult<OrderInfo>(
            result.getRecords(),
        return new PageResult<OrderDetailVO>(
            voList,
            result.getTotal(),
            queryDTO.getPageNum().longValue(),
            queryDTO.getPageSize().longValue(),
@@ -432,6 +531,34 @@
        }
        // 生成订单编号
        String orderId = orderNoService.generateOrderNo();
        // 先调用工作流接口,获取工作流ID
        String workflowId = null;
        String taskId = null;
        try {
            // 检查是否有价格类型为"协议"的明细项
            boolean hasAgreementPrice = createOrderDTO.getItems().stream()
                    .anyMatch(item -> "协议".equals(item.getPriceType()));
            // 根据是否包含协议确定type值
            String type = hasAgreementPrice ? "trade_agreement" : "trade_point";
            // 调用获取流程模板ID的接口
            // String processTemplateId = getProcessTemplateId(type);
            if (createOrderDTO.getProcessdefId() != null) {
                // 调用发起工作流的接口
                Map<String,Object> resMap = startWorkflowProcess(createOrderDTO.getProcessdefId(), createOrderDTO.getUserId(), type);
                workflowId = resMap.get("processinstId").toString();
                taskId = resMap.get("taskId").toString();
            } else {
                throw new BusinessException("流程定义Id为空!");
            }
        } catch (Exception e) {
            log.error("调用工作流接口失败,订单ID: {}", orderId, e);
            // 工作流调用失败,抛出异常触发事务回滚
            throw new BusinessException("工作流调用失败: " + e.getMessage());
        }
        // 计算总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
@@ -464,6 +591,9 @@
        orderInfo.setPaymentType(createOrderDTO.getPaymentType());
        orderInfo.setPaymentStatus("未支付");
        orderInfo.setBuyerRemarks(createOrderDTO.getBuyerRemarks());
        orderInfo.setIsEvaluate("未评价");
        orderInfo.setWorkflowId(workflowId); // 设置工作流ID
        orderInfo.setTaskId(taskId);
        orderInfo.setCreatedAt(LocalDateTime.now());
        orderInfo.setUpdatedAt(LocalDateTime.now());
@@ -505,7 +635,7 @@
    @Transactional(rollbackFor = Exception.class)
    public Long uploadOrderAttachment(String orderId, String fileName, String originalName, 
                                    String fileType, Long fileSize, String fileUrl, 
                                    String bucketName, String objectName, Long uploadUserId,
                                    String bucketName, String objectName, String uploadUserId,
                                    String uploadUserName, String attachmentType, String description) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
@@ -826,6 +956,58 @@
            throw new BusinessException("插入审批记录失败");
        }
        // 更新交易信息备注(只更新remarks,不更新订单状态)
        // 只更新订单详情备注,不更新订单状态
        if(orderApprovalDTO.getOrderDetails() != null) {
            for (UpdateOrderDetailDTO.UpdateOrderDetailItemDTO itemDTO : orderApprovalDTO.getOrderDetails()) {
                if (itemDTO.getId() == null) {
                    continue;
                }
                OrderDetail orderDetail = orderDetailMapper.selectById(itemDTO.getId());
                if (orderDetail == null) {
                    log.warn("订单详情不存在,ID: {}", itemDTO.getId());
                    continue;
                }
                // 更新备注
                orderDetail.setRemarks(itemDTO.getRemarks());
                orderDetail.setUpdatedAt(LocalDateTime.now());
                int detailUpdated = orderDetailMapper.updateById(orderDetail);
                if (detailUpdated <= 0) {
                    log.warn("更新订单详情失败,ID: {}", itemDTO.getId());
                }
            }
        }
        // 更新订单状态(通过 -> 下一个;驳回 -> 上一个)
        String currentStatus = orderInfo.getOrderStatus();
        if (!StringUtils.hasText(currentStatus)) {
            throw new BusinessException("订单当前状态为空");
        }
        boolean isReject = orderApprovalDTO.getApprovalResult().contains("驳回");
        String targetStatus = isReject ? getPreviousOrderStatus(currentStatus) : getNextOrderStatus(currentStatus);
        if (targetStatus == null) {
            throw new BusinessException((isReject ? "已是初始状态,无法回退" : "已是最终状态,无法继续流转"));
        }
        orderInfo.setOrderStatus(targetStatus);
        orderInfo.setUpdatedAt(LocalDateTime.now());
        int updated = this.baseMapper.updateById(orderInfo);
        if (updated <= 0) {
            throw new BusinessException("更新订单状态失败");
        }
        log.info("订单状态更新成功,订单ID: {}, 从 {} 更新为 {}", orderInfo.getOrderId(), currentStatus, targetStatus);
        // 根据审批结果调用提交或驳回接口
        String comment = orderApprovalDTO.getApprovalResult().contains("驳回") ? "审核驳回" : "审核通过";
        if ("审核驳回".equals(comment)) {
            rejectWorkflowTask(orderApprovalDTO.getTaskId(), String.valueOf(orderApprovalDTO.getApproverId()), comment);
        } else {
            completeWorkflowTask(orderApprovalDTO.getTaskId(), String.valueOf(orderApprovalDTO.getApproverId()), comment);
        }
        log.info("审批记录添加成功,订单ID: {}, 审批类型: {}, 审批结果: {}, 审批人: {}, 审批意见: {}", 
                orderApprovalDTO.getOrderId(),
                orderApprovalDTO.getApprovalType(),
@@ -939,9 +1121,10 @@
    private String getNextOrderStatus(String currentStatus) {
        switch (currentStatus) {
            case "待上传文件":
                return "待授权";
                return "待审批授权";
            case "待审批授权":
            case "待授权":
                return "待交易确认";
                return  "待交易确认";
            case "待交易确认":
                return "已完成";
            case "已完成":
@@ -962,7 +1145,7 @@
        switch (currentStatus) {
            case "待上传文件":
                return null; // 初始状态
            case "待授权":
            case "待审批授权":
                return "待上传文件";
            case "待交易确认":
                return "待授权";
@@ -1196,7 +1379,267 @@
        wrapper.eq("deleted", 0);
        // 审核中:状态不为 已完成 或 已取消
        wrapper.notIn("order_status", Arrays.asList("已完成", "已取消"));
        Integer count = this.baseMapper.selectCount(wrapper);
        Long count = this.baseMapper.selectCount(wrapper);
        return count != null && count > 0;
    }
    @Override
    public boolean updateOrderIsEvaluate(String orderId) {
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        OrderInfo orderInfo = this.getById(orderId);
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        orderInfo.setIsEvaluate("已评价");
        return this.updateById(orderInfo);
    }
    /**
     * 获取流程模板ID
     * @param type 类型参数
     * @return 流程模板ID
     */
    private String getProcessTemplateId(String type) {
        try {
            String url = workflowProperties.getApproval().getBaseUrl() + workflowProperties.getApproval().getTemplateRelationUrl();
            // 构建请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("type", type);
            params.put("unitId", workflowProperties.getApproval().getUnitId());
            // 发送POST请求
            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                new HttpEntity<>(params),
                new ParameterizedTypeReference<Map<String, Object>>() {}
            );
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Map<String, Object> responseBody = response.getBody();
                return (String) responseBody.get("processTemplateId");
            } else {
                log.warn("获取流程模板ID失败,响应状态: {}", response.getStatusCode());
                return null;
            }
        } catch (Exception e) {
            log.error("调用获取流程模板ID接口失败", e);
            throw new BusinessException("获取流程模板ID失败: " + e.getMessage());
        }
    }
    /**
     * 启动工作流流程
     * @param processTemplateId 流程模板ID
     * @param userId 用户ID
     * @param businessKey 业务键(订单ID)
     * @return 流程实例ID
     */
    private Map<String,Object> startWorkflowProcess(String processTemplateId, String userId, String businessKey) {
        try {
            String url = workflowProperties.getProcess().getBaseUrl() + workflowProperties.getProcess().getStartProcessUrl();
            // 构建请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("processdefId", processTemplateId);
            params.put("userid", userId);
            params.put("businessKey", businessKey);
            // 发送POST请求
            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                new HttpEntity<>(params),
                new ParameterizedTypeReference<Map<String, Object>>() {}
            );
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Object code = response.getBody().get("code");
                boolean ok = (code instanceof Number && ((Number) code).intValue() == 200) || "200".equals(String.valueOf(code));
                if (!ok) {
                    throw new BusinessException("工作流启动任务失败,返回码: " + code);
                }
                Map<String, Object> data = (Map<String, Object>) response.getBody().get("data");
                if (data == null) {
                    throw new BusinessException("工作流启动任务失败,返回数据为空");
                }
                return  data;
            } else {
                throw new BusinessException("启动工作流失败,响应状态:"+response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("调用启动工作流接口失败", e);
            throw new BusinessException("启动工作流失败: " + e.getMessage());
        }
    }
    /**
     * 提交流程任务
     * @param taskId 任务ID(使用订单的workflowId)
     * @param userId 用户ID
     * @param comment 审批意见(如:审核通过)
     */
    private void completeWorkflowTask(String taskId, String userId, String comment) {
        try {
            String url = workflowProperties.getProcess().getBaseUrl() + workflowProperties.getProcess().getCompleteUrl();
            Map<String, Object> params = new HashMap<>();
            params.put("taskId", taskId);
            params.put("userid", userId);
            params.put("commponet", comment);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                entity,
                new ParameterizedTypeReference<Map<String, Object>>() {}
            );
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Object code = response.getBody().get("code");
                boolean ok = (code instanceof Number && ((Number) code).intValue() == 200) || "200".equals(String.valueOf(code));
                if (!ok) {
                    throw new BusinessException("工作流完成任务失败,返回码: " + code);
                }
                Map<?, ?> data = (Map<?, ?>) response.getBody().get("data");
                if (data == null) {
                    throw new BusinessException("工作流完成任务失败,返回数据为空");
                }
                log.info("完成工作流任务成功,processinstId: {}", data.get("processinstId"));
            } else {
                throw new BusinessException("工作流完成任务接口调用失败,HTTP状态: " + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("提交工作流失败", e);
            throw new BusinessException("提交工作流失败: " + e.getMessage());
        }
    }
    /**
     * 驳回流程任务
     */
    private void rejectWorkflowTask(String taskId, String userId, String comment) {
        try {
            String url = workflowProperties.getProcess().getBaseUrl() + workflowProperties.getProcess().getRejectUrl();
            Map<String, Object> params = new HashMap<>();
            params.put("taskId", taskId);
            params.put("userid", userId);
            params.put("commponet", comment);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                entity,
                new ParameterizedTypeReference<Map<String, Object>>() {}
            );
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Object code = response.getBody().get("code");
                boolean ok = (code instanceof Number && ((Number) code).intValue() == 200) || "200".equals(String.valueOf(code));
                if (!ok) {
                    throw new BusinessException("工作流驳回任务失败,返回码: " + code);
                }
                Map<?, ?> data = (Map<?, ?>) response.getBody().get("data");
                if (data == null) {
                    throw new BusinessException("工作流驳回任务失败,返回数据为空");
                }
                log.info("驳回工作流任务成功,processinstId: {}", data.get("processinstId"));
            } else {
                throw new BusinessException("工作流驳回任务接口调用失败,HTTP状态: " + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("驳回工作流失败", e);
            throw new BusinessException("驳回工作流失败: " + e.getMessage());
        }
    }
    /**
     * 按照workFlowType查询流程实例ID集合
     * workFlowType: 0=代办,1=已办
     */
    private List<Object> fetchWorkflowProcessInstanceIds(Integer workFlowType, String userId, String depId,String businessKey,Integer pageIndex, Integer pageSize) {
        try {
            if (workFlowType == null) {
                return java.util.Collections.emptyList();
            }
            String base = workflowProperties.getProcess().getBaseUrl();
            Map<String, Object> params = new HashMap<>();
            params.put("userid", userId);
            params.put("businessKey", businessKey);
            params.put("pageIndex", pageIndex != null ? pageIndex : 1);
            params.put("pageSize", pageSize != null ? pageSize : 10);
            String url;
            if (workFlowType != null && workFlowType == 0) {
                // 代办
                url = base + workflowProperties.getProcess().getFindTodoUrl();
                params.put("depid", depId);
            } else {
                // 已办
                url = base + workflowProperties.getProcess().getFindDoneUrl();
            }
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                entity,
                new ParameterizedTypeReference<Map<String, Object>>() {}
            );
            if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null) {
                return java.util.Collections.emptyList();
            }
            Object dataObj = response.getBody().get("data");
            if (workFlowType != null && workFlowType == 0) {
                if (!(dataObj instanceof java.util.List)) {
                    return java.util.Collections.emptyList();
                }
                java.util.List<Object> list = (java.util.List<Object>) dataObj;
                return list;
//                        list.stream()
//                        .filter(item -> item instanceof Map)
//                        .map(item -> (Map<?, ?>) item)
//                        .map(m -> m.get("processInstanceId"))
//                        .filter(Objects::nonNull)
//                        .map(Object::toString)
//                        .collect(Collectors.toList());
            }else {
                if (!(dataObj instanceof Map)) {
                    return java.util.Collections.emptyList();
                }
                Map<?,?> map = (Map<?,?>) dataObj;
                Object dataObj1 = ((Map<?, ?>) dataObj).get("list");
                java.util.List<Object> list = (java.util.List<Object>) dataObj1;
                return list;
//                        list.stream()
//                        .filter(item -> item instanceof Map)
//                        .map(item -> (Map<?, ?>) item)
//                        .map(m -> m.get("processInstanceId"))
//                        .filter(Objects::nonNull)
//                        .map(Object::toString)
//                        .collect(Collectors.toList());
            }
        } catch (Exception e) {
            log.error("查询工作流实例ID失败", e);
            return java.util.Collections.emptyList();
        }
    }
}