导读:运费看似小事,算错一次就可能亏掉整单毛利或引发客诉。多数商城用"全国统一包邮"糊弄过去,跨区域就崩。本文拆解运费的三层建模:模板规则、计价因子、匹配优先级。
运费系统如果做成"一个字段存运费",后期必然改不动。正确做法拆成三层:模板是一次业务配置的完整运费方案;规则是模板下的计价规则,如"首重 1kg 内 8 元""满 99 包邮";计价是下单时计算运费的过程。
CREATE TABLE freight_template (id INT PRIMARY KEY, name VARCHAR(64), status TINYINT DEFAULT 1);
CREATE TABLE freight_rule (
id INT PRIMARY KEY,
template_id INT NOT NULL,
region_code VARCHAR(16),
weight_end DECIMAL(8,2),
first_fee DECIMAL(8,2),
extra_fee DECIMAL(8,2),
min_amount DECIMAL(10,2),
priority INT DEFAULT 0
);配置与计算分离后,改运费不动代码,运营在后台调模板即可。
计价因子通常有四个:区域决定适用哪套费率,是第一个过滤条件;重量决定首重/续重计费,商品需维护重量字段;件数按件计费时使用,与重量计费互斥;金额门槛是满额包邮的判定条件。
// 计价因子归一化:重量与件数二选一
function normalizeItem(item) {
return item.byWeight
? { key: 'weight', value: item.weight * item.quantity }
: { key: 'count', value: item.quantity };
}要点:不要同时启用"重量"和"件数",否则规则自相矛盾;金额门槛放在区域规则之后判定,避免跨区域误判包邮。
同一订单可能命中多条规则,必须定死匹配顺序。常用两种策略:最细粒度优先(华东 > 江苏 > 苏州,区域越精确越优先)和最惠优先(取计费最低的一条)。
// 最细粒度优先:region 越具体优先级越高,priority 字段兜底
function pickRule(rules, region) {
return rules
.filter(r => !r.region_code || region.startsWith(r.region_code))
.sort((a, b) => {
const da = a.region_code ? a.region_code.length : 0;
const db = b.region_code ? b.region_code.length : 0;
return db - da || b.priority - a.priority;
})[0];
}"最细粒度优先"更可预期:配置什么就执行什么,不会出现包邮吞掉偏远地区加价。
把上面逻辑串成一次完整计价:
function calcFreight(order, region, rules) {
const rule = pickRule(rules, region);
if (!rule) return null;
if (order.amount >= rule.min_amount) return 0;
if (order.totalWeight <= rule.weight_end) return rule.first_fee;
const extra = Math.ceil((order.totalWeight - rule.weight_end) / 1);
return rule.first_fee + extra * rule.extra_fee;
}两个细节:金额门槛用商品金额(优惠前的货款)判定,否则订单被抵扣后频繁触发免运费;重量向上取整按整 kg 计,避免计价混乱。
最大的坑是"改模板影响历史订单"。解决办法是下单时做快照:订单里记录当时命中的规则与金额,后续改模板不影响已生成订单。
# 每日对账:检查"计费 0 但商品金额低于门槛"的异常订单
awk -F',' '$6 == 0 && $5 < 99 {print "异常订单:", $1}' orders_daily.csv后台重算只对未发货订单开放,且必须留操作日志。对账脚本要发现两类问题:门槛被绕过、规则未命中。
运费模板的关键是把"配置"与"计算"分离,并固定匹配优先级。同类分层在乔拓云商城的交易模块中有对应实现,模板与规则配置可直接复用本文的分层思路。
运费模块的复杂度不在"算一次",而在"长期可维护"。把三层模型立起来、优先级定死、快照与对账补齐,商城在多区域、多仓并存时也能保持计费准确。先从一张模板表开始,再逐步加规则。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。