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,34 @@
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 基于workFlowType查询流程实例ID集合
        List<String> workFlowIds = fetchWorkflowProcessInstanceIds(
            queryDTO.getWorkFlowType(),
            queryDTO.getUserId(),
            queryDTO.getDepartmentId(),
            queryDTO.getBusinessType(),
            queryDTO.getPageNum(),
            queryDTO.getPageSize()
        );
        // 如果没有任何流程ID,直接返回空分页
        if (workFlowIds == null || workFlowIds.isEmpty()) {
            return new PageResult<OrderDetailVO>(
                java.util.Collections.emptyList(),
                0L,
                queryDTO.getPageNum().longValue(),
                queryDTO.getPageSize().longValue(),
                0L
            );
        }
        // 执行分页查询
        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
@@ -227,12 +266,33 @@
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 执行分页查询
        // 基于workFlowType查询流程实例ID集合
        List<String> workFlowIds = fetchWorkflowProcessInstanceIds(
            queryDTO.getWorkFlowType(),
            queryDTO.getUserId(),
            queryDTO.getDepartmentId(),
            queryDTO.getBusinessType(),
            queryDTO.getPageNum(),
            queryDTO.getPageSize()
        );
        // 如果没有任何流程ID,直接返回空分页
        if (workFlowIds == null || workFlowIds.isEmpty()) {
            return new PageResult<OrderInfo>(
                java.util.Collections.emptyList(),
                0L,
                queryDTO.getPageNum().longValue(),
                queryDTO.getPageSize().longValue(),
                0L
            );
        }
        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
        );
        // 构建返回结果
@@ -433,6 +493,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;
        for (CreateOrderItemDTO item : createOrderDTO.getItems()) {
@@ -465,6 +553,8 @@
        orderInfo.setPaymentStatus("未支付");
        orderInfo.setBuyerRemarks(createOrderDTO.getBuyerRemarks());
        orderInfo.setIsEvaluate("未评价");
        orderInfo.setWorkflowId(workflowId); // 设置工作流ID
        orderInfo.setTaskId(taskId);
        orderInfo.setCreatedAt(LocalDateTime.now());
        orderInfo.setUpdatedAt(LocalDateTime.now());
@@ -827,6 +917,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(orderInfo.getTaskId(), String.valueOf(orderApprovalDTO.getApproverId()), comment);
        } else {
            completeWorkflowTask(orderInfo.getTaskId(), String.valueOf(orderApprovalDTO.getApproverId()), comment);
        }
        log.info("审批记录添加成功,订单ID: {}, 审批类型: {}, 审批结果: {}, 审批人: {}, 审批意见: {}", 
                orderApprovalDTO.getOrderId(),
                orderApprovalDTO.getApprovalType(),
@@ -940,7 +1082,8 @@
    private String getNextOrderStatus(String currentStatus) {
        switch (currentStatus) {
            case "待上传文件":
                return "待授权";
                return "待审批授权";
            case "待审批授权":
            case "待授权":
                return "待交易确认";
            case "待交易确认":
@@ -963,7 +1106,7 @@
        switch (currentStatus) {
            case "待上传文件":
                return null; // 初始状态
            case "待授权":
            case "待审批授权":
                return "待上传文件";
            case "待交易确认":
                return "待授权";
@@ -1213,4 +1356,249 @@
        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<String> 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<?> list = (java.util.List<?>) dataObj;
                return 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<?> list = (java.util.List<?>) dataObj1;
                return 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();
        }
    }
}