liujie
2026-04-28 a4b9938d86ccbd870a49bf8ab3f03e62fdda82e1
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TExchangeCodePackageServiceImpl.java
@@ -356,6 +356,7 @@
        List<TExchangeCodeUseRecord> existingRecords = useRecordMapper.selectList(new QueryWrapper<TExchangeCodeUseRecord>()
                .eq("order_id", dto.getOrderId())
                .gt("order_id", 0)
                .eq("change_type", USE_RECORD_TYPE_CONSUME)
                .eq("del_flag", 0));
        if (!existingRecords.isEmpty()) {
            BigDecimal deducted = existingRecords.stream()
@@ -399,6 +400,70 @@
        return resultVO;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExchangeCodeConsumeResultVO refundBalance(ExchangeCodeConsumeDTO dto) {
        if (dto == null || dto.getUserId() == null || dto.getOrderId() == null || dto.getAmount() == null) {
            throw new ServiceException("????????");
        }
        ExchangeCodeConsumeResultVO resultVO = new ExchangeCodeConsumeResultVO();
        BigDecimal remainingRefund = dto.getAmount().setScale(2, RoundingMode.HALF_UP);
        if (remainingRefund.compareTo(BigDecimal.ZERO) <= 0) {
            resultVO.setDeductedAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
            return resultVO;
        }
        List<TExchangeCodeUseRecord> existingRecords = useRecordMapper.selectList(new QueryWrapper<TExchangeCodeUseRecord>()
                .eq("order_id", dto.getOrderId())
                .eq("change_type", USE_RECORD_TYPE_REFUND)
                .eq(dto.getRefundNo() != null && !dto.getRefundNo().isEmpty(), "refund_no", dto.getRefundNo())
                .eq("del_flag", 0));
        if (!existingRecords.isEmpty()) {
            BigDecimal refunded = existingRecords.stream()
                    .map(TExchangeCodeUseRecord::getUsedAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .setScale(2, RoundingMode.HALF_UP);
            resultVO.setDeductedAmount(refunded);
            return resultVO;
        }
        List<TExchangeCodeUseRecord> consumeRecords = useRecordMapper.selectList(new QueryWrapper<TExchangeCodeUseRecord>()
                .eq("order_id", dto.getOrderId())
                .eq("user_id", dto.getUserId())
                .eq("change_type", USE_RECORD_TYPE_CONSUME)
                .eq("del_flag", 0)
                .orderByDesc("id"));
        BigDecimal refundedAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        for (TExchangeCodeUseRecord consumeRecord : consumeRecords) {
            if (remainingRefund.compareTo(BigDecimal.ZERO) <= 0) {
                break;
            }
            if (consumeRecord.getDetailId() == null) {
                continue;
            }
            TExchangeCodeDetail detail = codeDetailMapper.selectById(consumeRecord.getDetailId());
            if (detail == null) {
                continue;
            }
            BigDecimal useAmount = defaultMoney(consumeRecord.getUsedAmount());
            BigDecimal refundAmount = remainingRefund.min(useAmount).setScale(2, RoundingMode.HALF_UP);
            detail.setUsedAmount(defaultMoney(detail.getUsedAmount()).subtract(refundAmount).max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP));
            codeDetailMapper.updateById(detail);
            TExchangeCodeUseRecord record = new TExchangeCodeUseRecord();
            record.setDetailId(detail.getId());
            record.setOrderId(dto.getOrderId());
            record.setRefundNo(dto.getRefundNo());
            record.setUserId(dto.getUserId());
            record.setChangeType(USE_RECORD_TYPE_REFUND);
            record.setUsedAmount(refundAmount);
            record.setGiftUsedAmount(calculateGiftUsedAmount(refundAmount, detail));
            useRecordMapper.insert(record);
            remainingRefund = remainingRefund.subtract(refundAmount);
            refundedAmount = refundedAmount.add(refundAmount);
        }
        resultVO.setDeductedAmount(refundedAmount.setScale(2, RoundingMode.HALF_UP));
        return resultVO;
    }
    private BigDecimal calculateGiftUsedAmount(BigDecimal useAmount, TExchangeCodeDetail detail) {
        if (useAmount == null || detail == null || detail.getGiftRatio() == null) {
            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);