很多人在使用了CRMEB单商户系统之后,对于系统内的运费模版功能不会进行设置,在这篇文章内,我会对运费模版的设计与计算流程进行详细的解释,看过这篇文章的小伙伴们,就能按照自己的想法随意的设置运费模版啦!
运费模版添加
后台添加运费模版的页面,填写运费模版的名称,选择该运费模版是按照那种计费方式进行计费(件数,重量,体积),选择对应的城市数据,添加运费和包邮信息等。
运费模版的计算逻辑
如上图所示,如果购买的商品设置的是该运费模版,在计算运费的时候,会经过如下几个步骤。
1.先获取到用户订单的商品和地址信息,将所有的商品按照运费模版进行分组整理,得到每个运费模版的商品总数,总价和此运费模版的运费金额,指定包邮信息等。
$cartInfo变量里面存储的就是该订单下所有的商品信息,包括金额,件数或体积或重量,对应的运费模版ID等信息。
$addr里面包含用户现在选择的的地址信息,用于最后查询包邮或者运费。
$temp_num = [];
foreach ($cartInfo as $cart) {
$tempId = $cart['productInfo']['temp_id'] ?? 1;
$type = isset($temp[$tempId]['type']) ? $temp[$tempId]['type'] : $temp[1]['type'];
if ($type == 1) {
$num = $cart['cart_num'];
} elseif ($type == 2) {
$num = $cart['cart_num'] * $cart['productInfo']['attrInfo']['weight'];
} else {
$num = $cart['cart_num'] * $cart['productInfo']['attrInfo']['volume'];
}
$region = isset($regions[$tempId]) ? $regions[$tempId] : $regions[1];
if (!isset($temp_num[$cart['productInfo']['temp_id']])) {
$temp_num[$cart['productInfo']['temp_id']]['number'] = $num;
$temp_num[$cart['productInfo']['temp_id']]['price'] = bcmul($cart['cart_num'], $cart['truePrice'], 2);
$temp_num[$cart['productInfo']['temp_id']]['first'] = $region['first'];
$temp_num[$cart['productInfo']['temp_id']]['first_price'] = $region['first_price'];
$temp_num[$cart['productInfo']['temp_id']]['continue'] = $region['continue'];
$temp_num[$cart['productInfo']['temp_id']]['continue_price'] = $region['continue_price'];
$temp_num[$cart['productInfo']['temp_id']]['temp_id'] = $cart['productInfo']['temp_id'];
$temp_num[$cart['productInfo']['temp_id']]['city_id'] = $addr['city_id'];
} else {
$temp_num[$cart['productInfo']['temp_id']]['number'] += $num;
$temp_num[$cart['productInfo']['temp_id']]['price'] += bcmul($cart['cart_num'], $cart['truePrice'], 2);
}
}
2.按照用户当前选择的地址,根据当前地址数据内的city_id查询当前地址是否在指定包邮的地区内,然后在判断商品件数和金额是否大于设定的件数和金额,满足条件在运费模版的数组中删除此运费模版的数据。
/** @var ShippingTemplatesFreeServices $freeServices */
$freeServices = app()->make(ShippingTemplatesFreeServices::class);
foreach ($temp_num as $k => $v) {
if (isset($temp[$v['temp_id']]['appoint']) && $temp[$v['temp_id']]['appoint']) {
if ($freeServices->isFree($v['temp_id'], $v['city_id'], $v['number'], $v['price'])) {
unset($temp_num[$k]);
}
}
}
3.经过步骤2,$temp_num数组中,只会剩下需要计算运费的数据,系统接下来会在先计算出首件运费最大值,设置初始运费为0开始计算订单所需运费。
//首件运费最大值
$maxFirstPrice = $temp_num ? max(array_column($temp_num, 'first_price')) : 0;
//初始运费为0
$storePostage = 0;
4.循环计算运费,将首件最大的运费模版设置为首件计算,剩余的模版都按照续件进行金额的计算,如果有多个首件金额等于最大值,会将多个运费模版当作首件进行计算,最后取得运费最大值返回。
foreach ($temp_num as $fk => $fv) {
//找到首件运费等于最大值
if ($fv['first_price'] == $maxFirstPrice) {
//每次循环设置初始值
$tempArr = $temp_num;
$Postage = 0;
//计算首件运费
if ($fv['number'] <= $fv['first']) {
$Postage = bcadd($Postage, $fv['first_price'], 2);
} else {
if ($fv['continue'] <= 0) {
$Postage = $Postage;
} else {
$Postage = bcadd(bcadd($Postage, $fv['first_price'], 2), bcmul(ceil(bcdiv(bcsub($fv['number'], $fv['first'], 2), $fv['continue'] ?? 0, 2)), $fv['continue_price'], 4), 2);
}
}
//删除计算过的首件数据
unset($tempArr[$fk]);
//循环计算剩余运费
foreach ($tempArr as $cv) {
if ($cv['continue'] <= 0) {
$Postage = $Postage;
} else {
$Postage = bcadd($Postage, bcmul(ceil(bcdiv($cv['number'], $cv['continue'] ?? 0, 2)), $cv['continue_price'], 2), 2);
}
}
//获取运费计算中的最大值
if ($Postage > $storePostage) $storePostage = $Postage;
}
}