seatonwan9
2025-08-28 e5d17ab1bc9e0779b325c53bf23d61ae4a15432e
src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java
@@ -8,17 +8,24 @@
import com.webmanage.common.PageResult;
import com.webmanage.dto.CreateOrderDTO;
import com.webmanage.dto.CreateOrderItemDTO;
import com.webmanage.dto.FileCheckDTO;
import com.webmanage.dto.OrderApprovalDTO;
import com.webmanage.dto.OrderQueryDTO;
import com.webmanage.dto.UpdateOrderDetailDTO;
import com.webmanage.entity.OrderApproval;
import com.webmanage.entity.OrderAttachment;
import com.webmanage.entity.OrderDetail;
import com.webmanage.entity.OrderEvaluation;
import com.webmanage.entity.OrderInfo;
import com.webmanage.mapper.OrderApprovalMapper;
import com.webmanage.mapper.OrderAttachmentMapper;
import com.webmanage.mapper.OrderDetailMapper;
import com.webmanage.mapper.OrderEvaluationMapper;
import com.webmanage.mapper.OrderInfoMapper;
import com.webmanage.mapper.ReportResultSubmissionMapper;
import com.webmanage.service.OrderInfoService;
import com.webmanage.service.OrderNoService;
import com.webmanage.service.MinioService;
import com.webmanage.vo.OrderAttachmentVO;
import com.webmanage.vo.OrderDetailItemVO;
import com.webmanage.vo.OrderDetailVO;
@@ -34,6 +41,7 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
@@ -53,10 +61,19 @@
    private OrderEvaluationMapper orderEvaluationMapper;
    @Resource
    private OrderApprovalMapper orderApprovalMapper;
    @Resource
    private OrderNoService orderNoService;
    @Resource
    private MinioService minioService;
    @Resource
    private ReportResultSubmissionMapper reportResultSubmissionMapper;
    @Override
    public PageResult<OrderInfo> getBuyerOrderPage(OrderQueryDTO queryDTO) {
    public PageResult<OrderDetailVO> getBuyerOrderPage(OrderQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO.getUserId() == null) {
            throw new BusinessException("用户ID不能为空");
@@ -76,10 +93,23 @@
            queryDTO.getCreateTimeEnd() != null ? queryDTO.getCreateTimeEnd().toString() : null,
            queryDTO.getOrderBy(), queryDTO.getOrderDirection()
        );
        // 将订单与详情联表封装到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);
            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(),
@@ -88,10 +118,10 @@
    }
    @Override
    public PageResult<OrderInfo> getSellerOrderPage(OrderQueryDTO queryDTO) {
    public PageResult<OrderDetailVO> getSellerOrderPage(OrderQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO.getUserId() == null) {
            throw new BusinessException("用户ID不能为空");
        if (queryDTO.getProviderId() == null) {
            throw new BusinessException("提供者ID不能为空");
        }
        // 创建分页对象
@@ -99,7 +129,7 @@
        // 执行分页查询
        IPage<OrderInfo> result = baseMapper.selectSellerOrderPage(
            page, queryDTO.getUserId(), queryDTO.getOrderStatus(), queryDTO.getPaymentStatus(),
            page, queryDTO.getProviderId(), queryDTO.getOrderStatus(), queryDTO.getPaymentStatus(),
            queryDTO.getProductName(), queryDTO.getOrderId(),
            queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null,
            queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null,
@@ -108,9 +138,23 @@
            queryDTO.getOrderBy(), queryDTO.getOrderDirection()
        );
        // 将订单与详情联表封装到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);
            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(),
@@ -119,7 +163,7 @@
    }
    @Override
    public PageResult<OrderInfo> getPendingApprovalOrderPage(OrderQueryDTO queryDTO) {
    public PageResult<OrderDetailVO> getPendingApprovalOrderPage(OrderQueryDTO queryDTO) {
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
@@ -132,9 +176,201 @@
            queryDTO.getOrderBy(), queryDTO.getOrderDirection()
        );
        // 将订单与详情联表封装到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);
            return vo;
        }).collect(java.util.stream.Collectors.toList());
        // 构建返回结果
        return new PageResult<OrderDetailVO>(
                voList,
                result.getTotal(),
                queryDTO.getPageNum().longValue(),
                queryDTO.getPageSize().longValue(),
                result.getPages()
        );
    }
    @Override
    public PageResult<OrderInfo> getPendingApprovalOrderPageWithProductConditions(OrderQueryDTO queryDTO) {
        // 根据产品条件查询产品ID列表
        List<String> productIds = null;
        if (StringUtils.hasText(queryDTO.getIndustryId()) || StringUtils.hasText(queryDTO.getUnitProjectId()) ||
            StringUtils.hasText(queryDTO.getProductTypeId()) || StringUtils.hasText(queryDTO.getProductSubTypeId())) {
            productIds = reportResultSubmissionMapper.selectProductIdsByConditions(
                queryDTO.getIndustryId(), queryDTO.getUnitProjectId(),
                queryDTO.getProductTypeId(), queryDTO.getProductSubTypeId()
            );
            // 如果没有找到匹配的产品,直接返回空结果
            if (CollectionUtils.isEmpty(productIds)) {
                return new PageResult<OrderInfo>(
                    java.util.Collections.emptyList(),
                    0L,
                    queryDTO.getPageNum().longValue(),
                    queryDTO.getPageSize().longValue(),
                    0L
                );
            }
        }
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 执行分页查询
        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
        );
        // 构建返回结果
        return new PageResult<OrderInfo>(
            result.getRecords(),
            result.getTotal(),
            queryDTO.getPageNum().longValue(),
            queryDTO.getPageSize().longValue(),
            result.getPages()
        );
    }
    @Override
    public PageResult<OrderDetailVO> getBuyerOrderPageWithProductConditions(OrderQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO.getUserId() == null) {
            throw new BusinessException("用户ID不能为空");
        }
        // 根据产品条件查询产品ID列表
        List<String> productIds = null;
        if (StringUtils.hasText(queryDTO.getIndustryId()) || StringUtils.hasText(queryDTO.getUnitProjectId()) ||
            StringUtils.hasText(queryDTO.getProductTypeId()) || StringUtils.hasText(queryDTO.getProductSubTypeId())) {
            productIds = reportResultSubmissionMapper.selectProductIdsByConditions(
                queryDTO.getIndustryId(), queryDTO.getUnitProjectId(),
                queryDTO.getProductTypeId(), queryDTO.getProductSubTypeId()
            );
            // 如果没有找到匹配的产品,直接返回空结果
            if (CollectionUtils.isEmpty(productIds)) {
                return new PageResult<OrderDetailVO>(
                    java.util.Collections.emptyList(),
                    0L,
                    queryDTO.getPageNum().longValue(),
                    queryDTO.getPageSize().longValue(),
                    0L
                );
            }
        }
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 执行分页查询
        IPage<OrderInfo> result = baseMapper.selectBuyerOrderPageWithProductConditions(
            page, queryDTO.getUserId(), queryDTO.getUnitId(), queryDTO.getOrderStatus(),
            queryDTO.getPaymentStatus(), queryDTO.getPaymentType(), queryDTO.getProductName(),
            queryDTO.getProviderName(), queryDTO.getOrderId(),
            queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null,
            queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null,
            queryDTO.getCreateTimeStart() != null ? queryDTO.getCreateTimeStart().toString() : null,
            queryDTO.getCreateTimeEnd() != null ? queryDTO.getCreateTimeEnd().toString() : null,
            queryDTO.getOrderBy(), queryDTO.getOrderDirection(), productIds
        );
        // 将订单与详情联表封装到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);
            return vo;
        }).collect(java.util.stream.Collectors.toList());
        // 构建返回结果
        return new PageResult<OrderDetailVO>(
            voList,
            result.getTotal(),
            queryDTO.getPageNum().longValue(),
            queryDTO.getPageSize().longValue(),
            result.getPages()
        );
    }
    @Override
    public PageResult<OrderDetailVO> getSellerOrderPageWithProductConditions(OrderQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO.getProviderId() == null) {
            throw new BusinessException("提供者ID不能为空");
        }
        // 根据产品条件查询产品ID列表
        List<String> productIds = null;
        if (StringUtils.hasText(queryDTO.getIndustryId()) || StringUtils.hasText(queryDTO.getUnitProjectId()) ||
            StringUtils.hasText(queryDTO.getProductTypeId()) || StringUtils.hasText(queryDTO.getProductSubTypeId())) {
            productIds = reportResultSubmissionMapper.selectProductIdsByConditions(
                queryDTO.getIndustryId(), queryDTO.getUnitProjectId(),
                queryDTO.getProductTypeId(), queryDTO.getProductSubTypeId()
            );
            // 如果没有找到匹配的产品,直接返回空结果
            if (CollectionUtils.isEmpty(productIds)) {
                return new PageResult<OrderDetailVO>(
                    java.util.Collections.emptyList(),
                    0L,
                    queryDTO.getPageNum().longValue(),
                    queryDTO.getPageSize().longValue(),
                    0L
                );
            }
        }
        // 创建分页对象
        Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 执行分页查询
        IPage<OrderInfo> result = baseMapper.selectSellerOrderPageWithProductConditions(
            page, queryDTO.getProviderId(), queryDTO.getOrderStatus(), queryDTO.getPaymentStatus(),
            queryDTO.getProductName(), queryDTO.getOrderId(),
            queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null,
            queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null,
            queryDTO.getCreateTimeStart() != null ? queryDTO.getCreateTimeStart().toString() : null,
            queryDTO.getCreateTimeEnd() != null ? queryDTO.getCreateTimeEnd().toString() : null,
            queryDTO.getOrderBy(), queryDTO.getOrderDirection(), productIds
        );
        // 将订单与详情联表封装到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);
            return vo;
        }).collect(java.util.stream.Collectors.toList());
        // 构建返回结果
        return new PageResult<OrderDetailVO>(
            voList,
            result.getTotal(),
            queryDTO.getPageNum().longValue(),
            queryDTO.getPageSize().longValue(),
@@ -190,7 +426,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(CreateOrderDTO createOrderDTO) {
    public OrderInfo createOrder(CreateOrderDTO createOrderDTO) {
        if (createOrderDTO == null || CollectionUtils.isEmpty(createOrderDTO.getItems())) {
            throw new BusinessException("订单信息不完整");
        }
@@ -219,7 +455,11 @@
        orderInfo.setUserId(createOrderDTO.getUserId());
        orderInfo.setUnitId(createOrderDTO.getUnitId());
        orderInfo.setApplyTime(LocalDateTime.now());
        orderInfo.setOrderStatus("待审批");
        // 根据订单明细中是否包含协议价格类型来决定初始状态
        String initialStatus = determineInitialOrderStatus(createOrderDTO.getItems());
        orderInfo.setOrderStatus(initialStatus);
        orderInfo.setTotalAmount(createOrderDTO.getTotalAmount() != null ? createOrderDTO.getTotalAmount() : totalAmount);
        orderInfo.setPaymentType(createOrderDTO.getPaymentType());
        orderInfo.setPaymentStatus("未支付");
@@ -258,15 +498,15 @@
            orderDetailMapper.insert(detail);
        }
        return orderId;
        return orderInfo;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean uploadOrderAttachment(String orderId, String fileName, String originalName,
                                      String fileType, Long fileSize, String fileUrl,
                                      String bucketName, String objectName, Long uploadUserId,
                                      String uploadUserName, String attachmentType, String description) {
    public Long uploadOrderAttachment(String orderId, String fileName, String originalName,
                                    String fileType, Long fileSize, String fileUrl,
                                    String bucketName, String objectName, Long uploadUserId,
                                    String uploadUserName, String attachmentType, String description) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
@@ -296,8 +536,13 @@
        attachment.setAttachmentType(attachmentType);
        attachment.setDescription(description);
        // 保存附件
        return orderAttachmentMapper.insert(attachment) > 0;
        // 保存附件并返回附件ID
        int result = orderAttachmentMapper.insert(attachment);
        if (result > 0) {
            return attachment.getId();
        } else {
            throw new BusinessException("保存附件失败");
        }
    }
    @Override
@@ -419,4 +664,539 @@
        // 保存评价
        return orderEvaluationMapper.updateById(evaluation) > 0;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderDetail(UpdateOrderDetailDTO updateOrderDetailDTO) {
        // 参数校验
        if (updateOrderDetailDTO == null) {
            throw new BusinessException("更新参数不能为空");
        }
        if (!StringUtils.hasText(updateOrderDetailDTO.getOrderId())) {
            throw new BusinessException("订单ID不能为空");
        }
        if (!StringUtils.hasText(updateOrderDetailDTO.getOrderStatus())) {
            throw new BusinessException("订单状态不能为空");
        }
        if (CollectionUtils.isEmpty(updateOrderDetailDTO.getOrderDetails())) {
            throw new BusinessException("订单详情列表不能为空");
        }
        // 查询订单信息
        OrderInfo orderInfo = this.getById(updateOrderDetailDTO.getOrderId());
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 更新订单状态
        orderInfo.setOrderStatus(updateOrderDetailDTO.getOrderStatus());
        orderInfo.setUpdatedAt(LocalDateTime.now());
        int orderUpdated = this.baseMapper.updateById(orderInfo);
        if (orderUpdated <= 0) {
            throw new BusinessException("更新订单状态失败");
        }
        // 更新订单详情备注
        for (UpdateOrderDetailDTO.UpdateOrderDetailItemDTO itemDTO : updateOrderDetailDTO.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());
            }
        }
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkFiles(FileCheckDTO fileCheckDTO) {
        // 参数校验
        if (fileCheckDTO == null) {
            throw new BusinessException("文件核查参数不能为空");
        }
        if (!StringUtils.hasText(fileCheckDTO.getOrderId())) {
            throw new BusinessException("订单ID不能为空");
        }
        if (fileCheckDTO.getIsApprove() == null) {
            throw new BusinessException("审批结果不能为空");
        }
        if (fileCheckDTO.getApproverId() == null) {
            throw new BusinessException("审批人ID不能为空");
        }
        if (!StringUtils.hasText(fileCheckDTO.getApproverName())) {
            throw new BusinessException("审批人姓名不能为空");
        }
        // 查询订单信息
        OrderInfo orderInfo = this.getById(fileCheckDTO.getOrderId());
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 检查订单状态是否为"待授权"
        if (!"待授权".equals(orderInfo.getOrderStatus())) {
            throw new BusinessException("订单状态不正确,当前状态为:" + orderInfo.getOrderStatus());
        }
        // 更新订单状态
        if (fileCheckDTO.getIsApprove()) {
            // 通过:更新为"待交易确认"
            orderInfo.setOrderStatus("待交易确认");
        } else {
            // 驳回:更新为"待上传文件"(需要重新上传)
            orderInfo.setOrderStatus("待上传文件");
        }
        orderInfo.setUpdatedAt(LocalDateTime.now());
        // 保存订单
        int updated = this.baseMapper.updateById(orderInfo);
        if (updated <= 0) {
            throw new BusinessException("更新订单状态失败");
        }
        log.info("文件核查完成,订单ID: {}, 审批结果: {}, 审批人: {}, 审批意见: {}",
                fileCheckDTO.getOrderId(),
                fileCheckDTO.getIsApprove() ? "通过" : "驳回",
                fileCheckDTO.getApproverName(),
                fileCheckDTO.getApprovalOpinion());
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approveOrder(OrderApprovalDTO orderApprovalDTO) {
        // 参数校验
        if (orderApprovalDTO == null) {
            throw new BusinessException("审批参数不能为空");
        }
        if (!StringUtils.hasText(orderApprovalDTO.getOrderId())) {
            throw new BusinessException("订单ID不能为空");
        }
        if (!StringUtils.hasText(orderApprovalDTO.getApprovalOpinion())) {
            throw new BusinessException("审批意见不能为空");
        }
        if (orderApprovalDTO.getApproverId() == null) {
            throw new BusinessException("审批人ID不能为空");
        }
        if (!StringUtils.hasText(orderApprovalDTO.getApproverName())) {
            throw new BusinessException("审批人姓名不能为空");
        }
        if (!StringUtils.hasText(orderApprovalDTO.getApprovalType())) {
            throw new BusinessException("审批类型不能为空");
        }
        if (!StringUtils.hasText(orderApprovalDTO.getApprovalResult())) {
            throw new BusinessException("审批结果不能为空");
        }
        // 查询订单信息
        OrderInfo orderInfo = this.getById(orderApprovalDTO.getOrderId());
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 创建审批记录
        OrderApproval orderApproval = new OrderApproval();
        orderApproval.setOrderId(orderApprovalDTO.getOrderId());
        orderApproval.setApprovalStep("审批授权");
        orderApproval.setApprovalType(orderApprovalDTO.getApprovalType());
        orderApproval.setApprovalResult(orderApprovalDTO.getApprovalResult());
        orderApproval.setApproverId(orderApprovalDTO.getApproverId());
        orderApproval.setApproverName(orderApprovalDTO.getApproverName());
        orderApproval.setApprovalOpinion(orderApprovalDTO.getApprovalOpinion());
        orderApproval.setApprovalTime(LocalDateTime.now());
        // 插入审批记录
        int insertResult = orderApprovalMapper.insert(orderApproval);
        if (insertResult <= 0) {
            throw new BusinessException("插入审批记录失败");
        }
        log.info("审批记录添加成功,订单ID: {}, 审批类型: {}, 审批结果: {}, 审批人: {}, 审批意见: {}",
                orderApprovalDTO.getOrderId(),
                orderApprovalDTO.getApprovalType(),
                orderApprovalDTO.getApprovalResult(),
                orderApprovalDTO.getApproverName(),
                orderApprovalDTO.getApprovalOpinion());
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatusToNext(String orderId) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        // 查询订单信息
        OrderInfo orderInfo = this.getById(orderId);
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 获取当前状态
        String currentStatus = orderInfo.getOrderStatus();
        if (!StringUtils.hasText(currentStatus)) {
            throw new BusinessException("订单当前状态为空");
        }
        // 获取下一个状态
        String nextStatus = getNextOrderStatus(currentStatus);
        if (nextStatus == null) {
            throw new BusinessException("当前状态 " + currentStatus + " 已是最终状态,无法继续流转");
        }
        // 更新订单状态
        orderInfo.setOrderStatus(nextStatus);
        orderInfo.setUpdatedAt(LocalDateTime.now());
        int updated = this.baseMapper.updateById(orderInfo);
        if (updated <= 0) {
            throw new BusinessException("更新订单状态失败");
        }
        log.info("订单状态更新成功,订单ID: {}, 从 {} 更新为 {}", orderId, currentStatus, nextStatus);
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatusToPrevious(String orderId) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        // 查询订单信息
        OrderInfo orderInfo = this.getById(orderId);
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 获取当前状态
        String currentStatus = orderInfo.getOrderStatus();
        if (!StringUtils.hasText(currentStatus)) {
            throw new BusinessException("订单当前状态为空");
        }
        // 获取上一个状态
        String previousStatus = getPreviousOrderStatus(currentStatus);
        if (previousStatus == null) {
            throw new BusinessException("当前状态 " + currentStatus + " 已是初始状态,无法回退");
        }
        // 更新订单状态
        orderInfo.setOrderStatus(previousStatus);
        orderInfo.setUpdatedAt(LocalDateTime.now());
        int updated = this.baseMapper.updateById(orderInfo);
        if (updated <= 0) {
            throw new BusinessException("更新订单状态失败");
        }
        log.info("订单状态更新成功,订单ID: {}, 从 {} 回退为 {}", orderId, currentStatus, previousStatus);
        return true;
    }
    /**
     * 根据订单明细确定初始订单状态
     * @param items 订单明细列表
     * @return 初始状态
     */
    private String determineInitialOrderStatus(List<CreateOrderItemDTO> items) {
        // 检查是否有价格类型为"协议"的明细项
        boolean hasAgreementPrice = items.stream()
                .anyMatch(item -> "协议".equals(item.getPriceType()));
        // 如果有协议价格,从"待上传文件"开始,否则从"待授权"开始
        String initialStatus = hasAgreementPrice ? "待上传文件" : "待授权";
        log.info("订单初始状态确定为: {}, 是否包含协议价格: {}", initialStatus, hasAgreementPrice);
        return initialStatus;
    }
    /**
     * 获取下一个订单状态
     * @param currentStatus 当前状态
     * @return 下一个状态,如果是最终状态则返回null
     */
    private String getNextOrderStatus(String currentStatus) {
        switch (currentStatus) {
            case "待上传文件":
                return "待授权";
            case "待授权":
                return "待交易确认";
            case "待交易确认":
                return "已完成";
            case "已完成":
                return "已评价";
            case "已评价":
                return null; // 最终状态
            default:
                throw new BusinessException("未知的订单状态:" + currentStatus);
        }
    }
    /**
     * 获取上一个订单状态
     * @param currentStatus 当前状态
     * @return 上一个状态,如果是初始状态则返回null
     */
    private String getPreviousOrderStatus(String currentStatus) {
        switch (currentStatus) {
            case "待上传文件":
                return null; // 初始状态
            case "待授权":
                return "待上传文件";
            case "待交易确认":
                return "待授权";
            case "已完成":
                return "待交易确认";
            case "已评价":
                return "已完成";
            default:
                throw new BusinessException("未知的订单状态:" + currentStatus);
        }
    }
    @Override
    public boolean hasAgreementPriceType(String orderId) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        // 查询订单详情,检查是否有价格类型为"协议"的子订单
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        queryWrapper.eq("price_type", "协议");
        queryWrapper.eq("deleted", 0);
        List<OrderDetail> agreementDetails = orderDetailMapper.selectList(queryWrapper);
        boolean hasAgreement = !CollectionUtils.isEmpty(agreementDetails);
        log.info("检查订单协议类型,订单ID: {}, 是否包含协议类型: {}", orderId, hasAgreement);
        return hasAgreement;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderDetailRemarksOnly(UpdateOrderDetailDTO.UpdateOrderDetailRemarksOnlyDTO updateOrderDetailDTO) {
        // 参数校验
        if (updateOrderDetailDTO == null) {
            throw new BusinessException("更新参数不能为空");
        }
        if (!StringUtils.hasText(updateOrderDetailDTO.getOrderId())) {
            throw new BusinessException("订单ID不能为空");
        }
        if (CollectionUtils.isEmpty(updateOrderDetailDTO.getOrderDetails())) {
            throw new BusinessException("订单详情列表不能为空");
        }
        // 查询订单信息(验证订单存在)
        OrderInfo orderInfo = this.getById(updateOrderDetailDTO.getOrderId());
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 只更新订单详情备注,不更新订单状态
        for (UpdateOrderDetailDTO.UpdateOrderDetailItemDTO itemDTO : updateOrderDetailDTO.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());
            }
        }
        log.info("订单详情备注更新成功,订单ID: {}", updateOrderDetailDTO.getOrderId());
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteOrderAttachment(Long attachmentId) {
        // 参数校验
        if (attachmentId == null) {
            throw new BusinessException("附件ID不能为空");
        }
        log.info("开始删除订单附件,附件ID: {}", attachmentId);
        // 查询附件信息
        OrderAttachment attachment = orderAttachmentMapper.selectById(attachmentId);
        if (attachment == null) {
            log.error("附件不存在,附件ID: {}", attachmentId);
            throw new BusinessException("附件不存在");
        }
        log.info("查询到附件信息: ID={}, 文件名={}, 对象名称={}, 当前删除状态={}",
                attachment.getId(), attachment.getFileName(), attachment.getObjectName(), attachment.getDeleted());
        try {
            // 1. 删除MinIO中的文件
            if (StringUtils.hasText(attachment.getObjectName())) {
                log.info("开始删除MinIO文件,对象名称: {}", attachment.getObjectName());
                minioService.deleteFile(attachment.getObjectName());
                log.info("MinIO文件删除成功,对象名称: {}", attachment.getObjectName());
            } else {
                log.warn("附件对象名称为空,跳过MinIO文件删除");
            }
            // 2. 删除数据库中的附件记录(逻辑删除)
            log.info("开始逻辑删除数据库记录,附件ID: {}", attachmentId);
            // 使用MyBatis-Plus的逻辑删除方法
            int result = orderAttachmentMapper.deleteById(attachmentId);
            log.info("数据库逻辑删除结果: 影响行数={}", result);
            if (result > 0) {
                log.info("订单附件删除成功,附件ID: {}, 文件名: {}", attachmentId, attachment.getFileName());
                return true;
            } else {
                log.error("数据库更新失败,影响行数为0,附件ID: {}", attachmentId);
                throw new BusinessException("删除附件记录失败");
            }
        } catch (Exception e) {
            log.error("删除订单附件失败,附件ID: {}", attachmentId, e);
            throw new BusinessException("删除订单附件失败:" + e.getMessage());
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(String orderId) {
        // 参数校验
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        log.info("开始取消订单,订单ID: {}", orderId);
        // 查询订单信息
        OrderInfo orderInfo = this.getById(orderId);
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        // 检查订单状态,只有"已完成"状态前的订单才能取消
        String currentStatus = orderInfo.getOrderStatus();
        if ("已完成".equals(currentStatus) || "已评价".equals(currentStatus)) {
            throw new BusinessException("已完成或已评价的订单不能取消");
        }
        try {
            // 1. 删除订单附件(包括MinIO文件和数据库记录)
            log.info("开始删除订单附件,订单ID: {}", orderId);
            List<OrderAttachment> attachments = orderAttachmentMapper.selectByOrderId(orderId);
            for (OrderAttachment attachment : attachments) {
                try {
                    // 删除MinIO中的文件
                    if (StringUtils.hasText(attachment.getObjectName())) {
                        log.info("删除MinIO文件,对象名称: {}", attachment.getObjectName());
                        minioService.deleteFile(attachment.getObjectName());
                    }
                    // 删除数据库记录
                    orderAttachmentMapper.deleteById(attachment.getId());
                    log.info("删除附件记录成功,附件ID: {}", attachment.getId());
                } catch (Exception e) {
                    log.error("删除附件失败,附件ID: {}, 错误: {}", attachment.getId(), e.getMessage());
                    // 继续删除其他附件,不中断整个流程
                }
            }
            // 2. 逻辑删除订单详情
            log.info("开始逻辑删除订单详情,订单ID: {}", orderId);
            // 先查询订单详情列表,然后逐个逻辑删除
            List<OrderDetail> orderDetails = orderDetailMapper.selectByOrderId(orderId);
            int detailDeleted = 0;
            for (OrderDetail detail : orderDetails) {
                int result = orderDetailMapper.deleteById(detail.getId());
                if (result > 0) {
                    detailDeleted++;
                }
            }
            log.info("逻辑删除订单详情完成,影响行数: {}", detailDeleted);
            // 3. 删除订单信息(逻辑删除)
            log.info("开始删除订单信息,订单ID: {}", orderId);
            int orderDeleted = this.baseMapper.deleteById(orderId);
            log.info("删除订单信息完成,影响行数: {}", orderDeleted);
            if (orderDeleted > 0) {
                log.info("订单取消成功,订单ID: {}", orderId);
                return true;
            } else {
                log.error("删除订单信息失败,影响行数为0,订单ID: {}", orderId);
                throw new BusinessException("删除订单信息失败");
            }
        } catch (Exception e) {
            log.error("取消订单失败,订单ID: {}", orderId, e);
            throw new BusinessException("取消订单失败:" + e.getMessage());
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWorkflowId(String orderId, String workflowId) {
        if (!StringUtils.hasText(orderId)) {
            throw new BusinessException("订单ID不能为空");
        }
        if (!StringUtils.hasText(workflowId)) {
            throw new BusinessException("工作流ID不能为空");
        }
        OrderInfo orderInfo = this.getById(orderId);
        if (orderInfo == null) {
            throw new BusinessException("订单不存在");
        }
        orderInfo.setWorkflowId(workflowId);
        orderInfo.setUpdatedAt(LocalDateTime.now());
        return this.updateById(orderInfo);
    }
    @Override
    public boolean existsCompletedNotCancelledOrderByProductId(String productId) {
        if (!StringUtils.hasText(productId)) {
            throw new BusinessException("产品ID不能为空");
        }
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("product_id", productId);
        // 未取消:逻辑未删除
        wrapper.eq("deleted", 0);
        // 审核中:状态不为 已完成 或 已取消
        wrapper.notIn("order_status", Arrays.asList("已完成", "已取消"));
        Integer count = this.baseMapper.selectCount(wrapper);
        return count != null && count > 0;
    }
}