Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop
This commit is contained in:
commit
2e8c40bcf3
@ -296,4 +296,13 @@ public interface GoodsSkuService extends IService<GoodsSku> {
|
|||||||
* @return 库存数量
|
* @return 库存数量
|
||||||
*/
|
*/
|
||||||
Integer getGoodsStock(String goodsId);
|
Integer getGoodsStock(String goodsId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新sku运费模版
|
||||||
|
*
|
||||||
|
* @param goodsId 商品id
|
||||||
|
* @param templateId 运费模版id
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
Boolean freight(List<String> goodsId, String templateId);
|
||||||
}
|
}
|
@ -437,6 +437,7 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements
|
|||||||
lambdaUpdateWrapper.in(Goods::getId, goodsIds);
|
lambdaUpdateWrapper.in(Goods::getId, goodsIds);
|
||||||
List<String> goodsCache = goodsIds.stream().map(item -> CachePrefix.GOODS.getPrefix() + item).collect(Collectors.toList());
|
List<String> goodsCache = goodsIds.stream().map(item -> CachePrefix.GOODS.getPrefix() + item).collect(Collectors.toList());
|
||||||
cache.multiDel(goodsCache);
|
cache.multiDel(goodsCache);
|
||||||
|
goodsSkuService.freight(goodsIds, templateId);
|
||||||
return this.update(lambdaUpdateWrapper);
|
return this.update(lambdaUpdateWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,6 +888,17 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean freight(List<String> goodsId, String templateId) {
|
||||||
|
LambdaUpdateWrapper<GoodsSku> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.in(GoodsSku::getGoodsId, goodsId);
|
||||||
|
updateWrapper.set(GoodsSku::getFreightTemplateId, templateId);
|
||||||
|
updateWrapper.set(GoodsSku::getUpdateTime, new Date());
|
||||||
|
List<String> skuIds = this.list(updateWrapper).stream().map(GoodsSku::getId).collect(Collectors.toList());
|
||||||
|
skuIds.forEach(this::clearCache);
|
||||||
|
return this.update(updateWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染商品sku
|
* 渲染商品sku
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.lili.modules.order.cart.render.util;
|
package cn.lili.modules.order.cart.render.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.lili.common.enums.PromotionTypeEnum;
|
import cn.lili.common.enums.PromotionTypeEnum;
|
||||||
import cn.lili.common.utils.CurrencyUtil;
|
import cn.lili.common.utils.CurrencyUtil;
|
||||||
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
|
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
|
||||||
@ -10,7 +11,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 促销价格计算业务层实现
|
* 促销价格计算业务层实现
|
||||||
@ -33,7 +35,7 @@ public class PromotionPriceUtil {
|
|||||||
PromotionTypeEnum promotionTypeEnum, String activityId) {
|
PromotionTypeEnum promotionTypeEnum, String activityId) {
|
||||||
|
|
||||||
// sku 促销信息非空判定
|
// sku 促销信息非空判定
|
||||||
if (skuPromotionDetail == null || skuPromotionDetail.size() == 0) {
|
if (skuPromotionDetail == null || skuPromotionDetail.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,40 +70,39 @@ public class PromotionPriceUtil {
|
|||||||
List<CartSkuVO> skuVOList = tradeDTO.getSkuList();
|
List<CartSkuVO> skuVOList = tradeDTO.getSkuList();
|
||||||
|
|
||||||
// 获取map分配sku的总数,如果是最后一个商品分配金额,则将金额从百分比改为总金额扣减,避免出现小数除不尽
|
// 获取map分配sku的总数,如果是最后一个商品分配金额,则将金额从百分比改为总金额扣减,避免出现小数除不尽
|
||||||
int count = skuPromotionDetail.size();
|
AtomicInteger count = new AtomicInteger(skuPromotionDetail.size());
|
||||||
|
|
||||||
//已优惠金额
|
//已优惠金额
|
||||||
Double deducted = 0D;
|
AtomicReference<Double> deducted = new AtomicReference<>(0D);
|
||||||
|
|
||||||
for (String skuId : skuPromotionDetail.keySet()) {
|
for (String skuId : skuPromotionDetail.keySet()) {
|
||||||
|
|
||||||
//获取对应商品进行计算
|
//获取对应商品进行计算
|
||||||
for (CartSkuVO cartSkuVO : skuVOList) {
|
|
||||||
|
|
||||||
if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
|
Double finalDiscountPrice = discountPrice;
|
||||||
|
Double finalTotalPrice = totalPrice;
|
||||||
|
skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuId)).findFirst().ifPresent(cartSkuVO -> {
|
||||||
|
//sku 优惠金额
|
||||||
|
Double skuDiscountPrice;
|
||||||
|
count.getAndDecrement();
|
||||||
|
|
||||||
count--;
|
//非最后一个商品,则按照比例计算
|
||||||
|
if (count.get() > 0) {
|
||||||
//sku 优惠金额
|
//商品金额占比
|
||||||
Double skuDiscountPrice;
|
double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4);
|
||||||
|
//商品优惠金额
|
||||||
//非最后一个商品,则按照比例计算
|
skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point);
|
||||||
if (count > 0) {
|
//累加已优惠金额
|
||||||
//商品金额占比
|
deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice));
|
||||||
double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4);
|
|
||||||
//商品优惠金额
|
|
||||||
skuDiscountPrice = CurrencyUtil.mul(discountPrice, point);
|
|
||||||
//累加已优惠金额
|
|
||||||
deducted = CurrencyUtil.add(deducted, skuDiscountPrice);
|
|
||||||
}
|
|
||||||
// 如果是最后一个商品 则减去之前优惠的金额来进行计算
|
|
||||||
else {
|
|
||||||
skuDiscountPrice = CurrencyUtil.sub(discountPrice, deducted);
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId);
|
|
||||||
}
|
}
|
||||||
}
|
// 如果是最后一个商品 则减去之前优惠的金额来进行计算
|
||||||
|
else {
|
||||||
|
skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateNotEnoughPromotionsPrice(skuVOList, skuPromotionDetail, discountPrice, totalPrice, promotionTypeEnum, activityId);
|
calculateNotEnoughPromotionsPrice(skuVOList, skuPromotionDetail, discountPrice, totalPrice, promotionTypeEnum, activityId);
|
||||||
@ -186,51 +187,100 @@ public class PromotionPriceUtil {
|
|||||||
// 特殊情况处理,如参与多个促销活动,部分商品在其他促销计算后的金额不足以满足与当前参与的促销活动的优惠金额
|
// 特殊情况处理,如参与多个促销活动,部分商品在其他促销计算后的金额不足以满足与当前参与的促销活动的优惠金额
|
||||||
// 但当前购物车内存在当前当前促销活动的其他商品且剩余金额也满足分摊不足商品的不足金额,则分摊到其他商品上
|
// 但当前购物车内存在当前当前促销活动的其他商品且剩余金额也满足分摊不足商品的不足金额,则分摊到其他商品上
|
||||||
// 满足当前促销的总优惠金额
|
// 满足当前促销的总优惠金额
|
||||||
if (skuPromotionDetail == null || skuPromotionDetail.isEmpty()) {
|
if (skuPromotionDetail == null || skuPromotionDetail.size() < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clone skuPromotionDetail
|
||||||
|
Map<String, Double> skuPromotionDetailClone = MapUtil.sortByValue(skuPromotionDetail, false);
|
||||||
|
|
||||||
|
// 未满足优惠金额的商品
|
||||||
long matchPromotionsZeroCount =
|
long matchPromotionsZeroCount =
|
||||||
skuVOList.stream().filter(l -> l.getPriceDetailDTO().getFlowPrice() == 0 && skuPromotionDetail.containsKey(l.getGoodsSku().getId())).count();
|
skuVOList.stream().filter(l -> l.getPriceDetailDTO().getFlowPrice() == 0 && skuPromotionDetailClone.containsKey(l.getGoodsSku().getId())).count();
|
||||||
long matchPromotionsCount = skuVOList.stream().filter(l -> skuPromotionDetail.containsKey(l.getGoodsSku().getId())).count();
|
// 参与当前促销活动的商品
|
||||||
|
long matchPromotionsCount = skuVOList.stream().filter(l -> skuPromotionDetailClone.containsKey(l.getGoodsSku().getId())).count();
|
||||||
if (matchPromotionsZeroCount == matchPromotionsCount) {
|
if (matchPromotionsZeroCount == matchPromotionsCount) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 获取剩余金额不足优惠金额的商品
|
// 分配到其他商品的优惠金额
|
||||||
List<CartSkuVO> unEnoughSku = skuVOList.stream().filter(k -> {
|
AtomicReference<Double> balance = new AtomicReference<>(0D);
|
||||||
if (skuPromotionDetail.containsKey(k.getGoodsSku().getId()) && skuPromotionDetail.size() >= 2) {
|
StringBuilder lastSkuId = new StringBuilder();
|
||||||
//商品金额占比
|
|
||||||
double point = CurrencyUtil.div(k.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4);
|
// 计数器
|
||||||
//商品优惠金额
|
int count = 0;
|
||||||
Double skuDiscountPrice = CurrencyUtil.mul(discountPrice, point);
|
|
||||||
return k.getPriceDetailDTO().getCouponPrice() > 0 && skuDiscountPrice > k.getPriceDetailDTO().getCouponPrice();
|
|
||||||
|
// 检查是否有不满足优惠金额的商品
|
||||||
|
filterEnoughSku(skuVOList, skuPromotionDetailClone, discountPrice, totalPrice, balance, lastSkuId, promotionTypeEnum, activityId);
|
||||||
|
|
||||||
|
// 循环 优惠金额分摊,直到所有商品都满足优惠金额
|
||||||
|
while (true) {
|
||||||
|
// 如果还有剩余金额,则继续分摊
|
||||||
|
if (balance.get() > 0) {
|
||||||
|
skuPromotionDetailClone.remove(lastSkuId.toString());
|
||||||
|
double lastDiscountPrice = CurrencyUtil.sub(discountPrice, skuPromotionDetail.get(lastSkuId.toString()));
|
||||||
|
double lastTotalPrice = CurrencyUtil.sub(totalPrice, skuPromotionDetail.get(lastSkuId.toString()));
|
||||||
|
filterEnoughSku(skuVOList, skuPromotionDetailClone, lastDiscountPrice, lastTotalPrice, balance, lastSkuId, promotionTypeEnum, activityId);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
count++;
|
||||||
}).collect(Collectors.toList());
|
|
||||||
if (!unEnoughSku.isEmpty()) {
|
// 防止死循环
|
||||||
if (unEnoughSku.size() == skuVOList.size()) {
|
if (count > skuPromotionDetail.size()) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
for (CartSkuVO cartSkuVO : skuVOList) {
|
|
||||||
if (unEnoughSku.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (skuPromotionDetail.containsKey(cartSkuVO.getGoodsSku().getId()) && unEnoughSku.stream().noneMatch(k -> k.getGoodsSku().getId().equals(cartSkuVO.getGoodsSku().getId()))) {
|
|
||||||
// 商品金额占比
|
|
||||||
double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4);
|
|
||||||
// 商品优惠金额
|
|
||||||
Double skuDiscountPrice = CurrencyUtil.mul(discountPrice, point);
|
|
||||||
// 商品优惠金额 - 不足优惠金额 = 差额
|
|
||||||
Double sub = CurrencyUtil.sub(skuDiscountPrice, unEnoughSku.get(0).getPriceDetailDTO().getCouponPrice());
|
|
||||||
// 分摊到其他商品: 其他商品原优惠金额 + 差额
|
|
||||||
calculateCartSkuPromotionsPrice(cartSkuVO, sub, promotionTypeEnum, activityId);
|
|
||||||
// 从不足商品列表中移除
|
|
||||||
unEnoughSku.remove(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
calculateNotEnoughPromotionsPrice(skuVOList, skuPromotionDetail, discountPrice, totalPrice, promotionTypeEnum, activityId);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void filterEnoughSku(List<CartSkuVO> skuVOList, Map<String, Double> skuPromotionDetail,
|
||||||
|
Double discountPrice, Double totalPrice,
|
||||||
|
AtomicReference<Double> balance, StringBuilder lastSkuId,
|
||||||
|
PromotionTypeEnum promotionTypeEnum, String activityId) {
|
||||||
|
AtomicInteger count = new AtomicInteger(skuPromotionDetail.size());
|
||||||
|
AtomicReference<Double> countPrice = new AtomicReference<>(0D);
|
||||||
|
for (String skuId : skuPromotionDetail.keySet()) {
|
||||||
|
skuVOList.forEach(l -> {
|
||||||
|
if (l.getGoodsSku().getId().equals(skuId)) {
|
||||||
|
count.getAndDecrement();
|
||||||
|
|
||||||
|
//商品金额占比
|
||||||
|
double point = CurrencyUtil.div(l.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4);
|
||||||
|
|
||||||
|
//商品优惠金额
|
||||||
|
Double skuDiscountPrice;
|
||||||
|
|
||||||
|
if (count.get() > 0) {
|
||||||
|
//非最后一个商品,则按照比例计算
|
||||||
|
skuDiscountPrice = CurrencyUtil.mul(discountPrice, point);
|
||||||
|
} else {
|
||||||
|
// 如果是最后一个商品 则减去之前优惠的金额来进行计算
|
||||||
|
skuDiscountPrice = CurrencyUtil.sub(discountPrice, countPrice.get());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (balance.get() > 0) {
|
||||||
|
// 分摊到其他商品: 其他商品原优惠金额 + 差额
|
||||||
|
calculateCartSkuPromotionsPrice(l, balance.get(), promotionTypeEnum, activityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果商品优惠金额大于商品金额,则取商品金额。差额分摊到其他商品
|
||||||
|
if (skuDiscountPrice > l.getPriceDetailDTO().getGoodsPrice()) {
|
||||||
|
balance.set(CurrencyUtil.sub(skuDiscountPrice, l.getPriceDetailDTO().getGoodsPrice()));
|
||||||
|
lastSkuId.append(skuId);
|
||||||
|
skuDiscountPrice = l.getPriceDetailDTO().getGoodsPrice();
|
||||||
|
} else {
|
||||||
|
balance.set(0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
countPrice.set(CurrencyUtil.add(countPrice.get(), skuDiscountPrice));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user