当前位置: 首页 > news >正文

DDD拼团系统常用设计模式

首先是产品需求分拼团模式是线性
创建活动领域工厂,返回对应责任策略
下面是表设计
根据你提供的数据库结构,我将每个表的字段信息整理成表格形式:

1. crowd_tags(人群标签表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
tag_id varchar(32) 人群ID
tag_name varchar(64) 人群名称
tag_desc varchar(256) 人群描述
statistics int 人群标签统计量
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

2. crowd_tags_detail(人群标签明细表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
tag_id varchar(32) 人群ID
user_id varchar(16) 用户ID
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

3. crowd_tags_job(人群标签任务表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
tag_id varchar(32) 标签ID
batch_id varchar(8) 批次ID
tag_type tinyint(1) 1 标签类型(参与量、消费金额)
tag_rule varchar(8) 标签规则(限定类型 N次)
stat_start_time datetime CURRENT_TIMESTAMP 统计数据,开始时间
stat_end_time datetime CURRENT_TIMESTAMP 统计数据,结束时间
status tinyint(1) 0 状态;0初始、1计划、2重置、3完成
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

4. group_buy_activity(拼团活动表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id bigint unsigned AUTO_INCREMENT 自增
activity_id bigint 活动ID
activity_name varchar(128) 活动名称
discount_id varchar(8) 折扣ID
group_type tinyint(1) 0 拼团方式(0自动成团、1达成目标拼团)
take_limit_count int 1 拼团次数限制
target int 1 拼团目标
valid_time int 15 拼团时长(分钟)
status tinyint(1) 0 活动状态(0创建、1生效、2过期、3废弃)
start_time datetime CURRENT_TIMESTAMP 活动开始时间
end_time datetime CURRENT_TIMESTAMP 活动结束时间
tag_id varchar(8) NULL 人群标签规则标识
tag_scope varchar(4) NULL 人群标签规则范围(多选;1可见限制、2参与限制)
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

5. group_buy_discount(拼团折扣表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id bigint unsigned AUTO_INCREMENT 自增ID
discount_id varchar(8) 折扣ID
discount_name varchar(64) 折扣标题
discount_desc varchar(256) 折扣描述
discount_type tinyint(1) 0 折扣类型(0:base、1:tag)
market_plan varchar(4) ZJ 营销优惠计划(ZJ:直减、MJ:满减、N元购)
market_expr varchar(32) 营销优惠表达式
tag_id varchar(8) NULL 人群标签,特定优惠限定
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

6. group_buy_order(拼团订单表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
team_id varchar(8) 拼单组队ID
activity_id bigint 活动ID
source varchar(8) 渠道
channel varchar(8) 来源
original_price decimal(8,2) 原始价格
deduction_price decimal(8,2) 折扣金额
pay_price decimal(8,2) 支付价格
target_count int 目标数量
complete_count int 完成数量
lock_count int 锁单数量
status tinyint(1) 0 状态(0-拼单中、1-完成、2-失败、3-完成-含退单)
valid_start_time datetime 拼团开始时间
valid_end_time datetime 拼团结束时间
notify_type varchar(8) HTTP 回调类型(HTTP、MQ)
notify_url varchar(512) NULL 回调地址(HTTP 回调不可为空)
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

7. group_buy_order_list(拼团订单列表表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
user_id varchar(64) 用户ID
team_id varchar(8) 拼单组队ID
order_id varchar(12) 订单ID
activity_id bigint 活动ID
start_time datetime 活动开始时间
end_time datetime 活动结束时间
goods_id varchar(16) 商品ID
source varchar(8) 渠道
channel varchar(8) 来源
original_price decimal(8,2) 原始价格
deduction_price decimal(8,2) 折扣金额
pay_price decimal(8,2) 支付金额
status tinyint(1) 0 状态;0初始锁定、1消费完成、2用户退单
out_trade_no varchar(12) 外部交易单号-确保外部调用唯一幂等
out_trade_time datetime NULL 外部交易时间
biz_id varchar(64) 业务唯一ID
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

8. notify_task(通知任务表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
activity_id bigint 活动ID
team_id varchar(8) 拼单组队ID
notify_category varchar(64) NULL 回调种类
notify_type varchar(8) HTTP 回调类型(HTTP、MQ)
notify_mq varchar(32) NULL 回调消息
notify_url varchar(128) NULL 回调接口
notify_count int 回调次数
notify_status tinyint(1) 回调状态【0初始、1完成、2重试、3失败】
parameter_json varchar(256) 参数对象
uuid varchar(128) 唯一标识
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

9. sc_sku_activity(渠道商品活动配置关联表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
source varchar(8) 渠道
channel varchar(8) 来源
activity_id bigint 活动ID
goods_id varchar(16) 商品ID
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

10. sku(商品信息表)

字段名 数据类型 是否主键 是否必填 默认值 注释
id int unsigned AUTO_INCREMENT 自增ID
source varchar(8) 渠道
channel varchar(8) 来源
goods_id varchar(16) 商品ID
goods_name varchar(128) 商品名称
original_price decimal(10,2) 商品价格
create_time datetime CURRENT_TIMESTAMP 创建时间
update_time datetime CURRENT_TIMESTAMP ON UPDATE 更新时间

索引信息:

  • 每个表都有主键索引
  • 多个表有唯一索引(uq_*)
  • 部分表有复合索引和普通索引

结合之前领域模式,我们可以创建一个接口StrategyMapper<T,D,R>策略下一个节点,StrategyHandler<T,D,R>策略处理器
T入参,D领域封装对象,R返回

/*** @author Yu.Pan* @description 策略映射器* T 入参类型* D 上下文参数* R 返参类型* @create 2024-12-14 12:05*/
public interface StrategyMapper<T, D, R> {/*** 获取待执行策略** @param requestParameter 入参* @param dynamicContext   上下文* @return 返参* @throws Exception 异常*/StrategyHandler<T, D, R> get(T requestParameter, D dynamicContext) throws Exception;}
/*** @author Yu.Pan* @description 受理策略处理* T 入参类型* D 上下文参数* R 返参类型* @create 2024-12-14 12:06*/
public interface StrategyHandler<T, D, R> {StrategyHandler DEFAULT = (T, D) -> null;R apply(T requestParameter, D dynamicContext) throws Exception;}public abstract class AbstractMultiThreadStrategyRouter<T, D, R> implements StrategyMapper<T, D, R>, StrategyHandler<T, D, R> {protected StrategyHandler<T, D, R> defaultStrategyHandler = StrategyHandler.DEFAULT;public R router(T requestParameter, D dynamicContext) throws Exception {//获取下一个节点,然后执行apply方法StrategyHandler<T, D, R> next = get(requestParameter, dynamicContext);if(null != next) return next.apply(requestParameter, dynamicContext);//如果下一个节点不存在,默认返回return defaultStrategyHandler.apply(requestParameter, dynamicContext);}//    public R chain(T requestParameter, D dynamicContext) throws Exception {
//        R apply = apply(requestParameter, dynamicContext);
//        if(apply != null) {
//            return apply;
//        }else{
//            StrategyHandler<T, D, R> next = get(requestParameter, dynamicContext);//可以在StrategyHandler增加chain方法可以地柜调用了
//            return next.chain(requestParameter,dynamicContext);
//        }
//    }@Overridepublic R apply(T requestParameter, D dynamicContext) throws Exception {// 异步加载数据multiThread(requestParameter, dynamicContext);// 业务流程受理return doApply(requestParameter, dynamicContext);}/*** 异步加载数据*/protected abstract void multiThread(T requestParameter, D dynamicContext) throws ExecutionException, InterruptedException, TimeoutException;/*** 业务流程受理*/protected abstract R doApply(T requestParameter, D dynamicContext) throws Exception;}

构建拼团工厂默认返回RootNode,其中包含整个流程的传输对象


@Service
public class DefaultActivityStrategyFactory {private final RootNode rootNode;public DefaultActivityStrategyFactory(RootNode rootNode) {this.rootNode = rootNode;}public StrategyHandler<MarketProductEntity, DynamicContext, TrialBalanceEntity> strategyHandler() {return rootNode;}@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic static class DynamicContext {// 拼团活动营销配置值对象private GroupBuyActivityDiscountVO groupBuyActivityDiscountVO;// 商品信息private SkuVO skuVO;// 折扣金额private BigDecimal deductionPrice;// 支付金额private BigDecimal payPrice;// 活动可见性限制private boolean visible;// 活动private boolean enable;}}

整个服务降级,限流,黑名单可以使用demo版本动态配置


@Service
public class DCCService {/*** 降级开关 0关闭、1开启*/@DCCValue("downgradeSwitch:0")private String downgradeSwitch;@DCCValue("cutRange:100")private String cutRange;@DCCValue("scBlacklist:s02c02")private String scBlacklist;@DCCValue("cacheSwitch:0")private String cacheOpenSwitch;public boolean isDowngradeSwitch() {return "1".equals(downgradeSwitch);}public boolean isCutRange(String userId) {// 计算哈希码的绝对值int hashCode = Math.abs(userId.hashCode());// 获取最后两位int lastTwoDigits = hashCode % 100;// 判断是否在切量范围内if (lastTwoDigits <= Integer.parseInt(cutRange)) {return true;}return false;}/*** 判断黑名单拦截渠道,true 拦截、false 放行*/public boolean isSCBlackIntercept(String source, String channel) {List<String> list = Arrays.asList(scBlacklist.split(Constants.SPLIT));return list.contains(source + channel);}/*** 缓存开启开关,true为开启,1为关闭*/public boolean isCacheOpenSwitch(){return "0".equals(cacheOpenSwitch);}}

缓存配置开关用于封装了Repository

public abstract class AbstractRepository {private final Logger logger = LoggerFactory.getLogger(AbstractRepository.class);@Resourceprotected IRedisService redisService;@Resourceprotected DCCService dccService;/*** 通用缓存处理方法* 优先从缓存获取,缓存不存在则从数据库获取并写入缓存** @param cacheKey      缓存键* @param dbFallback    数据库查询函数* @param <T>           返回类型* @return              查询结果*/protected <T> T getFromCacheOrDb(String cacheKey, Supplier<T> dbFallback) {// 判断是否开启缓存if (dccService.isCacheOpenSwitch()) {// 从缓存获取T cacheResult = redisService.getValue(cacheKey);// 缓存存在则直接返回if (null != cacheResult) {return cacheResult;}// 缓存不存在则从数据库获取T dbResult = dbFallback.get();// 数据库查询结果为空则直接返回if (null == dbResult) {return null;}// 写入缓存redisService.setValue(cacheKey, dbResult);return dbResult;} else {// 缓存未开启,直接从数据库获取logger.warn("缓存降级 {}", cacheKey);return dbFallback.get();}}

RootNode做参数校验,用户 商品 来源 渠道
SwitchNode做降级 用户切量拦截
MarketNode使用线程池填充DynamicContext,拼团活动()对象,SKU商品对象,计算优惠结果封装到dynamicContext
TagNode对用户标签管理,是否可见,可参与
EndNode返回封装对象结果
主要包含

public class TrialBalanceEntity {/** 商品ID */private String goodsId;/** 商品名称 */private String goodsName;/** 原始价格 */private BigDecimal originalPrice;// 折扣金额private BigDecimal deductionPrice;// 支付金额private BigDecimal payPrice;/** 拼团目标数量 */private Integer targetCount;/** 拼团开始时间 */private Date startTime;/** 拼团结束时间 */private Date endTime;/** 是否可见拼团 */private Boolean isVisible;/** 是否可参与进团 */private Boolean isEnable;/** 活动配置信息 */private GroupBuyActivityDiscountVO groupBuyActivityDiscountVO;}
@Overrideprotected void multiThread(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws ExecutionException, InterruptedException, TimeoutException {// 异步查询活动配置QueryGroupBuyActivityDiscountVOThreadTask queryGroupBuyActivityDiscountVOThreadTask = new QueryGroupBuyActivityDiscountVOThreadTask(requestParameter.getActivityId(), requestParameter.getSource(), requestParameter.getChannel(), requestParameter.getGoodsId(), repository);FutureTask<GroupBuyActivityDiscountVO> groupBuyActivityDiscountVOFutureTask = new FutureTask<>(queryGroupBuyActivityDiscountVOThreadTask);threadPoolExecutor.execute(groupBuyActivityDiscountVOFutureTask);// 异步查询商品信息 - 在实际生产中,商品有同步库或者调用接口查询。这里暂时使用DB方式查询。QuerySkuVOFromDBThreadTask querySkuVOFromDBThreadTask = new QuerySkuVOFromDBThreadTask(requestParameter.getGoodsId(), repository);FutureTask<SkuVO> skuVOFutureTask = new FutureTask<>(querySkuVOFromDBThreadTask);threadPoolExecutor.execute(skuVOFutureTask);// 写入上下文 - 对于一些复杂场景,获取数据的操作,有时候会在下N个节点获取,这样前置查询数据,可以提高接口响应效率dynamicContext.setGroupBuyActivityDiscountVO(groupBuyActivityDiscountVOFutureTask.get(timeout, TimeUnit.MILLISECONDS));dynamicContext.setSkuVO(skuVOFutureTask.get(timeout, TimeUnit.MILLISECONDS));log.info("拼团商品查询试算服务-MarketNode userId:{} 异步线程加载数据「GroupBuyActivityDiscountVO、SkuVO」完成", requestParameter.getUserId());}@Overridepublic TrialBalanceEntity doApply(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {log.info("拼团商品查询试算服务-MarketNode userId:{} requestParameter:{}", requestParameter.getUserId(), JSON.toJSONString(requestParameter));// 获取上下文数据GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = dynamicContext.getGroupBuyActivityDiscountVO();if (null == groupBuyActivityDiscountVO) {return router(requestParameter, dynamicContext);}GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = groupBuyActivityDiscountVO.getGroupBuyDiscount();SkuVO skuVO = dynamicContext.getSkuVO();if (null == groupBuyDiscount || null == skuVO) {return router(requestParameter, dynamicContext);}// 优惠试算IDiscountCalculateService discountCalculateService = discountCalculateServiceMap.get(groupBuyDiscount.getMarketPlan());if (null == discountCalculateService) {log.info("不存在{}类型的折扣计算服务,支持类型为:{}", groupBuyDiscount.getMarketPlan(), JSON.toJSONString(discountCalculateServiceMap.keySet()));throw new AppException(ResponseCode.E0001.getCode(), ResponseCode.E0001.getInfo());}// 折扣价格BigDecimal payPrice = discountCalculateService.calculate(requestParameter.getUserId(), skuVO.getOriginalPrice(), groupBuyDiscount);dynamicContext.setDeductionPrice(skuVO.getOriginalPrice().subtract(payPrice));dynamicContext.setPayPrice(payPrice);return router(requestParameter, dynamicContext);}

试算金额完成之后

查询用户参与的进行中的拼团队伍信息,支持两种查询模式:
个人模式:查询用户自己参与的拼团队伍
随机模式:查询其他用户参与的进行中的拼团队伍(用于推荐用户加入)

  1. 统计拼团数据
    多少个团,多少个成团,多少个锁定用户

4.返回1个个人团,2个组队团数据

拼团营销锁单
1.根据外部订单号和用户id查询 子拼团表 是否存在创建状态订单
2.查询拼团进度,如果已经完成返回拦截,已完成
3.营销优惠试算
4.人群限定过滤
5.锁定,营销预支付订单;商品下单前,预购锁定。
黑名单校验,外部订单关闭状态/时间限制校验,外部交易时间限制
6.插入/更新 组团表 新增 订单列表


@Slf4j
@Service
public class TradeSettlementRuleFilterFactory {@Bean("tradeSettlementRuleFilter")public BusinessLinkedList<TradeSettlementRuleCommandEntity,DynamicContext, TradeSettlementRuleFilterBackEntity> tradeSettlementRuleFilter(SCRuleFilter scRuleFilter,OutTradeNoRuleFilter outTradeNoRuleFilter,SettableRuleFilter settableRuleFilter,EndRuleFilter endRuleFilter) {// 组装链LinkArmory<TradeSettlementRuleCommandEntity, DynamicContext, TradeSettlementRuleFilterBackEntity> linkArmory =new LinkArmory<>("交易结算规则过滤链", scRuleFilter, outTradeNoRuleFilter, settableRuleFilter, endRuleFilter);// 链对象return linkArmory.getLogicLink();}@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic static class DynamicContext {// 订单营销实体对象private MarketPayOrderEntity marketPayOrderEntity;// 拼团组队实体对象private GroupBuyTeamEntity groupBuyTeamEntity;}}
http://www.gsyq.cn/news/65370.html

相关文章:

  • 幻颜之约有哪些产品?一篇读懂五大系列如何对应私密问题
  • 2025成都装修公司最新品牌排行榜公布!家装行业权威推荐,资质服务双优,装修/整装/家装/全包装修/房屋装修品牌选择指南
  • 幻颜之约凝胶用户评价如何?小红书真实反馈与使用注意事项
  • 2025 年东莞摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(东莞分公司)人像摄影十杰创办
  • 2025 年惠州摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(惠州分公司)实战为王、人像十杰创办
  • 【Linux】GCC编译FQS
  • 深圳成长训练供应商推荐排行榜单?成长训练供应商 成长训练代理商 成长训练代理 成长训练渠道商 成长训练渠道 成长训练品牌代理商 成长训练系统代理商
  • 2025年着色剂订做厂家权威推荐榜单:营养强化剂/肉制品改良剂/化妆品原料源头厂家精选
  • 2025学习机选购攻略:家长必看的品牌对比与推荐,让教育投入不花冤枉钱
  • 本地靠谱的专业汽车窗膜公司推荐排行榜单?专业汽车窗膜公司 专业汽车窗膜电话 专业汽车窗膜推荐 专业汽车窗膜服务商 专业汽车窗膜品牌 专业汽车窗膜供应商 专业汽车窗膜企业 专业汽车窗膜平台
  • 评价高的灵活办公空间公司推荐排行榜单?灵活办公空间品牌 灵活办公空间公司 灵活办公空间推荐 灵活办公空间出租 灵活办公空间租赁
  • 市面上靠谱的办公室公司推荐排行榜单?办公室品牌 办公室公司 办公室推荐 办公室出租 办公室租赁
  • 质量好的联合办公工位公司推荐排行榜单?联合办公工位品牌 联合办公工位公司 联合办公工位推荐 联合办公工位出租 联合办公工位租赁
  • 市面上符合越南标准防火卷帘门厂家排名哪家强
  • 2025年度GEO优化行业报告总结:技术迭代与市场重构下的全域机遇
  • Skywalking 链路追踪
  • 计算孤岛面积:从错误踩坑到优雅优化的完整实战指南
  • 2025年CSS新特性大盘点
  • 工业冷风机2025年度销量冠军榜单,汽车制造车间通风降温/家具厂车间通风降温/制造业车间通风降温/铁皮棚车间通风降温工业冷风机公司选哪家
  • 可靠的袋装骆驼奶粉工厂口碑推荐榜单?袋装骆驼奶粉工厂 袋装骆驼奶粉品牌 袋装骆驼奶粉牌子 袋装骆驼奶粉企业 袋装骆驼奶粉公司 袋装骆驼奶粉源头工厂
  • NVIDIA DriveOS 推动新一代智能汽车实现突破 - 实践
  • 口碑好的智能中高考加盟电话推荐排行榜单?智能中高考加盟电话哪家强 智能中高考加盟电话公司 智能中高考加盟电话机构智能中高考加盟电话中心 智能中高考加盟电话哪家靠谱 智能中高考加盟电话单位
  • 专业的的压焊钢格板供应商推荐排行榜单?压焊钢格板供应商 压焊钢格板销售厂家 压焊钢格板制造厂 压焊钢格板生产商 压焊钢格板厂商 压焊钢格板企业 压焊钢格板供货商
  • 2025年湖南到张家界旅游服务权威推荐榜单:张家界三日游‌/张家界旅行‌/张家界跟团游‌服务精选
  • 实验四 组合与继承
  • 市场散热器铝型材供应厂家推荐排行榜?散热器铝型材供应厂家 散热器铝型材工厂 散热器铝型材厂家 散热器铝型材生产厂家 散热器铝型材源头厂家 散热器铝型材供应商
  • 比较好的双免个体户品牌推荐?双免个体户品牌公司 双免个体户产品 双免个体户收费 双免个体户费用 双免个体户代办公司 双免个体户代办 双免个体户一手园区 双免个体户平台 双免个体户服务
  • 2025企业AI培训TOP榜:权威评测揭示行业变革关键
  • 市面上高铅锡膏品牌推荐排行榜单?高铅锡膏品牌 高铅锡膏公司 高铅锡膏产品 高铅锡膏供应厂家 高铅锡膏工厂 高铅锡膏厂家 高铅锡膏生产厂家
  • 评价高的无骨架类变压器公司口碑推荐榜?无骨架类变压器公司 无骨架类变压器品牌 无骨架类变压器产品 无骨架类变压器厂商 无骨架类变压器供应商 无骨架类变压器渠道