From 390c4247e81e57e5a8f154e38590ddbe53c6a49f Mon Sep 17 00:00:00 2001 From: Guoqs <123@jsowell.com> Date: Wed, 17 Dec 2025 09:24:50 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E9=80=80=E4=BF=9D=E9=99=A9=E8=B4=B9?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TestCalculateBalanceRefund.java | 122 ------------------ .../pile/service/OrderPayRecordService.java | 3 + .../impl/MemberBasicInfoServiceImpl.java | 6 + .../impl/OrderBasicInfoServiceImpl.java | 112 +++++++++++++++- .../impl/OrderPayRecordServiceImpl.java | 36 ++++++ .../programlogic/AbstractProgramLogic.java | 6 +- 6 files changed, 156 insertions(+), 129 deletions(-) delete mode 100644 TestCalculateBalanceRefund.java diff --git a/TestCalculateBalanceRefund.java b/TestCalculateBalanceRefund.java deleted file mode 100644 index 7821e95e7..000000000 --- a/TestCalculateBalanceRefund.java +++ /dev/null @@ -1,122 +0,0 @@ -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; - -public class TestCalculateBalanceRefund { - - /** - * 计算余额退款(包含电费和保险费) - *

- * 业务规则: - * 1. 总支付金额 = principalPay + giftPay - * 2. 电费预付款 = 总支付金额 - insuranceAmount - * 3. 实际电费消费金额 = orderAmount - discountAmount - * 4. 支付时优先使用本金,消费时也优先扣除本金 - * 5. 保险费优先从本金中扣除 - * 6. 电费实际消费金额 > 1 时,保险费不退;否则需要退保险费 - * - * @param principalPay 本金支付金额 - * @param giftPay 赠金支付金额 - * @param orderAmount 消费金额 - * @param discountAmount 折扣金额 - * @param insuranceAmount 保险费金额 - * @return Map包含:returnPrincipal(本金退款for电费),returnGift(赠金退款for电费), - * returnPrincipalForInsurance(本金退款for保险费),returnGiftForInsurance(赠金退款for保险费) - */ - protected static Map calculateBalanceRefund(BigDecimal principalPay, BigDecimal giftPay, - BigDecimal orderAmount, BigDecimal discountAmount, - BigDecimal insuranceAmount) { - Map resultMap = new HashMap<>(); - - // 参数校验,null值处理为0 - principalPay = principalPay == null ? BigDecimal.ZERO : principalPay; - giftPay = giftPay == null ? BigDecimal.ZERO : giftPay; - orderAmount = orderAmount == null ? BigDecimal.ZERO : orderAmount; - discountAmount = discountAmount == null ? BigDecimal.ZERO : discountAmount; - insuranceAmount = insuranceAmount == null ? BigDecimal.ZERO : insuranceAmount; - - // 总支付金额 - BigDecimal totalPay = principalPay.add(giftPay); - - // 电费预付款 = 总支付金额 - 保险费 - BigDecimal electricityPrepayment = totalPay.subtract(insuranceAmount); - - // 实际电费消费金额 = 消费金额 - 折扣金额 - BigDecimal actualElectricityConsumption = orderAmount.subtract(discountAmount); - if (actualElectricityConsumption.compareTo(BigDecimal.ZERO) < 0) { - actualElectricityConsumption = BigDecimal.ZERO; - } - - // 支付时优先用本金,保险费全部从本金中扣除 - // 本金用于保险费的部分(优先从本金扣除保险费) - BigDecimal principalForInsurance = principalPay.min(insuranceAmount); - // 赠金用于保险费的部分(如果本金不够支付保险费,从赠金中扣除) - BigDecimal giftForInsurance = insuranceAmount.subtract(principalForInsurance); - if (giftForInsurance.compareTo(BigDecimal.ZERO) < 0) { - giftForInsurance = BigDecimal.ZERO; - } - // 本金用于电费的部分 = 总本金 - 本金用于保险费的部分 - BigDecimal principalForElectricity = principalPay.subtract(principalForInsurance); - // 赠金用于电费的部分 = 总赠金 - 赠金用于保险费的部分 - BigDecimal giftForElectricity = giftPay.subtract(giftForInsurance); - - // 计算电费退款(消费时优先扣除本金) - BigDecimal principalConsumed = principalForElectricity.min(actualElectricityConsumption); - BigDecimal giftConsumed = actualElectricityConsumption.subtract(principalConsumed); - if (giftConsumed.compareTo(BigDecimal.ZERO) < 0) { - giftConsumed = BigDecimal.ZERO; - } - - // 电费退款 - BigDecimal returnPrincipal = principalForElectricity.subtract(principalConsumed); - BigDecimal returnGift = giftForElectricity.subtract(giftConsumed); - if (returnPrincipal.compareTo(BigDecimal.ZERO) < 0) { - returnPrincipal = BigDecimal.ZERO; - } - if (returnGift.compareTo(BigDecimal.ZERO) < 0) { - returnGift = BigDecimal.ZERO; - } - - // 计算保险费退款:电费实际消费金额 > 1 时,保险费不退;否则需要退保险费 - BigDecimal returnPrincipalForInsurance = BigDecimal.ZERO; - BigDecimal returnGiftForInsurance = BigDecimal.ZERO; - - if (actualElectricityConsumption.compareTo(BigDecimal.ONE) <= 0) { - // 需要退保险费 - returnPrincipalForInsurance = principalForInsurance; - returnGiftForInsurance = giftForInsurance; - } - - resultMap.put("returnPrincipal", returnPrincipal); - resultMap.put("returnGift", returnGift); - resultMap.put("returnPrincipalForInsurance", returnPrincipalForInsurance); - resultMap.put("returnGiftForInsurance", returnGiftForInsurance); - - System.out.println("计算余额退款: 本金支付=" + principalPay + ", 赠金支付=" + giftPay + - ", 消费金额=" + orderAmount + ", 折扣金额=" + discountAmount + - ", 保险费=" + insuranceAmount + ", 实际电费消费=" + actualElectricityConsumption + - ", 电费退款(本金=" + returnPrincipal + ", 赠金=" + returnGift + - "), 保险费退款(本金=" + returnPrincipalForInsurance + ", 赠金=" + returnGiftForInsurance + ")"); - - return resultMap; - } - - public static void main(String[] args) { - System.out.println("测试用例1: 本金30.5, 赠金20, 消费10, 折扣0, 保险费0.5"); - BigDecimal principalPay = new BigDecimal("30.5"); - BigDecimal giftPay = new BigDecimal("20"); - BigDecimal orderAmount = new BigDecimal("10"); - BigDecimal discountAmount = new BigDecimal("0"); - BigDecimal insuranceAmount = new BigDecimal("0.5"); - - Map result = calculateBalanceRefund(principalPay, giftPay, orderAmount, discountAmount, insuranceAmount); - System.out.println("结果: " + result); - System.out.println(); - - System.out.println("期望结果: 电费退款(本金=20.5, 赠金=19.5), 保险费退款(本金=0, 赠金=0)"); - System.out.println("实际结果: 电费退款(本金=" + result.get("returnPrincipal") + - ", 赠金=" + result.get("returnGift") + - "), 保险费退款(本金=" + result.get("returnPrincipalForInsurance") + - ", 赠金=" + result.get("returnGiftForInsurance") + ")"); - } -} \ No newline at end of file diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderPayRecordService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderPayRecordService.java index f19e22a86..aa9712e80 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderPayRecordService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderPayRecordService.java @@ -7,6 +7,7 @@ import com.jsowell.pile.vo.web.OrderDetailInfoVO; import java.math.BigDecimal; import java.util.List; +import java.util.Map; public interface OrderPayRecordService{ @@ -32,6 +33,8 @@ public interface OrderPayRecordService{ List getOrderPayRecordList(String orderCode); + Map selectOrderBalancePayInfoList(String orderCode); + List queryPaymentInfosByOrderCode(String orderCode); List selectOrderPayRecordList(String orderCode); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java index 4a364c152..a4e048af8 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java @@ -216,6 +216,12 @@ public class MemberBasicInfoServiceImpl implements MemberBasicInfoService { return 0; } + // 为0也返回 + if (BigDecimal.ZERO.compareTo(updateGiftBalance) == 0 && BigDecimal.ZERO.compareTo(updatePrincipalBalance) == 0) { + log.info("修改用户余额-金额为0, 直接返回:{}", JSON.toJSONString(dto)); + return 0; + } + // 没有传过来目标运营商,有可能是希晓的小程序在线充值 if (StringUtils.isBlank(dto.getTargetMerchantId())) { // 根据memberId查询会员信息 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 6b48c614e..0375336f3 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -809,16 +809,24 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { // 判断订单的支付方式 String payMode = orderBasicInfo.getPayMode(); if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue())) { - BigDecimal returnPrincipal = BigDecimal.ZERO; - BigDecimal returnGift = BigDecimal.ZERO; + // 查询余额支付订单的支付明细 + Map balancePayMap = orderPayRecordService.selectOrderBalancePayInfoList(orderBasicInfo.getOrderCode()); + BigDecimal principalPay = balancePayMap.get("principalPay"); + BigDecimal giftPay = balancePayMap.get("giftPay"); + + // 计算退保金额 + Map refundMap = calculateBalanceRefund(principalPay, giftPay, orderBasicInfo.getOrderAmount(), orderBasicInfo.getDiscountAmount(), insuranceAmount); + BigDecimal returnPrincipalForInsurance = refundMap.get("returnPrincipalForInsurance"); + BigDecimal returnGiftForInsurance = refundMap.get("returnGiftForInsurance"); + // 余额支付 UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() .memberId(orderBasicInfo.getMemberId()) .targetMerchantId(orderBasicInfo.getMerchantId()) .type(MemberWalletEnum.TYPE_IN.getValue()) // 进账 .subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款 - .updatePrincipalBalance(orderBasicInfo.getInsuranceAmount()) - .updateGiftBalance(returnGift) + .updatePrincipalBalance(returnPrincipalForInsurance) + .updateGiftBalance(returnGiftForInsurance) .relatedOrderCode(orderBasicInfo.getOrderCode()) .build(); // 更新会员钱包/余额退回到钱包 @@ -845,6 +853,102 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { } } + /** + * 计算余额退款(包含电费和保险费) + *

+ * 业务规则: + * 1. 总支付金额 = principalPay + giftPay + * 2. 电费预付款 = 总支付金额 - insuranceAmount + * 3. 实际电费消费金额 = orderAmount - discountAmount + * 4. 支付时优先使用本金,消费时也优先扣除本金 + * 5. 电费实际消费金额 > 1 时,保险费不退;否则需要退保险费 + * + * @param principalPay 本金支付金额 + * @param giftPay 赠金支付金额 + * @param orderAmount 消费金额 + * @param discountAmount 折扣金额 + * @param insuranceAmount 保险费金额 + * @return Map包含:returnPrincipal(本金退款for电费),returnGift(赠金退款for电费), + * returnPrincipalForInsurance(本金退款for保险费),returnGiftForInsurance(赠金退款for保险费) + */ + private Map calculateBalanceRefund(BigDecimal principalPay, BigDecimal giftPay, + BigDecimal orderAmount, BigDecimal discountAmount, + BigDecimal insuranceAmount) { + Map resultMap = Maps.newHashMap(); + + // 参数校验,null值处理为0 + principalPay = principalPay == null ? BigDecimal.ZERO : principalPay; + giftPay = giftPay == null ? BigDecimal.ZERO : giftPay; + orderAmount = orderAmount == null ? BigDecimal.ZERO : orderAmount; + discountAmount = discountAmount == null ? BigDecimal.ZERO : discountAmount; + insuranceAmount = insuranceAmount == null ? BigDecimal.ZERO : insuranceAmount; + + // 总支付金额 + BigDecimal totalPay = principalPay.add(giftPay); + + // 电费预付款 = 总支付金额 - 保险费 + BigDecimal electricityPrepayment = totalPay.subtract(insuranceAmount); + + // 实际电费消费金额 = 消费金额 - 折扣金额 + BigDecimal actualElectricityConsumption = orderAmount.subtract(discountAmount); + if (actualElectricityConsumption.compareTo(BigDecimal.ZERO) < 0) { + actualElectricityConsumption = BigDecimal.ZERO; + } + + // 支付时优先用本金,保险费全部从本金中扣除 + // 本金用于保险费的部分(优先从本金扣除保险费) + BigDecimal principalForInsurance = principalPay.min(insuranceAmount); + // 赠金用于保险费的部分(如果本金不够支付保险费,从赠金中扣除) + BigDecimal giftForInsurance = insuranceAmount.subtract(principalForInsurance); + if (giftForInsurance.compareTo(BigDecimal.ZERO) < 0) { + giftForInsurance = BigDecimal.ZERO; + } + // 本金用于电费的部分 = 总本金 - 本金用于保险费的部分 + BigDecimal principalForElectricity = principalPay.subtract(principalForInsurance); + // 赠金用于电费的部分 = 总赠金 - 赠金用于保险费的部分 + BigDecimal giftForElectricity = giftPay.subtract(giftForInsurance); + + // 计算电费退款(消费时优先扣除本金) + BigDecimal principalConsumed = principalForElectricity.min(actualElectricityConsumption); + BigDecimal giftConsumed = actualElectricityConsumption.subtract(principalConsumed); + if (giftConsumed.compareTo(BigDecimal.ZERO) < 0) { + giftConsumed = BigDecimal.ZERO; + } + + // 电费退款 + BigDecimal returnPrincipal = principalForElectricity.subtract(principalConsumed); + BigDecimal returnGift = giftForElectricity.subtract(giftConsumed); + if (returnPrincipal.compareTo(BigDecimal.ZERO) < 0) { + returnPrincipal = BigDecimal.ZERO; + } + if (returnGift.compareTo(BigDecimal.ZERO) < 0) { + returnGift = BigDecimal.ZERO; + } + + // 计算保险费退款:电费实际消费金额 > 1 时,保险费不退;否则需要退保险费 + BigDecimal returnPrincipalForInsurance = BigDecimal.ZERO; + BigDecimal returnGiftForInsurance = BigDecimal.ZERO; + + if (actualElectricityConsumption.compareTo(BigDecimal.ONE) < 0) { + // 需要退保险费 + returnPrincipalForInsurance = principalForInsurance; + returnGiftForInsurance = giftForInsurance; + } + + resultMap.put("returnPrincipal", returnPrincipal); + resultMap.put("returnGift", returnGift); + resultMap.put("returnPrincipalForInsurance", returnPrincipalForInsurance); + resultMap.put("returnGiftForInsurance", returnGiftForInsurance); + + logger.info("计算余额退款: 本金支付={}, 赠金支付={}, 消费金额={}, 折扣金额={}, 保险费={}, " + + "实际电费消费={}, 电费退款(本金={}, 赠金={}), 保险费退款(本金={}, 赠金={})", + principalPay, giftPay, orderAmount, discountAmount, insuranceAmount, + actualElectricityConsumption, returnPrincipal, returnGift, + returnPrincipalForInsurance, returnGiftForInsurance); + + return resultMap; + } + /** * 查询充电中的订单,没有数据权限校验,后管不要用 * diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderPayRecordServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderPayRecordServiceImpl.java index 1126a8a3f..626d6fab4 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderPayRecordServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderPayRecordServiceImpl.java @@ -3,6 +3,7 @@ package com.jsowell.pile.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.jsowell.adapay.vo.PaymentInfo; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; @@ -30,6 +31,7 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -80,6 +82,40 @@ public class OrderPayRecordServiceImpl implements OrderPayRecordService { return orderPayRecordMapper.getOrderPayRecordList(orderCode); } + /** + * 查询余额支付订单的支付明细 + * @param orderCode + * @return + */ + @Override + public Map selectOrderBalancePayInfoList(String orderCode) { + Map resultMap = Maps.newHashMap(); + // 查询余额支付订单的支付明细 + List payRecordList = this.getOrderPayRecordList(orderCode); + + // 根据payMode分组 + Map> payRecordMap = payRecordList.stream() + .collect(Collectors.groupingBy(OrderPayRecord::getPayMode)); + + // 获取本金支付的记录 + List principalPayRecordList = payRecordMap.get(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()); + BigDecimal principalPay = BigDecimal.ZERO; + if (CollectionUtils.isNotEmpty(principalPayRecordList)) { + principalPay = principalPayRecordList.stream().map(OrderPayRecord::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + // 获取赠送金支付的记录 + List giftPayRecordList = payRecordMap.get(OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue()); + BigDecimal giftPay = BigDecimal.ZERO; + if (CollectionUtils.isNotEmpty(giftPayRecordList)) { + giftPay = giftPayRecordList.stream().map(OrderPayRecord::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + } + resultMap.put("principalPay", principalPay); + resultMap.put("giftPay", giftPay); + return resultMap; + } + + @Override public List queryPaymentInfosByOrderCode(String orderCode) { List resultList = Lists.newArrayList(); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java index 8902d1a5c..ea8c73f45 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java @@ -1240,7 +1240,7 @@ public abstract class AbstractProgramLogic implements InitializingBean { BigDecimal returnPrincipalForInsurance = BigDecimal.ZERO; BigDecimal returnGiftForInsurance = BigDecimal.ZERO; - if (actualElectricityConsumption.compareTo(BigDecimal.ONE) <= 0) { + if (actualElectricityConsumption.compareTo(BigDecimal.ONE) < 0) { // 需要退保险费 returnPrincipalForInsurance = principalForInsurance; returnGiftForInsurance = giftForInsurance; @@ -1264,12 +1264,12 @@ public abstract class AbstractProgramLogic implements InitializingBean { BigDecimal principalPay = new BigDecimal("30.5"); BigDecimal giftPay = new BigDecimal("20"); BigDecimal orderAmount = new BigDecimal("10"); - BigDecimal discountAmount = new BigDecimal("9.1"); + BigDecimal discountAmount = new BigDecimal("9.0"); BigDecimal insuranceAmount = new BigDecimal("0.5"); calculateBalanceRefund(principalPay, giftPay, orderAmount, discountAmount, insuranceAmount); - }// + } /** * 计算余额支付下发金额