diff --git a/TestCalculateBalanceRefund.java b/TestCalculateBalanceRefund.java
new file mode 100644
index 000000000..7821e95e7
--- /dev/null
+++ b/TestCalculateBalanceRefund.java
@@ -0,0 +1,122 @@
+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/programlogic/AbstractProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java
index bf4e803bb..8902d1a5c 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
@@ -47,7 +47,7 @@ import java.util.stream.Collectors;
* 描述订单逻辑
*/
public abstract class AbstractProgramLogic implements InitializingBean {
- protected Logger logger = LoggerFactory.getLogger(this.getClass());
+ protected static Logger logger = LoggerFactory.getLogger(AbstractProgramLogic.class);
@Value("${adapay.callback}")
protected String ADAPAY_CALLBACK_URL;
@@ -1164,6 +1164,113 @@ public abstract class AbstractProgramLogic implements InitializingBean {
return valid1.compareTo(valid2) < 0 ? valid1 : valid2;
}
+ /**
+ * 计算余额退款(包含电费和保险费)
+ *
+ * 业务规则:
+ * 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保险费)
+ */
+ protected static 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;
+ }
+
+ public static void main(String[] args) {
+ BigDecimal principalPay = new BigDecimal("30.5");
+ BigDecimal giftPay = new BigDecimal("20");
+ BigDecimal orderAmount = new BigDecimal("10");
+ BigDecimal discountAmount = new BigDecimal("9.1");
+ BigDecimal insuranceAmount = new BigDecimal("0.5");
+
+ calculateBalanceRefund(principalPay, giftPay, orderAmount, discountAmount, insuranceAmount);
+
+ }//
+
/**
* 计算余额支付下发金额
* xixiao在用