5.4 KiB
5.4 KiB
“一客一价” (客户专属单品折扣) 改造设计方案
1. 背景与业务痛点
- 当前系统瓶颈:目前系统仅支持“全局统一折扣”或“商品级统一折扣”。也就是说,如果给商品 A 设置了 8 折,那么所有 VIP 卡客户买商品 A 都是 8 折。
- 新业务需求:为了精细化管理客户(尤其是 B2B 批发客户或核心大客户),需要实现客户维度与商品维度的交叉定价。例如:核心客户张三由于拿货量大,商品 A 给他 7.5 折;而普通客户李四拿货少,商品 A 只能给他 9 折;同时,张三买商品 B 可能利润薄,这件只给 95 折。
- 业务目标:打造千人千面的私有价格体系(一客一价),增强熟客黏性。
2. 数据库设计 (Database Schema)
由于需求属于“多对多”(多客户对应多商品,各有独立折扣价),必须引入一张新的映射关联表。
新增关联表:ml_user_product_discounts
我们需要在 Supabase 中创建这张记录专属折扣的桥接表。
CREATE TABLE ml_user_product_discounts (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL, -- 关联:客户(买家) ID
product_id UUID NOT NULL, -- 关联:商品 ID
discount_rate NUMERIC NOT NULL, -- 该客户买该商品的专属折扣率 (例如 0.75)
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, product_id) -- 核心约束:保证同个客户对同个商品只有一条有效规则
);
-- 出于性能考虑,建议在 `user_id` 和 `product_id` 上添加索引,方便检索某个用户购物车里商品的价格。
CREATE INDEX idx_user_discount_user ON ml_user_product_discounts(user_id);
(附注:该表的数据由商家端维护分配,买家端在此表面前仅为“只读查询”角色。)
3. 商家端 (Merchant App) 功能拆解
系统需要提供给商家的管理入口从“发商品时”转移到“管客户时”。
3.1 【客户分析/管理】入口
- 若当前缺少直接管理消费者的模块,需先建设一个简单的【客户列表页】,加载已在平台注册/下单过的用户。
- 点击具体用户,进入【客户详情管理页】。
3.2 专属商品折扣分配功能
- 功能入口:在【客户详情页】底部增加按钮或标签卡——「配置专属折扣商品」。
- 交互流程:
- 商家调出平台的全量商品列表面板(可能带有搜索与分类)。
- 商家勾选指定的若干个商品,将它们加入到此客户的“专属打折清单”中。
- 出现在专属清单中的每一个商品,商家可通过步进器或输入框单独设置对于该客户的专属折扣率。
- 提交保存后,数据
UPSERT存入ml_user_product_discounts表。 - 商家也可以随时将某个商品从该客户的专属清单中踢出(删除记录)。
3.3 系统融合建议
- 如果商家发现给每个特定商品设价格太累,仍可以保留“商品通用VIP折扣”作为保底。
4. 消费者端 (Consumer App) 核心计价降级逻辑 (重要!)
在价格体系变得复杂后,消费者渲染的价格、加入购物车的价格、结算付款时的价格,这三端必须遵循绝对严格的“逐层降级(Fallback)”查询机制。
价格优先级链条设定如下(权重由高到低):
- 👑 T0 级别(最高):一客一价
- 前端去查当前商品是否在
ml_user_product_discounts里有当前用户的专属记录。如果有,以此为准。(如:张三专属 75 折)
- 前端去查当前商品是否在
- 🥇 T1 级别:单品通用 VIP 折扣
- 如果 T0 没有,接着查
ml_products中该商品的is_vip_discount是否为 true 且配置了vip_discount_rate。如果有,以此为准。(如:全民VIP买此衣服 8 折)
- 如果 T0 没有,接着查
- 🥈 T2 级别:全站全局 VIP 折扣
- 如果 T1 也没有,接着查询该用户绑定等级的全局默认折扣(如:白银会员全场 95 折,如果在历史版本中还在生效的话)。
- 🥉 T3 级别(底线):原价销售
- 兜底机制,以原先的
base_price(销售商品原价)售卖。
- 兜底机制,以原先的
4.1 查询性能优化 (购物车与订单结算)
防止 N+1 查询问题:当用户在购物车勾选了 20 个不同商品进行结算时,绝对不能在后端使用循环去数据库查 20 次个人折扣表!
- 正确做法:将购物车里所有商品的
product_id组装成一个数组。执行一次SELECT * FROM ml_user_product_discounts WHERE user_id = 'xxx' AND product_id IN (id1, id2, id3...);构建一个映射字典(Map/Hash),然后在内存在结算链中匹配。
5. 项目分期与落地计划
为了控制风险保障业务不中断,建议采取“两周敏捷迭代”策略。
- Phase 1 (第一期):打通通道与数据库
- 在 Supabase
ml_user_product_discounts建表与打入测试数据。 - 改写买家端商品详情与结算页的逻辑,先完成后端价格过滤模型。这一步让消费者能准确以多级降级的形式算清最后的价格。
- 在 Supabase
- Phase 2 (第二期):商家端可视化管理体系
- 开发并上线商家的【客户管理页】。
- 根据客户维度拉取列表,并制作批量打折与分配商品的界面。
- 上线后通知业务方进行试发价。