添加:商品详情 - 物流切换列表中不显示不符合条件的物流

优化:商品详情 - 默认显示运费最低的物流。
This commit is contained in:
wuhui_zzw 2023-08-29 10:36:27 +08:00
parent caf65fa1d8
commit df8cff8869
5 changed files with 123 additions and 49 deletions

View File

@ -37,6 +37,7 @@ class Logistics extends Base{
public static function getAll(int $countryId,$field = ['id','name','warehouse_name','type','day_min','day_max']){
$list = self::select($field)
->whereRaw(\DB::raw('FIND_IN_SET('.$countryId.',country_ids)'))
->with(['weights'])
->orderBy('position','ASC')
->orderBy('id','ASC')
->get();
@ -45,7 +46,57 @@ class Logistics extends Base{
return $list ? $list->toArray() : [];
}
/**
* Common: 物流过滤 - 根据商品和物流列表过滤 仅返回有效的物流
* Author: wu-hui
* Time: 2023/08/29 10:02
* @param $logisticsList
* @param $productsList
* @return array|array[]
*/
public static function LogisticsFiltering($logisticsList,$productsList){
$eligibleList = array_map(function($logisticsItem) use ($productsList){
// 判断:物流是否按照重量计算 weight按重量计费num按数量计费free卖家包邮
if($logisticsItem['type'] == 'weight'){
$weights = (array)$logisticsItem['weights'];// 续重区间列表
$firstWeight = (float)$logisticsItem['first_weight'];// 首重
if(!$weights) {
$logisticsItem = [];
}else{
// 循环判断:只要有一个商品不符合条件 则当前物流不可用;
foreach($productsList as $productItem){
$surplusWeight = $productItem['sum_weight'] - $firstWeight;// 总重量 - 减首重 = 剩余重量
// 判断如果剩余重量小于等于0 则符合条件;否则计算续重区间
if($surplusWeight <= 0){
continue;
}else{
$eligibleCount = collect($weights)
->where('min','<=',$surplusWeight)
->where('max','>',$surplusWeight)
->count();
if($eligibleCount <= 0) {
$logisticsItem = [];
break;
}
}
}
}
}
return $logisticsItem;
},$logisticsList);
return array_filter($eligibleList);
}
public function country(){
return $this->belongsTo(Country::class,'country_id','id');
}
public function weights(){
return $this->hasMany(LogisticsWeight::class,'logistics_id','id');
}
}

View File

@ -149,7 +149,14 @@ class ProductController extends Controller
return json_success(trans('common.success'),$totals);
}
// 获取物流列表
/**
* Common: 获取物流列表
* Author: wu-hui
* Time: 2023/08/29 10:06
* @param Request $request
* @return array
* @throws \Exception
*/
public function productsLogistics(Request $request){
$data = [
'list' => [],
@ -191,10 +198,14 @@ class ProductController extends Controller
$request->change_logistics_id = $logisticsItem['id'];
$totals = $this->computeOrderMoney($request);
$shipping = array_column($totals['data'],null,'code')['shipping'] ?? [];
$logisticsItem['shipping_fee'] = $shipping['show_tips'] == 0 ? $shipping['amount_format'] : trans('shop/carts.to_be_negotiated');
// $logisticsItem['shipping_fee'] = $shipping['show_tips'] == 0 ? $shipping['amount_format'] : trans('shop/carts.to_be_negotiated');
if($shipping['show_tips'] == 0) $logisticsItem['shipping_fee'] = $shipping['amount_format'];
else $logisticsItem = [];
}
}
$data['list'] = array_filter($data['list']);
return json_success(trans('common.success'),$data);
}

View File

@ -21,7 +21,8 @@ use Beike\Shop\Services\CheckoutService;
use Illuminate\Support\Str;
class ShippingService{
protected static $country;
protected static $country;// 国家信息
protected static $productsList;// 商品分组统计列表
// 运费计算
public static function getTotal(CheckoutService $checkout): ?array{
@ -50,40 +51,33 @@ class ShippingService{
$amount = (float)(new $className)->getShippingFee($checkout);
}
else{
// 商品信息处理 获取同一个商品的数量、重量
$products = $totalService->getCartProducts();
self::$productsList = collect($products)->groupBy('product_id')->map(function($group){
$firstInfo = $group->first();
$productWeightInfo = Product::query()
->select(['id','weight','weight_class'])
->find($firstInfo['product_id']);
if($productWeightInfo) $productWeightInfo = $productWeightInfo->toArray();
// 重量转换 - 物流重量单位为 千克;商品重量需要进行转换
$weight = $productWeightInfo['weight'] ?? 0;
$sumQuantity = $group->sum('quantity');
$sumWeight = (float)sprintf("%.2f",($weight * $sumQuantity));
$weightClass = $productWeightInfo['weight_class'];
$sumWeight = Weight::convert($sumWeight,$weightClass);// 总重量 单位:克
return [
'product_id' => $firstInfo['product_id'],
'sum_quantity' => $sumQuantity,
'sum_weight' => $sumWeight,
'weight' => $weight,
'weight_class' => $weightClass,
];
});
// 通过物流进行计算
$logisticsId = (int)$checkout->cart->shipping_method_code;
$logisticsInfo = self::getLogistics($logisticsId,$checkout->cart);
if($logisticsInfo) {
// 商品信息处理 获取同一个商品的数量
$products = $totalService->getCartProducts();
$productsList = collect($products)->groupBy('product_id')->map(function($group){
$firstInfo = $group->first();
$productWeightInfo = Product::query()
->select(['id','weight','weight_class'])
->find($firstInfo['product_id']);
if($productWeightInfo) $productWeightInfo = $productWeightInfo->toArray();
// 重量转换 - 物流重量单位为 千克;商品重量需要进行转换
$weight = $productWeightInfo['weight'] ?? 0;
$sumQuantity = $group->sum('quantity');
$sumWeight = (float)sprintf("%.2f",($weight * $sumQuantity));
$weightClass = $productWeightInfo['weight_class'];
$sumWeight = Weight::convert($sumWeight,$weightClass);// 总重量 单位:克
return [
'product_id' => $firstInfo['product_id'],
'sum_quantity' => $sumQuantity,
'sum_weight' => $sumWeight,
'weight' => $weight,
'weight_class' => $weightClass,
];
});
// weight按重量计费num按数量计费free卖家包邮
$logisticsHandleFun = 'compute_'.$logisticsInfo['type'];
$amount = self::$logisticsHandleFun($logisticsInfo,$productsList);
}
else{
// 如果还是不能获取物流信息 则显示 待协商
$showTips = 1;
}
if($logisticsInfo) $amount = $logisticsInfo['amount'];// 存在物流 获取运费
else $showTips = 1;// 如果还是不能获取物流信息 则显示 待协商
}
$totalData = [
'code' => 'shipping',
@ -109,7 +103,7 @@ class ShippingService{
* @return array|mixed|mixed[]
*/
private static function getLogistics($logisticsId,$cart){
$logisticsField = ['type', 'name','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee'];
$logisticsField = ['id','type', 'name','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee'];
// 判断:客服端是否切换国家 如果存在切换的国家id 则使用切换的国家id不存在则继续执行
$countryId = (int)request()->input('products_country_id');
if($countryId > 0) {
@ -120,6 +114,7 @@ class ShippingService{
// 同时存在国家ID 获取物流ID
$logisticsInfo = Logistics::query()
->whereRaw(\DB::raw('FIND_IN_SET('.$countryId.',country_ids)'))
->with(['weights'])
->where('id',$logisticsId)
->select($logisticsField)
->first();
@ -127,7 +122,9 @@ class ShippingService{
// 刷新国家信息
self::refreshCurrentCountry($countryId);
return $logisticsInfo->toArray();
$logisticsList = [$logisticsInfo->toArray()];
goto logisticsListHandle;
}
}
// 仅存在国家ID时
@ -146,25 +143,41 @@ class ShippingService{
// 刷新国家信息
self::refreshCurrentCountry($countryId);
return $logisticsList[0] ?? [];
}else{
// 获取物流信息
$logisticsInfo = Logistics::query()
->with(['weights'])
->select($logisticsField)
->find($logisticsId);
return $logisticsInfo ? $logisticsInfo->toArray() : [];
$logisticsList = [$logisticsInfo ? $logisticsInfo->toArray() : []];
}
// 根据已查询的物流列表 筛选出符合条件的物流并且返回第一个
logisticsListHandle:
$eligibleLogisticsList = Logistics::LogisticsFiltering($logisticsList,self::$productsList);
// 循环计算物流运费
foreach($eligibleLogisticsList as &$eligibleLogisticsListItem){
// weight按重量计费num按数量计费free卖家包邮
$logisticsHandleFun = 'compute_'.$eligibleLogisticsListItem['type'];
$eligibleLogisticsListItem['amount'] = (float)self::$logisticsHandleFun($eligibleLogisticsListItem);
}
// 存在多个物流 需要获取运费最小的物流
if(count($eligibleLogisticsList) > 1){
$amounts = array_column($eligibleLogisticsList,'amount');
array_multisort($amounts,SORT_ASC,$eligibleLogisticsList);
}
return $eligibleLogisticsList[0] ?? [];
}
/**
* Common: 运费计算 - 物流运费 - 运费计算(按重量计费)
* Author: wu-hui
* Time: 2023/08/22 15:34
* @param $logisticsInfo
* @param $productsList
* @return float|int
*/
private static function compute_weight($logisticsInfo,$productsList){
private static function compute_weight($logisticsInfo){
/**
* 计算规则:
* 总重量 - 低于首重;则运费 = 【首重运费】
@ -176,7 +189,7 @@ class ShippingService{
$addWeight = (float)$logisticsInfo['add_weight'];// 每增加重量
$continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续重运费
// 循环处理商品
foreach($productsList as $productInfo){
foreach(self::$productsList as $productInfo){
// 首重运费
$amount += (float)sprintf("%.2f",$firstWeightFee);
// 判断:如果总重量超过首重 则计算续重运费
@ -191,10 +204,9 @@ class ShippingService{
* Author: wu-hui
* Time: 2023/08/22 14:47
* @param $logisticsInfo
* @param $productsList
* @return float|int
*/
private static function compute_num($logisticsInfo,$productsList){
private static function compute_num($logisticsInfo){
/**
* 计算规则:
* 购买数量 - 低于首件数量;则运费 = 【首件运费】
@ -206,7 +218,7 @@ class ShippingService{
$addWeight = (int)$logisticsInfo['add_weight'];// 每增加件
$continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续件运费
// 循环处理商品
foreach($productsList as $productInfo){
foreach(self::$productsList as $productInfo){
// 首件运费
$amount += (float)sprintf("%.2f",$firstWeightFee);
// 判断:如果数量超过首件数量 则计算续件运费
@ -221,10 +233,9 @@ class ShippingService{
* Author: wu-hui
* Time: 2023/08/22 11:59
* @param $logisticsInfo
* @param $productsList
* @return int
*/
private static function compute_free($logisticsInfo,$productsList){
private static function compute_free($logisticsInfo){
return 0;
}
@ -240,8 +251,6 @@ class ShippingService{
/**
* 通过配送方式获取插件编码
*

View File

@ -623,6 +623,7 @@
_this.goods_list = list;
_this.computeOrderMoney();
_this.$refs['select-logistics'].getLogisticsList()
// let price = 0;
// if (this.numPrices.light == 0) {
@ -653,7 +654,9 @@
};
})
_this.goods_list = list;
_this.computeOrderMoney();
_this.$refs['select-logistics'].getLogisticsList()
}
}
},

View File

@ -99,7 +99,7 @@
goods_list: JSON.stringify(_this.goods_list),
}).then((res) => {
if(res.status === 'success'){
_this.logistics_list = res.data.list || {};
_this.logistics_list = Object.values(Object.assign({},res.data.list || {})) ;
_this.country = res.data.country || {};
}
})