当前位置: 首页 > 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.jsqmd.com/news/55278/

相关文章:

  • 详细介绍:HarmonyOS Divider组件深度定制:从基础分割到高级视觉表达
  • 幻颜之约有哪些产品?一篇读懂五大系列如何对应私密问题
  • 口碑好的微型电机公司推荐榜单?微型电机品牌 微型电机公司 微型电机工厂 微型电机厂家 微型电机厂商 微型电机生产厂家
  • 内置私护益生菌管用吗?幻颜之约黑白片益生菌如何精准调理菌群
  • 2025 年中山摄影培训人像摄影培训排行榜:路人贾摄影讲堂(中山分公司)荣登榜首、人像十杰创办
  • 2025成都装修公司最新品牌排行榜公布!家装行业权威推荐,资质服务双优,装修/整装/家装/全包装修/房屋装修品牌选择指南
  • 幻颜之约是正规品牌吗?从研发实验室到10万级车间的品质承诺
  • 幻颜之约凝胶用户评价如何?小红书真实反馈与使用注意事项
  • 2025最新成都装修公司最新top5实力榜!装修/整装/家装/全包装修/房屋装修,全案定制,行业数据、市场口碑及选择指南
  • 广州诚信的展会大巴出租公司推荐排行榜单? 展会大巴出租品牌 展会大巴出租公司 展会大巴出租服务商 展会大巴出租平台 展会大巴出租渠道
  • 2025 年东莞摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(东莞分公司)人像摄影十杰创办
  • NOIP2025 退役记
  • 冒泡排序 2st
  • 比较好的少儿训练供应商推荐排行榜单?少儿训练供应商 少儿训练代理商 少儿训练代理 少儿训练渠道商 少儿训练渠道 少儿训练品牌代理商 少儿训练系统代理商
  • 2025 年惠州摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(惠州分公司)实战为王、人像十杰创办
  • 2025-11-29 NestJS菜单模块CRUD接口开发指南(deepseek)
  • .NET+AI | MEAI | 上下文压缩(7)
  • 广州比较好的包车公司推荐排行榜单?包车品牌 包车公司 包车服务商 包车平台 包车渠道
  • 靠谱的城际网约车公司推荐排行榜单? 城际网约车品牌 城际网约车公司 城际网约车服务商 城际网约车渠道
  • 2025 年佛山人像摄影培训推荐榜:路人贾摄影讲堂(佛山分公司)排名第一、摄影十杰创办
  • 【Linux】GCC编译FQS
  • 办公室设计公司有哪些?国内专业机构盘点
  • 深圳成长训练供应商推荐排行榜单?成长训练供应商 成长训练代理商 成长训练代理 成长训练渠道商 成长训练渠道 成长训练品牌代理商 成长训练系统代理商
  • 2025年低压电缆厂权威推荐榜单:中压电缆/防火电缆/电线电缆源头厂家精选
  • 2025年着色剂订做厂家权威推荐榜单:营养强化剂/肉制品改良剂/化妆品原料源头厂家精选
  • 深入解析:Spring Boot常见问题
  • 可靠的淘宝运营电商培训品牌推荐排行榜?淘宝运营电商培训品牌 淘宝运营电商培训公司 淘宝运营电商培训机构 淘宝运营电商培训中心 淘宝运营电商培训企业 淘宝运营电商培训单位
  • 2025学习机选购攻略:家长必看的品牌对比与推荐,让教育投入不花冤枉钱
  • 渲染管线
  • 评价高的灵活办公空间公司推荐排行榜单?灵活办公空间品牌 灵活办公空间公司 灵活办公空间推荐 灵活办公空间出租 灵活办公空间租赁