Explorar o código

需求ID:112,115
封顶费,税率,BUG,权限,生成方式
优化返回数据结构

Zhouzhendong %!s(int64=5) %!d(string=hai) anos
pai
achega
fff1a71ffc
Modificáronse 40 ficheiros con 544 adicións e 109 borrados
  1. 6 1
      app/Console/Commands/CreateOwnerBillReport.php
  2. 3 2
      app/Http/Controllers/CustomerController.php
  3. 2 0
      app/Http/Controllers/LogisticController.php
  4. 64 6
      app/Http/Controllers/PriceModelController.php
  5. 5 0
      app/Http/Controllers/TestController.php
  6. 39 16
      app/Jobs/ResetInstantBill.php
  7. 1 1
      app/Logistic.php
  8. 17 1
      app/Owner.php
  9. 2 1
      app/OwnerBillReport.php
  10. 2 0
      app/OwnerFeeDetail.php
  11. 1 1
      app/OwnerFeeDetailLogistic.php
  12. 5 1
      app/OwnerPriceDirectLogistic.php
  13. 5 0
      app/OwnerPriceExpress.php
  14. 5 0
      app/OwnerPriceLogistic.php
  15. 5 0
      app/OwnerPriceOperation.php
  16. 16 0
      app/OwnerPriceSystem.php
  17. 5 0
      app/OwnerStoragePriceModel.php
  18. 42 22
      app/Services/OrderService.php
  19. 5 4
      app/Services/OwnerPriceDirectLogisticService.php
  20. 6 5
      app/Services/OwnerPriceExpressService.php
  21. 8 6
      app/Services/OwnerPriceLogisticService.php
  22. 20 7
      app/Services/OwnerPriceOperationService.php
  23. 6 5
      app/Services/RejectedBillService.php
  24. 4 3
      app/Services/StoreService.php
  25. 4 3
      app/Services/WaybillService.php
  26. 13 6
      app/Services/common/QueryService.php
  27. 76 0
      database/migrations/2021_04_16_151135_create_owner_price_systems_table.php
  28. 76 10
      resources/views/customer/project/create.blade.php
  29. 3 2
      resources/views/customer/project/index.blade.php
  30. 6 0
      resources/views/customer/project/part/_directLogistic.blade.php
  31. 7 1
      resources/views/customer/project/part/_express.blade.php
  32. 7 1
      resources/views/customer/project/part/_logistic.blade.php
  33. 6 0
      resources/views/customer/project/part/_operation.blade.php
  34. 6 0
      resources/views/customer/project/part/_storage.blade.php
  35. 13 0
      resources/views/customer/project/part/_system.blade.php
  36. 37 2
      resources/views/customer/project/part/_three.blade.php
  37. 6 0
      resources/views/maintenance/logistic/create.blade.php
  38. 6 0
      resources/views/maintenance/logistic/edit.blade.php
  39. 2 2
      resources/views/maintenance/logistic/index.blade.php
  40. 2 0
      routes/web.php

+ 6 - 1
app/Console/Commands/CreateOwnerBillReport.php

@@ -3,6 +3,7 @@
 namespace App\Console\Commands;
 
 use App\OwnerAreaReport;
+use App\OwnerPriceSystem;
 use App\Services\LogService;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
@@ -62,19 +63,23 @@ class CreateOwnerBillReport extends Command
                     ->calculationAmount($area->ownerStoragePriceModel,$area->accounting_area,$area->owner_id,$area->counting_month);
             }
         }
-
+        foreach (OwnerPriceSystem::query()->select("owner_id","usage_fee")->whereNull("operation")->orWhere("operation","")->get() as $system){
+            $systemFee[$system->owner_id] = $system->usage_fee;
+        }
         $chunks = array_chunk($billDetails,50);
         foreach ($chunks as $bills){
             $date = date('Y-m-d H:i:s');
             $createOwnerBillReport = [];
             foreach ($bills as $bill){
                 $key = $bill->owner_id."_".$year."-".$lastMonth;
+                $otherFee = $systemFee[$bill->owner_id] ?? null;
                 $createOwnerBillReport[] = [
                     "owner_id"          => $bill->owner_id,       //项目ID
                     "counting_month"    => $year."-".$lastMonth."-01", //结算月
                     "work_fee"          => $bill->work_fee,
                     "logistic_fee"      => $bill->logistic_fee,
                     "storage_fee"       => $map[$key] ?? 0,
+                    "other_fee"         => $otherFee,
                     "created_at"        => $date,
                 ];
             }

+ 3 - 2
app/Http/Controllers/CustomerController.php

@@ -97,7 +97,7 @@ class CustomerController extends Controller
         /** @var OwnerService $service */
         $service = app('OwnerService');
         $owners = $service->paginate(request()->input(),['customer',"userOwnerGroup","userWorkGroup",
-            "ownerStoragePriceModels","storageAudit","operationAudit","expressAudit","logisticAudit","directLogisticAudit"]);
+            "ownerStoragePriceModels","storageAudit","operationAudit","expressAudit","logisticAudit","directLogisticAudit","systemAudit"]);
         $models = app('OwnerService')->getIntersectPermitting();
         $customers = app('CustomerService')->getSelection();
         $ownerGroups = app('UserOwnerGroupService')->getSelection();
@@ -205,13 +205,14 @@ class CustomerController extends Controller
         if(!Gate::allows('项目管理-项目-编辑')){ return redirect('denied');  }
         /** @var Owner $owner */
         $owner = app('OwnerService')->find($id);
-        $owner->loadCount(["ownerStoragePriceModels","ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics"]);
+        $owner->loadCount(["ownerStoragePriceModels","ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics","ownerPriceSystem"]);
         $isExist = false;
         /** @var \stdClass $owner */
         if($owner->owner_storage_price_models_count ||
             $owner->owner_price_operations_count ||
             $owner->owner_price_expresses_count ||
             $owner->owner_price_logistics_count ||
+            $owner->owner_price_system_count ||
             $owner->owner_price_direct_logistics_count) $isExist = true;
         $customers = app('CustomerService')->getSelection();
         $ownerGroups = app('UserOwnerGroupService')->getSelection();

+ 2 - 0
app/Http/Controllers/LogisticController.php

@@ -45,6 +45,7 @@ class LogisticController extends Controller
     {
         if(!Gate::allows('物流公司-录入')){ return redirect(url('/'));  }
         $this->validatorCreate($request->all())->validate();
+        $request->offsetSet("is_bunched",$request->input("is_bunched") ? 'Y' : 'N');
         $logistic=new Logistic($request->all());
         $logistic->save();
 
@@ -96,6 +97,7 @@ class LogisticController extends Controller
     {
         if(!Gate::allows('物流公司-编辑')){ return redirect(url('/'));  }
         $this->validatorUpdate($request->all(),$logistic->id)->validate();
+        $request->offsetSet("is_bunched",$request->input("is_bunched") ? 'Y' : 'N');
         $logistic->fill($request->all());
         $logistic->update();
         app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);

+ 64 - 6
app/Http/Controllers/PriceModelController.php

@@ -15,9 +15,11 @@ use App\OwnerPriceLogistic;
 use App\OwnerPriceLogisticDetail;
 use App\OwnerPriceOperation;
 use App\OwnerPriceOperationItem;
+use App\OwnerPriceSystem;
 use App\OwnerStoragePriceModel;
 use App\Services\common\BatchUpdateService;
 use App\Services\common\ExportService;
+use App\Services\common\QueryService;
 use App\Services\LogService;
 use App\Services\OwnerPriceOperationItemService;
 use App\Services\OwnerPriceOperationService;
@@ -1133,6 +1135,7 @@ class PriceModelController extends Controller
             "unit_id"           => request("unit_id"),
             "time_unit_id"      => request("time_unit_id"),
             "amount_interval"   => request("amount_interval") ?? null,
+            "tax_rate_id"       => request("tax_rate_id") ?? null,
         ];
         if (request("id")){
             $model = app('OwnerStoragePriceModelService')->find(request("id"));
@@ -1150,7 +1153,7 @@ class PriceModelController extends Controller
 
     public function apiStoreOperation()
     {
-        $this->gate("项目管理-项目-录入");
+        $this->gate("计费模型-仓储-录入");
         $params = request()->input();
         $params["owner_id"] = [$params["owner_id"]];
         $errors = $this->operationValidator($params,request("id"))->errors();
@@ -1170,6 +1173,7 @@ class PriceModelController extends Controller
             "discount_count"    => implode(",",request("discount_count")),
             "total_price"       => request("total_price"),
             "total_discount_price"=> implode(",",request("total_discount_price")),
+            "tax_rate_id"       => request("tax_rate_id") ?? null,
         ];
         if (request("id")){
             $model = app('OwnerPriceOperationService')->find(request("id"),["items"]);
@@ -1232,7 +1236,7 @@ class PriceModelController extends Controller
 
     public function apiStoreExpress()
     {
-        $this->gate("项目管理-项目-录入");
+        $this->gate("计费模型-快递-录入");
         $params = request()->input();
         $params["logistic_id"] = $params["logistics"];
         $errors = $this->expressValidator($params,request("id"))->errors()->toArray();
@@ -1249,6 +1253,7 @@ class PriceModelController extends Controller
             "additional_weight" => request("additional_weight"),
             "amount_interval"   => request("amount_interval"),
             "weight_interval"   => request("weight_interval"),
+            "tax_rate_id"       => request("tax_rate_id") ?? null,
         ];
         if (request("id")){
             /** @var \stdClass $model */
@@ -1307,7 +1312,7 @@ class PriceModelController extends Controller
 
     public function apiStoreLogistic()
     {
-        $this->gate("项目管理-项目-录入");
+        $this->gate("计费模型-物流-录入");
         $params = request()->input();
         $params["owner_id"] = [$params["owner_id"]];
         $params["logistic_id"] = $params["logistics"];
@@ -1329,6 +1334,7 @@ class PriceModelController extends Controller
             "pick_up_price"     => request('pick_up_price'),
             "fuel_price"        => request('fuel_price'),
             "service_price"     => request('service_price'),
+            "tax_rate_id"       => request("tax_rate_id") ?? null,
         ];
         if (request("id")){
             $model = app("OwnerPriceLogisticService")->find(request("id"),["details"]);
@@ -1388,7 +1394,7 @@ class PriceModelController extends Controller
 
     public function apiStoreDirectLogistic()
     {
-        $this->gate("项目管理-项目-录入");
+        $this->gate("计费模型-直发-录入");
         $errors = $this->directLogisticValidator(request()->input(),request("id"))->errors()->toArray();
         $exist = [];
         foreach (request("items") as $index=>$item){
@@ -1401,6 +1407,7 @@ class PriceModelController extends Controller
         $obj = [
             "name"      => request("name"),
             "base_km"   => request("base_km"),
+            "tax_rate_id"=> request("tax_rate_id") ?? null,
         ];
         if (request("id")){
             $model = app("OwnerPriceDirectLogisticService")->find(request("id"),["details"]);
@@ -1449,6 +1456,27 @@ class PriceModelController extends Controller
         $this->success($model);
     }
 
+    public function apiStoreSystem()
+    {
+        $this->gate("计费模型-系统-录入");
+        if (!request("owner_id") || !request("usage_fee") || \request("usage_fee")<0)$this->success(["errors"=>["usage_fee"=>["不得小于0"]]]);
+        if (request("id")){
+            /** @var OwnerPriceSystem|\stdClass $model */
+            $model = OwnerPriceSystem::query()->find(request("id"));
+            if ($model->operation)$model->update(["usage_fee"=>\request("usage_fee"),"operation"=>"U","tax_rate_id"=>\request("tax_rate_id")]);
+            else $model = OwnerPriceSystem::query()->create([
+                "usage_fee" => \request("usage_fee"),
+                "operation"=>"U",
+                "target_id"=>$model->id,
+                "owner_id"=>$model->owner_id,
+                "tax_rate_id"=>\request("tax_rate_id")
+            ]);
+        }else{
+            $model = OwnerPriceSystem::query()->create(["usage_fee" => \request("usage_fee"),"owner_id"=>request("owner_id"),"operation"=>"C","tax_rate_id"=>\request("tax_rate_id")]);
+        }
+        $this->success($model);
+    }
+
     public function getPriceModel()
     {
         /** @var Owner|\stdClass $owner */
@@ -1466,8 +1494,8 @@ class PriceModelController extends Controller
         },"ownerPriceLogistics"=>function($query){
             /** @var Builder $query */
             $query->with(["details","logistics"]);
-        },"ownerPriceDirectLogistics.details"]);
-        $owner->loadCount(["storageAudit","operationAudit","expressAudit","logisticAudit","directLogisticAudit"]);
+        },"ownerPriceDirectLogistics.details","ownerPriceSystem"]);
+        $owner->loadCount(["storageAudit","operationAudit","expressAudit","logisticAudit","directLogisticAudit","systemAudit"]);
         $features = app("FeatureService")->getMapArray();
         OwnerPriceOperation::$features = $features;
         OwnerPriceOperationItem::$features = $features;
@@ -1737,6 +1765,18 @@ class PriceModelController extends Controller
         }
         $this->success();
     }
+    public function apiDelSystem()
+    {
+        $this->gate("项目管理-系统-录入");
+        if (!request("id"))$this->error("非法参数");
+        /** @var OwnerPriceSystem|\stdClass $model */
+        $model = OwnerPriceSystem::query()->find(\request("id"));
+        if ($model->operation && $model->target_id){
+            OwnerPriceSystem::query()->where($model->target_id,\request("id"))->update(["operation"=>"D"]);
+            $model->delete();
+        }
+        $this->success();
+    }
 
     private function publicDeleteNode(string $serviceName)
     {
@@ -1811,7 +1851,25 @@ class PriceModelController extends Controller
                 $owner->load("ownerPriceDirectLogistics.details");
                 $this->success($owner->ownerPriceDirectLogistics);
                 break;
+            case "system":
+                $result = app(QueryService::class)->priceModelAuditOrRecoverQuery(request("isAudit"),OwnerPriceSystem::query(),$ownerId,null,true);
+                if ($result["delete"]){
+                    OwnerPriceSystem::destroy($result["delete"]);
+                    app("OwnerService")->refreshRelevance($ownerId,5,true);
+                }
+                if ($result["update"]){
+                    OwnerPriceSystem::query()->whereIn("id",$result["update"])->update(["operation"=>null,"target_id"=>null]);
+                    app("OwnerService")->refreshRelevance($ownerId,5);
+                }
+                $owner->load("ownerPriceSystem");
+                $this->success($owner->ownerPriceSystem);
+                break;
         }
     }
 
+    /**
+     * 获取审核对比信息
+     */
+
+
 }

+ 5 - 0
app/Http/Controllers/TestController.php

@@ -166,8 +166,13 @@ class TestController extends Controller
 
     public function test()
     {
+        list($a,$ab) = $this->a();
+        dd($a,$ab);
         return view("test");
     }
+    public function a(){
+        return array(null,null);
+    }
     public function supplementMarchOwnerReport()
     {
         $ows = OwnerAreaReport::query()->select("owner_id")->where("counting_month",'like',"2021-03%")->get();

+ 39 - 16
app/Jobs/ResetInstantBill.php

@@ -61,43 +61,58 @@ class ResetInstantBill implements ShouldQueue
                 $volume = 0;
                 $weight = 0;
                 $logistic_bill = "";
+
                 if (!$order->logistic || $order->logistic->type == "物流")$logistic_fee = null;
+
                 $items = [];
+                $isBunched = $order->logistic->is_bunched=='Y';
+                $weightExceptionMark = false;
+                $provinceId = null;
+                $logisticTaxFee = 0;
                 foreach ($order->packages as &$package){
+                    $tax = 0;
+
                     $logistic_bill .= $package->logistic_number.",";
                     $volume += $package->bulk;
                     $weight += $package->weight;
+                    if (!$weightExceptionMark && (!$package->weight || $package->weight<0))$weightExceptionMark = true;
                     $partAmount = 0;
                     foreach($package->commodities as $commodity){
                         $partAmount += $commodity->amount;
                     }
                     $amount += $partAmount;
+
                     $provinceName = mb_substr($order->province,0,2);
                     $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
                         return Province::query()->where("name","like",$provinceName."%")->first();
                     },86400);
+                    $fee = null;
                     if ($province){
-                        $fee = $service->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
-                    }else{
-                        $logistic_fee = null;
-                        $fee = null;
-                    }
+                        if (!$provinceId)$provinceId = $province->id;
+                        else if ($provinceId!=$province->id)$weightExceptionMark = true;
+                        if (!$isBunched)list($fee,$tax) = $service->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
+                    }else $logistic_fee = null;
+
                     $items[] = [
                         "amount" => $partAmount,
                         "logistic_bill" => $package->logistic_number,
                         "volume"=>$package->bulk,
                         "weight"=>$package->weight,
-                        "logistic_fee" => $fee>0 ? $fee : null,
+                        "logistic_fee" => $fee,
+                        "tax_fee" => $tax,
                     ];
                     if ($logistic_fee!==null){
-                        if ($fee<0)$logistic_fee = null;
+                        if (!$fee || $fee<0)$logistic_fee = null;
                         else $logistic_fee += $fee;
                     }
+                    $logisticTaxFee += $tax;
                 }
+                /* 为字母单 且 重量与省份完整 且 重量大于0 且 省份存在 进入子母单计算 */
+                if ($isBunched && !$weightExceptionMark && $weight>0 && $provinceId)list($logistic_fee,$logisticTaxFee) = $service->matching($weight, $order->owner_id, $order->logistic_id, $provinceId);
                 if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
                 /** @var OwnerPriceOperationService $service */
                 $service = app("OwnerPriceOperationService");
-                $result = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
+                list($id,$money,$workTaxFee) = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
 
                 $detail = $this->detail->update([
                     "owner_id"          => $order->owner_id,
@@ -111,9 +126,11 @@ class ResetInstantBill implements ShouldQueue
                     "volume"            => $volume,
                     "weight"            => $weight,
                     "logistic_id"       => $order->logistic_id,
-                    "work_fee"          => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-                    "owner_price_operation_id"  => is_array($result) ? $result["id"] : null,
+                    "work_fee"          => $money,
+                    "owner_price_operation_id"  => $id,
                     "logistic_fee"      => $logistic_fee,
+                    "work_tax_fee"      => $workTaxFee,
+                    "logistic_tax_fee"  => $logistic_fee ? $logisticTaxFee : null,
                 ]);
                 if ($detail){
                     OwnerFeeDetailLogistic::query()->where("owner_fee_detail_id",$detail->id)->delete();
@@ -136,20 +153,25 @@ class ResetInstantBill implements ShouldQueue
                 if (!$waybill->destinationCity && !$waybill->order)break;
 
                 $owner_id = $waybill->order->owner_id ?? $waybill->owner_id;
+                $detail = OwnerFeeDetail::query()->where("type","发货")
+                    ->where("owner_id",$owner_id)->whereIn("operation_bill",[$waybill->wms_bill_number,$waybill->waybill_number])->first();
+
+                if ($detail && $detail->logistic_fee !== null)break;
 
                 if ($waybill->type == "专线"){
                     /** @var OwnerPriceLogisticService $service */
                     $service = app("OwnerPriceLogisticService");
-                    $fee = $service->matching($waybill->carrier_weight_other,$owner_id,$waybill->logistic_id,
+                    list($fee,$taxFee) = $service->matching($waybill->carrier_weight_other,$owner_id,$waybill->logistic_id,
                         $waybill->carrier_weight_unit_id_other,$waybill->order ? app("RegionService")->getProvince($waybill->order->province) : $waybill->destinationCity->province_id,
                         $waybill->destination_city_id);
                 }else{
                     /** @var OwnerPriceDirectLogisticService $service */
                     $service = app("OwnerPriceDirectLogisticService");
-                    $fee = $service->matching($waybill->mileage,$owner_id,$waybill->carType_id);
+                    list($fee,$taxFee) = $service->matching($waybill->mileage,$owner_id,$waybill->carType_id);
                 }
                 $this->detail->update([
-                    "logistic_fee" => $fee ?? null,
+                    "logistic_fee" => $fee,
+                    "logistic_tax_fee" => $taxFee,
                 ]);
                 break;
             case "stores":
@@ -160,14 +182,15 @@ class ResetInstantBill implements ShouldQueue
 
                 /** @var OwnerPriceOperationService $service */
                 $service = app("OwnerPriceOperationService");
-                $result = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库");
+                list($id,$money,$taxFee) = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库");
                 $this->detail->update([
                     "owner_id" => $store->owner_id,
                     "worked_at" => $store->created_at,
                     "operation_bill" => $store->asn_code,
                     "commodity_amount" => array_sum(array_column($store->storeItems->toArray(), "amount")),
-                    "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-                    "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+                    "work_fee" => $money,
+                    "owner_price_operation_id" => $id,
+                    "work_tax_fee" => $taxFee
                 ]);
                 break;
         }

+ 1 - 1
app/Logistic.php

@@ -17,7 +17,7 @@ class Logistic extends Model
     use ModelLogChanging;
     use SoftDeletes;
     use ModelTimeFormat;
-    protected $fillable = ['name','code',"type","mobile","remark","delivery_fee"];
+    protected $fillable = ['name','code',"type","mobile","remark","delivery_fee","is_bunched"];
 
 
     static function nameById($id){

+ 17 - 1
app/Owner.php

@@ -36,7 +36,7 @@ class Owner extends Model
         "relevance",             //关联模型的JSON数组
         'subjection'             //主体公司
     ];
-    //relevance说明 0:仓储 1:作业 2:快递 3:物流 4:直发 存储示例:["0","1"]存在仓储与作业计费
+    //relevance说明 0:仓储 1:作业 2:快递 3:物流 4:直发 5:系统 存储示例:["0","1"]存在仓储与作业计费
     protected $casts = [
         "relevance" => "array"
     ];
@@ -150,6 +150,16 @@ class Owner extends Model
                 $query->where("operation","!=","D")->orWhereNull("operation");
             });
     }
+    public function ownerPriceSystem()
+    {   //系统计费
+        $query = OwnerPriceSystem::query()->select("target_id")
+            ->whereNotNull("operation")->where("operation","!=","")
+            ->whereNotNull("target_id")->where("target_id","!=","");
+        return $this->hasOne(OwnerPriceSystem::class,"owner_id","id")
+            ->whereNotIn("id",$query)->where(function(Builder $query){
+                $query->where("operation","!=","D")->orWhereNull("operation");
+            });
+    }
     public function warehouse()
     {   //仓库
         return $this->belongsTo(Warehouse::class,"warehouse_id","id");
@@ -197,4 +207,10 @@ class Owner extends Model
             ->where("operation","!=","")
             ->limit(1);
     }
+    public function systemAudit()
+    {   //审核的直发模型
+        return $this->hasOne(OwnerPriceSystem::class,"owner_id","id")
+            ->select(DB::raw(1))->whereNotNull("operation")
+            ->where("operation","!=","");
+    }
 }

+ 2 - 1
app/OwnerBillReport.php

@@ -19,6 +19,7 @@ class OwnerBillReport extends Model
        "confirm_fee",    //确认账单金额
        "difference",     //差额
        "confirmed",      //确认状态
+       "other_fee",      //其他费用
    ];
    protected $appends=[
         "initial_fee"
@@ -39,6 +40,6 @@ class OwnerBillReport extends Model
     }
     public function getInitialFeeAttribute()
     {   //初始账单金额
-        return $this->work_fee + $this->logistic_fee + $this->storage_fee;
+        return $this->work_fee + $this->logistic_fee + $this->storage_fee + $this->other_fee;
     }
 }

+ 2 - 0
app/OwnerFeeDetail.php

@@ -30,6 +30,8 @@ class OwnerFeeDetail extends Model
         "created_at",       //创建时间
         "outer_id",         //关联表ID
         "outer_table_name", //关联表名
+        "work_tax_fee",     //作业税费
+        "logistic_tax_fee", //物流税费
     ];
     public $timestamps = false;
 

+ 1 - 1
app/OwnerFeeDetailLogistic.php

@@ -11,7 +11,7 @@ class OwnerFeeDetailLogistic extends Model
     use ModelLogChanging;
 
     protected $fillable=[
-      "owner_fee_detail_id","amount","logistic_bill","volume","weight","logistic_fee"
+      "owner_fee_detail_id","amount","logistic_bill","volume","weight","logistic_fee","tax_fee"
     ];
 
     public $timestamps = false;

+ 5 - 1
app/OwnerPriceDirectLogistic.php

@@ -16,7 +16,7 @@ class OwnerPriceDirectLogistic extends Model
         "base_km",  //起步公里数
         "operation",//操作
         "target_id",//目标ID
-
+        "tax_rate_id",//税率
     ];
 
     public function details()
@@ -27,6 +27,10 @@ class OwnerPriceDirectLogistic extends Model
     {   //货主中间表
         return $this->belongsToMany(Owner::class,"owner_price_direct_logistic_owner","owner_price_direct_logistic_id","owner_id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 
     public function getOwnerIdAttribute()
     {   //获取货主ID数组

+ 5 - 0
app/OwnerPriceExpress.php

@@ -19,6 +19,7 @@ class OwnerPriceExpress extends Model
         "target_id",        //目标ID
         "amount_interval",  //数量区间
         "weight_interval",  //重量区间
+        "tax_rate_id",      //税率
     ];
     protected $casts = [
         "amount_interval" => "array",
@@ -37,6 +38,10 @@ class OwnerPriceExpress extends Model
     {   //计费详情
         return $this->hasMany(OwnerPriceExpressProvince::class,"owner_price_express_id","id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 
     public function getOwnerIdAttribute()
     {   //获取货主ID数组

+ 5 - 0
app/OwnerPriceLogistic.php

@@ -22,6 +22,7 @@ class OwnerPriceLogistic extends Model
         "service_price",    //信息服务费
         "operation",        //操作
         "target_id",        //目标ID
+        "tax_rate_id",      //税率
     ];
 
     public function getUnitRangeJsonAttribute()
@@ -53,6 +54,10 @@ class OwnerPriceLogistic extends Model
     {   //物流
         return $this->belongsToMany(Logistic::class,"owner_price_logistic_logistic","owner_price_logistic_id","logistic_id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 
     public function getOwnerIdAttribute()
     {   //获取货主ID数组

+ 5 - 0
app/OwnerPriceOperation.php

@@ -26,6 +26,7 @@ class OwnerPriceOperation extends Model
         "surcharge",        //附加费
         "surcharge_unit_id",//附加费单位
         "max_fee",          //封顶费
+        "tax_rate_id",      //税率
     ];
     public static $features = null;
     public static $columnMapping = null;
@@ -41,6 +42,10 @@ class OwnerPriceOperation extends Model
     {   //货主
         return $this->belongsToMany(Owner::class,"owner_price_operation_owner","owner_price_operation_id","owner_id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 
     public function getFeatureFormatAttribute()
     {

+ 16 - 0
app/OwnerPriceSystem.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class OwnerPriceSystem extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable=[
+        "owner_id","usage_fee","operation","target_id","tax_rate_id"
+    ];
+}

+ 5 - 0
app/OwnerStoragePriceModel.php

@@ -23,6 +23,7 @@ class OwnerStoragePriceModel extends Model
         "operation",        //操作
         "target_id",        //目标ID
         "amount_interval",  //数量区间
+        "tax_rate_id",      //税率
     ];
     protected $casts = [
         "amount_interval" => "array",
@@ -41,4 +42,8 @@ class OwnerStoragePriceModel extends Model
     {   //计时单位
         return $this->belongsTo(Unit::class,"time_unit_id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 }

+ 42 - 22
app/Services/OrderService.php

@@ -1096,11 +1096,17 @@ sql
         if (!$order->logistic || $order->logistic->type == "物流")$logistic_fee = null;
 
         $items = [];
+        $isBunched = $order->logistic->is_bunched=='Y';
+        $weightExceptionMark = false;
+        $provinceId = null;
+        $logisticTaxFee = 0;
         foreach ($order->packages as &$package){
+            $tax = 0;
+
             $logistic_bill .= $package->logistic_number.",";
             $volume += $package->bulk;
             $weight += $package->weight;
-
+            if (!$weightExceptionMark && (!$package->weight || $package->weight<0))$weightExceptionMark = true;
             $partAmount = 0;
             foreach($package->commodities as $commodity){
                 $partAmount += $commodity->amount;
@@ -1111,30 +1117,33 @@ sql
             $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
                 return Province::query()->where("name","like",$provinceName."%")->first();
             },86400);
+            $fee = null;
             if ($province){
-                $fee = $service->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
-            }else{
-                $logistic_fee = null;
-                $fee = null;
-            }
+                if (!$provinceId)$provinceId = $province->id;
+                else if ($provinceId!=$province->id)$weightExceptionMark = true;
+                if (!$isBunched)list($fee,$tax) = $service->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
+            }else $logistic_fee = null;
 
             $items[] = [
                 "amount" => $partAmount,
                 "logistic_bill" => $package->logistic_number,
                 "volume"=>$package->bulk,
                 "weight"=>$package->weight,
-                "logistic_fee" => $fee>0 ? $fee : null,
+                "logistic_fee" => $fee,
+                "tax_fee" => $tax,
             ];
             if ($logistic_fee!==null){
-                if ($fee<0)$logistic_fee = null;
+                if (!$fee || $fee<0)$logistic_fee = null;
                 else $logistic_fee += $fee;
             }
+            $logisticTaxFee += $tax;
         }
+        /* 为字母单 且 重量与省份完整 且 重量大于0 且 省份存在 进入子母单计算 */
+        if ($isBunched && !$weightExceptionMark && $weight>0 && $provinceId)list($logistic_fee,$logisticTaxFee) = $service->matching($weight, $order->owner_id, $order->logistic_id, $provinceId);
         if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
-
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
-        $result = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
+        list($id,$money,$workTaxFee) = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
 
         $detail = app("OwnerFeeDetailService")->create([
             "owner_id"          => $order->owner_id,
@@ -1149,12 +1158,14 @@ sql
             "volume"            => $volume,
             "weight"            => $weight,
             "logistic_id"       => $order->logistic_id,
-            "work_fee"          => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-            "owner_price_operation_id"  => is_array($result) ? $result["id"] : null,
+            "work_fee"          => $money,
+            "owner_price_operation_id"  => $id,
             "logistic_fee"      => $logistic_fee,
             "created_at"        => date('Y-m-d H:i:s'),
             "outer_id"          => $order->id,
             "outer_table_name"  => "orders",
+            "work_tax_fee"      => $workTaxFee,
+            "logistic_tax_fee"  => $logistic_fee ? $logisticTaxFee : null,
        ]);
        if ($detail){
             foreach ($items as &$item)$item["owner_fee_detail_id"] = $detail->id;
@@ -1262,19 +1273,28 @@ sql
         $volume = 0;
         $weight = 0;
         if (!$order->logistic || $order->logistic->type != "快递")$logistic_fee = null;
+        $isBunched = $order->logistic->is_bunched=='Y';
+        $weightExceptionMark = false;
+        $provinceId = null;
+        $taxFee = 0;
         foreach ($order->packages as $package){
+            $tax = 0;
+
             $volume += $package->bulk;
             $weight += $package->weight;
+            if (!$weightExceptionMark && (!$package->weight || $package->weight<0))$weightExceptionMark = true;
+            $fee = null;
 
             $provinceName = mb_substr($order->province,0,2);
+            $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
+                return Province::query()->where("name","like",$provinceName."%")->first();
+            },86400);
             $fee = null;
-            if ($provinceName){
-                $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
-                    return Province::query()->where("name","like",$provinceName."%")->first();
-                },86400);
-                if (!$province)$logistic_fee = null;
-                else $fee = app("OwnerPriceExpressService")->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
-            }
+            if ($province){
+                if (!$provinceId)$provinceId = $province->id;
+                else if ($provinceId!=$province->id)$weightExceptionMark = true;
+                if (!$isBunched)list($fee,$tax) = app("OwnerPriceExpressService")->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
+            }else $logistic_fee = null;
 
             OwnerFeeDetailLogistic::query()->where("owner_fee_detail_id",$feeBill->id)->where("logistic_bill",$package->logistic_number)->update([
                 "volume"=>$package->bulk,
@@ -1285,10 +1305,10 @@ sql
                 if ($fee<0)$logistic_fee = null;
                 else $logistic_fee += $fee;
             }
+            $taxFee += $tax;
         }
-        if ($logistic_fee===null || $logistic_fee<0)
-            LogService::log(__METHOD__,"ERROR-校正即时账单计算物流费错误","订单ID:".$order->id."  费用结果:".$logistic_fee);
-        else $feeBill->update(["logistic_fee"=>$logistic_fee,"volume"=>$volume,"weight"=>$weight]);
+        if ($isBunched && !$weightExceptionMark && $weight>0 && $provinceId)list($logistic_fee,$taxFee) = app("OwnerPriceExpressService")->matching($weight, $order->owner_id, $order->logistic_id, $provinceId);
+        if ($logistic_fee!==null && $logistic_fee>0) $feeBill->update(["logistic_fee"=>$logistic_fee,"volume"=>$volume,"weight"=>$weight,"logistic_tax_fee"=>$taxFee]);
         return true;
     }
 

+ 5 - 4
app/Services/OwnerPriceDirectLogisticService.php

@@ -174,12 +174,11 @@ class OwnerPriceDirectLogisticService
 
 
     /**
-     * CODE: -1:未找到计费模型
      *
      * @param double $amount
      * @param integer $owner_id
      * @param integer $car_id
-     * @return double
+     * @return array
      */
     public function matching($amount, $owner_id, $car_id)
     {
@@ -192,10 +191,12 @@ class OwnerPriceDirectLogisticService
         })->where(function(Builder $query){
             $query->whereNull("operation")->orWhere("operation","");
         })->first();
-        if (!$model || !$model->details)return -1;
+        if (!$model || !$model->details)return array(null,null);
         if ($amount < $model->base_km)$amount = $model->base_km;
         $initialMoney = $model->details[0]->base_fee;
         $amount -= $model->base_km;
-        return ($amount*$model->details[0]->additional_fee)+$initialMoney;
+        $money = ($amount*$model->details[0]->additional_fee)+$initialMoney;
+        $taxFee = $model->tax_rate_id && $model->taxRate ? $money*($model->taxRate->value/100) : null;
+        return array($money,$taxFee);
     }
 }

+ 6 - 5
app/Services/OwnerPriceExpressService.php

@@ -234,17 +234,16 @@ sql
     }
 
     /**
-     * CODE: -1:未找到计费模型 -2:重量无效
      *
      * @param double $weight
      * @param integer $owner_id
      * @param integer $logistic_id
      * @param integer $province_id
-     * @return double
+     * @return array
      */
     public function matching($weight, $owner_id, $logistic_id, $province_id)
     {
-        if (!$weight)return -2;
+        if (!$weight)return array(null,null);
 
         $model = OwnerPriceExpress::query()->with(["details"=>function($query)use($province_id){
             /** @var Builder $query */
@@ -258,7 +257,7 @@ sql
         })->where(function(Builder $query){
             $query->whereNull("operation")->orWhere("operation","");
         })->first();
-        if (!$model || count($model->details)<1)return -1;
+        if (!$model || count($model->details)<1)return array(null,null);
 
         if ($model->amount_interval){
             $total = app("OrderService")->getOrderQuantity($owner_id);//获取该货主本月C端单量
@@ -278,6 +277,8 @@ sql
         $additionalPrice = $model->details[0]->additional_weight_price[$to1][$to2];
         if ($weight <= $model->initial_weight)return $initPrice;
         $weight -= $model->initial_weight;
-        return (ceil($weight/$model->additional_weight)*$additionalPrice)+$initPrice;
+        $money = (ceil($weight/$model->additional_weight)*$additionalPrice)+$initPrice;
+        $taxFee = $model->tax_rate_id && $model->taxRate ? $money*($model->taxRate->value/100) : null;
+        return array($money,$taxFee);
     }
 }

+ 8 - 6
app/Services/OwnerPriceLogisticService.php

@@ -192,7 +192,6 @@ class OwnerPriceLogisticService
     }
 
     /**
-     * CODE: -1:未找到计费模型
      *
      * @param double $amount
      * @param integer $owner_id
@@ -200,7 +199,7 @@ class OwnerPriceLogisticService
      * @param integer $unit_id
      * @param integer $province_id
      * @param integer $city_id
-     * @return double
+     * @return array
      */
     public function matching($amount, $owner_id, $logistic_id, $unit_id, $province_id, $city_id)
     {
@@ -219,18 +218,21 @@ class OwnerPriceLogisticService
         })->where(function(Builder $query){
             $query->whereNull("operation")->orWhere("operation","");
         })->first();
-        if (!$model || !$model->details)return -1;
+        if (!$model || !$model->details)return array(null,null);
+        $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;
             $arr = explode("-",$detail->range);
             if (count($arr) < 2 || !$arr[1]){
-                if ($amount >= $arr[0])return $this->calculation($amount,$detail,$fee);
+                if ($amount >= $arr[0])$money = $this->calculation($amount,$detail,$fee);
             }else{
-                if ($amount >= $arr[0] && $amount < $arr[1])return $this->calculation($amount,$detail,$fee);
+                if ($amount >= $arr[0] && $amount < $arr[1])$money = $this->calculation($amount,$detail,$fee);
             }
+            if ($money)break;
         }
-        return -1;
+        $taxFee = $model->tax_rate_id && $model->taxRate ? $money*($model->taxRate->value/100) : null;
+        return array($money,$taxFee);
     }
 
     private function calculation($amount, $detail, $fee)

+ 20 - 7
app/Services/OwnerPriceOperationService.php

@@ -310,12 +310,20 @@ class OwnerPriceOperationService
      *      不严格区分入库出库差异 统一模型
      * 七. 2021-03-30 zzd
      *      增加一级二级特征,零头价,满减按总件,附加费用等
+     * 八. 2021-04-19 zzd
+     *      增加税率计算,改变返回值数据结构,增加封顶费
      */
     public function matching($matchObject, $columnMapping, $ownerId, $type = '出库', $typeMark = null)
     {
         $units = app("UnitService")->getUnitMapping(["件","箱"]); //获取单位映射集
         $rules = $this->getOwnerPriceOperation($ownerId,$type,$typeMark);//货主下的全部规则
         if (!$rules)return -2;  //规则不存在跳出
+
+        //建立一组返回变量
+        $id = null;
+        $money = 0;
+        $taxFee = null;
+
         if ($type == '出库')$total = app("OrderService")->getOrderQuantity($ownerId);//获取该货主本月C端单量
         else {
             $total = 0;
@@ -330,17 +338,22 @@ class OwnerPriceOperationService
 
             if ($rule->strategy == '特征'){
                 if (app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject)){
-                    if ($rule->total_price)return ["id"=>$rule->id,"money"=>$result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price];//按单计价存在,直接返回单总价或减免总价
-                    $money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);
-                    if ($money>0)return ["id"=>$rule->id,"money"=>$rule->max_fee&&$money>$rule->max_fee ? $rule->max_fee : $money];
+                    if (!$rule->total_price)$money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);
+                    $id = $rule->id;
                 };
             }else{
-                if ($rule->total_price)return ["id"=>$rule->id,"money"=>$result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price]; //按单计价存在,直接返回单总价或减免总价
-                $money = $this->matchItem($rule,$columnMapping,$matchObject,$units,$ownerId,$result);
-                if ($money>0)return ["id"=>$rule->id,"money"=>$rule->max_fee&&$money>$rule->max_fee ? $rule->max_fee : $money];
+                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);
+                break;
+            }
         }
-        return $money ?? -7;
+        return array($id,$money,$taxFee);
     }
     /**
      * 根据货主 sku寻找箱规并将指定数量切换为箱 返回箱规

+ 6 - 5
app/Services/RejectedBillService.php

@@ -352,22 +352,23 @@ class RejectedBillService
         foreach (Store::query()->with("storeItems")->whereIn("id",$number)->get() as $store){
             /** @var OwnerPriceOperationService $service */
             $service = app("OwnerPriceOperationService");
-            $result = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库",0);
+            list($id,$money,$taxFee) = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库",0);
             $bill = OwnerFeeDetail::query()->where("outer_id",$store->id)->where("outer_table_name","stores")->first();
             if ($bill) $bill->update([
-                    "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-                    "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+                    "work_fee" => $money,
+                    "owner_price_operation_id" => $id,
             ]); else app("OwnerFeeDetailService")->create([
                 "owner_id" => $store->owner_id,
                 "worked_at" => $store->created_at,
                 "type" => "收货",
                 "operation_bill" => $store->asn_code,
                 "commodity_amount" => array_sum(array_column($store->storeItems->toArray(), "amount")),
-                "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-                "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+                "work_fee" => $money,
+                "owner_price_operation_id" => $id,
                 "created_at" => date('Y-m-d H:i:s'),
                 "outer_id" => $store->id,
                 "outer_table_name" => "stores",
+                "work_tax_fee" => $taxFee,
             ]);
         }
     }

+ 4 - 3
app/Services/StoreService.php

@@ -328,7 +328,7 @@ class StoreService
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
 
-        $result = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库");
+        list($id,$money,$taxFee) = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库");
 
         if (app("OwnerFeeDetailService")->create([
             "owner_id" => $store->owner_id,
@@ -336,11 +336,12 @@ class StoreService
             "type" => "收货",
             "operation_bill" => $store->asn_code,
             "commodity_amount" => array_sum(array_column($store->storeItems->toArray(), "amount")),
-            "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
-            "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+            "work_fee" => $money,
+            "owner_price_operation_id" => $id,
             "created_at" => date('Y-m-d H:i:s'),
             "outer_id" => $store->id,
             "outer_table_name" => "stores",
+            "work_tax_fee" => $taxFee,
         ])){
             $amount = 0;
             if ($store->storeItems)foreach ($store->storeItems as $item)$amount += $item->amount;

+ 4 - 3
app/Services/WaybillService.php

@@ -189,13 +189,13 @@ class WaybillService
         if ($waybill->type == "专线"){
             /** @var OwnerPriceLogisticService $service */
             $service = app("OwnerPriceLogisticService");
-            $fee = $service->matching($waybill->carrier_weight_other,$owner_id,$waybill->logistic_id,
+            list($fee,$taxFee) = $service->matching($waybill->carrier_weight_other,$owner_id,$waybill->logistic_id,
                 $waybill->carrier_weight_unit_id_other,$waybill->order ? app("RegionService")->getProvince($waybill->order->province) : $waybill->destinationCity->province_id,
                 $waybill->destination_city_id);
         }else{
             /** @var OwnerPriceDirectLogisticService $service */
             $service = app("OwnerPriceDirectLogisticService");
-            $fee = $service->matching($waybill->mileage,$owner_id,$waybill->carType_id);
+            list($fee,$taxFee) = $service->matching($waybill->mileage,$owner_id,$waybill->carType_id);
         }
 
         $obj = [
@@ -210,9 +210,10 @@ class WaybillService
             "volume" =>$waybill->carrier_weight ?? $waybill->warehouse_weight,
             "weight" => $waybill->carrier_weight_other ?? $waybill->warehouse_weight_other,
             "logistic_id" => $waybill->logistic_id,
-            "logistic_fee" => $fee ?? null,
+            "logistic_fee" => $fee,
             "outer_id" => $waybill->id,
             "outer_table_name" => "waybills",
+            "logistic_tax_fee" => $taxFee,
         ];
         if ($detail)app("OwnerFeeDetailService")->updateFind($detail,$obj);
         else OwnerFeeDetail::query()->create($obj);

+ 13 - 6
app/Services/common/QueryService.php

@@ -77,14 +77,21 @@ class QueryService
         return $query;
     }
 
-    public function priceModelAuditOrRecoverQuery($isAudit, Builder $query, $ownerId, $ids)
+    public function priceModelAuditOrRecoverQuery($isAudit, Builder $query, $ownerId, $ids, $notRelation = false)
     {
         $query = $query->whereNotNull("operation")->where("operation","!=","");
-        if ($ownerId) $query->whereHas("owners",function ($query)use($ownerId){
-            /** @var Builder $query */
-            if (is_array($ownerId))$query->whereIn("id",$ownerId);
-            else $query->where("id",$ownerId);
-        });
+        if ($ownerId){
+            if ($notRelation){
+                if (is_array($ownerId))$query->whereIn("id",$ownerId);
+                else $query->where("id",$ownerId);
+            }else{
+                $query->whereHas("owners",function ($query)use($ownerId){
+                    /** @var Builder $query */
+                    if (is_array($ownerId))$query->whereIn("id",$ownerId);
+                    else $query->where("id",$ownerId);
+                });
+            }
+        }
         if ($ids){
             if (is_array($ids))$query->whereIn("id",$ids);
             else $query->where("id",$ids);

+ 76 - 0
database/migrations/2021_04_16_151135_create_owner_price_systems_table.php

@@ -0,0 +1,76 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateOwnerPriceSystemsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('owner_price_systems', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger("owner_id")->index()->comment("货主");
+            $table->decimal("usage_fee",9,3)->default(0)->comment("使用费");
+            $table->char("operation",1)->index()->nullable()->comment("操作类型");
+            $table->bigInteger("target_id")->index()->nullable()->comment("目标ID");
+            $table->bigInteger("tax_rate_id")->nullable()->comment("税率");
+            $table->timestamps();
+        });
+        \App\Authority::query()->firstOrCreate(["name"=>"计费模型-系统-录入"],["name"=>"计费模型-系统-录入","alias_name"=>"计费模型-系统-录入"]);
+        Schema::table("logistics",function (Blueprint $table){
+            $table->char("is_bunched")->default("N")->comment("是否子母件");
+        });
+        $tables = ["owner_storage_price_models","owner_price_operations","owner_price_logistics","owner_price_expresses","owner_price_direct_logistics"];
+        foreach ($tables as $t){
+            Schema::table($t, function (Blueprint $table) {
+                $table->bigInteger("tax_rate_id")->nullable()->comment("税率");
+            });
+        }
+        Schema::table("owner_fee_details", function (Blueprint $table) {
+            $table->decimal("work_tax_fee",9,3)->nullable()->comment("作业税费");
+            $table->decimal("logistic_tax_fee",9,3)->nullable()->comment("物流税费");
+        });
+        Schema::table("owner_bill_reports", function (Blueprint $table) {
+            $table->decimal("other_fee",9,3)->nullable()->comment("其他费用");
+        });
+        Schema::table("owner_fee_detail_logistics", function (Blueprint $table) {
+            $table->decimal("tax_fee",9,3)->nullable()->comment("物流税费");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('owner_price_systems');
+        \App\Authority::query()->where("alias_name","计费模型-系统-录入")->delete();
+        Schema::table("logistics",function (Blueprint $table){
+            $table->dropColumn("is_bunched");
+        });
+        $tables = ["owner_storage_price_models","owner_price_operations","owner_price_logistics","owner_price_expresses","owner_price_direct_logistics"];
+        foreach ($tables as $t){
+            Schema::table($t, function (Blueprint $table) {
+                $table->dropColumn("tax_rate_id");
+            });
+        }
+        Schema::table("owner_fee_details", function (Blueprint $table) {
+            $table->dropColumn("work_tax_fee");
+            $table->dropColumn("logistic_tax_fee");
+        });
+        Schema::table("owner_bill_reports", function (Blueprint $table) {
+            $table->dropColumn("other_fee");
+        });
+        Schema::table("owner_fee_detail_logistics", function (Blueprint $table) {
+            $table->dropColumn("tax_fee");
+        });
+    }
+}

+ 76 - 10
resources/views/customer/project/create.blade.php

@@ -165,6 +165,9 @@
                     directLogistic:{
                         items:[],
                     },
+                    system:{
+                        usage_fee:""
+                    },
                 },
                 pool:{//基础数据选择池,以方便异步懒加载而非即时加载 例:units,owners等
                     counting_type:[
@@ -186,6 +189,7 @@
                     express:[],
                     logistic:[],
                     directLogistic:{},
+                    system:{},
                 },
                 thisOperationItemIndex:-1,//当前选中的作业费子项下标,用以唤起特征模态框
                 operationItems:{},//控制作业费子项的渐入展开
@@ -213,7 +217,7 @@
                 this._resetOperation();
                 this.ownerTemp = JSON.parse(JSON.stringify(this.owner));
                 if (type){
-                    this.base = "three";
+                    this.switchBase("three");
                     this.type = "";
                     setTimeout(()=>{
                         this.switchType(type);
@@ -266,9 +270,14 @@
                 switchBase(base){
                     if (!this.owner.id)return;
                     if (base === this.base)return;
-                    if (base === 'three') this._loadStorage();
-                    if (base === 'two')this._getTaxRates();
-                    this.base = base;
+                    if (base === 'three'){
+                        if (!this.pool.taxRates) this._getTaxRates();
+                        this._loadStorage();
+                    }
+                    if (base === 'two')if (!this.pool.taxRates) this._getTaxRates();
+                    setTimeout(()=>{
+                        this.base = base;
+                    },300);
                 },
                 //切换类型
                 switchType(type){
@@ -298,6 +307,10 @@
                             this._loadDirectLogistic();
                             dom = $("#directLogistic-card");
                             break;
+                        case "system":
+                            dom = $("#system-card");
+                            if(this.selectedModel.system)this.model.system = this.selectedModel.system;
+                            break;
                     }
                     dom.addClass("animation-translation");
                     dom.fadeOut(500);
@@ -317,8 +330,9 @@
                             });
                             break;
                         case "two":
-                            if (this._verifyTwo())this.base = "three";
-                            this._loadStorage();
+                            if (this._verifyTwo()){
+                                this.switchBase('three');
+                            }
                             break;
                     }
                 },
@@ -487,6 +501,7 @@
                         if (res.express_audit_count)audit.express = true;
                         if (res.logistic_audit_count)audit.logistic = true;
                         if (res.direct_logistic_audit_count)audit.directLogistic = true;
+                        if (res.system_audit_count)audit.system = true;
                         this.audit = audit;
                         if (res.owner_storage_price_models.length>0)this.selectedModel.storage = res.owner_storage_price_models;
                         if (res.owner_price_operations.length>0){
@@ -516,6 +531,7 @@
                             this.upList["directLogistic-item"] = true;
                             this.selectedModel.directLogistic = this._overrideDirectLogistic(res.owner_price_direct_logistics[0]);
                         }
+                        if (res.owner_price_system)this.selectedModel.system = res.owner_price_system;
                         setTimeout(()=> {
                             $(".up").slideUp();
                             this.isLoad = true;
@@ -553,11 +569,11 @@
                     if (!this.pool.owners)this._getOwners();
                     if (!this.pool.logistics)this._getLogistics();
                 },
-                _setModelData(key,val){
+                _setModelData(key,val,column='name',append=""){
                     if (!val)return;
                     let mapping = [];
                     val.forEach(item=>{
-                        mapping[item.id] = item.name;
+                        mapping[item.id] = item[column]+append;
                     });
                     this.$set(this.pool,key,val);
                     this.$set(this.poolMapping,key,mapping);
@@ -589,7 +605,7 @@
                         this._setModelData("logistics",res);
                         setTimeout(()=>{
                             $(".selectpicker").selectpicker('refresh');
-                        },0);
+                        },100);
                     });
                 },
                 //获取车型
@@ -600,7 +616,7 @@
                 //获取税率
                 _getTaxRates(){
                     let url = "{{url('maintenance/taxRate/get')}}";
-                    window.axios.post(url).then(res=>{this._setModelData("taxRates",res.data);});
+                    window.axios.post(url).then(res=>{this._setModelData("taxRates",res.data,"value","%");});
                 },
                 //保存模型
                 saveModel(){
@@ -621,8 +637,32 @@
                         case "directLogistic":
                             this._verifyDirectLogistic();
                             break;
+                        case "system":
+                            this._verifySystem();
+                            break;
                     }
                 },
+                _verifySystem(){
+                    if (this.model.system.usage_fee<0){
+                        this.errors = {usage_fee:["费用不得小于0"]};
+                        return;
+                    }
+                    let url = "{{url('maintenance/priceModel/apiStoreSystem')}}";
+                    let params = this.model.system;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            this.errors = res.errors;
+                            return;
+                        }
+                        this.selectedModel.system = res;
+                        this.model.system = {
+                            usage_fee:"",
+                        };
+                        this.errors = {};
+                        this.audit.system = true;
+                    });
+                },
                 _verifyStorage(){
                     let error = {};
                     if (!this.model.storage.counting_type)error["counting_type"] = ["未选择计费类型"];
@@ -1362,6 +1402,9 @@
                         case "logistic":
                             this._getLogisticPriceModel();
                             break;
+                        case "system":
+                            this._getSystemPriceModel();
+                            break;
                         default:
                             this._getDirectLogisticPriceModel();
                     }
@@ -1453,6 +1496,11 @@
                         this.isSearch = false;
                     });
                 },
+                _getSystemPriceModel(){
+                    this.searchResult = [];
+                    this.searchResultMapping = [];
+                    this.isSearch = false;
+                },
                 _getLogisticPriceModel(){
                     let url = "{{url('maintenance/priceModel/apiGetLogistic')}}";
                     window.tempTip.postBasicRequest(url,this.introduce,res=>{
@@ -1648,6 +1696,16 @@
                         });
                     });
                 },
+                //删除系统
+                deleteSystem(item){
+                    window.tempTip.confirm("您确定要删除该系统计费吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelSystem')}}",{id:item.id},res=>{
+                            this.$set(this.selectedModel,"system",{usage_fee:""});
+                            this.audit.system = true;
+                            return "删除成功";
+                        });
+                    });
+                },
                 //编辑仓储
                 editStorage(index){
                     this.switchType("storage");
@@ -1679,6 +1737,11 @@
                     this.switchType("directLogistic");
                     this.model.directLogistic = JSON.parse(JSON.stringify(this.selectedModel.directLogistic));
                 },
+                //编辑系统
+                editSystem(){
+                    this.switchType("system");
+                    this.model.system = JSON.parse(JSON.stringify(this.selectedModel.system));
+                },
                 //搜索快递子项
                 searchExpress(e){
                     let val = e.target.value;
@@ -1775,6 +1838,9 @@
                                     this.upList["directLogistic-item"] = true;
                                     this.selectedModel.directLogistic = this._overrideDirectLogistic(res[0]);
                                     break;
+                                case "system":
+                                    this.selectedModel.system = res;
+                                    break;
                             }
                             this.$set(this.audit,type,false);
                         })

+ 3 - 2
resources/views/customer/project/index.blade.php

@@ -66,7 +66,7 @@
                     <td><span>@{{ owner.customer_name }}</span></td>
                     <td><span>@{{ owner.user_owner_group_name }}</span></td>
                     <td><span>@{{ owner.user_work_group_name }}</span></td>
-                    <td><span><b>@{{owner.relevance ? owner.relevance.length : 0}}</b>/5&nbsp;<span class="badge badge-success" v-if="owner.audit_count>0">@{{ owner.audit_count }}项待审</span></span></td>
+                    <td><span><b>@{{owner.relevance ? owner.relevance.length : 0}}</b>/6&nbsp;<span class="badge badge-success" v-if="owner.audit_count>0">@{{ owner.audit_count }}项待审</span></span></td>
                     <td><span>@{{ owner.created_at }}</span></td>
                     <td><span>@{{ owner.customer_company_name }}</span></td>
                     <td><span>@{{ ownerSubjection[owner.subjection] }}</span></td>
@@ -108,7 +108,8 @@
                         user_work_group_name:"{{$owner->userWorkGroup ? $owner->userWorkGroup->name : ''}}",
                         is_activation : "{{$owner->deleted_at ? '否' : '是'}}",
                         ownerStoragePriceModels : {!! $owner->ownerStoragePriceModels !!},
-                        audit_count:"{{count($owner->storageAudit)+count($owner->operationAudit)+count($owner->expressAudit)+count($owner->logisticAudit)+count($owner->directLogisticAudit)}}",
+                        audit_count:"{{count($owner->storageAudit)+count($owner->operationAudit)+count($owner->expressAudit)+count($owner->logisticAudit)+count($owner->directLogisticAudit)+($owner->systemAudit ? 1 : 0)}}",
+                        a:"{{$owner}}"
                     },
                     @endforeach
                 ],

+ 6 - 0
resources/views/customer/project/part/_directLogistic.blade.php

@@ -14,6 +14,12 @@
         <strong>@{{ errors.base_km[0] }}</strong>
     </span>
 </div>
+<div class="row mt-3">
+    <label for="tax_rate_id" class="col-3 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control ml-3" v-model="model.directLogistic.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
+</div>
 <div class="row mt-3">
     <label class="col-3 cursor-pointer" @click="show('directLogistic-item-card')"><span @click="show('directLogistic-item-card')">详情&nbsp;
         <span class="fa" :class="upList['express-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span></span></label>

+ 7 - 1
resources/views/customer/project/part/_express.blade.php

@@ -21,7 +21,13 @@
            v-model="model.express.additional_weight" :class="errors.additional_weight ? 'is-invalid' : ''"></label>
 </div>
 <div class="row mt-3">
-    <label for="isInterval" class="col-3"><b class="text-danger">* </b>设定区间</label>
+    <label for="tax_rate_id" class="col-3 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control ml-3" v-model="model.express.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
+</div>
+<div class="row mt-3">
+    <label for="isInterval" class="col-3">设定区间</label>
     <label class="col-7"><input id="isInterval" type="checkbox" class="switch"  v-model="model.express.isInterval"></label>
 </div>
 <div class="row mt-3" v-if="model.express.isInterval">

+ 7 - 1
resources/views/customer/project/part/_logistic.blade.php

@@ -58,7 +58,7 @@
         <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
     </select>
     <label for="logistic_other_unit_range" class="col-2 text-right"><b class="text-danger">*</b>区间值</label>
-    <input id="logistic_other_unit_range" type="text" placeholder="文字描述区间逗号(,)间隔,示例:0-5,10-30,30-"
+    <input id="logistic_other_unit_range" type="text" placeholder="文字描述区间逗号(,)间隔,示例:0-5,5-30,30-" title="文字描述区间逗号(,)间隔,示例:0-5,5-30,30-"
            v-model="model.logistic.other_unit_range" class="col-3 form-control" :class="errors.other_unit_range ? 'is-invalid' : ''" @change="changeRange('other_ranges')">
 </div>
 <div class="row mt-0">
@@ -72,4 +72,10 @@
             <button type="button" class="btn btn-sm btn-outline-info col-4" @click="showDetailModal()">详情列表</button>
         </div>
     </div>
+</div>
+<div class="row mt-3">
+    <label for="tax_rate_id" class="col-2 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control" v-model="model.logistic.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
 </div>

+ 6 - 0
resources/views/customer/project/part/_operation.blade.php

@@ -181,4 +181,10 @@
 <div class="row mt-3">
     <label for="remark" class="col-2">备注</label>
     <textarea id="remark" class="col-6 form-control" v-model="model.operation.remark"></textarea>
+</div>
+<div class="row mt-3">
+    <label for="tax_rate_id" class="col-2 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control" v-model="model.operation.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
 </div>

+ 6 - 0
resources/views/customer/project/part/_storage.blade.php

@@ -123,4 +123,10 @@
     <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.discount_value">
         <strong>@{{ errors.discount_value[0] }}</strong>
     </span>
+</div>
+<div class="row mt-3">
+    <label for="tax_rate_id" class="col-2 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control" v-model="model.storage.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
 </div>

+ 13 - 0
resources/views/customer/project/part/_system.blade.php

@@ -0,0 +1,13 @@
+<div class="row">
+    <label for="usage_fee" class="col-2 text-info">系统使用费</label>
+    <input id="usage_fee" type="number" step="0.01" min="0" :class="errors.usage_fee ? 'is-invalid' : ''" class="col-6 form-control" v-model="model.system.usage_fee">
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.usage_fee">
+        <strong>@{{ errors.usage_fee[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="tax_rate_id" class="col-2 text-muted">税率</label>
+    <select id="tax_rate_id" class="col-3 form-control" v-model="model.system.tax_rate_id">
+        <option v-for="tax in pool.taxRates" :value="tax.id">@{{ tax.value }}%</option>
+    </select>
+</div>

+ 37 - 2
resources/views/customer/project/part/_three.blade.php

@@ -23,6 +23,7 @@
                         <th>计时单位</th>
                         <th>减免类型</th>
                         <th>减免值</th>
+                        <th>税率</th>
                         <th></th>
                     </tr>
                     <tr v-for="(item,i) in selectedModel.storage" style="cursor: pointer" @dblclick="editStorage(i)">
@@ -43,6 +44,7 @@
                         <td>@{{ poolMapping.units ? poolMapping.units[item.time_unit_id] : '' }}</td>
                         <td>@{{ item.discount_type }}</td>
                         <td>@{{ item.discount_value }}</td>
+                        <td>@{{ poolMapping.taxRates ? poolMapping.taxRates[item.tax_rate_id] : '' }}</td>
                         <td class="cursor-pointer" @click.stop="delStorage(item,i)"><span class="font-weight-bold text-danger">&times;</span></td>
                     </tr>
                 </table>
@@ -76,6 +78,7 @@
                                     <label>@{{ operation.name }}</label><span class="badge badge-pill badge-danger" v-if="operation.isRejected">退</span>
                                     <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
                                     <label v-if="operation.surcharge">耗材附加费:<b>@{{ operation.surcharge }}</b>/@{{ poolMapping.units ? poolMapping.units[operation.surcharge_unit_id] : '' }}</label>
+                                    <label v-if="operation.tax_rate_id">税率:@{{ poolMapping.taxRates ? poolMapping.taxRates[operation.tax_rate_id] : '' }}</label>
                                 </div>
                                 <div class="col-1">
                                     <span class="cursor-pointer text-danger font-weight-bold"
@@ -123,6 +126,7 @@
                                     <label>@{{ operation.name }}</label>
                                     <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
                                     <label v-if="operation.surcharge">耗材附加费:<b>@{{ operation.surcharge }}</b>/@{{ poolMapping.units ? poolMapping.units[operation.surcharge_unit_id] : '' }}</label>
+                                    <label v-if="operation.tax_rate_id">税率:@{{ poolMapping.taxRates ? poolMapping.taxRates[operation.tax_rate_id] : '' }}</label>
                                 </div>
                                 <div class="col-1">
                                     <span class="cursor-pointer text-danger font-weight-bold"
@@ -186,6 +190,7 @@
                         <th>名称</th>
                         <th>首重值(KG)</th>
                         <th>续重值(KG)</th>
+                        <th>税率</th>
                         <th>详情</th>
                         <th></th>
                     </tr>
@@ -193,12 +198,13 @@
                         <tr>
                             <td>
                                 <div class="text-overflow-warp-100 small">
-                                    <label v-for="(logistic,j) in express.logistics" class="m-0">@{{ poolMapping.logistics ? poolMapping.logistics[logistic] : '' }}</label>
+                                    <label v-for="(logistic,j) in express.logistics" class="m-0">@{{ poolMapping.logistics ? poolMapping.logistics[logistic] : '' }}<br></label>
                                 </div>
                             </td>
                             <td>@{{ express.name }}</td>
                             <td>@{{ express.initial_weight }}</td>
                             <td>@{{ express.additional_weight }}</td>
+                            <td>@{{ poolMapping.taxRates ? poolMapping.taxRates[express.tax_rate_id] : '' }}</td>
                             <td @click.stop="show('express-item-'+i)" class="cursor-pointer">
                                 <span class="fa" :class="upList['express-item-'+i] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span>
                                 &nbsp;@{{ express.items.length }} 省份</td>
@@ -284,6 +290,7 @@
                         <th>提货费</th>
                         <th>燃油附加费</th>
                         <th>信息服务费</th>
+                        <th>税率</th>
                         <th>详情</th>
                         <th></th>
                     </tr>
@@ -302,6 +309,7 @@
                             <td>@{{ logistic.pick_up_price }}</td>
                             <td>@{{ logistic.fuel_price }}</td>
                             <td>@{{ logistic.service_price }}</td>
+                            <td>@{{ poolMapping.taxRates ? poolMapping.taxRates[logistic.tax_rate_id] : '' }}</td>
                             <td @click.stop="show('logistic-item-'+i)" class="cursor-pointer">
                                 <span class="fa" :class="upList['logistic-item-'+i] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span>
                                 &nbsp;@{{ logistic.items.length }} 地区
@@ -363,7 +371,8 @@
                 <div class="row">
                     <span class="col-4">名称:<b>@{{ selectedModel.directLogistic.name }}</b></span>
                     <span class="col-4">起步数(KM):<b>@{{ selectedModel.directLogistic.base_km }}</b></span>
-                    <span class="col-1 offset-3" v-if="selectedModel.directLogistic.name">
+                    <span class="col-3">税率:<b>@{{ poolMapping.taxRates ? poolMapping.taxRates[selectedModel.directLogistic.tax_rate_id] : '' }}</b></span>
+                    <span class="col-1" v-if="selectedModel.directLogistic.name">
                         <span class="cursor-pointer text-danger font-weight-bold" @click.stop="delDirectLogistic(selectedModel.directLogistic)">&times;</span>
                     </span>
                 </div>
@@ -391,6 +400,28 @@
                 </div>
             </div>
         </div>
+        <div class="card" id="system-card">
+            <div class="card-header bg-light-info row">
+                <div class="col-3 pull-left font-weight-bold cursor-pointer text-secondary" @click="show('system')"><span class="fa fa-align-justify"></span>&nbsp;系统</div>
+                <div class="col-6 text-center">
+                    <div v-if="audit.system">
+                        @can("项目管理-项目-计费模型-审核")<button class="btn btn-sm btn-success" type="button" @click="auditOrRecoverModel('system')">审核</button>
+                        <button class="btn btn-sm btn-danger" type="button" @click="auditOrRecoverModel('system',false)">恢复</button>@endcan
+                    </div>
+                </div>
+                <div class="col-3 pull-right small mb-0 text-secondary" v-if="selectedModel.system.id">双击下方已添加内容可编辑</div>
+            </div>
+            <div class="card-body" id="system" @dblclick="editSystem()" style="cursor: pointer">
+                <div class="row">
+                    <label class="col-3">系统使用费:</label>
+                    <label class="col-9">@{{ selectedModel.system.usage_fee }}</label>
+                </div>
+                <div class="row">
+                    <label class="col-3">税率:</label>
+                    <label class="col-9">@{{ poolMapping.taxRates ? poolMapping.taxRates[selectedModel.system.tax_rate_id] : '' }}</label>
+                </div>
+            </div>
+        </div>
     </div>
     <div class="col-6">
         <div class="card">
@@ -400,6 +431,7 @@
                 <button type="button" class="btn mr-1" :class="type == 'express' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('express')">快递</button>
                 <button type="button" class="btn mr-1" :class="type == 'logistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('logistic')">物流</button>
                 <button type="button" class="btn mr-1" :class="type == 'directLogistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('directLogistic')">直发</button>
+                <button type="button" class="btn mr-1" :class="type == 'system' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('system')">系统</button>
             </div>
             <div class="card-body">
                 @can("计费模型-仓储-录入")<div v-if="type == 'storage'">
@@ -419,6 +451,9 @@
                 @can("计费模型-直发-录入")<div v-show="type == 'directLogistic'">
                     @include("customer.project.part._directLogistic")
                 </div>@endcan
+                @can("计费模型-系统-录入")<div v-show="type == 'system'">
+                    @include("customer.project.part._system")
+                </div>@endcan
                 @include("customer.project.part._introducePriceModel")
                 <div class="row mt-3" v-if="base=='three'">
                     <div class="col-2"></div>

+ 6 - 0
resources/views/maintenance/logistic/create.blade.php

@@ -53,6 +53,12 @@
                             @enderror
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="is_bunched" class="col-2 col-form-label text-right">是否子母单</label>
+                        <div class="col-8">
+                            <input id="is_bunched" name="is_bunched" type="checkbox" class="switch" @if(old('is_bunched')) checked @endif>
+                        </div>
+                    </div>
                     <div class="form-group row">
                         <label for="mobile" class="col-2 col-form-label text-right">承运商电话</label>
                         <div class="col-8">

+ 6 - 0
resources/views/maintenance/logistic/edit.blade.php

@@ -59,6 +59,12 @@
                             @enderror
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="is_bunched" class="col-2 col-form-label text-right">是否子母单</label>
+                        <div class="col-8">
+                            <input id="is_bunched" type="checkbox" name="is_bunched" class="switch" @if(old('is_bunched') ?? $logistic->is_bunched=='Y') checked @endif>
+                        </div>
+                    </div>
                     <div class="form-group row">
                         <label for="mobile" class="col-2 col-form-label text-right">承运商电话</label>
                         <div class="col-8">

+ 2 - 2
resources/views/maintenance/logistic/index.blade.php

@@ -26,7 +26,7 @@
                     </tr>
                     <tr v-for="(logistic,i) in logistics" @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
                         <td class="text-muted">@{{logistic.id}}</td>
-                        <td>@{{logistic.name}}</td>
+                        <td>@{{logistic.name}}&nbsp;<span class="badge badge-success" v-if="logistic.is_bunched=='Y'">子母单</span></td>
                         <td>@{{logistic.code}}</td>
                         <td>@{{logistic.mobile}}</td>
                         <td>@{{logistic.type}}</td>
@@ -56,7 +56,7 @@
                     @foreach( $logistics as $logistic )
                     {id:'{{$logistic->id}}',name:'{{$logistic->name}}',code:'{{$logistic->code}}',
                         mobile:"{{$logistic->mobile}}",type:"{{$logistic->type}}",delivery_fee:"{{$logistic->delivery_fee}}",
-                        remark:"{{$logistic->remark}}",created_at:'{{$logistic->created_at}}'},
+                        remark:"{{$logistic->remark}}",created_at:'{{$logistic->created_at}}',is_bunched:"{{$logistic->is_bunched}}"},
                     @endforeach
                 ],
                 selectTr:0

+ 2 - 0
routes/web.php

@@ -160,6 +160,7 @@ Route::group(['prefix'=>'maintenance'],function(){
         Route::post('apiStoreExpress','PriceModelController@apiStoreExpress');
         Route::post('apiStoreLogistic','PriceModelController@apiStoreLogistic');
         Route::post('apiStoreDirectLogistic','PriceModelController@apiStoreDirectLogistic');
+        Route::post('apiStoreSystem','PriceModelController@apiStoreSystem');
         //api 获取计费模型
         Route::post('apiGetStorage','PriceModelController@apiGetStorage');
         Route::post('apiGetOperation','PriceModelController@apiGetOperation');
@@ -176,6 +177,7 @@ Route::group(['prefix'=>'maintenance'],function(){
         Route::post('apiDelLogisticItem','PriceModelController@apiDelLogisticItem');
         Route::post('apiDelDirectLogistic','PriceModelController@apiDelDirectLogistic');
         Route::post('apiDelDirectLogisticItem','PriceModelController@apiDelDirectLogisticItem');
+        Route::post('apiDelSystem','PriceModelController@apiDelSystem');
         //审核或恢复计费模型
         Route::post('auditOrRecoverModel','PriceModelController@auditOrRecoverModel');
     });