mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-07-05 14:38:06 +08:00
计算余额退款方法
This commit is contained in:
@@ -806,21 +806,43 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退保险
|
// 判断订单的支付方式
|
||||||
ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
|
String payMode = orderBasicInfo.getPayMode();
|
||||||
applyRefundDTO.setOrderCode(orderBasicInfo.getOrderCode());
|
if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue())) {
|
||||||
applyRefundDTO.setRefundType(Constants.ONE);
|
BigDecimal returnPrincipal = BigDecimal.ZERO;
|
||||||
applyRefundDTO.setRefundAmount(insuranceAmount);
|
BigDecimal returnGift = BigDecimal.ZERO;
|
||||||
applyRefundDTO.setMemberId(orderBasicInfo.getMemberId());
|
// 余额支付
|
||||||
applyRefundDTO.setScenarioType(ScenarioEnum.INSURANCE.getValue());
|
UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
|
||||||
|
.memberId(orderBasicInfo.getMemberId())
|
||||||
// 汇付退款需要一级运营商的小程序appId, 否则会退款失败
|
.targetMerchantId(orderBasicInfo.getMerchantId())
|
||||||
String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());
|
.type(MemberWalletEnum.TYPE_IN.getValue()) // 进账
|
||||||
if (StringUtils.isNotBlank(wechatAppId)) {
|
.subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款
|
||||||
applyRefundDTO.setWechatAppId(wechatAppId);
|
.updatePrincipalBalance(orderBasicInfo.getInsuranceAmount())
|
||||||
|
.updateGiftBalance(returnGift)
|
||||||
|
.relatedOrderCode(orderBasicInfo.getOrderCode())
|
||||||
|
.build();
|
||||||
|
// 更新会员钱包/余额退回到钱包
|
||||||
|
memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);
|
||||||
|
} else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
|
||||||
|
|| StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) {
|
||||||
|
// 在线支付
|
||||||
|
// 退保险
|
||||||
|
ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
|
||||||
|
applyRefundDTO.setOrderCode(orderBasicInfo.getOrderCode());
|
||||||
|
applyRefundDTO.setRefundType(Constants.ONE);
|
||||||
|
applyRefundDTO.setRefundAmount(insuranceAmount);
|
||||||
|
applyRefundDTO.setMemberId(orderBasicInfo.getMemberId());
|
||||||
|
applyRefundDTO.setScenarioType(ScenarioEnum.INSURANCE.getValue());
|
||||||
|
// 汇付退款需要一级运营商的小程序appId, 否则会退款失败
|
||||||
|
String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());
|
||||||
|
if (StringUtils.isNotBlank(wechatAppId)) {
|
||||||
|
applyRefundDTO.setWechatAppId(wechatAppId);
|
||||||
|
}
|
||||||
|
this.refundOrderWithAdapay(applyRefundDTO);
|
||||||
|
} else {
|
||||||
|
// 白名单支付或者ETC支付
|
||||||
|
logger.debug("订单:{}使用:{},不退保险费", orderBasicInfo.getOrderCode(), OrderPayModeEnum.getPayModeDescription(payMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refundOrderWithAdapay(applyRefundDTO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -799,6 +800,147 @@ public abstract class AbstractProgramLogic implements InitializingBean {
|
|||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额支付 计算需要退回的金额
|
||||||
|
* 【公共方法】
|
||||||
|
*
|
||||||
|
* @param principalPay 本金支付金额
|
||||||
|
* @param giftPay 赠送金额支付的金额
|
||||||
|
* @param orderAmount 订单消费金额
|
||||||
|
* @param discountAmount 订单折扣金额
|
||||||
|
* @param insuranceAmount 保险金额
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected static Map<String, BigDecimal> calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount, BigDecimal discountAmount, BigDecimal insuranceAmount) {
|
||||||
|
// 创建返回的Map
|
||||||
|
Map<String, BigDecimal> refundMap = new HashMap<>();
|
||||||
|
|
||||||
|
// 初始化所有返回值为0
|
||||||
|
refundMap.put("returnPrincipal", BigDecimal.ZERO);
|
||||||
|
refundMap.put("returnGift", BigDecimal.ZERO);
|
||||||
|
refundMap.put("returnPrincipalForInsurance", BigDecimal.ZERO);
|
||||||
|
refundMap.put("returnGiftForInsurance", BigDecimal.ZERO);
|
||||||
|
|
||||||
|
// 设置精度为2位小数
|
||||||
|
RoundingMode roundingMode = RoundingMode.HALF_UP;
|
||||||
|
int scale = 2;
|
||||||
|
|
||||||
|
// 1. 计算总支付金额和电费预付金额
|
||||||
|
BigDecimal totalPay = principalPay.add(giftPay).setScale(scale, roundingMode);
|
||||||
|
BigDecimal prepaidElectricity = totalPay.subtract(insuranceAmount).setScale(scale, roundingMode);
|
||||||
|
|
||||||
|
// 2. 计算实际电费消费金额(应用折扣)
|
||||||
|
BigDecimal actualConsume = orderAmount.subtract(discountAmount);
|
||||||
|
if (actualConsume.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
actualConsume = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
actualConsume = actualConsume.setScale(scale, roundingMode);
|
||||||
|
|
||||||
|
// 3. 计算电费应退款金额
|
||||||
|
BigDecimal electricityRefund = prepaidElectricity.subtract(actualConsume);
|
||||||
|
if (electricityRefund.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
electricityRefund = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
electricityRefund = electricityRefund.setScale(scale, roundingMode);
|
||||||
|
|
||||||
|
// 4. 判断保险是否退款(实际电费消费 < 1元时退还保险)
|
||||||
|
BigDecimal insuranceRefund = BigDecimal.ZERO;
|
||||||
|
boolean isInsuranceRefund = actualConsume.compareTo(new BigDecimal("1.00")) < 0;
|
||||||
|
if (isInsuranceRefund) {
|
||||||
|
insuranceRefund = insuranceAmount.setScale(scale, roundingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 计算电费退款中本金和赠金的部分(优先使用本金,退款时优先退回赠金)
|
||||||
|
BigDecimal remainingElectricityRefund = electricityRefund;
|
||||||
|
BigDecimal principalUsedForElectricity = BigDecimal.ZERO;
|
||||||
|
BigDecimal giftUsedForElectricity = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
// 5.1 计算本金和赠金在电费预付中的使用情况
|
||||||
|
if (prepaidElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
// 本金优先用于支付电费,最多不超过本金总额且不超过电费预付金额
|
||||||
|
principalUsedForElectricity = principalPay.min(prepaidElectricity);
|
||||||
|
principalUsedForElectricity = principalUsedForElectricity.setScale(scale, roundingMode);
|
||||||
|
|
||||||
|
// 剩余的电费预付由赠金支付
|
||||||
|
giftUsedForElectricity = prepaidElectricity.subtract(principalUsedForElectricity);
|
||||||
|
giftUsedForElectricity = giftUsedForElectricity.setScale(scale, roundingMode);
|
||||||
|
|
||||||
|
// 5.2 分配电费退款(优先退回赠金)
|
||||||
|
// 先退赠金支付的部分
|
||||||
|
if (giftUsedForElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal giftRefundForElectricity = remainingElectricityRefund.min(giftUsedForElectricity);
|
||||||
|
giftRefundForElectricity = giftRefundForElectricity.setScale(scale, roundingMode);
|
||||||
|
refundMap.put("returnGift", giftRefundForElectricity);
|
||||||
|
remainingElectricityRefund = remainingElectricityRefund.subtract(giftRefundForElectricity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剩余的电费退款退回到本金
|
||||||
|
if (remainingElectricityRefund.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal principalRefundForElectricity = remainingElectricityRefund.min(principalUsedForElectricity);
|
||||||
|
principalRefundForElectricity = principalRefundForElectricity.setScale(scale, roundingMode);
|
||||||
|
refundMap.put("returnPrincipal", principalRefundForElectricity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 计算保险退款中本金和赠金的部分
|
||||||
|
if (insuranceRefund.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
// 计算支付电费后剩余的本金和赠金
|
||||||
|
BigDecimal remainingPrincipalAfterElectricity = principalPay.subtract(refundMap.get("returnPrincipal"));
|
||||||
|
BigDecimal remainingGiftAfterElectricity = giftPay.subtract(refundMap.get("returnGift"));
|
||||||
|
|
||||||
|
// 保险支付顺序:优先使用剩余本金,不足部分用赠金
|
||||||
|
BigDecimal principalUsedForInsurance = remainingPrincipalAfterElectricity.min(insuranceAmount);
|
||||||
|
BigDecimal giftUsedForInsurance = insuranceAmount.subtract(principalUsedForInsurance);
|
||||||
|
|
||||||
|
// 保险退款(优先退回赠金部分)
|
||||||
|
BigDecimal remainingInsuranceRefund = insuranceRefund;
|
||||||
|
|
||||||
|
// 先退赠金支付的保险部分
|
||||||
|
if (giftUsedForInsurance.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal giftRefundForInsurance = remainingInsuranceRefund.min(giftUsedForInsurance);
|
||||||
|
giftRefundForInsurance = giftRefundForInsurance.setScale(scale, roundingMode);
|
||||||
|
refundMap.put("returnGiftForInsurance", giftRefundForInsurance);
|
||||||
|
remainingInsuranceRefund = remainingInsuranceRefund.subtract(giftRefundForInsurance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剩余的保险退款退回到本金
|
||||||
|
if (remainingInsuranceRefund.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
BigDecimal principalRefundForInsurance = remainingInsuranceRefund.min(principalUsedForInsurance);
|
||||||
|
principalRefundForInsurance = principalRefundForInsurance.setScale(scale, roundingMode);
|
||||||
|
refundMap.put("returnPrincipalForInsurance", principalRefundForInsurance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return refundMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BigDecimal principalPay = new BigDecimal("30");
|
||||||
|
BigDecimal giftPay = new BigDecimal("20");
|
||||||
|
BigDecimal orderAmount = new BigDecimal("0.8");
|
||||||
|
BigDecimal discountAmount = new BigDecimal("0");
|
||||||
|
BigDecimal insuranceAmount = new BigDecimal("0.0");
|
||||||
|
Map<String, BigDecimal> stringBigDecimalMap = calculateReturnAmount(principalPay, giftPay, orderAmount, discountAmount, insuranceAmount);
|
||||||
|
|
||||||
|
// 获取各项退款金额
|
||||||
|
BigDecimal returnPrincipal = stringBigDecimalMap.get("returnPrincipal");
|
||||||
|
BigDecimal returnGift = stringBigDecimalMap.get("returnGift");
|
||||||
|
BigDecimal returnPrincipalForInsurance = stringBigDecimalMap.get("returnPrincipalForInsurance");
|
||||||
|
BigDecimal returnGiftForInsurance = stringBigDecimalMap.get("returnGiftForInsurance");
|
||||||
|
|
||||||
|
// 计算总计
|
||||||
|
BigDecimal electricityRefund = returnPrincipal.add(returnGift);
|
||||||
|
BigDecimal insuranceRefund = returnPrincipalForInsurance.add(returnGiftForInsurance);
|
||||||
|
BigDecimal totalRefund = electricityRefund.add(insuranceRefund);
|
||||||
|
BigDecimal totalPrincipalRefund = returnPrincipal.add(returnPrincipalForInsurance);
|
||||||
|
BigDecimal totalGiftRefund = returnGift.add(returnGiftForInsurance);
|
||||||
|
|
||||||
|
String input = String.format("输入:本金%s元,赠金%s元,消费%s元,折扣%s元,保险%s元", principalPay, giftPay, orderAmount, discountAmount, insuranceAmount);
|
||||||
|
System.out.println(input);
|
||||||
|
String output = String.format("输出:%s元,赠金%s元,保险%s元,总退款%s元", returnPrincipal, returnGift, returnPrincipalForInsurance, returnGiftForInsurance, totalRefund);
|
||||||
|
System.out.println(output);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算解冻金额
|
* 计算解冻金额
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user