学习日报 20250930|多优惠券叠加核销及场景互斥逻辑

要实现多优惠券叠加核销及场景互斥逻辑,需从规则定义、校验流程、核销执行 三方面入手,结合优惠券模板(CouponTemplate)的配置来控制业务逻辑。以下是具体实现方案:

一、核心思路

通过优惠券模板(CouponTemplate配置每张优惠券的叠加规则适用场景,在核销前先校验多券的兼容性,再按规则执行核销。

二、具体实现步骤

1. 扩展优惠券模板(CouponTemplate
java 复制代码
import lombok.Data;
import java.util.List;

/**
 * 优惠券模板:定义优惠券的基础规则(可叠加、适用场景等)
 */
@Data
public class CouponTemplate {
    private Long id;
    private String name;
    private CouponTypeEnum type; // 优惠券类型(满减、折扣等)
    
    /** 可叠加的优惠券类型(为空表示可与所有类型叠加;非空则仅能与指定类型叠加) */
    private List<CouponTypeEnum> allowStackWith;
    
    /** 适用场景标签(如 "生鲜"、"数码"、"全品类" 等) */
    private List<String> sceneTags;
}
2. 多优惠券叠加核销实现

步骤 1:校验多券叠加规则在核销前,先检查所有优惠券是否满足 "可叠加" 规则:

java 复制代码
/**
 * 校验多优惠券是否可叠加
 * @param coupons 待核销的优惠券列表(需包含关联的 CouponTemplate)
 * @return 是否可叠加
 */
private boolean checkStackable(List<UserCoupon> coupons) {
    // 若只有1张券,默认可核销
    if (coupons.size() <= 1) return true;
    
    // 遍历每两张券,检查是否满足互相叠加规则
    for (int i = 0; i < coupons.size(); i++) {
        for (int j = i + 1; j < coupons.size(); j++) {
            UserCoupon couponA = coupons.get(i);
            UserCoupon couponB = coupons.get(j);
            
            CouponTemplate templateA = couponA.getTemplate();
            CouponTemplate templateB = couponB.getTemplate();
            
            // 检查 A 是否允许与 B 类型叠加
            if (!templateA.getAllowStackWith().contains(templateB.getType())) {
                log.warn("优惠券{}(类型:{})不允许与优惠券{}(类型:{})叠加",
                        couponA.getId(), templateA.getType(),
                        couponB.getId(), templateB.getType());
                return false;
            }
        }
    }
    return true;
}

步骤 2:执行多券核销若校验通过,循环调用各券的核销逻辑:

java 复制代码
public void writeOffMultipleCoupons(List<UserCoupon> coupons) {
    // 1. 校验叠加规则
    if (!checkStackable(coupons)) {
        throw new CouponStackException("优惠券不可叠加");
    }
    
    // 2. 循环核销每张券
    for (UserCoupon coupon : coupons) {
        CouponTypeEnum type = coupon.getTemplate().getType();
        ICouponWriteOffService service = factory.getWriteOffService(type);
        service.writeOff(coupon);
    }
}
3. 多优惠券场景互斥实现

步骤 1:定义订单与商品的场景标签 订单或商品需携带 "场景标签",与优惠券模板的 sceneTags 匹配:

java 复制代码
@Data
public class Order {
    private Long id;
    private List<OrderItem> items; // 订单商品
    private List<String> sceneTags; // 订单整体场景(如 "全品类")
}

@Data
public class OrderItem {
    private Long id;
    private String sceneTag; // 商品所属场景(如 "生鲜")
    private BigDecimal price;
}

步骤 2:校验优惠券场景兼容性

java 复制代码
/**
 * 校验优惠券与订单场景是否匹配
 * @param coupons 待核销优惠券
 * @param order 目标订单
 * @return 是否匹配
 */
private boolean checkSceneMatch(List<UserCoupon> coupons, Order order) {
    for (UserCoupon coupon : coupons) {
        CouponTemplate template = coupon.getTemplate();
        List<String> couponScenes = template.getSceneTags();
        
        // 检查订单整体场景是否匹配
        boolean orderSceneMatch = order.getSceneTags().stream()
                .anyMatch(couponScenes::contains);
        
        // 检查订单商品场景是否匹配
        boolean itemSceneMatch = order.getItems().stream()
                .anyMatch(item -> couponScenes.contains(item.getSceneTag()));
        
        if (!orderSceneMatch && !itemSceneMatch) {
            log.warn("优惠券{}(场景:{})与订单场景不匹配",
                    coupon.getId(), couponScenes);
            return false;
        }
    }
    return true;
}

步骤 3:整合场景校验到核销流程

java 复制代码
public void writeOffCouponsWithSceneCheck(List<UserCoupon> coupons, Order order) {
    // 1. 校验场景匹配
    if (!checkSceneMatch(coupons, order)) {
        throw new CouponSceneException("优惠券场景不匹配");
    }
    
    // 2. 校验叠加规则(复用之前的 checkStackable 方法)
    if (!checkStackable(coupons)) {
        throw new CouponStackException("优惠券不可叠加");
    }
    
    // 3. 执行核销
    writeOffMultipleCoupons(coupons);
}

三、总结

  • 多券叠加 :通过 CouponTemplateallowStackWith 配置可叠加的优惠券类型,核销前校验每两张券是否满足互相叠加规则。
  • 场景互斥 :通过 CouponTemplatesceneTags 配置适用场景,核销前校验优惠券场景与订单 / 商品场景是否匹配。
  • 优势 :所有规则通过 CouponTemplate 外部配置,无需修改代码即可灵活控制优惠券的叠加和场景逻辑,扩展性极强。
相关推荐
Nan_Shu_6143 小时前
学习:uniapp全栈微信小程序vue3后台-额外/精彩报错篇
前端·学习·微信小程序·小程序·uni-app·notepad++
zhangxuyu11184 小时前
Vue2 学习记录
学习
charlie1145141914 小时前
精读C++20设计模式——行为型设计模式:迭代器模式
c++·学习·设计模式·迭代器模式·c++20
尘似鹤4 小时前
微信小程序学习(三)补充
学习·微信小程序
Le1Yu5 小时前
2025-9-28学习笔记
java·笔记·学习
yuxb735 小时前
Ceph 分布式存储学习笔记(三):块存储和对象存储管理
笔记·ceph·学习
yuxb735 小时前
Ceph 分布式存储学习笔记(一):介绍、部署与集群配置(上)
笔记·ceph·学习
GoldenaArcher8 小时前
Postman 学习笔记 IV:Workflow、Newman 与 Mock Server 实战技巧
笔记·学习·postman
知识分享小能手8 小时前
微信小程序入门学习教程,从入门到精通,微信小程序常用API(下)——知识点详解 + 案例实战(5)
前端·javascript·学习·微信小程序·小程序·vue·前端开发