| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | |
| | | final class ChargingCouponSupport { |
| | | public final class ChargingCouponSupport { |
| | | private static final BigDecimal TEN = new BigDecimal("10"); |
| | | private static final int WHITELIST_BENEFIT_ALL_FREE = 1; |
| | | private static final int WHITELIST_BENEFIT_ELECTRIC_FREE = 2; |
| | | private static final int WHITELIST_BENEFIT_SERVICE_FREE = 3; |
| | | |
| | | private ChargingCouponSupport() { |
| | | } |
| | | |
| | | static BigDecimal calculateUpfrontDiscount(TCoupon coupon, BigDecimal rechargeAmount) { |
| | | if (coupon == null || rechargeAmount == null || rechargeAmount.compareTo(BigDecimal.ZERO) <= 0) { |
| | | static BigDecimal calculatePrepaymentAmount(BigDecimal rechargeAmount, boolean whitelistAllFree) { |
| | | if (whitelistAllFree) { |
| | | return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | if (!Integer.valueOf(1).equals(coupon.getType())) { |
| | | throw new IllegalArgumentException("请选择充电优惠券"); |
| | | return money(rechargeAmount).setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | /** |
| | | * 兼容曾在预付阶段直接减掉优惠券金额的在途订单,退款基数不能超过真实收款。 |
| | | */ |
| | | static BigDecimal resolveSettlementPrepayment(BigDecimal rechargeAmount, |
| | | BigDecimal balancePayAmount, |
| | | BigDecimal thirdPayAmount, |
| | | BigDecimal upfrontCouponDiscount) { |
| | | BigDecimal recharge = money(rechargeAmount); |
| | | BigDecimal collected = money(balancePayAmount).add(money(thirdPayAmount)); |
| | | if (money(upfrontCouponDiscount).compareTo(BigDecimal.ZERO) > 0 |
| | | && collected.compareTo(BigDecimal.ZERO) > 0 |
| | | && collected.compareTo(recharge) < 0) { |
| | | return collected; |
| | | } |
| | | BigDecimal threshold = coupon.getMeetTheConditions() == null |
| | | ? BigDecimal.ZERO : coupon.getMeetTheConditions(); |
| | | if (rechargeAmount.compareTo(threshold) < 0) { |
| | | throw new IllegalArgumentException("预付金额未达到优惠券使用门槛"); |
| | | return recharge; |
| | | } |
| | | |
| | | /** |
| | | * 优惠券只在充电结束时结算,且优惠金额不能超过剩余服务费。 |
| | | */ |
| | | static BigDecimal calculateSettlementDiscount(TCoupon coupon, |
| | | BigDecimal actualAmountBeforeCoupon, |
| | | BigDecimal remainingServiceCharge) { |
| | | BigDecimal actualAmount = money(actualAmountBeforeCoupon); |
| | | BigDecimal serviceCharge = money(remainingServiceCharge); |
| | | if (coupon == null || actualAmount.compareTo(BigDecimal.ZERO) <= 0 |
| | | || serviceCharge.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return BigDecimal.ZERO.setScale(4, RoundingMode.HALF_EVEN); |
| | | } |
| | | BigDecimal threshold = money(coupon.getMeetTheConditions()); |
| | | if (actualAmount.compareTo(threshold) < 0) { |
| | | return BigDecimal.ZERO.setScale(4, RoundingMode.HALF_EVEN); |
| | | } |
| | | |
| | | BigDecimal discount; |
| | | BigDecimal discount = BigDecimal.ZERO; |
| | | if (Integer.valueOf(1).equals(coupon.getPreferentialMode())) { |
| | | discount = coupon.getDiscountAmount(); |
| | | } else if (Integer.valueOf(2).equals(coupon.getPreferentialMode())) { |
| | | if (coupon.getDiscount() == null) { |
| | | throw new IllegalArgumentException("优惠券折扣配置无效"); |
| | | } |
| | | discount = rechargeAmount.multiply(TEN.subtract(coupon.getDiscount())) |
| | | .divide(TEN, 2, RoundingMode.HALF_UP); |
| | | discount = money(coupon.getDiscountAmount()); |
| | | } else if (Integer.valueOf(2).equals(coupon.getPreferentialMode()) && coupon.getDiscount() != null) { |
| | | discount = actualAmount.multiply(TEN.subtract(coupon.getDiscount())).divide(TEN); |
| | | if (coupon.getMaximumDiscountAmount() != null) { |
| | | discount = discount.min(coupon.getMaximumDiscountAmount()); |
| | | } |
| | | } else { |
| | | throw new IllegalArgumentException("优惠券优惠方式无效"); |
| | | } |
| | | if (discount == null || discount.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new IllegalArgumentException("优惠券优惠金额无效"); |
| | | return discount.max(BigDecimal.ZERO).min(serviceCharge).setScale(4, RoundingMode.HALF_EVEN); |
| | | } |
| | | |
| | | public static BigDecimal[] calculateWhitelistRefundSplitByBenefitType(boolean whitelistOrder, |
| | | Integer whitelistBenefitType, |
| | | BigDecimal electrovalence, |
| | | BigDecimal serviceCharge) { |
| | | BigDecimal electricDiscount = BigDecimal.ZERO; |
| | | BigDecimal serviceDiscount = BigDecimal.ZERO; |
| | | if (!whitelistOrder) { |
| | | return new BigDecimal[]{electricDiscount, serviceDiscount}; |
| | | } |
| | | return discount.min(rechargeAmount).setScale(2, RoundingMode.HALF_UP); |
| | | if (Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(whitelistBenefitType)) { |
| | | electricDiscount = money(electrovalence); |
| | | serviceDiscount = money(serviceCharge); |
| | | } else if (Integer.valueOf(WHITELIST_BENEFIT_ELECTRIC_FREE).equals(whitelistBenefitType)) { |
| | | electricDiscount = money(electrovalence); |
| | | } else if (Integer.valueOf(WHITELIST_BENEFIT_SERVICE_FREE).equals(whitelistBenefitType)) { |
| | | serviceDiscount = money(serviceCharge); |
| | | } |
| | | return new BigDecimal[]{electricDiscount, serviceDiscount}; |
| | | } |
| | | |
| | | private static BigDecimal money(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | } |