浏览代码

feat(coupon): 新增商品价格计算功能

- 在 MercCouponFactory 接口中添加了 goodsListPrice 方法
- 在 MercCouponFactoryBase 基类中实现了 goodsListPrice 方法的逻辑
- 在 MercCouponFactoryV2 实现类中添加了对 goodsListPrice 方法的引用
- 该功能可以计算商品在使用优惠券时的折后价和优惠价
hechunping 3 月之前
父节点
当前提交
93ffc3aba9

+ 10 - 0
src/main/java/com/xynet/marketing/service/factory/coupon/merc/MercCouponFactory.java

@@ -3,6 +3,8 @@ package com.xynet.marketing.service.factory.coupon.merc;
 
 import com.xynet.marketing.utils.collections.map.JMap;
 
+import java.util.List;
+
 /**
  * 优惠券工厂-接口
  *
@@ -47,4 +49,12 @@ public interface MercCouponFactory {
      * @param param
      */
     void autoSend(JMap<String, Object> param);
+
+    /**
+     * 获取商品价格
+     *
+     * @param param
+     * @return
+     */
+    List<JMap<String, Object>> goodsListPrice(JMap<String, Object> param);
 }

+ 134 - 2
src/main/java/com/xynet/marketing/service/factory/coupon/merc/impl/base/MercCouponFactoryBase.java

@@ -1,14 +1,14 @@
 package com.xynet.marketing.service.factory.coupon.merc.impl.base;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xynet.marketing.entity.MemberCoupon;
 import com.xynet.marketing.entity.MercCoupon;
-import com.xynet.marketing.enums.CouponSendTypeEnum;
-import com.xynet.marketing.enums.CouponValidTypeEnum;
+import com.xynet.marketing.enums.*;
 import com.xynet.marketing.mapper.MercCouponMapper;
 import com.xynet.marketing.service.MemberCouponService;
 import com.xynet.marketing.service.MercProjectDeviceService;
@@ -21,10 +21,15 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * 优惠券工厂-基类
@@ -193,4 +198,131 @@ public class MercCouponFactoryBase extends ServiceImpl<MercCouponMapper, MercCou
                 .setRemark(remark);
         return new JHashMap<>(BeanUtil.beanToMap(memberCoupon));
     }
+
+    @Override
+    public List<JMap<String, Object>> goodsListPrice(JMap<String, Object> param) {
+        List<JMap<String, Object>> goodsList = param.getListMap("goodsList");
+        String thirdMemberId = param.getString("thirdMemberId");
+        Integer memberCouponId = param.getInt("memberCouponId");
+        String deviceId = param.getString("deviceId");
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalDateTime orderCreateTime = LocalDateTime.parse(param.getString("orderCreateTime"), formatter);
+        //查询会员优惠券信息
+        Map<String, Object> memberCoupon = memberCouponService.obj(new JHashMap<String, Object>().set("id", memberCouponId));
+        if (!Emptys.check(memberCoupon)) {
+            throw new RuntimeException("会员优惠券不存在!");
+        }
+        //判断券是否属于该用户
+        JMap<String, Object> memberCouponJMap = new JHashMap<String, Object>(memberCoupon);
+        if (!Objects.equals(thirdMemberId, memberCouponJMap.getString("thirdMemberId"))) {
+            throw new RuntimeException("会员优惠券不属于该用户!");
+        }
+        //判断券是否已使用
+        if (!Objects.equals(memberCouponJMap.getString("status"), MemberCouponStatusEnum.UNUSED.getCode())) {
+            throw new RuntimeException("该券已失效!");
+        }
+        //查询商户券
+        MercCoupon mercCoupon = getById(memberCouponJMap.getInt("couponId"));
+        if (mercCoupon.getValidStartDate().isAfter(orderCreateTime.toLocalDate())) {
+            throw new RuntimeException("该券于!" + mercCoupon.getValidStartDate().toString() + "开始使用!");
+        }
+        if (mercCoupon.getValidEndDate().isBefore(orderCreateTime.toLocalDate())) {
+            throw new RuntimeException("该券于!" + mercCoupon.getValidEndDate().toString() + "结束!");
+        }
+        //判断优惠券是可用于该设备
+        if (!mercCoupon.getIsAllDevice()) {
+            Boolean deviceCheck = deviceService.checkDeviceId(mercCoupon.getId(), deviceId, "coupon");
+            if (!deviceCheck) {
+                throw new RuntimeException("该券不可用于该设备!");
+            }
+        }
+        Map<String, Map<String, Object>> couponGoodsMap = new HashMap<>();
+        if (!mercCoupon.getIsAllGoods()) {
+            List<Map<String, Object>> couponGoods = goodsService.listByActId(mercCoupon.getId(), "coupon");
+            couponGoodsMap = couponGoods.stream().collect(Collectors.toMap(i -> i.get("goodsId").toString(), i -> i));
+        }
+        int type1Amount = 0;
+        for (int g = 0; g < goodsList.size(); g++) {
+            JMap<String, Object> goods = goodsList.get(g);
+            //判断商品是否可以使用该优惠券
+            Map<String, Object> couponGoods = couponGoodsMap.get(goods.getString("goodsId"));
+            if (!mercCoupon.getIsAllGoods() && !Emptys.check(couponGoods)) {
+                continue;
+            }
+            //判断商品中是否有不能使用优惠券的促销活动
+            //1.特价活动不能使用优惠券
+            if (goods.getBoolean("promotionType3", false)) {
+                continue;
+            }
+            Boolean promotionCanCoupon = true;
+            //2.促销活动不能使用优惠券 //3.满减活动不能使用优惠券
+            List<JMap<String, Object>> promotionList = goods.getListMap("promotionList");
+            for (int p = 0; p < promotionList.size(); p++) {
+                JMap<String, Object> promotion = promotionList.get(p);
+                promotionCanCoupon = promotion.getBoolean("canCoupon");
+                if (!promotionCanCoupon) {
+                    break;
+                }
+                if (Objects.equals(promotion.getString("type"), PromotionTypeEnum.T_1.getCode())
+                        && Objects.equals(mercCoupon.getType(), CouponTypeEnum.T_1.getCode())
+                ) {
+                    break;
+                }
+            }
+            if (!promotionCanCoupon) {
+                continue;
+            }
+            //满足条件,计算价格
+            //折扣券
+            if (Objects.equals(mercCoupon.getType(), CouponTypeEnum.T_2.getCode())) {
+                JSONObject priceJson = JSONUtil.parseObj(mercCoupon.getPrice());
+                BigDecimal scalar = new BigDecimal(priceJson.getStr("scalar"));
+                goods.set("priceOnsale", goods.getInt("priceOnsale") * scalar.doubleValue());
+            }
+            //满减券
+            if (Objects.equals(mercCoupon.getType(), CouponTypeEnum.T_1.getCode())) {
+                goods.set("canCouponType1", true);
+                //累计价格
+                type1Amount += goods.getInt("priceOnsale") * goods.getInt("num");
+            }
+        }
+        //判断满减金额
+        Integer priceOnsaleType1 = 0;
+        if (type1Amount > 0) {
+            JSONArray priceJson = JSONUtil.parseArray(mercCoupon.getPrice());
+            for (int p = 0; p < priceJson.size(); p++) {
+                JSONObject priceObject = priceJson.getJSONObject(p);
+                //格式:[{"limit":200,"price":100,"isLoop":1}]
+                Integer limit = Integer.valueOf(priceObject.get("limit").toString());
+                Integer price = Integer.valueOf(priceObject.get("price").toString());
+                String isLoop = priceObject.get("isLoop").toString();
+                //判断是哪个挡位
+                if (type1Amount >= limit) {
+                    if ("1".equals(isLoop)) {
+                        int n = Integer.valueOf(type1Amount / limit);
+                        priceOnsaleType1 = price * n;
+                    } else {
+                        priceOnsaleType1 = price;
+                    }
+                }
+            }
+            //映射到商品
+            for (int g = 0; g < goodsList.size(); g++) {
+                JMap<String, Object> goods = goodsList.get(g);
+                if (goods.getBoolean("canCouponType1")) {
+                    //单价
+                    BigDecimal price = goods.getBigDecimal("price");
+                    //数量
+                    BigDecimal num = goods.getBigDecimal("num");
+                    //总金额
+                    BigDecimal zje = new BigDecimal(type1Amount);
+                    //总优惠
+                    BigDecimal zyh = new BigDecimal(priceOnsaleType1);
+                    Integer priceOnsale = price.multiply(num).multiply(zyh).divide(zje, 0, BigDecimal.ROUND_HALF_UP).intValue();
+                    goods.set("priceOnsale", priceOnsale);
+                }
+            }
+        }
+        return goodsList;
+    }
 }

+ 7 - 0
src/main/java/com/xynet/marketing/service/factory/coupon/merc/impl/v2/MercCouponFactoryV2.java

@@ -10,6 +10,8 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * @author hechunping
  * @date 2025/2/10
@@ -45,4 +47,9 @@ public class MercCouponFactoryV2 extends ServiceImpl<MercCouponMapper, MercCoupo
     public void autoSend(JMap<String, Object> param) {
         mercCouponFactoryBase.autoSend(param);
     }
+
+    @Override
+    public List<JMap<String, Object>> goodsListPrice(JMap<String, Object> param) {
+        return mercCouponFactoryBase.goodsListPrice(param);
+    }
 }