From 18e2c898911d580ec04dafee4ba6b49a20ebe218 Mon Sep 17 00:00:00 2001 From: misworga831 Date: Fri, 13 Sep 2024 17:27:39 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=95=86=E5=93=81=E9=85=8D=E9=80=81=E6=A8=A1?= =?UTF-8?q?=E7=89=88=EF=BC=8C=E6=B2=A1=E6=9C=89=E6=9B=B4=E6=96=B0sku?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lili/modules/goods/service/GoodsSkuService.java | 9 +++++++++ .../modules/goods/serviceimpl/GoodsServiceImpl.java | 1 + .../goods/serviceimpl/GoodsSkuServiceImpl.java | 11 +++++++++++ 3 files changed, 21 insertions(+) diff --git a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java index dbea9b24..61b555e8 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java @@ -296,4 +296,13 @@ public interface GoodsSkuService extends IService { * @return 库存数量 */ Integer getGoodsStock(String goodsId); + + /** + * 更新sku运费模版 + * + * @param goodsId 商品id + * @param templateId 运费模版id + * @return 操作结果 + */ + Boolean freight(List goodsId, String templateId); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java index b3c9e18e..6909add2 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java @@ -437,6 +437,7 @@ public class GoodsServiceImpl extends ServiceImpl implements lambdaUpdateWrapper.in(Goods::getId, goodsIds); List goodsCache = goodsIds.stream().map(item -> CachePrefix.GOODS.getPrefix() + item).collect(Collectors.toList()); cache.multiDel(goodsCache); + goodsSkuService.freight(goodsIds, templateId); return this.update(lambdaUpdateWrapper); } diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java index d67639ff..b71b1eae 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java @@ -888,6 +888,17 @@ public class GoodsSkuServiceImpl extends ServiceImpl i } + @Override + public Boolean freight(List goodsId, String templateId) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.in(GoodsSku::getGoodsId, goodsId); + updateWrapper.set(GoodsSku::getFreightTemplateId, templateId); + updateWrapper.set(GoodsSku::getUpdateTime, new Date()); + List skuIds = this.list(updateWrapper).stream().map(GoodsSku::getId).collect(Collectors.toList()); + skuIds.forEach(this::clearCache); + return this.update(updateWrapper); + } + /** * 渲染商品sku * From b3bb771066021649e5172a5fdc1afccc16ad9e38 Mon Sep 17 00:00:00 2001 From: misworga831 Date: Sat, 14 Sep 2024 01:39:19 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=9C=A8=E8=B4=AD=E7=89=A9=E8=BD=A6?= =?UTF-8?q?=E5=86=85=E5=A4=9A=E4=BF=83=E9=94=80=E6=B4=BB=E5=8A=A8=E5=A4=9A?= =?UTF-8?q?=E5=95=86=E5=93=81=E7=9A=84=E6=B8=85=E7=A9=BA=E4=B8=8B=E7=9A=84?= =?UTF-8?q?=E4=BF=83=E9=94=80=E9=87=91=E9=A2=9D=E5=88=86=E9=85=8D=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cart/render/util/PromotionPriceUtil.java | 176 +++++++++++------- 1 file changed, 113 insertions(+), 63 deletions(-) diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java index d375c16f..f3dedc37 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java @@ -1,5 +1,6 @@ package cn.lili.modules.order.cart.render.util; +import cn.hutool.core.map.MapUtil; import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.utils.CurrencyUtil; 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.List; 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) { // sku 促销信息非空判定 - if (skuPromotionDetail == null || skuPromotionDetail.size() == 0) { + if (skuPromotionDetail == null || skuPromotionDetail.isEmpty()) { return; } @@ -68,40 +70,39 @@ public class PromotionPriceUtil { List skuVOList = tradeDTO.getSkuList(); // 获取map分配sku的总数,如果是最后一个商品分配金额,则将金额从百分比改为总金额扣减,避免出现小数除不尽 - int count = skuPromotionDetail.size(); + AtomicInteger count = new AtomicInteger(skuPromotionDetail.size()); //已优惠金额 - Double deducted = 0D; + AtomicReference deducted = new AtomicReference<>(0D); 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--; - - //sku 优惠金额 - Double skuDiscountPrice; - - //非最后一个商品,则按照比例计算 - if (count > 0) { - //商品金额占比 - 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); + //非最后一个商品,则按照比例计算 + if (count.get() > 0) { + //商品金额占比 + double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4); + //商品优惠金额 + skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point); + //累加已优惠金额 + deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice)); } - } + // 如果是最后一个商品 则减去之前优惠的金额来进行计算 + else { + skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get()); + } + + calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, 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; } + + // clone skuPromotionDetail + Map skuPromotionDetailClone = MapUtil.sortByValue(skuPromotionDetail, false); + + // 未满足优惠金额的商品 long matchPromotionsZeroCount = - skuVOList.stream().filter(l -> l.getPriceDetailDTO().getFlowPrice() == 0 && skuPromotionDetail.containsKey(l.getGoodsSku().getId())).count(); - long matchPromotionsCount = skuVOList.stream().filter(l -> 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 -> skuPromotionDetailClone.containsKey(l.getGoodsSku().getId())).count(); if (matchPromotionsZeroCount == matchPromotionsCount) { return; } - // 获取剩余金额不足优惠金额的商品 - List unEnoughSku = skuVOList.stream().filter(k -> { - if (skuPromotionDetail.containsKey(k.getGoodsSku().getId()) && skuPromotionDetail.size() >= 2) { - //商品金额占比 - double point = CurrencyUtil.div(k.getPriceDetailDTO().getGoodsPrice(), totalPrice, 4); - //商品优惠金额 - Double skuDiscountPrice = CurrencyUtil.mul(discountPrice, point); - return k.getPriceDetailDTO().getCouponPrice() > 0 && skuDiscountPrice > k.getPriceDetailDTO().getCouponPrice(); + // 分配到其他商品的优惠金额 + AtomicReference balance = new AtomicReference<>(0D); + StringBuilder lastSkuId = new StringBuilder(); + + // 计数器 + int count = 0; + + + // 检查是否有不满足优惠金额的商品 + 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; - }).collect(Collectors.toList()); - if (!unEnoughSku.isEmpty()) { - if (unEnoughSku.size() == skuVOList.size()) { - return; + count++; + + // 防止死循环 + if (count > skuPromotionDetail.size()) { + 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 skuVOList, Map skuPromotionDetail, + Double discountPrice, Double totalPrice, + AtomicReference balance, StringBuilder lastSkuId, + PromotionTypeEnum promotionTypeEnum, String activityId) { + AtomicInteger count = new AtomicInteger(skuPromotionDetail.size()); + AtomicReference 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)); + + } + }); + } } /**