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

电商价格系统怎么设计?一次讲清一口价、活动价、券后价、价格快照与改价留痕

电商价格系统怎么设计?一次讲清一口价、活动价、券后价、价格快照与改价留痕

大家好,我是一名有 4 年工作经验的 Java 后端开发。
电商系统里,很多人一开始会觉得价格就是商品表里的一个字段,但真正做起来会发现,价格系统几乎会牵扯商品、营销、订单、优惠券、结算、审计一整条链路。
这篇文章我想系统聊一聊,电商价格系统到底应该怎么设计。

🦅个人主页
🐼

文章目录

  • 电商价格系统怎么设计?一次讲清一口价、活动价、券后价、价格快照与改价留痕
    • 一、前言
    • 二、价格系统里最容易混的几个概念
    • 三、推荐的整体设计思路
      • 3.1 基础价格层
      • 3.2 营销规则层
      • 3.3 订单结算层
    • 四、数据库怎么设计
      • 4.1 SKU 基础价格表
      • 4.2 价格变更记录表
      • 4.3 订单价格快照
    • 五、结算时怎么计算价格
    • 六、为什么一定要有价格快照
    • 七、最容易踩的坑
      • 7.1 把最终支付价直接写回商品表
      • 7.2 没有价格日志
      • 7.3 下单不落快照
      • 7.4 优惠分摊不清晰
    • 八、面试中怎么回答
    • 九、总结
    • 十、结尾

一、前言

很多项目最开始的商品表大概都会有这种字段:

product.id product.name product.price

刚开始看起来很简单,但业务一复杂,问题马上就来了:

  • 原价、售价、活动价到底存哪个?
  • 会员价放哪?
  • 满减、优惠券、平台补贴算谁的价格?
  • 价格改了以后,历史订单按哪个价格算?
  • 商品详情页显示价、购物车预估价、下单结算价为什么可能不一样?

所以价格系统真正要解决的,不是“多少钱”,而是:

在不同场景下,当前价格从哪里来、怎么算、如何留痕、如何和订单结算对齐。


二、价格系统里最容易混的几个概念

我建议至少先分清这些价格:

  • 吊牌价 / 原价
  • 销售价
  • 活动价
  • 会员价
  • 券后价
  • 结算价

其中最关键的一点是:

用户最终支付价格,并不一定应该直接落在商品表里。

很多时候商品表里适合存的是:

  • 基础销售价

而最终结算价要通过规则实时计算。


三、推荐的整体设计思路

我更建议价格系统按三层来拆:

3.1 基础价格层

描述 SKU 的基础价格:

  • 原价
  • 售价

3.2 营销规则层

描述额外变化:

  • 活动价
  • 限时折扣
  • 满减
  • 会员价
  • 平台补贴

3.3 订单结算层

最终在下单时计算:

  • 本次成交价
  • 优惠分摊
  • 实付金额

这样拆的好处是:

  • 商品价格和营销规则解耦
  • 历史订单价格可追溯
  • 改价和活动结束后不会污染订单历史

四、数据库怎么设计

4.1 SKU 基础价格表

CREATETABLEsku_price(sku_idBIGINTPRIMARYKEY,origin_priceDECIMAL(10,2)NOTNULL,sale_priceDECIMAL(10,2)NOTNULL,currencyVARCHAR(8)NOTNULLDEFAULT'CNY',updated_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP);

4.2 价格变更记录表

CREATETABLEsku_price_log(idBIGINTPRIMARYKEYAUTO_INCREMENT,sku_idBIGINTNOTNULL,before_origin_priceDECIMAL(10,2)DEFAULTNULL,before_sale_priceDECIMAL(10,2)DEFAULTNULL,after_origin_priceDECIMAL(10,2)DEFAULTNULL,after_sale_priceDECIMAL(10,2)DEFAULTNULL,operator_idBIGINTDEFAULTNULL,reasonVARCHAR(255)DEFAULTNULL,created_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMP);

4.3 订单价格快照

订单明细里建议直接落快照:

CREATETABLEorder_item(idBIGINTPRIMARYKEYAUTO_INCREMENT,order_idBIGINTNOTNULL,sku_idBIGINTNOTNULL,sku_nameVARCHAR(128)NOTNULL,sale_priceDECIMAL(10,2)NOTNULL,final_priceDECIMAL(10,2)NOTNULL,discount_amountDECIMAL(10,2)NOTNULLDEFAULT0,quantityINTNOTNULL);

这一步特别重要,因为:

商品未来价格可以变,但历史订单价格不能跟着漂。


五、结算时怎么计算价格

我更建议按这个顺序算:

  1. 取 SKU 基础销售价
  2. 应用活动价或会员价
  3. 计算店铺优惠 / 平台优惠
  4. 计算优惠券分摊
  5. 落订单快照

也就是说:

订单价格不是查一个字段,而是一条计算链。


六、为什么一定要有价格快照

如果没有价格快照,后面会出现很多问题:

  • 商品改价后,历史订单无法对账
  • 售后退款不知道按哪个价格退
  • 财务对账口径不一致
  • 用户投诉时拿不出当时成交价依据

所以我建议:

  • 商品表存当前价格
  • 订单表存成交快照
  • 日志表存改价记录

七、最容易踩的坑

7.1 把最终支付价直接写回商品表

这会把商品价格和订单价格彻底混乱。

7.2 没有价格日志

后面很难知道谁改了价格、为什么改。

7.3 下单不落快照

历史订单价格无法稳定复盘。

7.4 优惠分摊不清晰

平台补贴、店铺让利、优惠券抵扣混在一起,后面结算很容易扯不清。


八、面试中怎么回答

如果面试官问你:

电商价格系统一般怎么设计?

你可以这样回答:

第一,我不会把价格简单理解成商品表里的一个字段,而会把价格拆成基础价格、营销规则和订单结算三层。商品表更多承载基础销售价,活动价、会员价、优惠券等规则在结算时动态参与计算。

第二,订单下单时我一定会落价格快照,包括原销售价、优惠金额和最终成交价,因为商品价格未来可能变化,但历史订单价格必须可追溯。

第三,我还会单独设计价格变更日志表,记录谁改了价格、改前改后是多少、为什么改,这样后续排障、审计和结算都更清楚。


九、总结

价格系统真正难的,不是“字段怎么命名”,而是如何把:

  • 当前商品价格
  • 营销规则
  • 历史成交价
  • 改价留痕

这几层真正拆开。

如果只记一句结论,我觉得可以记住这句:

商品表适合存当前价格,订单表必须存成交快照,价格规则和价格日志不能混在一起。


十、结尾

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注。
后面我会继续整理一些更偏实战的 Java 后端和电商系统设计文章。

http://www.jsqmd.com/news/661905/

相关文章:

  • Git合并策略实战:从merge、rebase到squash的进阶指南
  • 今天不看就晚了:AGI创造性能力评估标准即将升级,3大新增硬性阈值倒计时披露
  • Open Images Dataset V6 + Extensions:一站式获取与实战转换目标检测数据集
  • K8s访问控制
  • 2026天津家暴离婚律所专项测评!人身保护令+损害赔偿实战指南 - 速递信息
  • 3步终极清理方案:彻底解决Visual Studio卸载残留问题
  • Android应用卡顿?从SurfaceFlinger的VSYNC信号与缓冲区管理说起
  • VSCode + Mermaid本地画图最强组合:无需插件,一个HTML文件搞定所有图表
  • K8s控制平面升级
  • 树莓派直连巴法云:TCP与MQTT双协议实战指南
  • STM32CubeMX实战:ADC采集光敏电阻数据实现环境光照监测
  • 高通Camera驱动(4)-- 从configure_streams到Usecase的创建与匹配
  • 余杭永鸿再生资源:杭州市废旧金属回收推荐哪几家 - LYL仔仔
  • STM32H743实战(三)-- 时钟树配置与性能调优实战
  • 5款AI工具大测评,助你轻松实现低查重的AI教材生成梦想!
  • 别再死记硬背了!用H模型和Π模型,手把手教你搞定三极管高频电路设计
  • 从光场相机到手机摄影:聊聊那些让你‘先拍照后对焦’的黑科技是怎么实现的
  • 漂浮式半潜风机(二)环境荷载:从理论谱分析到工程实践的关键考量
  • 基于MAVROS的Offboard模式实现无人机精准悬停控制
  • OP-TEE安全存储深度解析(一):密钥体系与文件加密流程
  • 从CTF题[鹤城杯 2021]EasyP剖析PHP安全:$_SERVER变量、正则绕过与basename的攻防实战
  • 2026天津协议离婚vs诉讼离婚律所测评!快速办结+权益保障指南 - 速递信息
  • 别再手动敲AT指令了!用正点原子官方软件搞定以太网转串口模块配置(附静态IP设置避坑点)
  • 如何在Chrome浏览器中实现一键画中画视频播放:终极免费扩展指南
  • Python中的常用函数使用及说明
  • 神经网络遗传算法函数极值寻优(非线性函数极值)
  • Attention U-Net:让模型学会“看”哪里
  • 从零开始构建SaaS多租户架构:SpringBoot + MyBatis-Plus动态数据源实战
  • 用Java Stream一行代码搞定彩票随机选号(双色球/大乐透)
  • Mysql--基础知识点--102--redo log内容