Authored by chenchao

fix calculate rule

... ... @@ -27,6 +27,7 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import static com.yohoufo.order.charge.model.ChargeParam.*;
import static com.yohoufo.order.constants.ApiVersionConfig.ApiVersion;
... ... @@ -85,62 +86,72 @@ public class ChargeService {
private void chooseOptimal(ChargeContext context){
ChargeParam chargeParam = context.getChargeParam();
ChargeGoods chargeGoods = context.getChargeGoods();
int uid = chargeParam.getUid();
int skup = chargeGoods.getSkup();
List<ShoppingPromotion> useablePromotionList = chargeGoods.getUseablePromotionList();
ChargeResult chargeResult = context.getChargeResult();
Double finalAmountOfCutPromotion0 = chargeResult.getFinalAmountOfCutPromotion();
double oldFinalAmount = chargeResult.getFinalAmount();
//calculate promotion
List<ShoppingPromotion> useablePromotionList = chargeGoods.getUseablePromotionList();
Double cutAmountOfPromotion = chargeResult.getFinalAmountCutPromotion() == null ? 0D : chargeResult.getFinalAmountCutPromotion();
Supplier<Double> finalAmountAfterCutPromotionSupplier = () -> {
double finalAmountAfterCutPromotion = YHMath.sub(oldFinalAmount, cutAmountOfPromotion);
logger.info("chooseOptimal of coupons and promotions uid {} skup {} cutAmountOfPromotion {} finalAmountAfterCutPromotion {} useablePromotionList {}",
uid, skup, cutAmountOfPromotion, finalAmountAfterCutPromotion, useablePromotionList);
return finalAmountAfterCutPromotion;
};
//calulate coupons
//用券优惠的总金额
Double finalAmountOfCutCoupons = chargeResult.getFinalAmountOfCutCoupons();
boolean useActivityCoupon = Objects.nonNull(finalAmountOfCutCoupons);
Supplier<Double> finalAmountAfterCutCuponsSupplier = ()-> {
double finalAmountAfterCutCupons = useActivityCoupon ? YHMath.sub(oldFinalAmount, finalAmountOfCutCoupons) : chargeResult.getFinalAmount() ;
logger.info("chooseOptimal of coupons and promotions uid {} skup {} finalAmountAfterCutCupons {} finalAmountOfCutCupons {}",
uid, skup, finalAmountAfterCutCupons, finalAmountOfCutCoupons);
return finalAmountAfterCutCupons;
};
//做优惠力度比较
boolean existUseablePromotion = CollectionUtils.isNotEmpty(useablePromotionList);
Double finalAmountOfCutCoupons0 = chargeResult.getFinalAmountOfCutCoupons();
boolean useActivityCoupon = Objects.nonNull(finalAmountOfCutCoupons0);
double finalAmountOfCutCupons = useActivityCoupon ? finalAmountOfCutCoupons0.doubleValue() : chargeResult.getFinalAmount() ;
logger.info("chooseOptimal of coupons and promotions uid {} skup {} finalAmountOfCutPromotion {} finalAmountOfCutCupons {} useablePromotionList {}",
uid, skup, finalAmountOfCutPromotion0, finalAmountOfCutCoupons0, useablePromotionList);
double finalAmount;
PromotionMutexLock promotionMutexLock = new PromotionMutexLock();
//有促销时 尝试比较促销和优惠券计算的结果
if (existUseablePromotion){
int compareResult = finalAmountCompare(finalAmountOfCutPromotion0, finalAmountOfCutCoupons0);
if (compareResult < 0){
finalAmount = finalAmountOfCutPromotion0.doubleValue();
int compareResult = finalAmountCompare(cutAmountOfPromotion, finalAmountOfCutCoupons);
if (compareResult > 0){
finalAmount = finalAmountAfterCutPromotionSupplier.get();
promotionMutexLock.setUsePromotion(true);
}else if(compareResult == 0){
//相等有两种情况 1.两个都为空 2 都不为空
if (useActivityCoupon){
//not null -> equals
//优先推荐促销
finalAmount = finalAmountOfCutCupons;
promotionMutexLock.setUsePromotion(true);
finalAmount = finalAmountAfterCutCuponsSupplier.get();
promotionMutexLock.setUseActivityCoupons(true);
}else{
//equals by null
finalAmount = chargeResult.getFinalAmount();
finalAmount = oldFinalAmount;
}
}else {
finalAmount = finalAmountOfCutCupons;
finalAmount = finalAmountAfterCutCuponsSupplier.get();
promotionMutexLock.setUseActivityCoupons(true);
}
}else{
//没有促销时 直接使用券后价格
finalAmount = finalAmountOfCutCupons;
finalAmount = finalAmountAfterCutCuponsSupplier.get();
promotionMutexLock.setUseActivityCoupons(true);
}
logger.info("chooseOptimal of coupons and promotions uid {} skup {} finalAmountOfCutPromotion {} finalAmountOfCutCupons {} useablePromotionList {} finalAmount {}",
uid, skup, finalAmountOfCutPromotion0, finalAmountOfCutCupons, useablePromotionList, finalAmount);
logger.info("chooseOptimal of coupons and promotions uid {} skup {} finalAmountOfCutPromotion {} finalAmountOfCutCupons {} useablePromotionList {} oldfinal {} finalAmount {}",
uid, skup, cutAmountOfPromotion, finalAmountOfCutCoupons, useablePromotionList, oldFinalAmount, finalAmount);
final double minLimit = 0.01D;
if (finalAmount < minLimit){
logger.warn("chooseOptimal use protected action uid {} skup {} oldFinalAmount {} finalAmount {} cutAmountOfPromotion {} finalAmountOfCutCoupons {}",
uid, skup, oldFinalAmount, finalAmount, cutAmountOfPromotion, finalAmountOfCutCoupons);
finalAmount = minLimit;
}
chargeResult.setFinalAmount(finalAmount);
chargeResult.setPromotionMutexLock(promotionMutexLock);
//
}
... ... @@ -572,7 +583,14 @@ public class ChargeService {
double couponPayAmount = Math.min(chargeContext.getChargeGoods().getRealPrice().doubleValue(), activityCouponsBo.getCouponAmount().doubleValue());
double oldFinalAmount = chargeResult.getFinalAmount();
double newFinalAmount = YHMath.sub(oldFinalAmount, couponPayAmount);
chargeResult.setFinalAmountOfCutCoupons(newFinalAmount);
Double oldFinalAmountOfCutCoupons = chargeResult.getFinalAmountOfCutCoupons();
double newFinalAmountOfCutCoupons;
if (Objects.isNull(oldFinalAmountOfCutCoupons)){
newFinalAmountOfCutCoupons = couponPayAmount;
}else {
newFinalAmountOfCutCoupons = YHMath.add(oldFinalAmountOfCutCoupons, couponPayAmount);
}
chargeResult.setFinalAmountOfCutCoupons(newFinalAmountOfCutCoupons);
CouponPayResult couponPayResult = CouponPayResult.builder().couponCode(activityCouponsBo.getCouponCode())
.couponAmount(couponPayAmount).couponType(activityCouponsBo.getCouponType()).build();
logger.info("[{}] step activity coupon charge,oldFinalAmount:{},newFinalAmount of cut coupons:{}",
... ...
... ... @@ -64,11 +64,11 @@ public class ChargeResult {
}
/**
* 使用促销后最终实付金额
* 使用促销后优惠金额
*/
private Double finalAmountOfCutPromotion;
private Double finalAmountCutPromotion;
/**
* 使用优惠券后最终实付金额
* 使用优惠券后最终优惠金额
*/
private Double finalAmountOfCutCoupons;
/**
... ...
... ... @@ -148,12 +148,15 @@ public class PromotionService {
chargeGoods.setUseableFullPromotionList(fullPromotionList);
}
private void getAndSetFinalAmount(int uid, int skup,PromotionActivityRspBo promotionRsp, BigDecimal cutPromotion, ChargeResult chargeResult){
double finalAmountOfCutPromotion = getAndSetFinalAmountOfCutPromotion(chargeResult);
BigDecimal newFinalAmount = new BigDecimal(finalAmountOfCutPromotion).subtract(cutPromotion);
chargeResult.setFinalAmountOfCutPromotion(BigDecimalHelper.halfUp(newFinalAmount).doubleValue());
logger.info("match promotion calculate new final amount, uid {} skup {} promotionRsp {},finalAmountOfCutPromotion {} newFinalAmount {}",
uid, skup, promotionRsp, finalAmountOfCutPromotion, newFinalAmount);
private void getAndSetFinalAmount(int uid, int skup,
PromotionActivityRspBo promotionRsp,
BigDecimal cutPromotion,
ChargeResult chargeResult){
Double cutAmountPromotion = getAndSetCutAmountPromotion(chargeResult);
BigDecimal newFinalAmount = new BigDecimal(cutAmountPromotion).add(cutPromotion);
chargeResult.setFinalAmountCutPromotion(BigDecimalHelper.halfUp(newFinalAmount).doubleValue());
logger.info("match promotion calculate new final amount, uid {} skup {} promotionRsp {},cutAmountPromotion {} newFinalAmount {}",
uid, skup, promotionRsp, cutAmountPromotion, newFinalAmount);
}
... ... @@ -293,11 +296,11 @@ public class PromotionService {
return shoppingPromotion;
}
private double getAndSetFinalAmountOfCutPromotion(ChargeResult chargeResult){
Double finalAmountOfCutPromotion = chargeResult.getFinalAmountOfCutPromotion();
private Double getAndSetCutAmountPromotion(ChargeResult chargeResult){
Double finalAmountOfCutPromotion = chargeResult.getFinalAmountCutPromotion();
if (finalAmountOfCutPromotion == null){
chargeResult.setFinalAmountOfCutPromotion(finalAmountOfCutPromotion=chargeResult.getFinalAmount());
if (finalAmountOfCutPromotion == finalAmountOfCutPromotion){
finalAmountOfCutPromotion = 0D;
}
return finalAmountOfCutPromotion;
}
... ...