简介
本文件面向电商平台开发者,系统化梳理 DouPHP 电商系统中“促销活动”的数据模型与业务流程。重点围绕以下目标展开:
- 明确活动主表与活动商品关联表的表结构设计(以 dou_promotion、dou_promotion_product 为核心)。
- 解释活动类型定义、活动时间范围、参与商品、折扣规则、限购策略等关键业务在数据层如何表达。
- 记录活动状态管理、库存扣减、价格计算等核心流程的落地方式。
- 提供活动并发控制、性能优化、数据统计的技术方案建议。
- 为后续扩展或迁移提供完整的数据模型参考。
说明:当前仓库未直接包含 dou_promotion 与 dou_promotion_product 的建表语句;但存在大量“促销价+起止时间”的通用促销字段实践(如 product/chat_package/vip/money 等),以及优惠券折扣计算逻辑。本文将基于这些既有实现,给出可落地的促销表设计建议与流程映射。
项目结构
与促销活动相关的关键位置包括:
- 系统表结构文档:集中定义了多类商品的促销价与促销时间字段,体现统一的促销数据约定。
- 前台商品服务:通过定价服务计算最终售价,支撑列表/详情页展示。
- 模块升级脚本:将旧版促销时间字段统一迁移为更规范的日期时间字段,体现演进方向。
- 优惠券服务:提供按条件、有效期、上限控制的折扣计算示例,可作为活动折扣计算的参考。
graph TB
A["系统表结构<br/>促销字段规范"] --> B["商品表<br/>含促销价/时间"]
A --> C["聊天套餐表<br/>含促销价/时间"]
D["前台商品服务"] --> E["定价服务<br/>salePrice"]
F["优惠券服务"] --> G["折扣计算<br/>有效期/条件/上限"]
H["模块升级脚本"] --> B
H --> C
核心组件
- 促销主表(建议:dou_promotion)
- 职责:承载一次营销活动的元信息,如活动名称、类型、状态、时间范围、适用范围、预算/限额、统计指标等。
- 关键字段建议:id、name、type、status、start_at、end_at、scope(商品/类目/品牌/全站)、budget、limit_per_user、limit_total、created_at、updated_at。
- 活动商品关联表(建议:dou_promotion_product)
- 职责:描述某活动覆盖的具体商品及该商品在活动中的专属规则(如活动价、限购数量、优先级、是否叠加等)。
- 关键字段建议:id、promotion_id、product_id、promote_price、limit_per_order、priority、is_override、created_at、updated_at。
- 商品表促销字段(已有)
- 促销价与促销时间:promote_price、promote_start_time/promote_end_time(部分模块已升级为 promote_start_at/promote_end_at)。
- 优惠券折扣(已有)
- 支持按金额门槛、百分比/固定面额、最大减免、有效期校验等,可作为活动折扣计算的参考实现。
架构总览
促销体系由“活动主表 + 活动商品关联表 + 商品促销字段 + 定价服务 + 优惠券折扣”共同构成。前端商品列表/详情通过定价服务获取 salePrice,结合商品自身的促销价与时间范围,决定最终展示价格。后台可通过活动主表统一管理活动生命周期与规则。
sequenceDiagram
participant 前端 as "前端"
participant 商品服务 as "商品服务"
participant 定价服务 as "定价服务"
participant 数据库 as "数据库"
前端->>商品服务 : "请求商品列表/详情"
商品服务->>定价服务 : "计算 salePrice(商品ID, 用户ID)"
定价服务->>数据库 : "读取商品基础价/促销价/时间"
定价服务-->>商品服务 : "返回折后价/原价/活动标识"
商品服务-->>前端 : "返回商品数据含价格信息"
详细组件分析
促销主表(dou_promotion)设计
- 设计目标
- 统一管理营销活动,解耦商品级促销配置,支持多活动并行、优先级与互斥。
- 建议字段
- id:主键
- name:活动名称
- type:活动类型(如满减、折扣、秒杀、阶梯价等)
- status:状态(草稿/预热/进行中/已结束/已取消)
- start_at/end_at:活动时间范围
- scope:适用范围(商品/类目/品牌/全站)
- budget:活动预算(可选)
- limit_per_user:每人限购(可选)
- limit_total:总量限制(可选)
- created_at/updated_at:时间戳
- 索引建议
- (status, start_at, end_at) 用于快速筛选进行中的活动
- (scope_type, scope_id) 用于按范围查询
活动商品关联表(dou_promotion_product)设计
- 设计目标
- 将活动与商品解耦,支持同一商品参与多个活动时的优先级与覆盖策略。
- 建议字段
- id:主键
- promotion_id:关联活动
- product_id:关联商品
- promote_price:活动价(可为空,表示沿用商品促销价)
- limit_per_order:单次限购
- priority:优先级(数值越小优先级越高)
- is_override:是否覆盖商品促销价
- created_at/updated_at:时间戳
- 索引建议
- (promotion_id, product_id) 唯一约束,避免重复
- (product_id, priority) 用于商品维度活动排序
商品促销字段与时间迁移
- 现状
- 多张商品/套餐表包含促销价与促销时间字段:promote_price、promote_start_time、promote_end_time。
- 部分模块已将时间字段从整型时间戳迁移为 DATETIME(promote_start_at/promote_end_at),提升可读性与查询效率。
- 影响
- 列表/详情页通过定价服务读取促销价与时间,判断是否在有效期内并展示活动价。
- 建议
- 统一采用 promote_start_at/promote_end_at 的 DATETIME 字段,便于范围查询与索引优化。
- 对促销价与时间建立联合索引,加速“进行中活动商品”的检索。
价格计算与活动生效流程
- 流程要点
- 商品列表/详情调用定价服务计算 salePrice。
- 定价服务读取商品基础价与促销价,并结合时间范围判断是否生效。
- 若存在活动商品关联表,则根据优先级与覆盖策略选择最终活动价。
- 可视化流程
flowchart TD Start(["进入价格计算"]) --> ReadBase["读取商品基础价/促销价/时间"] ReadBase --> CheckActive{"是否在活动时间内?"} CheckActive -- 否 --> UseBase["使用基础价或会员价"] CheckActive -- 是 --> LoadRules["加载活动规则优先级/覆盖"] LoadRules --> ApplyPromo["应用活动价/折扣"] ApplyPromo --> Finalize["输出最终售价"] UseBase --> Finalize Finalize --> End(["结束"])
折扣规则与限购策略(参考优惠券)
- 折扣规则
- 支持按订单金额门槛、百分比/固定面额、最大减免额度等计算。
- 有效期校验:仅当当前时间在活动有效期内且状态启用时生效。
- 限购策略
- 可在活动主表设置每人限购与总量限制;在关联表中设置单次限购。
- 下单时需校验剩余库存与限购计数,防止超卖。
- 参考实现
- 优惠券服务展示了有效期、条件、上限的综合折扣计算逻辑,可复用至活动折扣。
活动状态管理与库存扣减
- 状态管理
- 活动状态:草稿/预热/进行中/已结束/已取消。
- 通过 start_at/end_at 与 status 组合控制活动可见性与可用性。
- 库存扣减
- 下单时锁定库存,支付成功后正式扣减;超时未支付释放库存。
- 对于限量活动,需维护活动维度的已售数量与剩余库存。
- 并发控制
- 使用数据库行级锁或乐观锁(版本号)保证库存一致性。
- 高并发场景引入队列异步处理库存扣减与活动统计。
依赖关系分析
- 商品表与定价服务
- 商品表提供基础价与促销价;定价服务负责综合计算最终售价。
- 活动主表与关联表
- 活动主表定义全局规则;关联表细化到商品级别的价格与限购。
- 优惠券服务
- 提供折扣计算与有效期校验的参考实现,可与活动折扣合并或叠加。
graph LR
P["商品表"] --> S["定价服务"]
A["活动主表"] --> R["活动商品关联表"]
R --> S
C["优惠券服务"] --> S
性能考虑
- 索引优化
- 对促销价与时间字段建立联合索引,加速“进行中活动商品”的查询。
- 对活动范围(scope_type, scope_id)建立索引,提升范围匹配效率。
- 查询优化
- 使用分页与只读副本分担读压力。
- 将高频查询结果缓存至 Redis,减少数据库压力。
- 写入优化
- 批量更新活动状态与统计指标,减少频繁写库。
- 使用事务与重试机制确保数据一致性。
- 监控与告警
- 对慢查询与热点表进行监控,及时扩容或优化。
故障排查指南
- 常见问题
- 活动未生效:检查 start_at/end_at 与 status 是否正确。
- 价格异常:确认定价服务是否正确读取促销价与活动规则。
- 库存超卖:检查库存扣减逻辑与并发控制是否到位。
- 排查步骤
- 核对活动主表与关联表数据一致性。
- 查看定价服务日志与数据库查询执行计划。
- 验证优惠券/活动折扣叠加逻辑是否符合预期。
结论
- 通过“活动主表 + 活动商品关联表 + 商品促销字段 + 定价服务 + 优惠券折扣”的组合,可实现灵活、可扩展的促销活动体系。
- 建议统一采用 DATETIME 类型的促销时间字段,提升可读性与查询效率。
- 在高并发场景下,应重视库存一致性、缓存策略与监控告警,保障系统稳定性。
附录
- 数据模型图(概念)
erDiagram DOU_PROMOTION { int id PK varchar name enum type tinyint status datetime start_at datetime end_at json scope decimal budget int limit_per_user int limit_total datetime created_at datetime updated_at } DOU_PROMOTION_PRODUCT { int id PK int promotion_id FK int product_id FK decimal promote_price int limit_per_order tinyint priority tinyint is_override datetime created_at datetime updated_at } PRODUCT { int id PK decimal price decimal promote_price datetime promote_start_at datetime promote_end_at } DOU_PROMOTION ||--o{ DOU_PROMOTION_PRODUCT : "包含" PRODUCT ||--o{ DOU_PROMOTION_PRODUCT : "被关联"