浏览代码

优化即时账单

Zhouzhendong 4 年之前
父节点
当前提交
efb293cc52

+ 1 - 1
app/Services/OrderService.php

@@ -1212,7 +1212,7 @@ sql
         //获取作业费
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
-        list($id,$money,$workTaxFee) = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
+        list($id,$money,$workTaxFee) = $service->matching($order,Feature::MAPPING["order"],$order->owner_id);
 
         //数据组装
         $detail = OwnerFeeDetail::query()->create([

+ 12 - 23
app/Services/OwnerPriceExpressService.php

@@ -256,49 +256,38 @@ sql
     /**
      *
      * @param double $weight
-     * @param integer $owner_id
-     * @param integer $logistic_id
-     * @param integer $province_id
+     * @param integer $ownerId
+     * @param integer $logisticId
+     * @param integer $provinceId
+     *
      * @return array
      */
-    public function matching($weight, $owner_id, $logistic_id, $province_id)
+    public function matching(float $weight, int $ownerId, int $logisticId, int $provinceId):array
     {
         if (!$weight)return array(null,null);
 
-        $model = $this->getOwnerPriceExpress($owner_id,$logistic_id,$province_id);
+        $model = $this->getOwnerPriceExpress($ownerId,$logisticId,$provinceId);
         if (!$model || count($model->details)<1)return array(null,null);
 
+        $to1 = $to2 = 0;
         if ($model->amount_interval){
-            $total = app("OrderService")->getOrderQuantity($owner_id)+1;//获取该货主本月C端单量
-            for ($i=count($model->amount_interval);$i<0;$i--){
-                if ($total>=$model->amount_interval[$i]){$to1 = $i;break;}
-            }
+            $total = app("OrderService")->getOrderQuantity($ownerId)+1;//获取该货主本月C端单量
+            for ($i=count($model->amount_interval);$i<0;$i--)if ($total>=$model->amount_interval[$i]){$to1 = $i;break;}
             if (isset($to1) && isset($model->weight_interval[$to1])){
                 for ($i=count($model->weight_interval[$to1]);$i<0;$i--){
                     if ($weight>=$model->weight_interval[$to1][$i]){$to2 = $i;break;}
                 }
             }
         }
-        if (!isset($to1))$to1 = 0;
-        if (!isset($to2))$to2 = 0;
 
         $initPrice = $model->details[0]->initial_weight_price[$to1][$to2];
         $additionalPrice = $model->details[0]->additional_weight_price[$to1][$to2];
-        if ($weight <= $model->initial_weight)$money = $initPrice;
-        else{
+        if ($weight>$model->initial_weight){
             $weight -= $model->initial_weight;
             $money = (ceil($weight/$model->additional_weight)*$additionalPrice)+$initPrice;
-        }
-        if ($model->tax_rate_id && $model->taxRate){
-            $taxFee = $money*($model->taxRate->value/100);
-        }else{
-            /** @var Owner|\stdClass $owner */
-            $owner = Owner::query()->with("taxRate")
-                ->whereHas("taxRate")->find($owner_id);
-            if ($owner)$taxFee = $money*($owner->taxRate->value/100);
-            else $taxFee = null;
-        }
+        }else $money = $initPrice;
 
+        $taxFee = app("OwnerService")->getTaxRateFee($model, $ownerId, $money);
         return array($money,$taxFee);
     }
 }

+ 16 - 24
app/Services/OwnerPriceLogisticService.php

@@ -188,27 +188,27 @@ class OwnerPriceLogisticService
     /**
      *
      * @param double $amount
-     * @param integer $owner_id
-     * @param integer $logistic_id
-     * @param integer $unit_id
-     * @param integer $province_id
-     * @param integer $city_id
+     * @param integer $ownerId
+     * @param integer $logisticId
+     * @param integer $unitId
+     * @param integer $provinceId
+     * @param integer $cityId
      * @return array
      */
-    public function matching($amount, $owner_id, $logistic_id, $unit_id, $province_id, $city_id)
+    public function matching(float $amount, int $ownerId, int $logisticId, int $unitId, int $provinceId, int $cityId):array
     {
-        $model = OwnerPriceLogistic::query()->with(["details"=>function($query)use($province_id,$city_id){
+        $model = OwnerPriceLogistic::query()->with(["details"=>function($query)use($provinceId,$cityId){
             /** @var Builder $query */
-            $query->where("province_id",$province_id)->where("city_id",$city_id);
-        }])->where(function ($query)use($unit_id){
+            $query->where("province_id",$provinceId)->where("city_id",$cityId);
+        }])->where(function ($query)use($unitId){
             /** @var Builder $query */
-            $query->where("unit_id",$unit_id)->orWhere("other_unit_id",$unit_id);
-        })->whereHas("owners",function ($query)use($owner_id){
+            $query->where("unit_id",$unitId)->orWhere("other_unit_id",$unitId);
+        })->whereHas("owners",function ($query)use($ownerId){
             /** @var Builder $query */
-            $query->where("id",$owner_id);
-        })->whereHas("logistics",function ($query)use($logistic_id){
+            $query->where("id",$ownerId);
+        })->whereHas("logistics",function ($query)use($logisticId){
             /** @var Builder $query */
-            $query->where("id",$logistic_id);
+            $query->where("id",$logisticId);
         })->where(function(Builder $query){
             $query->whereNull("operation")->orWhere("operation","");
         })->first();
@@ -216,7 +216,7 @@ class OwnerPriceLogisticService
         $money = null;
         $fee = $model->pick_up_price + $model->fuel_price + $model->service_price; //服务费
         foreach ($model->details as $detail){
-            if ($unit_id != $detail->unit_id)continue;
+            if ($unitId != $detail->unit_id)continue;
             $arr = explode("-",$detail->range);
             if (count($arr) < 2 || !$arr[1]){
                 if ($amount >= $arr[0])$money = $this->calculation($amount,$detail,$fee);
@@ -225,15 +225,7 @@ class OwnerPriceLogisticService
             }
             if ($money)break;
         }
-        if ($model->tax_rate_id && $model->taxRate){
-            $taxFee = $money*($model->taxRate->value/100);
-        }else{
-            /** @var Owner|\stdClass $owner */
-            $owner = Owner::query()->with("taxRate")
-                ->whereHas("taxRate")->find($owner_id);
-            if ($owner)$taxFee = $money*($owner->taxRate->value/100);
-            else $taxFee = null;
-        }
+        $taxFee = app("OwnerService")->getTaxRateFee($model, $ownerId, $money);
         return array($money,$taxFee);
     }
 

+ 26 - 44
app/Services/OwnerPriceOperationService.php

@@ -198,7 +198,7 @@ class OwnerPriceOperationService
      * @return array|Collection
      *
      */
-    public function getOwnerPriceOperation($owner, $type, $typeMark)
+    public function getOwnerPriceOperation(int $owner, string $type, ?int $typeMark)
     {
         return Cache::tags("operationFeeOwner:".$owner)->remember("operationFee:".$owner.$type.$typeMark,config("cache.expirations.rarelyChange"),
             function ()use($owner,$type,$typeMark){
@@ -227,12 +227,11 @@ class OwnerPriceOperationService
      *
      * @return bool|array
      */
-    public function getDiscount($discount, $total)
+    public function getDiscount(?string $discount, int $total)
     {
-        if ($discount){
-            foreach (array_reverse(explode(",",$discount),true) as $index=>$discount){
-                if ($total >= $discount)return [$index=>$discount];
-            }
+        if (!$discount)return false;
+        foreach (array_reverse(explode(",",$discount),true) as $index=>$discount){
+            if ($total >= $discount)return [$index=>$discount];
         }
         return false;
     }
@@ -240,12 +239,13 @@ class OwnerPriceOperationService
     /**
      * 处理折扣单
      *
-     * @param object $rule
+     * @param Model|\stdClass $rule
      * @param integer $owner
      * @param bool|array $result
      */
-    public function handleDiscount($rule, $owner, $result)
+    public function handleDiscount(Model $rule, int $owner, $result)
     {
+        if (!$result)return;
         $sign = false;
         //入口仅在此处存在 缓存1000s
         $key = "owner_price_operation_owner_".$rule->id."_".$owner;
@@ -287,7 +287,7 @@ class OwnerPriceOperationService
      *
      * @param array|object|Model $matchObject  key-val
      * @param array $columnMapping       key-val
-     * @param string $ownerId
+     * @param integer $ownerId
      * @param string $type
      * @param int|null $typeMark
      *
@@ -312,16 +312,11 @@ class OwnerPriceOperationService
      * 九. 2021-04-21 zzd
      *      排除掉order不存在包裹情况,预设输出值为null防止返回0,历史账单处理推进队列防止超时
      */
-    public function matching($matchObject, $columnMapping, $ownerId, $type = '出库', $typeMark = null)
+    public function matching($matchObject, array $columnMapping, int $ownerId, string $type = '出库', ?int $typeMark = null):array
     {
-        $units = app("UnitService")->getUnitMapping(["件","单","箱","m³","T","kg"]); //获取单位映射集
+        $units = app("UnitService")->getUnitMapping(["件","单","箱","m³","T","kg"],true); //获取单位映射集
         $rules = $this->getOwnerPriceOperation($ownerId,$type,$typeMark);//货主下的全部规则
-        if (!$rules)return -2;  //规则不存在跳出
-
-        //建立一组返回变量
-        $id = null;
-        $money = null;
-        $taxFee = null;
+        if (!$rules)return array(null,null,null);  //规则不存在跳出
 
         if ($type == '出库'){
             $total = app("OrderService")->getOrderQuantity($ownerId)+1;//获取该货主本月C端单量
@@ -342,34 +337,21 @@ class OwnerPriceOperationService
         }
         foreach ($rules as $rule){
             if (!$rule->items)continue; //不存在子规则跳出
-
+            //第一级匹配 特征类别不符合要求跳出
+            if ($rule->strategy == '特征' && !app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject))continue;
+            //获取满减信息并处理满减
             $result = $this->getDiscount($rule->discount_count,$total); //满减信息
-            if ($result)$this->handleDiscount($rule,$ownerId,$result);//满减存在
+            $this->handleDiscount($rule,$ownerId,$result);
 
-            if ($rule->strategy == '特征'){
-                if (app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject)){
-                    if (!$rule->total_price)$money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);
-                    $id = $rule->id;
-                };
-            }else{
-                if (!$rule->total_price)$money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);
-                $id = $rule->id;
-            };
-            if ($id){
-                if ($rule->total_price)$money = $result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price;//按单计价存在,直接返回单总价或减免总价
-                $money = $rule->max_fee&&$money>$rule->max_fee ? $rule->max_fee : $money;//封顶费
-                if ($money<=0)$money=null;//计算失误
-                if ($rule->tax_rate_id && $rule->taxRate)$taxFee = $money*($rule->taxRate->value/100);
-                else{
-                    /** @var Owner|\stdClass $owner */
-                    $owner = Owner::query()->with("taxRate")
-                        ->whereHas("taxRate")->find($ownerId);
-                    if ($owner)$taxFee = $money*($owner->taxRate->value/100);
-                }
-                break;
-            }
+            if ($rule->total_price)$money = $result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price;//按单计价存在,直接返回单总价或减免总价
+            else $money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);//匹配子项获取详细报价
+
+            $money = $rule->max_fee&&$money>$rule->max_fee ? $rule->max_fee : $money;//封顶费
+            if ($money<=0)$money=null;//计算失误
+            $taxFee = app("OwnerService")->getTaxRateFee($rule, $ownerId, $money);
+            return array($rule->id,$money,$taxFee);
         }
-        return array($id,$money,$taxFee);
+        return array(null,null,null);
     }
     /**
      * 根据货主 sku寻找箱规并将指定数量切换为箱 返回箱规
@@ -421,14 +403,14 @@ class OwnerPriceOperationService
      *
      * @param Model|\stdClass $obj 策略对象
      * @param array $columnMapping 映射对象
-     * @param Model $matchObject 被匹配对象
+     * @param Model|\stdClass $matchObject 被匹配对象
      * @param array $units 单位集
      * @param integer $ownerId 货主ID
      * @param bool|array $result 满减信息
      *
      * @return double
      */
-    public function matchItem($obj, $columnMapping, $matchObject, $units, $ownerId, $result)
+    public function matchItem($obj, array $columnMapping, $matchObject, array $units, int $ownerId, $result)
     {
         $matchObject = $this->resetChildNodeMapping($matchObject->toArray(),$columnMapping);
         if (!$matchObject)return -1;

+ 24 - 0
app/Services/OwnerService.php

@@ -15,6 +15,7 @@ use App\Services\common\BatchUpdateService;
 use App\User;
 use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cache;
@@ -497,4 +498,27 @@ sql;
         OwnerPriceSystem::query()->where("owner_id",$owner->id)
             ->update(["tax_rate_id"=>null]);
     }
+
+    /**
+     * 获取税费
+     *
+     * @param Model|\stdClass $model
+     * @param int $ownerId
+     * @param float $money
+     *
+     * @return float|null
+     */
+    public function getTaxRateFee(Model $model, int $ownerId, float $money):?float
+    {
+        if (!$money)return 0;
+        $taxRate = null;
+        if ($model->tax_rate_id){
+            $model->loadMissing("taxRate");
+            $taxRate = $model->taxRate;
+        }
+        if (!$taxRate) $taxRate = Owner::query()->with("taxRate")
+            ->whereHas("taxRate")->find($ownerId)->taxRate;
+        if (!$taxRate)return null;
+        return $money*($taxRate->value/100);
+    }
 }

+ 12 - 2
app/Services/UnitService.php

@@ -50,12 +50,14 @@ class UnitService
      * 获取单位集的映射
      *
      * @param null|array $targets
+     * @param bool $notExistToCreate
      *
      * @return array
      */
-    public function getUnitMapping($targets = null)
+    public function getUnitMapping(?array $targets = null, bool $notExistToCreate = false):array
     {
-        return Cache::remember("unitMapping:".json_encode($targets,JSON_UNESCAPED_UNICODE),config("cache.expirations.rarelyChange"),function ()use($targets){
+        $key = "unitMapping:".json_encode($targets,JSON_UNESCAPED_UNICODE);
+        $units = Cache::remember($key,config("cache.expirations.rarelyChange"),function ()use($targets){
             $result = [];
             $units = $this->getUnitCache();
             if (!$units)return [];
@@ -65,6 +67,14 @@ class UnitService
             }
             return $result;
         });
+        if ($notExistToCreate && $targets && count($units)!=count($targets)){
+            $flip = array_flip($targets);
+            foreach ($units as $key=>$val)unset($flip[$val]);
+            foreach ($flip as $key=>$val)Unit::query()->firstOrCreate(["name"=>$key]);
+            Cache::pull($key);
+            return $this->getUnitMapping($targets);
+        }
+        return $units;
     }
 
     /**