From c92f4c5a78a77331c65059a635191b35752346bf Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 20 May 2025 17:58:20 +0800
Subject: [PATCH] refactor(mall): 重构 getCouponAmountMap 方法

---
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java |  210 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 157 insertions(+), 53 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
index 2a89336..5fdf95f 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -333,6 +333,91 @@
         return scoreAmountMap;
     }
 
+//    /**
+//     * 根据传入的优惠卷ID和商品明细集合计算出每个商品获取的实际支付金额
+//     * @param memberCouponId 优惠卷ID
+//     * @param items 商品明细
+//     * @return Map<Long,BigDecimal> skuId,实际支付金额
+//     */
+//    @Override
+//    public Map<Long,BigDecimal> getCouponAmountMap(Long memberCouponId,List<AddOrderItemDto> items){
+//        HashMap<Long,BigDecimal> couponAmountMap = new HashMap<>();
+//        MallMemberCoupon mallMemberCoupon = mallMemberCouponMapper.selectById(memberCouponId);
+//        if(ObjectUtil.isEmpty(mallMemberCoupon)){
+//            return couponAmountMap;
+//        }
+//        Integer state = mallMemberCoupon.getState();
+//        if(1 != state){
+//            return couponAmountMap;
+//        }
+//        Long couponId = mallMemberCoupon.getCouponId();//优惠卷ID
+//        List<Long> goodsIdsAll = couponGoodsMapper.selectByCouponId(couponId);
+//        List<MallGoodsSku> skusAll = mallGoodsSkuMapper.selectSkuIdsByGoodsId(goodsIdsAll);//获取该优惠卷绑定的全部商品sku
+//        List<Long> skuIdsAll = skusAll.stream().map(MallGoodsSku::getId).collect(Collectors.toList());//获取该优惠卷绑定的全部商品skuIDS
+//        List<Long> skuIds = items.stream().map(AddOrderItemDto::getSkuId).collect(Collectors.toList());//订单中的全部skuIds
+//
+//        /**
+//         * 获取这张优惠卷生效的skuIds
+//         */
+//        Set<Long> intersection = skuIdsAll.stream()
+//                .filter(item -> skuIds.contains(item))
+//                .collect(Collectors.toSet());//获取两个集合的交集
+//        if(CollUtil.isEmpty(intersection)){
+//            return couponAmountMap;
+//        }
+//        HashMap<Long,BigDecimal> skuMap = new HashMap<>();//每个订单详情的ID和amount的map
+//        List<MallGoodsSku> skus = mallGoodsSkuMapper.selectByIds(new ArrayList<>(intersection));
+//        BigDecimal totalAmount = BigDecimal.ZERO;//订单中的总金额
+//        Map<Long, AddOrderItemDto> itemMap = new HashMap<>();// 预先将items转换为Map,以skuId作为键
+//        for (AddOrderItemDto addOrderItemDto : items) {
+//            itemMap.put(addOrderItemDto.getSkuId(), addOrderItemDto);
+//        }
+//        for(MallGoodsSku mallGoodsSku : skus){
+//            Long id = mallGoodsSku.getId();
+//            BigDecimal presentPrice = mallGoodsSku.getPresentPrice();
+//            // 检查itemMap中是否存在该商品
+//            AddOrderItemDto addOrderItemDto = itemMap.get(id);
+//            if (addOrderItemDto != null) {
+//                BigDecimal skuAmount = presentPrice.multiply(BigDecimal.valueOf(addOrderItemDto.getCnt()));
+//                totalAmount = totalAmount.add(skuAmount);
+//                skuMap.put(id,skuAmount);
+//            }
+//        }
+//
+//        /**
+//         * 计算每个商品利用优惠卷打折的具体金额
+//         */
+//        MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(mallMemberCoupon.getCouponId());
+//        BigDecimal costAmount = mallGoodsCoupon.getCostAmount();
+//        BigDecimal realAmount = mallGoodsCoupon.getRealAmount();
+//        if(totalAmount.compareTo(costAmount) < 0){
+//            return couponAmountMap;
+//        }
+//        HashMap<Long,BigDecimal> skuMapPercent = new HashMap<>();//每个订单详情的ID和amount的map
+//        for (Map.Entry<Long,BigDecimal> entry : skuMap.entrySet()) {
+//            Long keySkuId = entry.getKey();
+//            BigDecimal valueSkuAmount = entry.getValue();
+//            BigDecimal divide = valueSkuAmount.divide(totalAmount, 4, BigDecimal.ROUND_DOWN);//每个商品占符合满减的总额的比例
+//            skuMapPercent.put(keySkuId,divide);
+//            Integer type = mallGoodsCoupon.getType();
+//            if(MallGoodsCoupon.TYPE_ONE == type){
+//                BigDecimal bigDecimal = realAmount.multiply(divide).setScale(0, BigDecimal.ROUND_DOWN);//每个SKU的减免金额(比例*减免金额)
+//                BigDecimal skuRealAmount = valueSkuAmount.subtract(bigDecimal.compareTo(BigDecimal.ZERO) > 0 ? bigDecimal : BigDecimal.ZERO);//实际支付金额
+//                couponAmountMap.put(keySkuId,skuRealAmount);
+//            }
+//            if(MallGoodsCoupon.TYPE_TWO == type){
+//                BigDecimal divideTime = totalAmount.divide(costAmount, 0, BigDecimal.ROUND_DOWN);//累计减免次数
+//                BigDecimal multiply = divideTime.multiply(realAmount);//实际减免金额
+//                BigDecimal bigDecimal = multiply.multiply(divide).setScale(0, BigDecimal.ROUND_DOWN);//每个SKU的减免金额(比例*实际减免金额)
+//                BigDecimal skuRealAmount = valueSkuAmount.subtract(bigDecimal.compareTo(BigDecimal.ZERO) > 0 ? bigDecimal : BigDecimal.ZERO);//实际支付金额
+//                couponAmountMap.put(keySkuId,skuRealAmount);
+//            }
+//        }
+//        return couponAmountMap;
+//    }
+
+
+
     /**
      * 根据传入的优惠卷ID和商品明细集合计算出每个商品获取的实际支付金额
      * @param memberCouponId 优惠卷ID
@@ -340,79 +425,98 @@
      * @return Map<Long,BigDecimal> skuId,实际支付金额
      */
     @Override
-    public Map<Long,BigDecimal> getCouponAmountMap(Long memberCouponId,List<AddOrderItemDto> items){
-        HashMap<Long,BigDecimal> couponAmountMap = new HashMap<>();
-        MallMemberCoupon mallMemberCoupon = mallMemberCouponMapper.selectById(memberCouponId);
-        if(ObjectUtil.isEmpty(mallMemberCoupon)){
-            return couponAmountMap;
-        }
-        Integer state = mallMemberCoupon.getState();
-        if(1 != state){
-            return couponAmountMap;
-        }
-        Long couponId = mallMemberCoupon.getCouponId();//优惠卷ID
-        List<Long> goodsIdsAll = couponGoodsMapper.selectByCouponId(couponId);
-        List<MallGoodsSku> skusAll = mallGoodsSkuMapper.selectSkuIdsByGoodsId(goodsIdsAll);//获取该优惠卷绑定的全部商品sku
-        List<Long> skuIdsAll = skusAll.stream().map(MallGoodsSku::getId).collect(Collectors.toList());//获取该优惠卷绑定的全部商品skuIDS
-        List<Long> skuIds = items.stream().map(AddOrderItemDto::getSkuId).collect(Collectors.toList());//订单中的全部skuIds
+    public Map<Long, BigDecimal> getCouponAmountMap(Long memberCouponId, List<AddOrderItemDto> items) {
+        HashMap<Long, BigDecimal> couponAmountMap = new HashMap<>();
+        // 获取优惠券信息
+        Optional<MallMemberCoupon> optionalMallMemberCoupon = Optional.ofNullable(mallMemberCouponMapper.selectById(memberCouponId));
+        MallMemberCoupon mallMemberCoupon = optionalMallMemberCoupon.orElse(null);
 
-        /**
-         * 获取这张优惠卷生效的skuIds
-         */
-        Set<Long> intersection = skuIdsAll.stream()
-                .filter(item -> skuIds.contains(item))
-                .collect(Collectors.toSet());//获取两个集合的交集
-        if(CollUtil.isEmpty(intersection)){
+        if (mallMemberCoupon == null || mallMemberCoupon.getState() != 1) {
             return couponAmountMap;
         }
-        HashMap<Long,BigDecimal> skuMap = new HashMap<>();//每个订单详情的ID和amount的map
-        List<MallGoodsSku> skus = mallGoodsSkuMapper.selectByIds(new ArrayList<>(intersection));
-        BigDecimal totalAmount = BigDecimal.ZERO;//订单中的总金额
-        Map<Long, AddOrderItemDto> itemMap = new HashMap<>();// 预先将items转换为Map,以skuId作为键
-        for (AddOrderItemDto addOrderItemDto : items) {
-            itemMap.put(addOrderItemDto.getSkuId(), addOrderItemDto);
+
+        Set<Long> intersection = items.stream().map(AddOrderItemDto::getSkuId).collect(Collectors.toSet()); // 订单中的全部skuIds
+
+        if (intersection.isEmpty()) {
+            return couponAmountMap;
         }
-        for(MallGoodsSku mallGoodsSku : skus){
+
+        // 获取订单详情的ID和amount的map
+        Map<Long, AddOrderItemDto> itemMap = items.stream()
+                .collect(Collectors.toMap(AddOrderItemDto::getSkuId, item -> item));
+
+        List<MallGoodsSku> skus = mallGoodsSkuMapper.selectList(
+                new LambdaQueryWrapper<MallGoodsSku>()
+                        .select(MallGoodsSku::getId, MallGoodsSku::getPresentPrice)
+                        .in(MallGoodsSku::getId, intersection)
+        );
+        BigDecimal totalAmount = BigDecimal.ZERO;
+        Map<Long, BigDecimal> skuMap = new HashMap<>();
+
+        for (MallGoodsSku mallGoodsSku : skus) {
             Long id = mallGoodsSku.getId();
             BigDecimal presentPrice = mallGoodsSku.getPresentPrice();
-            // 检查itemMap中是否存在该商品
             AddOrderItemDto addOrderItemDto = itemMap.get(id);
             if (addOrderItemDto != null) {
                 BigDecimal skuAmount = presentPrice.multiply(BigDecimal.valueOf(addOrderItemDto.getCnt()));
                 totalAmount = totalAmount.add(skuAmount);
-                skuMap.put(id,skuAmount);
+                skuMap.put(id, skuAmount);
             }
         }
 
-        /**
-         * 计算每个商品利用优惠卷打折的具体金额
-         */
-        MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(mallMemberCoupon.getCouponId());
-        BigDecimal costAmount = mallGoodsCoupon.getCostAmount();
-        BigDecimal realAmount = mallGoodsCoupon.getRealAmount();
-        if(totalAmount.compareTo(costAmount) < 0){
+        // 计算每个商品利用优惠卷打折的具体金额
+        Optional<MallGoodsCoupon> optionalMallGoodsCoupon = Optional.ofNullable(mallGoodsCouponMapper.selectById(mallMemberCoupon.getCouponId()));
+        MallGoodsCoupon mallGoodsCoupon = optionalMallGoodsCoupon.orElse(null);
+        if (mallGoodsCoupon == null) {
             return couponAmountMap;
         }
-        HashMap<Long,BigDecimal> skuMapPercent = new HashMap<>();//每个订单详情的ID和amount的map
-        for (Map.Entry<Long,BigDecimal> entry : skuMap.entrySet()) {
+
+        BigDecimal costAmount = mallGoodsCoupon.getCostAmount();
+        BigDecimal realAmount = mallGoodsCoupon.getRealAmount();
+        Integer type = mallGoodsCoupon.getType();
+        if (MallGoodsCoupon.TYPE_ONE == type) {
+            realAmount = mallGoodsCoupon.getRealAmount();
+        } else if (MallGoodsCoupon.TYPE_TWO == type) {
+            BigDecimal divideTime = totalAmount.divide(costAmount, 0, RoundingMode.DOWN); // 累计减免次数
+            realAmount = divideTime.multiply(realAmount); // 实际减免金额
+        }
+
+        if (totalAmount.compareTo(costAmount) < 0) {
+            return couponAmountMap;
+        }
+
+        BigDecimal totalDiscount = BigDecimal.ZERO;
+        for (Map.Entry<Long, BigDecimal> entry : skuMap.entrySet()) {
             Long keySkuId = entry.getKey();
             BigDecimal valueSkuAmount = entry.getValue();
-            BigDecimal divide = valueSkuAmount.divide(totalAmount, 4, BigDecimal.ROUND_DOWN);//每个商品占符合满减的总额的比例
-            skuMapPercent.put(keySkuId,divide);
-            Integer type = mallGoodsCoupon.getType();
-            if(MallGoodsCoupon.TYPE_ONE == type){
-                BigDecimal bigDecimal = realAmount.multiply(divide).setScale(0, BigDecimal.ROUND_DOWN);//每个SKU的减免金额(比例*减免金额)
-                BigDecimal skuRealAmount = valueSkuAmount.subtract(bigDecimal.compareTo(BigDecimal.ZERO) > 0 ? bigDecimal : BigDecimal.ZERO);//实际支付金额
-                couponAmountMap.put(keySkuId,skuRealAmount);
+            BigDecimal divide = valueSkuAmount.divide(totalAmount, 4, RoundingMode.DOWN); // 每个商品占符合满减的总额的比例
+            BigDecimal skuRealAmount = BigDecimal.ZERO;
+            if (MallGoodsCoupon.TYPE_ONE == type) {
+                BigDecimal bigDecimalOne = realAmount.multiply(divide).setScale(2, RoundingMode.DOWN); // 每个SKU的减免金额(比例*减免金额)
+                skuRealAmount = valueSkuAmount.subtract(bigDecimalOne.max(BigDecimal.ZERO)).setScale(2, RoundingMode.DOWN);
+                totalDiscount = totalDiscount.add(bigDecimalOne);
+            } else if (MallGoodsCoupon.TYPE_TWO == type) {
+                BigDecimal divideTime = totalAmount.divide(costAmount, 0, RoundingMode.DOWN); // 累计减免次数
+                BigDecimal multiply = divideTime.multiply(realAmount); // 实际减免金额
+                BigDecimal bigDecimalTwo = multiply.multiply(divide).setScale(2, RoundingMode.DOWN); // 每个SKU的减免金额(比例*实际减免金额)
+                skuRealAmount = valueSkuAmount.subtract(bigDecimalTwo.max(BigDecimal.ZERO)).setScale(2, RoundingMode.DOWN);
+                totalDiscount = totalDiscount.add(bigDecimalTwo);
             }
-            if(MallGoodsCoupon.TYPE_TWO == type){
-                BigDecimal divideTime = totalAmount.divide(costAmount, 0, BigDecimal.ROUND_DOWN);//累计减免次数
-                BigDecimal multiply = divideTime.multiply(realAmount);//实际减免金额
-                BigDecimal bigDecimal = multiply.multiply(divide).setScale(0, BigDecimal.ROUND_DOWN);//每个SKU的减免金额(比例*实际减免金额)
-                BigDecimal skuRealAmount = valueSkuAmount.subtract(bigDecimal.compareTo(BigDecimal.ZERO) > 0 ? bigDecimal : BigDecimal.ZERO);//实际支付金额
-                couponAmountMap.put(keySkuId,skuRealAmount);
+            couponAmountMap.put(keySkuId, skuRealAmount);
+        }
+
+        // 调整最后一个商品的减免金额以确保总减免金额达到预期
+        if (totalDiscount.compareTo(realAmount) < 0) {
+            BigDecimal difference = realAmount.subtract(totalDiscount);
+            for (Map.Entry<Long, BigDecimal> entry : couponAmountMap.entrySet()) {
+                Long keySkuId = entry.getKey();
+                BigDecimal skuRealAmount = entry.getValue();
+                BigDecimal newSkuRealAmount = skuRealAmount.subtract(difference).setScale(2, RoundingMode.DOWN);
+                couponAmountMap.put(keySkuId, newSkuRealAmount);
+                break; // 调整最后一个商品的减免金额
             }
         }
+
         return couponAmountMap;
     }
 

--
Gitblit v1.9.1