学习日报 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 外部配置,无需修改代码即可灵活控制优惠券的叠加和场景逻辑,扩展性极强。
相关推荐
firewood20241 小时前
共射三极管放大电路相关情况分析
笔记·学习
zl0_00_01 小时前
美亚2023
学习
AI_56781 小时前
SQL性能优化全景指南:从量子执行计划到自适应索引的终极实践
数据库·人工智能·学习·adb
zl0_00_02 小时前
pctf wp
学习
Hello_Embed2 小时前
libmodbus STM32 主机实验(USB 串口版)
笔记·stm32·学习·嵌入式·freertos·modbus
学编程的闹钟2 小时前
98【html的php化】
学习
林开落L2 小时前
从零开始学习Protobuf(C++实战版)
开发语言·c++·学习·protobuffer·结构化数据序列化机制
哎呦 你干嘛~2 小时前
MODBUS协议学习
学习
小陈phd2 小时前
多模态大模型学习笔记(一)——机器学习入门:监督/无监督学习核心任务全解析
笔记·学习·机器学习
小陈phd2 小时前
多模态大模型学习笔记(二)——机器学习十大经典算法:一张表看懂分类 / 回归 / 聚类 / 降维
学习·算法·机器学习