shish 2 дней назад
Родитель
Сommit
0a5c418668

+ 58 - 2
app-hd/controllers/GhsController.php

@@ -8,6 +8,7 @@ use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\custom\classes\CustomLevelClass;
 use bizGhs\merchant\classes\WlClass;
+use bizGhs\order\classes\ShMethodClass;
 use bizGhs\shop\classes\GhsNoticeClass;
 use bizHd\purchase\classes\PurchaseClass;
 use bizHd\shop\classes\ShopExtClass;
@@ -26,6 +27,61 @@ class GhsController extends BaseController
 
     public $guestAccess = ['info', 'get-ghs-data', 'detail', 'common-info', 'ghs-notice-detail'];
 
+    //根据自定义价格,计算跑腿费用 ssh 20270730
+    public function actionCalcCustomPtFee()
+    {
+        $get = Yii::$app->request->get();
+        $id = $get['id'] ?? 0;
+        $sendType = $get['sendType'] ?? 2;
+        $ghs = GhsClass::getById($id, true);
+        if (empty($ghs)) {
+            util::fail('没有找到批发店');
+        }
+        if (!isset($ghs->ownShopId) || $ghs->ownShopId != $this->shopId) {
+            util::fail('不是你的批发店');
+        }
+        $customId = $ghs->customId ?? 0;
+        $custom = CustomClass::getById($customId, true);
+        if (empty($custom)) {
+            util::success(['sendCost' => 0, 'sendDistance' => 0]);
+        }
+        $ghsShopId = $ghs->shopId ?? 0;
+        $ghsMainId = $ghs->mainId ?? 0;
+        $shCurrentConfig = shMethodClass::getConfig($ghsShopId, $ghsMainId, $sendType);
+
+        //使用自定义计算费用
+        $startKm = $shCurrentConfig['startKm'] ?? 0;
+        $startPrice = $shCurrentConfig['startPrice'] ?? 0;
+        $perKmPrice = $shCurrentConfig['perKmPrice'] ?? 0;//超出起步,每公里加收金额
+        $changeRate = $shCurrentConfig['changeRate'] ?? 0;//负值时为降价百分比,正值时为涨价百分比
+        if ($startKm <= 0 || $startPrice <= 0 || $perKmPrice <= 0) {
+            util::success(['sendCost' => 0, 'distanceKm' => 0,'distance'=>0]);
+        }
+        //计算客户到店的距离,骑电动车
+        $distanceRespond = mapUtil::calcShopDistanceByEleBike($custom, $ghs, 0);
+        $sendDistance = $distanceRespond['distanceKm'] ?? 0;
+        $distance = $distanceRespond['distance'] ?? 0;
+        $distance = floatval($distance);
+        $sendDistance = floatval($sendDistance);
+        if ($sendDistance <= 0) {
+            util::success(['sendCost' => 0, 'distanceKm' => 0,'distance'=>0]);
+        }
+        // 计算运费逻辑
+        $sendCost = $startPrice;
+        if ($sendDistance > $startKm) {
+            $extraDistance = bcsub($sendDistance, $startKm, 2);
+            $extraCost = bcmul($extraDistance, $perKmPrice, 2);
+            $sendCost = bcadd($sendCost, $extraCost, 2);
+        }
+        if ($changeRate != 0) {
+            // 临时涨价/降价百分比
+            $rate = bcadd(1, bcdiv($changeRate, 100, 4), 4);
+            $sendCost = bcmul($sendCost, $rate, 2);
+        }
+        $sendCost = floatval($sendCost);
+        util::success(['sendCost' => $sendCost, 'distanceKm' => $sendDistance,'distance'=>$distance]);
+    }
+
     //提示花店有多个供货商
     public function actionRemindMoreGhs()
     {
@@ -303,15 +359,14 @@ class GhsController extends BaseController
             }
         }
 
+        /*****此区域部分可以考虑删除******/
         $shopExt = ShopExtClass::getByCondition(['shopId' => $ghsShopId], false, false, 'purchaseGuide,purchaseGuideText,hcFreeKm,hcMap');
         $ghsInfo['buyNotice'] = $ghsShop->buyNotice ?? 0;
         $ghsInfo['buyNoticeText'] = $shopExt['purchaseGuideText'] ?? '';
-
         //判断是否开启同城配送功能
         $intraCityRet = ShopClass::hasIntraCity($ghsShop);
         $openIntraCity = $intraCityRet['openIntraCity'];
         $ghsInfo['openIntraCity'] = $openIntraCity;
-
         //花材的免费配送设置
         $hcFreeKm = $shopExt['hcFreeKm'] ?? 0;
         $ghsInfo['hcFreeKm'] = $hcFreeKm;
@@ -321,6 +376,7 @@ class GhsController extends BaseController
             $hcMap = json_decode($hcMapString, true);
         }
         $ghsInfo['hcMap'] = $hcMap;
+        /*****此区域部分可以考虑删除******/
 
         //是否使用新的配送方式,关键词 sh_method_area
         $newShMethod = dict::getNewMethodShop();

+ 110 - 24
app-hd/controllers/PurchaseController.php

@@ -22,6 +22,7 @@ use common\components\dateUtil;
 use common\components\delivery\util\DeliveryQuoteUtil;
 use common\components\dict;
 use common\components\imgUtil;
+use common\components\mapUtil;
 use common\components\noticeUtil;
 use common\components\orderSn;
 use Yii;
@@ -622,30 +623,114 @@ class PurchaseController extends BaseController
                 // xhShMethod 门店:下单前按配置写入不满最低消费时的附加包装费/运费,关键词 sh_method_area
                 $newShMethod = dict::getNewMethodShop();
                 if (in_array($ghsShopId, $newShMethod)) {
-                    $shMethodBigNum = 0;
-                    foreach ($productList as $itemData) {
-                        $shMethodBigNum += floatval($itemData['bigNum'] ?? 0);
-                    }
-                    $additionalCosts = ShMethodClass::calcFee(
-                        $ghsShopId,
-                        $ghsMainId,
-                        $sendType,
-                        $shMethodItemAmount,
-                        $shMethodBigNum,
-                        $customId,
-                        $ghsInfo
-                    );
-
-                    // 如果产生了附加运费,与前面可能产生的 sendCost 进行累加或覆盖
-                    if ($additionalCosts['sendCost'] > 0) {
-                        $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $additionalCosts['sendCost'], 2);
+
+                    $shCurrentConfig = shMethodClass::getConfig($ghsShopId, $ghsMainId, $sendType);
+                    $shCurrentName = $shCurrentConfig['name'] ?? '';
+                    if (isset($shCurrentConfig['status']) && $shCurrentConfig['status'] == 0) {
+                        util::fail($shCurrentName . '已停用');
                     }
 
-                    // 如果产生了附加包装费,覆盖前面赋值的 packCost
-                    if ($additionalCosts['packCost'] > 0) {
-                        $post['packCost'] = $additionalCosts['packCost'];
+                    if ($sendType == dict::getDict('sendType', 'thirdSend')) {
+                        //如果是发跑腿
+
+                        // 生成随机订单号,不要跟原来的订单号混起来,跑腿-销售单-
+                        $prefix = 'PT-XSD-' . $this->mainId . '-';
+                        $orderSn = $prefix . round(microtime(true) * 1000);
+
+                        $calcType = $shCurrentConfig['calcType'] ?? 0;
+                        if ($calcType == 1) {
+                            //使用自定义计算费用
+                            $startKm = $shCurrentConfig['startKm'] ?? 0;
+                            $startPrice = $shCurrentConfig['startPrice'] ?? 0;
+                            $perKmPrice = $shCurrentConfig['perKmPrice'] ?? 0;//超出起步,每公里加收金额
+                            $changeRate = $shCurrentConfig['changeRate'] ?? 0;//负值时为降价百分比,正值时为涨价百分比
+                            if ($startKm <= 0 || $startPrice <= 0 || $perKmPrice <= 0) {
+                                util::fail('算运费失败,请更换配送方式');
+                            }
+                            //计算客户到店的距离,骑电动车
+                            $distanceRespond = mapUtil::calcShopDistanceByEleBike($custom, $ghsShopInfo);
+                            $sendDistance = $distanceRespond['distanceKm'] ?? 0;
+                            if ($sendDistance <= 0) {
+                                util::fail('算运费失败,距离是0,请选到店自取');
+                            }
+                            // 计算运费逻辑
+                            $sendCost = $startPrice;
+                            if ($sendDistance > $startKm) {
+                                $extraDistance = bcsub($sendDistance, $startKm, 2);
+                                $extraCost = bcmul($extraDistance, $perKmPrice, 2);
+                                $sendCost = bcadd($sendCost, $extraCost, 2);
+                            }
+                            if ($changeRate != 0) {
+                                // 临时涨价/降价百分比
+                                $rate = bcadd(1, bcdiv($changeRate, 100, 4), 4);
+                                $sendCost = bcmul($sendCost, $rate, 2);
+                            }
+
+                            $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $sendCost, 2);
+                            $post['sendDistance'] = $sendDistance;
+
+                        } else {
+                            // 使用 DeliveryQuoteUtil 获取配送报价
+                            try {
+                                $quoteResult = DeliveryQuoteUtil::getDeliveryQuote([
+                                    'productList' => $productList,
+                                    'deliveryPlatform' => $post['deliveryPlatform'],
+                                    'deliveryBracketContent' => $post['deliveryBracketContent'], // 平台多报价识别id
+                                    'ghsInfo' => $ghsInfo,
+                                    'custom' => $custom,
+                                    'order' => [
+                                        'orderSn' => $orderSn,
+                                        'goodsType' => 1, //商品类型:0 花束 1 花材
+                                        'itemTotalAmount' => $post['itemTotalAmount'] ?? 0,
+                                        'remark' => $post['remark'] ?? '',
+                                    ],
+                                    'mainId' => $this->mainId,
+                                    'productCount' => $productCount,
+                                    //当前配送方式
+                                    'shConfig' => $shCurrentConfig,
+                                ]);
+
+                                $sendCost = $quoteResult['sendCost'];
+                                $sendDistance = $quoteResult['sendDistance'];
+
+                                $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $sendCost, 2);
+                                $post['sendDistance'] = $sendDistance;
+
+                            } catch (\Exception $e) {
+                                noticeUtil::push("计算跑腿费用出错了:" . $e->getMessage(), '15280215347');
+                                util::fail('下单失败,请选其他配送方式');
+                            }
+                        }
+
+                    } else {
+                        //如果是不是发跑腿,比如送货上门和发快递,则可能要收运费或打包费任一
+
+                        $shMethodBigNum = 0;
+                        foreach ($productList as $itemData) {
+                            $shMethodBigNum += floatval($itemData['bigNum'] ?? 0);
+                        }
+
+                        $additionalCosts = ShMethodClass::calcFee(
+                            $shCurrentConfig,
+                            $sendType,
+                            $shMethodItemAmount,
+                            $shMethodBigNum,
+                            $customId,
+                            $ghsInfo
+                        );
+
+                        // 如果产生了附加运费,与前面可能产生的 sendCost 进行累加或覆盖
+                        if ($additionalCosts['sendCost'] > 0) {
+                            $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $additionalCosts['sendCost'], 2);
+                        }
+                        // 如果产生了附加包装费,覆盖前面赋值的 packCost。
+                        if ($additionalCosts['packCost'] > 0) {
+                            $post['packCost'] = $additionalCosts['packCost'];
+                        }
+
                     }
-                }else{
+
+                } else {
 
                     //同城发货包装费和运费的计算
                     $sendCost = 0;
@@ -658,7 +743,7 @@ class PurchaseController extends BaseController
                             util::fail('不能使用跑腿');
                         }
                         if ($openIntraCity == 1) {
-                            // 生成随机订单号,不要跟原来的混起来,跑腿-销售单-
+                            // 生成随机订单号,不要跟原来的单号混起来,跑腿-销售单-
                             $prefix = 'PT-XSD-' . $this->mainId . '-';
                             $orderSn = $prefix . round(microtime(true) * 1000);
 
@@ -688,7 +773,8 @@ class PurchaseController extends BaseController
                                 $sendCost = $quoteResult['sendCost'];
                                 $sendDistance = $quoteResult['sendDistance'];
                             } catch (\Exception $e) {
-                                util::fail($e->getMessage());
+                                noticeUtil::push("计算跑腿费用出错了:" . $e->getMessage(), '15280215347');
+                                util::fail('下单失败,请选其他配送方式');
                             }
                         }
                     }
@@ -770,7 +856,7 @@ class PurchaseController extends BaseController
 
                         //情意花卉,必选品
                         if ($ghsShopId == 100883) {
-                            $hasMust = array_intersect($ids, [5017957,5036067,5036089,5036099,5017958,5036063,5017948,5035980,5036073,5036075,5036076,5036117,5036118,5017949,5035979,5035976,5035928,5035930,5036061,5035879]);
+                            $hasMust = array_intersect($ids, [5017957, 5036067, 5036089, 5036099, 5017958, 5036063, 5017948, 5035980, 5036073, 5036075, 5036076, 5036117, 5036118, 5017949, 5035979, 5035976, 5035928, 5035930, 5036061, 5035879]);
                             if (empty($hasMust)) {
                                 util::fail('请返回选择 必选商品');
                             }

+ 1 - 3
biz-ghs/order/classes/ShMethodClass.php

@@ -334,7 +334,7 @@ class ShMethodClass extends BaseClass
      * @param array|object $ghsInfo 客户与该供货商的关系信息(xhGhs)
      * @return array ['sendCost' => 运费, 'packCost' => 包装费]
      */
-    public static function calcFee($shopId, $mainId, $sendType, $itemTotalAmount, $bigNum, $customId = 0, $ghsInfo = [])
+    public static function calcFee($config, $sendType, $itemTotalAmount, $bigNum, $customId = 0, $ghsInfo = [])
     {
         $costs = ['sendCost' => 0, 'packCost' => 0];
         
@@ -343,8 +343,6 @@ class ShMethodClass extends BaseClass
             return $costs;
         }
 
-        $config = self::getConfig($shopId, $mainId, $style);
-
         if (empty($config)) {
             return $costs;
         }

+ 1 - 1
common/components/delivery/services/DispatchService.php

@@ -1060,7 +1060,7 @@ class DispatchService
                 case 'didi':
                     if(!isset($item['estimateList'])){
                         Yii::error('didi 报价数据为空:' . json_encode($item));
-                        continue;
+                        continue 2;
                     }
 
                     $serviceType = [0 => '拼送', 1 => '直送'];

+ 69 - 14
common/components/delivery/util/DeliveryQuoteUtil.php

@@ -115,20 +115,42 @@ class DeliveryQuoteUtil
         $sendCost = ($result['price'] ?? 0) / 100;
         $sendDistance = $result['distance'] ?? 0;
 
-        // 11. 应用免费配送规则
-        if(isset($params['order']['freightType']) && $params['order']['freightType'] == 0) { //用于处理及区分花束订单是否部分免跑腿费,还是完全收取跑腿费
-            $finalSendCost= $sendCost;
-        }else{
-            $finalSendCost = self::applyFreeDeliveryRules(
-                $sendCost,
-                $sendDistance,
-                $params['ghsInfo']['shopId'],
-                $params['productCount'],
-                $params['order']['itemTotalAmount'],
-                $params['ghsInfo']['mainId'],
-                $order['orderSn'],
-                $order['goodsType']
-            );
+        if (empty($params['shConfig'])) {
+            //旧的规则走这个
+
+            // 11. 应用免费配送规则
+            if (isset($params['order']['freightType']) && $params['order']['freightType'] == 0) { //用于处理及区分花束订单是否部分免跑腿费,还是完全收取跑腿费
+                $finalSendCost = $sendCost;
+            } else {
+                $finalSendCost = self::applyFreeDeliveryRules(
+                    $sendCost,
+                    $sendDistance,
+                    $params['ghsInfo']['shopId'],
+                    $params['productCount'],
+                    $params['order']['itemTotalAmount'],
+                    $params['ghsInfo']['mainId'],
+                    $order['orderSn'],
+                    $order['goodsType']
+                );
+            }
+        } else {
+            //新免费规则走这里,欧阳写到这里有问题沟通 ssh 20260730
+
+            $freightType = $params['order']['freightType'] ?? 0; //运费计算方式,0 按距离计算 1 免运费,包运费
+            $property = $order['goodsType'] ?? 1;//订单是什么类型订单 0 花束订单 1 花材订单,多种商品,只要含一把花束,就是花束订单
+            $totalPrice = $params['order']['itemTotalAmount'] ?? 0;
+            $totalNum = $params['productCount'] ?? 0;
+            $element = [
+                'shConfig' => $params['shConfig'],
+                'sendCost' => $sendCost,
+                'sendDistance' => $sendDistance,
+                'freightType' => $freightType,
+                'property' => $property,
+                'totalPrice' => $totalPrice,
+                'totalNum' => $totalNum,
+            ];
+            $discountRespond = self::discountSearch($element);
+            $finalSendCost = $discountRespond['sendCost'] ?? 0;
         }
 
         return [
@@ -139,6 +161,39 @@ class DeliveryQuoteUtil
         ];
     }
 
+    //查询是否符合跑腿的满减规则
+    private static function discountSearch($params)
+    {
+        $shConfig = $params['shConfig'] ?? [];
+        $sendCost = $params['sendCost'] ?? 0;
+        $sendDistance = $params['sendDistance'] ?? 0;
+        $freightType = $params['freightType'] ?? 0;
+        $property = $params['property'] ?? 1;
+        $totalPrice = $params['totalPrice'] ?? 0;
+        $totalNum = $params['totalNum'] ?? 0;
+
+        //免运费的情况 (配置本身设为包邮)
+        if ($freightType == 1) {
+            return ['sendCost' => 0];
+        }
+
+        // 遍历满减规则,判断是否符合免邮条件
+        if (!empty($shConfig['reduceRules']) && is_array($shConfig['reduceRules'])) {
+            foreach ($shConfig['reduceRules'] as $rule) {
+                $meetNum = (float)($rule['meetNum'] ?? 0);
+                $meetAmount = (float)($rule['meetAmount'] ?? 0);
+                $freeKm = (float)($rule['freeKm'] ?? 0);
+
+                // 校验规则:金额满 meetAmount 且 数量满 meetNum 且 距离在 freeKm 以内
+                if ($totalPrice >= $meetAmount && $totalNum >= $meetNum && $sendDistance <= $freeKm) {
+                    return ['sendCost' => 0];
+                }
+            }
+        }
+
+        return ['sendCost' => $sendCost];
+    }
+
     /**
      * 计算商品总重量
      *

+ 43 - 5
common/components/mapUtil.php

@@ -47,6 +47,44 @@ class mapUtil
         return $distance;
     }
 
+    //计算客户到店距离,骑电动车 ssh 2026.7.30
+    public static function calcShopDistanceByEleBike($beginPlace, $toPlace, $report = 1)
+    {
+        $beginLnt = $beginPlace->long ?? '';
+        $beginLat = $beginPlace->lat ?? '';
+        $toLnt = $toPlace->long ?? '';
+        $toLat = $toPlace->lat ?? '';
+
+        // 校验经纬度参数格式
+        if (empty($beginLnt) || empty($beginLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,请完善地址');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (!is_numeric($beginLnt) || !is_numeric($beginLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,请完善地址');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (empty($toLnt) || empty($toLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,商家地址没有完善');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (!is_numeric($toLnt) || !is_numeric($toLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,商家地址没有完善');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        $distance = self::calculateDistance($beginLnt, $beginLat, $toLnt, $toLat);
+        $distanceKm = bcdiv($distance, 1000, 2);
+        return ['distance' => $distance, 'distanceKm' => $distanceKm];
+    }
+
     /**
      * 批量计算多个起点到一个终点的距离 (高德 V3 距离测量接口)
      * @param array $origins 起点坐标数组,例如:[['lng' => '116.481028', 'lat' => '39.989643'], ...]
@@ -79,12 +117,12 @@ class mapUtil
         if (!empty($result['status']) && $result['status'] == 1 && !empty($result['results'])) {
             foreach ($result['results'] as $index => $res) {
                 // 返回的结果顺序与传入的 origins 顺序一致
-                $distances[$index] = $res['distance'] ?? 0; 
+                $distances[$index] = $res['distance'] ?? 0;
             }
-        }else{
-            noticeUtil::push("高德批量测距接口返回失败:".json_encode($result)." url:".$url);
+        } else {
+            noticeUtil::push("高德批量测距接口返回失败:" . json_encode($result) . " url:" . $url);
         }
-        
+
         return $distances;
     }
 
@@ -316,4 +354,4 @@ class mapUtil
         }
         return false;
     }
-}
+}