学习日报 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 外部配置,无需修改代码即可灵活控制优惠券的叠加和场景逻辑,扩展性极强。
相关推荐
小林有点嵌3 分钟前
UML之时序图学习
学习·uml
行业探路者6 分钟前
如何利用活码生成产品画册二维码?
学习·音视频·语音识别·二维码·设备巡检
好奇龙猫19 分钟前
人工智能学习-AI-MIT公开课-第三节:推理:目标树与基于规则的专家系统-笔记
人工智能·笔记·学习
好奇龙猫21 分钟前
【AI学习-comfyUI学习-第二十节-controlnet线稿+softedge线稿处理器工作流艺术线处理器工作流-各个部分学习】
人工智能·学习
小林有点嵌34 分钟前
UML之状态图学习
网络·学习·uml
小林有点嵌40 分钟前
UML之类图学习
学习·uml
小林有点嵌43 分钟前
UML之用例图学习
学习·microsoft·uml
wdfk_prog1 小时前
[Linux]学习笔记系列 -- [fs][fs_parser]
linux·笔记·学习
白帽子凯哥哥1 小时前
在学习SQL注入或XSS这类具体漏洞时,如何设计一个高效的“理论+实践”学习循环?
sql·学习·漏洞·xss
全栈陈序员2 小时前
v-if 和 v-for 的优先级是什么?
前端·javascript·vue.js·学习·前端框架·ecmascript