|
|
@@ -1,4 +1,5 @@
|
|
|
<?php
|
|
|
+
|
|
|
namespace common\components\delivery\util;
|
|
|
|
|
|
use biz\shop\classes\ShopClass;
|
|
|
@@ -16,7 +17,7 @@ class DeliveryQuoteUtil
|
|
|
{
|
|
|
/**
|
|
|
* 获取配送报价(含免费配送规则计算)
|
|
|
- *
|
|
|
+ *
|
|
|
* @param array $params 参数数组
|
|
|
* - productList: 商品列表 [['bigNum' => 数量, 'weight' => 重量], ...]
|
|
|
* - deliveryPlatform: 配送平台(shansong/huolala/fengniao等)
|
|
|
@@ -25,37 +26,37 @@ class DeliveryQuoteUtil
|
|
|
* - order: 订单基础信息 ['orderSn' => xxx, 'itemTotalAmount' => xxx, 'remark' => xxx]
|
|
|
* - mainId: 当前操作者的 mainId
|
|
|
* - productCount: 商品总数量(用于免费配送判断)
|
|
|
- *
|
|
|
+ *
|
|
|
* @return array 返回数组
|
|
|
* - sendCost: 配送费用(元)
|
|
|
* - sendDistance: 配送距离(米)
|
|
|
* - deliveryList: 可选配送方式列表
|
|
|
* - platformQuotes: 原始平台报价数据
|
|
|
- *
|
|
|
+ *
|
|
|
* @throws \Exception 当报价失败时抛出异常
|
|
|
*/
|
|
|
public static function getDeliveryQuote($params)
|
|
|
{
|
|
|
// 1. 参数验证
|
|
|
self::validateParams($params);
|
|
|
-
|
|
|
+
|
|
|
// 2. 计算商品总重量
|
|
|
$weight = self::calculateTotalWeight($params['productList']);
|
|
|
-
|
|
|
+
|
|
|
// 3. 构建订单数据
|
|
|
$order = self::buildOrderData($params, $weight);
|
|
|
-
|
|
|
+
|
|
|
// 4. 获取供货商店铺信息
|
|
|
$ghsShop = ShopClass::getById($params['ghsInfo']['shopId']);
|
|
|
if (empty($ghsShop)) {
|
|
|
throw new \Exception("供货商店铺信息不存在:shopId={$params['ghsInfo']['shopId']}");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 5. 调用跑腿平台获取报价
|
|
|
$orderTime = date('Y-m-d H:i:s');
|
|
|
$ds = new DispatchService($params['ghsInfo']['mainId'], $params['deliveryPlatform']);
|
|
|
$platformQuotes = $ds->getAllPlatformPrice($order, $ghsShop, $orderTime);
|
|
|
-
|
|
|
+
|
|
|
// 6. 检查报价结果
|
|
|
if (isset($platformQuotes['error'])) {
|
|
|
$errorMsg = $platformQuotes['error'];
|
|
|
@@ -63,17 +64,17 @@ class DeliveryQuoteUtil
|
|
|
noticeUtil::push("{$params['deliveryPlatform']}-跑腿平台估价接口获取费用与距离失败:mainId={$params['mainId']}");
|
|
|
throw new \Exception($errorMsg);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 7. 格式化平台报价
|
|
|
$deliveryList = $ds->formatPlatformQuotesForDisplay($platformQuotes);
|
|
|
-
|
|
|
+
|
|
|
// 8. 重试机制(如果第一次失败)
|
|
|
if (is_array($deliveryList) && empty($deliveryList)) {
|
|
|
sleep(2);
|
|
|
$platformQuotes = $ds->getAllPlatformPrice($order, $ghsShop, $orderTime);
|
|
|
$deliveryList = $ds->formatPlatformQuotesForDisplay($platformQuotes);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 9. 检查是否有可用的配送方式
|
|
|
if (is_array($deliveryList) && empty($deliveryList)) {
|
|
|
$errorMsg = "ghsMainId={$params['ghsInfo']['mainId']}, orderSn={$order['orderSn']} 请求{$params['deliveryPlatform']}平台报价失败。";
|
|
|
@@ -81,33 +82,33 @@ class DeliveryQuoteUtil
|
|
|
Yii::error($errorMsg);
|
|
|
throw new \Exception($errorMsg);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 10. 获取报价结果
|
|
|
$result = null;
|
|
|
- if(in_array($params['deliveryPlatform'], ['huolala', 'fengniao'])){
|
|
|
+ if (in_array($params['deliveryPlatform'], ['huolala', 'fengniao'])) {
|
|
|
$bracketContent = $params['deliveryBracketContent'] ?? '';
|
|
|
$key = '';
|
|
|
- foreach($deliveryList as $item){
|
|
|
- if($params['deliveryPlatform'] == 'huolala'){
|
|
|
+ foreach ($deliveryList as $item) {
|
|
|
+ if ($params['deliveryPlatform'] == 'huolala') {
|
|
|
$key = 'vehicle_type';
|
|
|
}
|
|
|
- if($params['deliveryPlatform'] == 'fengniao'){
|
|
|
+ if ($params['deliveryPlatform'] == 'fengniao') {
|
|
|
$key = 'base_goods_id';
|
|
|
}
|
|
|
- if($item[$key] == $bracketContent){
|
|
|
+ if ($item[$key] == $bracketContent) {
|
|
|
$result = $item;
|
|
|
}
|
|
|
}
|
|
|
- if($result === null){
|
|
|
+ if ($result === null) {
|
|
|
throw new \Exception('没有找到对应的配送方式');
|
|
|
}
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
$result = $deliveryList[0];
|
|
|
}
|
|
|
|
|
|
$sendCost = ($result['price'] ?? 0) / 100;
|
|
|
$sendDistance = $result['distance'] ?? 0;
|
|
|
-
|
|
|
+
|
|
|
// 11. 应用免费配送规则
|
|
|
$finalSendCost = self::applyFreeDeliveryRules(
|
|
|
$sendCost,
|
|
|
@@ -118,7 +119,7 @@ class DeliveryQuoteUtil
|
|
|
$params['ghsInfo']['mainId'],
|
|
|
$order['orderSn']
|
|
|
);
|
|
|
-
|
|
|
+
|
|
|
return [
|
|
|
'sendCost' => $finalSendCost,
|
|
|
'sendDistance' => $sendDistance,
|
|
|
@@ -126,10 +127,10 @@ class DeliveryQuoteUtil
|
|
|
'platformQuotes' => $platformQuotes,
|
|
|
];
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 计算商品总重量
|
|
|
- *
|
|
|
+ *
|
|
|
* @param array $productList 商品列表
|
|
|
* @return float 总重量(公斤)
|
|
|
*/
|
|
|
@@ -147,10 +148,10 @@ class DeliveryQuoteUtil
|
|
|
|
|
|
return $weight;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 构建订单数据
|
|
|
- *
|
|
|
+ *
|
|
|
* @param array $params 参数数组
|
|
|
* @param float $weight 总重量
|
|
|
* @return array 订单数据
|
|
|
@@ -159,7 +160,7 @@ class DeliveryQuoteUtil
|
|
|
{
|
|
|
$custom = $params['custom'];
|
|
|
$orderInfo = $params['order'];
|
|
|
-
|
|
|
+
|
|
|
return [
|
|
|
'orderSn' => $orderInfo['orderSn'],
|
|
|
'customName' => $custom->name,
|
|
|
@@ -177,10 +178,10 @@ class DeliveryQuoteUtil
|
|
|
'actPrice' => $orderInfo['itemTotalAmount'] ?? 0,
|
|
|
];
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 应用免费配送规则
|
|
|
- *
|
|
|
+ *
|
|
|
* @param float $sendCost 原始配送费用
|
|
|
* @param int $sendDistance 配送距离(米)
|
|
|
* @param int $shopId 店铺ID
|
|
|
@@ -198,7 +199,8 @@ class DeliveryQuoteUtil
|
|
|
$itemTotalAmount,
|
|
|
$ghsMainId,
|
|
|
$orderSn
|
|
|
- ) {
|
|
|
+ )
|
|
|
+ {
|
|
|
// 获取店铺扩展信息(免费配送设置)
|
|
|
$shopExt = ShopExtClass::getByCondition(['shopId' => $shopId], false, null, 'id,hcFreeKm,hcMap,hsFreeKm,hsAddFee');
|
|
|
if (empty($shopExt)) {
|
|
|
@@ -206,16 +208,16 @@ class DeliveryQuoteUtil
|
|
|
}
|
|
|
|
|
|
// XSD_CS- KD_CS-
|
|
|
- if(strstr($orderSn, 'XSD_CS') || strstr($orderSn, 'XSD')){//花材
|
|
|
+ if (strstr($orderSn, 'XSD_CS') || strstr($orderSn, 'XSD')) {//花材
|
|
|
// 获取花材的免费配送设置
|
|
|
$hcFreeKm = ($shopExt['hcFreeKm'] ?? 0) * 1000; // 转换为米
|
|
|
$hcMapString = $shopExt['hcMap'] ?? '';
|
|
|
$hcMap = [];
|
|
|
-
|
|
|
+
|
|
|
if (!empty($hcMapString)) {
|
|
|
$hcMap = json_decode($hcMapString, true);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 判断是否免跑腿费
|
|
|
if ($sendDistance > $hcFreeKm) {
|
|
|
// 超过免费距离,检查是否满足其他免费条件
|
|
|
@@ -224,13 +226,13 @@ class DeliveryQuoteUtil
|
|
|
$ruleNum = $rule['num'] ?? 0;
|
|
|
$rulePrice = $rule['price'] ?? 0;
|
|
|
$ruleDistance = ($rule['distance'] ?? 0) * 1000;
|
|
|
-
|
|
|
- if ($productCount >= $ruleNum
|
|
|
- && $itemTotalAmount >= $rulePrice
|
|
|
+
|
|
|
+ if ($productCount >= $ruleNum
|
|
|
+ && $itemTotalAmount >= $rulePrice
|
|
|
&& $sendDistance <= $ruleDistance
|
|
|
) {
|
|
|
noticeUtil::push(
|
|
|
- "ghsMainId={$ghsMainId}, orderSn={$orderSn}, 免跑腿费,满足条件:"
|
|
|
+ "ghsMainId={$ghsMainId}, orderSn={$orderSn}, 免跑腿费,满足条件:"
|
|
|
. json_encode($rule)
|
|
|
);
|
|
|
return 0;
|
|
|
@@ -241,52 +243,56 @@ class DeliveryQuoteUtil
|
|
|
// 在免费配送距离内
|
|
|
return 0;
|
|
|
}
|
|
|
- }else if(strstr($orderSn, 'KD_CS') || strstr($orderSn, 'KD')){//花束
|
|
|
+ } else if (strstr($orderSn, 'KD_CS') || strstr($orderSn, 'KD')) {//花束
|
|
|
// 获取花材的免费配送设置
|
|
|
$hsFreeKm = ($shopExt['hsFreeKm'] ?? 0) * 1000; // 转换为米
|
|
|
$hsAddFee = $shopExt['hsAddFee'] ?? 0;
|
|
|
-
|
|
|
+
|
|
|
// 判断是否免跑腿费
|
|
|
if ($sendDistance > $hsFreeKm) {
|
|
|
- return ($sendDistance - $hsFreeKm)/1000 * $hsAddFee;
|
|
|
+ $pass = bcsub($sendDistance, $hsFreeKm, 2);
|
|
|
+ $km = bcdiv($pass,1000,2);
|
|
|
+ //向上取整,不足1公里的按1公里算
|
|
|
+ $km = ceil($km);
|
|
|
+ return bcmul($km,$hsAddFee,2);
|
|
|
} else {
|
|
|
// 在免费配送距离内
|
|
|
return 0;
|
|
|
}
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
new \Exception('不支持的订单类型');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return $sendCost;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 参数验证
|
|
|
- *
|
|
|
+ *
|
|
|
* @param array $params 参数数组
|
|
|
* @throws \Exception 当参数不合法时抛出异常
|
|
|
*/
|
|
|
private static function validateParams($params)
|
|
|
{
|
|
|
$requiredFields = [
|
|
|
- 'productList',
|
|
|
- 'deliveryPlatform',
|
|
|
- 'ghsInfo',
|
|
|
- 'custom',
|
|
|
- 'order',
|
|
|
+ 'productList',
|
|
|
+ 'deliveryPlatform',
|
|
|
+ 'ghsInfo',
|
|
|
+ 'custom',
|
|
|
+ 'order',
|
|
|
'mainId'
|
|
|
];
|
|
|
-
|
|
|
+
|
|
|
foreach ($requiredFields as $field) {
|
|
|
if (!isset($params[$field])) {
|
|
|
throw new \Exception("缺少必要参数:{$field}");
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (empty($params['productList']) || !is_array($params['productList'])) {
|
|
|
throw new \Exception("商品列表不能为空");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (empty($params['ghsInfo']['mainId']) || empty($params['ghsInfo']['shopId'])) {
|
|
|
throw new \Exception("供货商信息不完整");
|
|
|
}
|