电商价格系统怎么设计一次讲清一口价、活动价、券后价、价格快照与改价留痕大家好我是一名有 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)NOTNULLDEFAULTCNY,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);这一步特别重要因为商品未来价格可以变但历史订单价格不能跟着漂。五、结算时怎么计算价格我更建议按这个顺序算取 SKU 基础销售价应用活动价或会员价计算店铺优惠 / 平台优惠计算优惠券分摊落订单快照也就是说订单价格不是查一个字段而是一条计算链。六、为什么一定要有价格快照如果没有价格快照后面会出现很多问题商品改价后历史订单无法对账售后退款不知道按哪个价格退财务对账口径不一致用户投诉时拿不出当时成交价依据所以我建议商品表存当前价格订单表存成交快照日志表存改价记录七、最容易踩的坑7.1 把最终支付价直接写回商品表这会把商品价格和订单价格彻底混乱。7.2 没有价格日志后面很难知道谁改了价格、为什么改。7.3 下单不落快照历史订单价格无法稳定复盘。7.4 优惠分摊不清晰平台补贴、店铺让利、优惠券抵扣混在一起后面结算很容易扯不清。八、面试中怎么回答如果面试官问你电商价格系统一般怎么设计你可以这样回答第一我不会把价格简单理解成商品表里的一个字段而会把价格拆成基础价格、营销规则和订单结算三层。商品表更多承载基础销售价活动价、会员价、优惠券等规则在结算时动态参与计算。第二订单下单时我一定会落价格快照包括原销售价、优惠金额和最终成交价因为商品价格未来可能变化但历史订单价格必须可追溯。第三我还会单独设计价格变更日志表记录谁改了价格、改前改后是多少、为什么改这样后续排障、审计和结算都更清楚。九、总结价格系统真正难的不是“字段怎么命名”而是如何把当前商品价格营销规则历史成交价改价留痕这几层真正拆开。如果只记一句结论我觉得可以记住这句商品表适合存当前价格订单表必须存成交快照价格规则和价格日志不能混在一起。十、结尾如果你觉得这篇文章对你有帮助欢迎点赞、收藏、关注。后面我会继续整理一些更偏实战的 Java 后端和电商系统设计文章。