Browse Source

Merge branch 'zzd' of ssh://was.baoshi56.com:10022/var/git/bswas

LD 5 years ago
parent
commit
f05b463a96
29 changed files with 662 additions and 216 deletions
  1. 6 2
      app/Http/Controllers/CustomerController.php
  2. 15 3
      app/Http/Controllers/OrderController.php
  3. 15 9
      app/Http/Controllers/PriceModelController.php
  4. 57 7
      app/Http/Controllers/TestController.php
  5. 56 0
      app/Http/Controllers/WaybillController.php
  6. 1 1
      app/Services/FeatureService.php
  7. 7 8
      app/Services/OwnerPriceOperationService.php
  8. 25 2
      app/Services/OwnerService.php
  9. 2 2
      app/Services/OwnerStoragePriceModelService.php
  10. 2 0
      app/Services/WaybillService.php
  11. 0 17
      database/factories/OwnerPriceOperationItemInFactory.php
  12. 2 2
      database/factories/OwnerPriceOperationItemService.php
  13. 32 0
      database/migrations/2021_01_14_174723_add_index_created_at_table_waybills.php
  14. 5 0
      resources/sass/text.scss
  15. 87 25
      resources/views/customer/project/create.blade.php
  16. 38 2
      resources/views/customer/project/index.blade.php
  17. 24 16
      resources/views/customer/project/part/_directLogistic.blade.php
  18. 25 17
      resources/views/customer/project/part/_express.blade.php
  19. 13 10
      resources/views/customer/project/part/_logisticDetail.blade.php
  20. 1 1
      resources/views/customer/project/part/_operation.blade.php
  21. 14 14
      resources/views/customer/project/part/_three.blade.php
  22. 15 1
      resources/views/maintenance/priceModel/storage/create.blade.php
  23. 5 0
      resources/views/maintenance/priceModel/storage/index.blade.php
  24. 48 0
      resources/views/waybill/_batchUploadImg.blade.php
  25. 84 14
      resources/views/waybill/index.blade.php
  26. 1 0
      routes/web.php
  27. 6 3
      tests/Services/OwnerPriceExpressService/OwnerPriceExpressServiceTest.php
  28. 11 11
      tests/Services/OwnerPriceOperationItemService/OwnerPriceOperationItemServiceTest.php
  29. 65 49
      tests/Services/OwnerPriceOperationService/OwnerPriceOperationServiceTest.php

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

@@ -91,12 +91,16 @@ class CustomerController extends Controller
         if(!Gate::allows('客户管理-项目-查询')){ return redirect('denied');  }
         /** @var OwnerService $service */
         $service = app('OwnerService');
-        $owners = $service->paginate(['customer_id'=>true],['customer',"contracts","userOwnerGroup","ownerStoragePriceModels","ownerAreaReport"=>function($query){
+        $owners = $service->paginate(request()->input(),['customer',"contracts","userOwnerGroup","ownerStoragePriceModels","ownerAreaReport"=>function($query){
             $month = date('Y-m');
             /** @var Builder $query */
             $query->where("counting_month","like",$month."%");
         }]);
-        return response()->view('customer.project.index',compact("owners"));
+        $models = app('OwnerService')->getIntersectPermitting();
+        $customers = app('CustomerService')->getSelection();
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $params = request()->input();
+        return response()->view('customer.project.index',compact("owners","models","customers","ownerGroups","params"));
     }
 
     public function projectIndexExport(Request $request)

+ 15 - 3
app/Http/Controllers/OrderController.php

@@ -86,6 +86,10 @@ class OrderController extends Controller
         //分箱号
         $picktotraceids = json_decode($result['picktotraceids'],true);
         $rejectedBill_collect = collect();// 保存生成的rejectedBill
+        foreach ($result['orders'] as $order){
+            $blacklist = ["00","10","20","30","90"/*,"99"*/];
+            if (array_search($order->sostatus,$blacklist) !== false)return ['success'=>false,'data'=>'“'.$order->orderno."”状态异常,无法操作"];
+        }
         foreach ($result['orders'] as $order){
             //不存在时将当前快递单号视为分箱号
             if (!($picktotraceids[$order->orderno] ?? false))$picktotraceids[$order->orderno] = [$order->soreference5];
@@ -109,13 +113,21 @@ class OrderController extends Controller
                 ]);
                 $rejectedBill_collect->push($rejectedBill);// 保存生成的rejectedBill
                 LogService::log(__METHOD__,"生成退货单",json_encode($order),Auth::user()['id']);
-                if ($commodities[$order->orderno] ?? false){
-                    foreach ($commodities[$order->orderno] as $orderCommodities){
+                $cms = $commodities[$order->orderno] ?? [];
+                if (count($picktotraceids[$order->orderno]) > 1 && $cms){
+                    $sql = <<<sql
+ SELECT sum(QTY) qty,sku FROM ACT_ALLOCATION_DETAILS where ORDERNO = ? and PICKTOTRACEID = ? GROUP BY sku
+sql;
+                    $acts = DB::connection("oracle")->select(DB::raw($sql),[$order->orderno,$orderno]);
+                    $skus = array_column($acts,"sku");
+                    foreach ($cms as $orderCommodities){
+                        $index = array_search($orderCommodities["sku"],$skus);
+                        if ($index === false)continue;
                         array_push($rejectedBillItems,[
                             'id_rejected_bill' => $rejectedBill->id,
                             'barcode_goods' => $orderCommodities['alternate_sku1'],
                             'name_goods' => $orderCommodities['descr_c'],
-                            'amount' => $orderCommodities['qtyordered'],
+                            'amount' => $acts[$index]->qty,//$orderCommodities['qtyordered'],
                             'id_quality_label' => 1,
                             'created_at' => date('Y-m-d H:i:s'),
                         ]);

+ 15 - 9
app/Http/Controllers/PriceModelController.php

@@ -22,7 +22,6 @@ use App\Services\LogService;
 use App\Services\OwnerPriceOperationItemService;
 use App\Services\OwnerPriceOperationService;
 use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\DB;
@@ -36,7 +35,7 @@ class PriceModelController extends Controller
     public function storageIndex(Request $request)
     {
         if(!Gate::allows('计费模型-仓储')){ return redirect('denied');  }
-        $models = app('OwnerStoragePriceModelService')->paginate($request->input("id"),["unit"]);
+        $models = app('OwnerStoragePriceModelService')->paginate($request->input("id"),["unit","owners"]);
         return response()->view('maintenance.priceModel.storage.index',compact("models"));
     }
 
@@ -44,14 +43,17 @@ class PriceModelController extends Controller
     {
         if(!Gate::allows('计费模型-仓储-录入')){ return redirect('denied');  }
         $units = app('UnitService')->getSelection();
-        return response()->view('maintenance.priceModel.storage.create',compact("units"));
+        $owners = app("OwnerService")->getIntersectPermitting();
+        return response()->view('maintenance.priceModel.storage.create',compact("units","owners"));
     }
 
     public function storageStore(Request $request)
     {
         if(!Gate::allows('计费模型-仓储-录入')){ return redirect('denied');  }
         $this->storageValidator($request->input())->validate();
-        app('OwnerStoragePriceModelService')->create($request->input());
+        /** @var OwnerStoragePriceModel $model */
+        $model = app('OwnerStoragePriceModelService')->create($request->input());
+        $model->owners()->sync(explode(",",$request->input("owner_id")));
         LogService::log(__METHOD__,"计费模型-创建仓储计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo('maintenance/priceModel/storage')->with('successTip',"创建成功!");
     }
@@ -59,9 +61,10 @@ class PriceModelController extends Controller
     public function storageEdit($id)
     {
         if(!Gate::allows('计费模型-仓储-编辑')){ return redirect('denied');  }
-        $model = app('OwnerStoragePriceModelService')->find($id);
+        $model = app('OwnerStoragePriceModelService')->find($id,["owners"]);
         $units = app('UnitService')->getSelection();
-        return response()->view('maintenance.priceModel.storage.create',compact("units","model"));
+        $owners = app("OwnerService")->getIntersectPermitting();
+        return response()->view('maintenance.priceModel.storage.create',compact("units","model","owners"));
     }
 
     public function storageUpdate(Request $request)
@@ -77,6 +80,9 @@ class PriceModelController extends Controller
             "discount_value"=> $request->input("discount_value"),
             "unit_id"       => $request->input("unit_id"),
         ]);
+        $model = new OwnerStoragePriceModel();
+        $model->id = $request->input("id");
+        $model->owners()->sync(explode(",",$request->input("owner_id")));
         LogService::log(__METHOD__,"计费模型-修改仓储计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo('maintenance/priceModel/storage')->with('successTip',"更新成功!");
     }
@@ -1096,7 +1102,7 @@ class PriceModelController extends Controller
         $this->gate("客户管理-项目-录入");
         $params = request()->input();
         $params["logistic_id"] = $params["logistics"];
-        $errors = $this->expressValidator($params,request("id"))->errors();
+        $errors = $this->expressValidator($params,request("id"))->errors()->toArray();
         $exist = [];
         foreach ($params["items"] as $index => $item){
             if (isset($exist[$item["province_id"]]))$errors["items.".$index.".province_id"] = ["已存在"];
@@ -1159,7 +1165,7 @@ class PriceModelController extends Controller
         $params = request()->input();
         $params["owner_id"] = [$params["owner_id"]];
         $params["logistic_id"] = $params["logistics"];
-        $errors = $this->logisticValidator($params,request("id"))->errors();
+        $errors = $this->logisticValidator($params,request("id"))->errors()->toArray();
         $exist = [];
         foreach ($params["items"] as $index => $item){
             $key = $item["unit_id"]."-".$item["range"]."-".$item["province_id"]."-".$item["city_id"];
@@ -1231,7 +1237,7 @@ class PriceModelController extends Controller
     public function apiStoreDirectLogistic()
     {
         $this->gate("客户管理-项目-录入");
-        $errors = $this->directLogisticValidator(request()->input(),request("id"))->errors();
+        $errors = $this->directLogisticValidator(request()->input(),request("id"))->errors()->toArray();
         $exist = [];
         foreach (request("items") as $index=>$item){
             if (isset($exist[$item['car_type_id']]))$errors["items.".$index.".car_type_id"] = ["已存在"];

+ 57 - 7
app/Http/Controllers/TestController.php

@@ -38,6 +38,8 @@ use App\OrderPackage;
 use App\OrderPackageCommodities;
 use App\OrderTracking;
 use App\Owner;
+use App\OwnerPriceOperation;
+use App\OwnerPriceOperationItem;
 use App\Package;
 use App\Process;
 use App\ProcessDaily;
@@ -62,6 +64,7 @@ use App\Services\OrderPackageService;
 use App\Services\OrderService;
 use App\Services\OrderTrackingOwnerService;
 use App\Services\OrderTrackingService;
+use App\Services\OwnerPriceOperationService;
 use App\Services\OwnerService;
 use App\Services\ShopService;
 use App\Services\StoreService;
@@ -90,6 +93,7 @@ use Illuminate\Support\Facades\Redis;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Str;
 use Maatwebsite\Excel\Facades\Excel;
+use Mockery\Mock;
 use PhpMyAdmin\Server\Status\Data;
 use Ramsey\Collection\Collection;
 use Zttp\Zttp;
@@ -157,17 +161,63 @@ sql;
     }
     public function zzd()
     {
-        $a = [1,2,3,4,5];
-        $c = [1,2,3,5,6];
-        dd(array_diff($c,$a));
+        $model4 = factory(OwnerPriceOperation::class)->create([
+            "operation_type"=>"出库",   //操作类型
+            "strategy"      =>"特征",         //策略
+        ]);
+        $pieces = Unit::query()->where("name","件")->first();
+        $box = Unit::query()->where("name","箱")->first();
+        $single = Unit::query()->where("name","单")->first();
+        if (!$pieces){
+            $pieces = factory(Unit::class)->create(["name"=>"件"]);
+        }
+        if (!$box){
+            $box = factory(Unit::class)->create(["name"=>"箱"]);
+        }
+        if (!$single){
+            $single = factory(Unit::class)->create(["name"=>"单"]);
+        }
+        $item8 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model4->id,
+            "strategy"                          => "起步",
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.5,
+        ]);
+        $item9 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model4->id,
+            "strategy"                          =>"默认",
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.6,
+        ]);
+        $item10 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model4->id,
+            "strategy"                          =>"特征",
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.7,
+        ]);
+        $owner = factory(Owner::class)->create([
+            "user_owner_group_id" => 1,
+        ]);
+        $model4->ownerPriceOperationOwners()->sync([$owner->id]);
+
+        $commodity = factory(Commodity::class)->create([
+            'sku' => md5(date('Ymd').\Illuminate\Support\Str::random(3)),
+            'owner_id' => $owner->id,
+            "pack_spec" => 3
+        ]);
+        $result = app(OwnerPriceOperationService::class)
+            ->matching(["packages"=>
+                [["commodity"=>"测试","amount"=>57,"sku"=>$commodity->sku]]]
+                ,[],
+                $owner->id,"出库");
+        dd($result);
     }
 
     public function zzd1()
     {
-        DB::transaction(function (){
-            ValueStore::query()->where("name","wave_detail_last_sync_date")->lockForUpdate()->first();
-        });
-        return microtime(true);
+        $a = [1,2];
+        $b = [2];
+        dd(array_diff($b,$a));
     }
 
     public function mergeCarrier()

+ 56 - 0
app/Http/Controllers/WaybillController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 
+use App\Components\AsyncResponse;
 use App\Services\CarTypeService;
 use App\Services\CityService;
 use App\Services\LogisticService;
@@ -27,6 +28,7 @@ use Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
+use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
@@ -37,6 +39,8 @@ use Ramsey\Uuid\Uuid;
 
 class WaybillController extends Controller
 {
+    use AsyncResponse;
+
     public function __construct()
     {
         app()->singleton('waybillService',WaybillService::class);
@@ -521,6 +525,58 @@ class WaybillController extends Controller
         return ['success'=>false,'error'=>"图片保存失败!"];
     }
 
+    //批量上传图片
+    public function batchUploadImages()
+    {
+        $this->gate("运输管理-图片上传");
+        $images = request("images");
+        $errors = [];
+        $number = [];
+        $mapping = [];
+        $type = ["jpg","png","gif","jfif","pjpeg","jpeg","webp"];
+        foreach ($images as $index => $image){
+            $suffix = $image->getClientOriginalExtension();
+            $name = $image->getClientOriginalName();
+            if (array_search(strtolower($suffix),$type) === false){
+                $errors[] = "“".$name."”格式错误";
+                unset($images[$index]);
+                continue;
+            }
+            $num = trim(rtrim($name,".".$suffix));
+            $number[] = $num;
+            $mapping[$num] = $index;
+        }
+        $waybills = Waybill::query()->select("id","wms_bill_number")->doesntHave("uploadFile")->whereIn('wms_bill_number',$number)->get();
+        foreach (array_diff($number,array_column($waybills->toArray(),"wms_bill_number")) as $diff){
+            $errors[] = "“".$diff."”不存在运单或已存在照片";
+            unset($images[$mapping[$diff]]);
+        }
+        $insert = [];
+        foreach ($waybills as $waybill){
+            $image = $images[$mapping[$waybill->wms_bill_number]];
+            $fileName = date('ymd').'-'.Uuid::uuid1();
+            $suffix = $image->getClientOriginalExtension();
+            $thumbnailName=storage_path('app/public/files/'.$fileName.'-thumbnail.'.$suffix);
+            $commonName=storage_path('app/public/files/'.$fileName.'-common.'.$suffix);
+            $bulkyName=storage_path('app/public/files/'.$fileName.'-bulky.'.$suffix);
+            move_uploaded_file ($image->getRealPath() ,$bulkyName);
+            $img=Image::make($bulkyName);
+            if ($img->height() > $img->width())
+                $img->heighten(250)->save($commonName);
+            else $img->widen(250)->save($commonName);
+            $img->heighten(28)->save($thumbnailName);
+            $insert[] = [
+                "table_name"=>"waybills",
+                "table_id"=>$waybill->id,
+                "url"=>'/files/'.$fileName,
+                "type"=>strtolower($suffix),
+            ];
+        }
+        if ($insert)UploadFile::query()->insert($insert);
+        $waybills->load("uploadFile");
+        $this->success(["errors"=>$errors,"data"=>$waybills]);
+    }
+
     //删除照片
     public function deleteImg(Request $request){
         if(!Gate::allows('运输管理-图片删除')){ return '没有权限';  }

+ 1 - 1
app/Services/FeatureService.php

@@ -236,7 +236,7 @@ Class FeatureService
                     $str = $this->multiMatching($packages,$logic,$describe,$columnMapping[$column] ?? '');
                     continue;
                 }
-                $value = isset($columnMapping[$column]) ? $matchObject[$columnMapping[$column]] : '';
+                $value = isset($columnMapping[$column]) ? ($matchObject[$columnMapping[$column]] ?? '') : '';
                 switch ($logic) {
                     case "包含":
                         $str = mb_strpos($value,$describe) === false ? 'false' : 'true';

+ 7 - 8
app/Services/OwnerPriceOperationService.php

@@ -108,7 +108,7 @@ Class OwnerPriceOperationService
 
         $rules = OwnerPriceOperation::query()->with(["items"=>function($query){
             /** @var Builder $query */
-            $query->orderByRaw("CASE strategy  WHEN '起步' THEN 1 WHEN '默认' THEN 2 WHEN '特征' THEN 3 END DESC,priority DESC");
+            $query->orderByRaw("CASE strategy  WHEN '起步' THEN 1 WHEN '默认' THEN 2 WHEN '特征' THEN 3 END DESC,priority");
         }])->where("operation_type",$type)->whereHas("ownerPriceOperationOwners",function ($query)use($owner_id){
                 /** @var Builder $query */
                 $query->where("id",$owner_id);
@@ -161,21 +161,20 @@ Class OwnerPriceOperationService
             }
             return -7;
         }*/
-        //出库
         foreach ($rules as $rule){
-            if (!$rule->ownerOutStorageRules)continue;
+            if (!$rule->items)continue;
             if ($rule->strategy == '特征'){
-                $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);//匹配特征
+                $bool = true;//app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);
                 if ($bool === true){
-                    $money = $this->matchItem($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
+                    $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
                     if ($money>0)return $money;
                 };
             }else{
-                $money = $this->matchItem($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
+                $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
                 if ($money>0)return $money;
             };
         }
-        return -7;
+        return $money ?? -7;
     }
     private function changeUnit($amount,$owner_id,$sku)
     {
@@ -254,7 +253,7 @@ Class OwnerPriceOperationService
                     }
                     break;
                 default:
-                    if ($isIn)continue;
+                    if ($isIn)break;
                     if ($unitName && $unitName != $units[$rule->unit_id])return -3; //校验单位是否一致
 
                     $money = $rule->amount * $rule->unit_price;

+ 25 - 2
app/Services/OwnerService.php

@@ -202,13 +202,14 @@ Class OwnerService
             $query->whereIn("id",$ids);
         }
         if ($notShowSoftDelete) $query->whereNull('deleted_at');
-        $query = $this->query($query,$params);
+        $query = $this->query($query,$params)->orderByDesc("id");
         return $query->paginate($params["paginate"] ?? 50);
     }
 
     private function query(Builder $builder, array $params)
     {
         foreach ($params as $column => $param){
+            if ($column == 'paginate' || $column == 'page' || !$param)continue;
             if ($param === true){
                 $builder->whereNotNull($column);
                 continue;
@@ -217,7 +218,29 @@ Class OwnerService
                 $builder->whereNull($column);
                 continue;
             }
-            $builder->where($column,$params);
+            if ($column == 'created_at_start'){
+                $builder->where("created_at",">=",$param.":00");
+                continue;
+            }
+            if ($column == 'created_at_end'){
+                $builder->where("created_at","<=",$param.":59");
+                continue;
+            }
+            if ($column == 'contract_number'){
+                $builder->whereHas("contracts",function ($query)use($param){
+                    /** @var Builder $query */
+                    $query->where("contract_number","like",$param."%");
+                });
+                continue;
+            }
+            if ($column == 'using_type'){
+                $builder->whereHas("ownerStoragePriceModels",function ($query)use($param){
+                    /** @var Builder $query */
+                    $query->where("using_type",$param);
+                });
+                continue;
+            }
+            $builder->where($column,$param);
         }
         return $builder;
     }

+ 2 - 2
app/Services/OwnerStoragePriceModelService.php

@@ -37,9 +37,9 @@ Class OwnerStoragePriceModelService
         return $query->update($values);
     }
 
-    public function find($id)
+    public function find($id, $withs = [])
     {
-        return OwnerStoragePriceModel::query()->find($id);
+        return OwnerStoragePriceModel::query()->with($withs)->find($id);
     }
     public function destroy($id)
     {

+ 2 - 0
app/Services/WaybillService.php

@@ -42,6 +42,8 @@ Class WaybillService
             'created_at_end' => ['alias' => 'created_at' , 'endDate' => ':59'],
             'uriType' => ['alias' => 'type'],
             'id' => ['multi' => ','],
+            'recipient' => ['timeLimit' => 15],
+            'recipient_mobile' => ['timeLimit' => 15],
         ];
         $waybills = app(QueryService::class)->query($param,$waybills,$columnQueryRules,"waybills");
         return $waybills;

+ 0 - 17
database/factories/OwnerPriceOperationItemInFactory.php

@@ -1,17 +0,0 @@
-<?php
-
-/** @var \Illuminate\Database\Eloquent\Factory $factory */
-
-use Faker\Generator as Faker;
-
-$factory->define(\App\OwnerPriceOperationItemIn::class, function (Faker $faker)use(&$unit){
-    $strategy = ['默认','特征'];
-    return [
-        "owner_price_operation_id"          => factory(\App\OwnerPriceOperation::class),         //作业计费ID
-        "strategy"                          => $strategy[array_rand($strategy)],         //策略
-        "amount"                            => mt_rand(0,100),                           //起步数
-        "unit_id"                           => factory(\App\Unit::class),//单位ID
-        "unit_price"                        => mt_rand(10,100) / 12,                       //单价
-        "feature"                           => \Illuminate\Support\Str::random(6),                          //特征
-    ];
-});

+ 2 - 2
database/factories/OwnerPriceOperationItemOutFactory.php → database/factories/OwnerPriceOperationItemService.php

@@ -2,10 +2,10 @@
 
 /** @var \Illuminate\Database\Eloquent\Factory $factory */
 
-use App\OwnerPriceOperationItemOut;
+use App\OwnerPriceOperationItem;
 use Faker\Generator as Faker;
 
-$factory->define(OwnerPriceOperationItemOut::class, function (Faker $faker) {
+$factory->define(OwnerPriceOperationItem::class, function (Faker $faker) {
     $strategy = ['默认','特征'];
     return [
         "owner_price_operation_id"          => factory(\App\OwnerPriceOperation::class),         //作业计费ID

+ 32 - 0
database/migrations/2021_01_14_174723_add_index_created_at_table_waybills.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddIndexCreatedAtTableWaybills extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->index("created_at");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->dropIndex("waybills_created_at_index");
+        });
+    }
+}

+ 5 - 0
resources/sass/text.scss

@@ -122,4 +122,9 @@
     height:3px;
     border:none;
     border-top:3px solid #007bff;
+}
+//文本强制换行
+.text-wrap{
+    white-space: normal;
+    word-break:break-all
 }

+ 87 - 25
resources/views/customer/project/create.blade.php

@@ -60,9 +60,14 @@
                 @include("customer.project.part._two")
             </div>
             <div v-if="base == 'three'">
-                @include("customer.project.part._three")
+                <div v-show="isLoad">@include("customer.project.part._three")</div>
+                <div class="row justify-content-center text-secondary" style="min-height: 200px;margin-left: -25%" v-show="!isLoad">
+                    <div class="align-self-center h1">
+                        <i class="fa fa-spinner fa-pulse"></i>
+                    </div>
+                </div>
             </div>
-            <div class="row mt-3">
+            <div class="row mt-3" v-if="base != 'three' || isLoad">
                 <div class="pull-right offset-7">
                     <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'one'" @click="back()">上一步</button>
                     <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'three'" @click="next()">下一步</button>
@@ -191,9 +196,11 @@
                 searchResult:[],//查询结果
                 searchResultMapping:{},//查询结果映射
                 selectedResult:"",
+                searchItem:{},//搜索子项集
+                searchBase:5,//搜索基数
             },
             mounted(){
-                this.ownerTemp = this.owner;
+                this.ownerTemp = JSON.parse(JSON.stringify(this.owner));
                 $('[data-toggle="tooltip"]').tooltip();
                 $("#container").removeClass("d-none");
             },
@@ -216,9 +223,9 @@
                 },
                 //切换选项
                 switchBase(base){
-                    if (!this.ownerTemp.id)return;
-                    if (base === 'three') this._loadStorage();
+                    if (!this.owner.id)return;
                     if (base === this.base)return;
+                    if (base === 'three') this._loadStorage();
                     this.base = base;
                 },
                 //切换类型
@@ -303,7 +310,7 @@
                     }
                     if (this.owner.name !== this.ownerTemp.name || this.owner.code !== this.ownerTemp.code){
                         let url = "{{url('maintenance/owner/apiStore')}}";
-                        let params = {name:this.owner.name,code:this.owner.code,id:this.ownerTemp.id};
+                        let params = {name:this.owner.name,code:this.owner.code,id:this.owner.id};
                         let result = undefined;
                         window.tempTip.postBasicRequest(url,params,res=>{
                             if (res.errors){
@@ -314,7 +321,6 @@
                             }
                             this.errors = [];
                             this.owner.id = res.id;
-                            this.ownerTemp.id = res.id;
                             this.ownerTemp.name = res.name;
                             this.ownerTemp.code = res.code;
                             result = true;
@@ -388,39 +394,52 @@
                     let url = "{{url('customer/project/getPriceModel')}}";
                     let params = {id:this.ownerTemp.id};
                     window.tempTip.postBasicRequest(url,params,res=>{
+                        this._getOwners();
+                        this._getUnits();
+                        this._getCars();
+                        this._getCities();
+                        this._getLogistics();
+                        this._getProvinces();
+                        setTimeout(()=> {
+                            $(".selectpicker").selectpicker('refresh');
+                        },500);
                         if (res.owner_storage_price_models.length>0)this.selectedModel.storage = res.owner_storage_price_models;
                         if (res.owner_price_operations.length>0)this.selectedModel.operation = res.owner_price_operations;
                         if (res.owner_price_expresses.length>0){
-                            this._loadExpress();
                             res.owner_price_expresses.forEach((express,i)=>{
                                 express.logistics.forEach((logistic,j)=>{
                                     express.logistics[j] = logistic.id;
                                 });
                                 res.owner_price_expresses[i] = JSON.parse(JSON.stringify(express).replace(/details/g,"items"));
+                                this.upList['express-item-'+i] = true;
                             });
                             this.selectedModel.express = res.owner_price_expresses;
                         }
                         if (res.owner_price_logistics.length>0){
-                            this._loadLogistic();
                             res.owner_price_logistics.forEach((logistic,i)=>{
                                 logistic.logistics.forEach((l,j)=>{
                                     logistic.logistics[j] = l.id;
                                 });
                                 res.owner_price_logistics[i] = JSON.parse(JSON.stringify(logistic).replace(/details/g,"items"));
+                                this.upList['logistic-item-'+i] = true;
                             });
                             this.selectedModel.logistic = res.owner_price_logistics;
                         }
                         if (res.owner_price_direct_logistics.length>0){
-                            this._loadDirectLogistic();
+                            this.upList["directLogistic-item"] = true;
                             this.selectedModel.directLogistic = JSON.parse(JSON.stringify(res.owner_price_direct_logistics[0]).replace(/details/g,"items"));
                         }
+                        setTimeout(()=> {
+                            $(".up").slideUp();
+                            this.isLoad = true;
+                        },0)
                     });
-                    this.isLoad = true;
                 },
                 //加载仓储所需基础信息
                 _loadStorage(){
                     if (!this.pool.units)this._getUnits();
                     if (!this.isLoad && this.ownerTemp.id)this._loadPriceModel();//计费模型未被加载且项目ID存在时
+                    if (!this.isLoad && !this.ownerTemp.id) this.isLoad = true;
                 },
                 //加载作业
                 _loadOperation(){
@@ -733,12 +752,12 @@
                     window.tempTip.postBasicRequest(url,params,res=>{
                         if (res && res.errors){
                             this.errors = res.errors;
+                            window.tempTip.show("检查您的子项详情列表是否完整");
                             return;
                         }
                         this.model.logistic.items.forEach((item,i)=>{
                             item.id = res.details[i].id;
                         });
-                        console.log(this.model.logistic);
                         if (this.model.logistic.id) this.selectedModel.logistic[this.model.logistic.index] = this.model.logistic;
                         else {
                             this.model.logistic.id = res.id;
@@ -982,22 +1001,20 @@
                 },
                 //新增物流详情
                 addLogisticDetail(){
-                    this.model.logistic.items.unshift({
-
-                    });
+                    this.model.logistic.items.unshift({});
                 },
                 //导入物流详情
                 importLogistic(e){
-                    tempTip.setIndex(1099);
+                    window.tempTip.setIndex(1099);
                     let file=e.target.files[0];
                     if (!file){
-                        tempTip.setDuration(3000);
-                        tempTip.show("未选择文件");
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("未选择文件");
                         return;
                     }
                     let formData = new FormData();
                     formData.append("file",file);
-                    axios.post('{{url('maintenance/priceModel/logistic/import')}}',formData,{
+                    window.axios.post('{{url('maintenance/priceModel/logistic/import')}}',formData,{
                         'Content-Type':'multipart/form-data'
                     }).then(res=>{
                         if (res.data.success) {
@@ -1020,15 +1037,15 @@
                                 }
                             });
                             this.importError = res.data.errors;
-                            tempTip.setDuration(3000);
-                            tempTip.showSuccess("导入成功!");
+                            window.tempTip.setDuration(3000);
+                            window.tempTip.showSuccess("导入成功!");
                             return;
                         }
-                        tempTip.setDuration(3000);
-                        tempTip.show(res.data.data);
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show(res.data.data);
                     }).catch(err=> {
-                        tempTip.setDuration(3000);
-                        tempTip.show("网络错误:"+err);
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:"+err);
                     })
                 },
                 //删除物流子项
@@ -1416,6 +1433,8 @@
                 editLogistic(index){
                     this.switchType("logistic");
                     this.model.logistic = JSON.parse(JSON.stringify(this.selectedModel.logistic[index]));
+                    this.model.logistic.ranges = this.model.logistic.unit_range.split(",");
+                    this.model.logistic.other_ranges = this.model.logistic.other_unit_range.split(",");
                     this.model.logistic.index = index;
                 },
                 //编辑直发车
@@ -1423,6 +1442,49 @@
                     this.switchType("directLogistic");
                     this.model.directLogistic = JSON.parse(JSON.stringify(this.selectedModel.directLogistic));
                 },
+                //搜索快递子项
+                searchExpress(e){
+                    let val = e.target.value;
+                    if (!val){
+                        this.$set(this.searchItem,'express',null);
+                        return;
+                    }
+                    let items = [];
+                    this.model.express.items.forEach((item,i)=>{
+                        if (this.poolMapping.provinces[item.province_id].indexOf(val) !== -1)items.push(i);
+                    });
+                    this.$set(this.searchItem,'express',items);
+                },
+                //搜索直发子项
+                searchDirectLogistic(e){
+                    let val = e.target.value;
+                    if (!val){
+                        this.$set(this.searchItem,'directLogistic',null);
+                        return;
+                    }
+                    let items = [];
+                    this.model.directLogistic.items.forEach((item,i)=>{
+                        if (this.poolMapping.cars[item.car_type_id].indexOf(val) !== -1)items.push(i);
+                    });
+                    this.$set(this.searchItem,'directLogistic',items);
+                },
+                //搜索物流子项
+                searchLogistic(e){
+                    let val = e.target.value;
+                    if (!val){
+                        this.$set(this.searchItem,'logistic',null);
+                        return;
+                    }
+                    let items = [];
+                    this.model.logistic.items.forEach((item,i)=>{
+                        if (item.unit_id || item.province_id || item.city_id){
+                            if ((item.unit_id && this.poolMapping.units[item.unit_id].indexOf(val) !== -1) ||
+                                (item.province_id && this.poolMapping.provinces[item.province_id].indexOf(val) !== -1) ||
+                                (item.city_id && this.poolMapping.cities[item.city_id].indexOf(val) !== -1))items.push(i);
+                        }
+                    });
+                    this.$set(this.searchItem,'logistic',items);
+                },
             },
         });
     </script>

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

@@ -4,6 +4,7 @@
 @section('content')
     @component('customer.project.menu')@endcomponent
     <div class="container-fluid" id="container">
+        <div id="form_div"></div>
         <div class="modal fade" tabindex="-1" role="dialog" id="modal">
             <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
                 <div class="modal-content">
@@ -66,7 +67,7 @@
                         <label><input type="checkbox" :value="owner.id" v-model="checkData"></label>
                     </td>
                     <td>
-                        <a :href="'{{url('customer/project')}}/'+owner.id+'/edit'"><button class="btn btn0sm btn-outline-info">编辑</button></a>
+                        <a :href="'{{url('customer/project')}}/'+owner.id+'/edit'"><button class="btn btn-sm btn0sm btn-outline-info">编辑</button></a>
                     </td>
                     <td>@{{ owner.customer_name }}</td>
                     <td>@{{ owner.tax_rate ? owner.tax_rate+'%' : '' }}</td>
@@ -83,7 +84,7 @@
                     <td>@{{ owner.phone_number }}</td>
                     <td>@{{ owner.user_owner_group_name }}</td>
                     <td>
-                        <button class="btn btn-sm btn-info" @click="showModal(owner)">各项计价</button>
+                        <button class="btn btn-sm btn-info text-white" @click="showModal(owner)">各项计价</button>
                     </td>
                     <td>@{{ owner.owner_storage_price_model_using_type }}</td>
                     <td>@{{ owner.owner_area_report_accounting_area }}</td>
@@ -92,6 +93,7 @@
                     <td>@{{ owner.description }}</td>
                 </tr>
             </table>
+            {{$owners->appends($params)->links()}}
         </div>
     </div>
 @endsection
@@ -99,6 +101,7 @@
 @section('lastScript')
     <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
     <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
     <script>
         let vue = new Vue({
             el:"#container",
@@ -133,9 +136,42 @@
                 sum : Number("{{ $owners->total() }}"),
                 priceModel : {},
                 thisClickIndex : "",
+                models:[
+                    @foreach($models as $model)
+                    {name:"{{$model->id}}",value:"{{$model->name}}"},
+                    @endforeach
+                ],
+                customers:[
+                    @foreach($customers as $customer)
+                    {name:"{{$customer->id}}",value:"{{$customer->name}}"},
+                    @endforeach
+                ],
+                ownerGroups:[
+                        @foreach($ownerGroups as $ownerGroup)
+                    {name:"{{$ownerGroup->id}}",value:"{{$ownerGroup->name}}"},
+                    @endforeach
+                ],
             },
             mounted(){
                 $('#container').removeClass('d-none');
+                let data=[
+                    [
+                        {name:'user_owner_group_id',type:'select',tip:'项目小组',placeholder: '项目小组',data:this.ownerGroups},
+                        {name:'created_at_start',type:'time',tip:['选择显示创建日期的起始时间','']},
+                        {name:'id',type:'select_multiple_select',tip:['输入关键词快速定位下拉列表,回车确定','选择要显示的项目'],
+                            placeholder:['项目','定位或多选项目'],data:this.models},
+                        {name:'contract_number',type:'input',tip: '合同号:可在左侧增加百分号(%)进行模糊搜索',placeholder: '合同号'},
+                    ],[
+                        {name:'customer_id',type:'select',tip:'客户',placeholder: '客户',data:this.customers},
+                        {name:'created_at_end',type:'time',tip:['选择显示创建日期的结束时间','']},
+                        {name:'using_type',type:'select',placeholder: '用仓类型',data:[{name:"常温",value:"常温"},{name:"恒温",value:"恒温"}]},
+                    ],
+                ];
+                this.form = new query({
+                    el:"#form_div",
+                    condition:data,
+                });
+                this.form.init();
                 let column = [
                     {name:'cloneCheckAll',customization:true,type:'checkAll',column:'id',
                         dom:$('#cloneCheckAll').removeClass('d-none'), neglect: true},

+ 24 - 16
resources/views/customer/project/part/_directLogistic.blade.php

@@ -15,7 +15,8 @@
     </span>
 </div>
 <div class="row mt-3">
-    <label class="col-3">详情</label>
+    <label class="col-3 cursor-pointer" @click="show('directLogistic-item-card')">详情&nbsp;
+        <span class="fa" :class="upList['express-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span></label>
     <div class="col-9">
         <div class="w-100 form-inline">
             <input id="directLogisticFile" type="file" class="d-none" accept=".csv, .xlsx, .xls" @change="importDirectLogistic($event)"/>
@@ -23,6 +24,11 @@
             <button type="button" class="btn btn-sm btn-outline-primary w-25 ml-2" @click="selectFile('directLogisticFile')">导入</button>
             <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer" data-toggle="tooltip" data-placement="top" title="导入与保存时自动过滤重复数据"></span></h5>
         </div>
+        <div class="w-100 mt-1 ml-1" v-if="model.directLogistic.items.length>searchBase">
+            <label>
+                <input placeholder="  定位" class="form-control form-control-sm rounded-pill" @input="searchDirectLogistic($event)"/>
+            </label>
+        </div>
         <div class="w-100 text-center mb-1 mt-1" v-if="importError.length > 0">
             <button type="button" class="btn btn-sm btn-danger mb-1" @click="isShowError = true" v-if="!isShowError">@{{ importError.length }}条错误,点击展开</button>
             <button type="button" class="btn btn-sm btn-dark mb-1" @click="isShowError = false" v-else>收起错误展示</button>
@@ -38,21 +44,23 @@
             <label class="col-4">续费(元/KM)</label>
             <label class="col-2"></label>
         </div>
-        <div class="row" v-for="(item,i) in model.directLogistic.items">
-            <label class="col-3">
-                <select class="form-control form-control-sm" v-model="item.car_type_id" :class="errors['items.'+i+'.car_type_id'] ? 'is-invalid' : ''">
-                    <option v-for="car in pool.cars" :value="car.id">@{{ car.name }}</option>
-                </select>
-            </label>
-            <label class="col-3">
-                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.base_fee" :class="errors['items.'+i+'.base_fee'] ? 'is-invalid' : ''">
-            </label>
-            <label class="col-4">
-                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.additional_fee" :class="errors['items.'+i+'.additional_fee'] ? 'is-invalid' : ''">
-            </label>
-            <label class="col-2 cursor-pointer h3 font-weight-bold text-danger" @click="delDirectLogisticItem(i)">
-                &times;
-            </label>
+        <div class="row" id="directLogistic-item-card">
+            <div class="row" v-for="(item,i) in model.directLogistic.items" v-if="!searchItem.directLogistic || (searchItem.directLogistic && searchItem.directLogistic.includes(i))">
+                <label class="col-3">
+                    <select class="form-control form-control-sm" v-model="item.car_type_id" :class="errors['items.'+i+'.car_type_id'] ? 'is-invalid' : ''">
+                        <option v-for="car in pool.cars" :value="car.id">@{{ car.name }}</option>
+                    </select>
+                </label>
+                <label class="col-3">
+                    <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.base_fee" :class="errors['items.'+i+'.base_fee'] ? 'is-invalid' : ''">
+                </label>
+                <label class="col-4">
+                    <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.additional_fee" :class="errors['items.'+i+'.additional_fee'] ? 'is-invalid' : ''">
+                </label>
+                <label class="col-2 cursor-pointer h3 font-weight-bold text-danger" @click="delDirectLogisticItem(i)">
+                    &times;
+                </label>
+            </div>
         </div>
     </div>
 </div>

+ 25 - 17
resources/views/customer/project/part/_express.blade.php

@@ -4,7 +4,7 @@
            v-model="model.express.name" :class="errors.name ? 'is-invalid' : ''"></label>
 </div>
 <div class="row mt-3">
-    <label class="col-3">承运商</label>
+    <label class="col-3">  承运商</label>
     <label class="col-5"><select class="selectpicker express" multiple data-live-search="true" title="承运商(多选)"
             v-model="model.express.logistics" :class="errors.logistic_id ? 'is-invalid' : ''">
         <option v-for="logistic in pool.logistics" :value="logistic.id" v-if="logistic.type != '物流'">@{{ logistic.name }}</option>
@@ -21,7 +21,8 @@
            v-model="model.express.additional_weight" :class="errors.additional_weight ? 'is-invalid' : ''"></label>
 </div>
 <div class="row mt-3">
-    <label class="col-3">详情</label>
+    <label class="col-3 cursor-pointer" @click="show('express-item')">详情&nbsp;
+        <span class="fa" :class="upList['express-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span></label>
     <div class="col-9">
         <div class="w-100 form-inline">
             <input id="expressFile" type="file" class="d-none" accept=".csv, .xlsx, .xls" @change="importExpress($event)"/>
@@ -29,6 +30,11 @@
             <button type="button" class="btn btn-sm btn-outline-primary w-25 ml-2" @click="selectFile('expressFile')">导入</button>
             <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer" data-toggle="tooltip" data-placement="top" title="导入与保存时自动过滤重复数据"></span></h5>
         </div>
+        <div class="w-100 mt-1 ml-1" v-if="model.express.items.length>searchBase">
+            <label>
+                <input placeholder="  定位" class="form-control form-control-sm rounded-pill" @input="searchExpress($event)"/>
+            </label>
+        </div>
         <div class="w-100 text-center mb-1 mt-1" v-if="importError.length > 0">
             <button type="button" class="btn btn-sm btn-danger mb-1" @click="isShowError = true" v-if="!isShowError">@{{ importError.length }}条错误,点击展开</button>
             <button type="button" class="btn btn-sm btn-dark mb-1" @click="isShowError = false" v-else>收起错误展示</button>
@@ -44,21 +50,23 @@
             <label class="col-3">续重价格</label>
             <label class="col-3"></label>
         </div>
-        <div class="row" v-for="(item,i) in model.express.items">
-            <label class="col-3">
-                <select class="form-control form-control-sm" v-model="item.province_id" :class="errors['items.'+i+'.province_id'] ? 'is-invalid' : ''">
-                    <option v-for="province in pool.provinces" :value="province.id">@{{ province.name }}</option>
-                </select>
-            </label>
-            <label class="col-3">
-                <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.initial_weight_price" :class="errors['items.'+i+'.initial_weight_price'] ? 'is-invalid' : ''">
-            </label>
-            <label class="col-3">
-                <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.additional_weight_price" :class="errors['items.'+i+'.additional_weight_price'] ? 'is-invalid' : ''">
-            </label>
-            <label class="col-3 cursor-pointer h3 font-weight-bold text-danger" @click="delExpressItem(i)">
-                &times;
-            </label>
+        <div class="row" id="express-item">
+            <div class="row" v-for="(item,i) in model.express.items" v-if="!searchItem.express || (searchItem.express && searchItem.express.includes(i))">
+                <label class="col-3">
+                    <select class="form-control form-control-sm" v-model="item.province_id" :class="errors['items.'+i+'.province_id'] ? 'is-invalid' : ''">
+                        <option v-for="province in pool.provinces" :value="province.id">@{{ province.name }}</option>
+                    </select>
+                </label>
+                <label class="col-3">
+                    <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.initial_weight_price" :class="errors['items.'+i+'.initial_weight_price'] ? 'is-invalid' : ''">
+                </label>
+                <label class="col-3">
+                    <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.additional_weight_price" :class="errors['items.'+i+'.additional_weight_price'] ? 'is-invalid' : ''">
+                </label>
+                <label class="col-3 cursor-pointer h3 font-weight-bold text-danger" @click="delExpressItem(i)">
+                    &times;
+                </label>
+            </div>
         </div>
     </div>
 </div>

+ 13 - 10
resources/views/customer/project/part/_logisticDetail.blade.php

@@ -7,6 +7,9 @@
                     <input id="logisticFile" type="file" style="display:none" accept=".csv, .xlsx, .xls" @change="importLogistic($event)"/>
                     <button type="button" class="btn btn-sm btn-outline-info col-1" @click="selectFile('logisticFile')">导入</button>
                     <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer" data-toggle="tooltip" data-placement="top" title="导入与保存时自动过滤重复数据和与当前选择单位不一致数据"></span></h5>
+                    <label class="ml-1" v-if="model.logistic.items.length>searchBase">
+                        <input placeholder="  定位" class="form-control form-control-sm rounded-pill" @input="searchLogistic($event)"/>
+                    </label>
                     <div class="font-weight-bolder offset-3">物流收费标准</div>
                 </div>
             </div>
@@ -36,49 +39,49 @@
                         <th>费率(%)</th>
                         <th>操作</th>
                     </tr>
-                    <tr v-for="(detail,i) in model.logistic.items">
+                    <tr v-for="(detail,i) in model.logistic.items" v-if="!searchItem.logistic || (searchItem.logistic && searchItem.logistic.includes(i))">
                         <td>
                             <label>
-                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.unit_id" :class="'items.'+i+'.unit_id' ? 'is-invalid' : ''">
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.unit_id" :class="errors['items.'+i+'.unit_id'] ? 'is-invalid' : ''">
                                     <option v-for="unit in pool.units" :value="unit.id" v-if="unit.id == model.logistic.unit_id || unit.id == model.logistic.other_unit_id">@{{ unit.name }}</option>
                                 </select>
                             </label>
                         </td>
                         <td>
                             <label>
-                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.range" :class="'items.'+i+'.range' ? 'is-invalid' : ''">
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.range" :class="errors['items.'+i+'.range'] ? 'is-invalid' : ''">
                                     <option v-for="range in (detail.unit_id == model.logistic.unit_id ? model.logistic.ranges : model.logistic.other_ranges)" :value="range">@{{ range }}</option>
                                 </select>
                             </label>
                         </td>
                         <td>
                             <label>
-                                <select class="form-control form-control-sm" v-model="detail.province_id" :class="'items.'+i+'.province_id' ? 'is-invalid' : ''">
+                                <select class="form-control form-control-sm" v-model="detail.province_id" :class="errors['items.'+i+'.province_id'] ? 'is-invalid' : ''">
                                     <option v-for="province in pool.provinces" :value="province.id">@{{ province.name }}</option>
                                 </select>
                             </label>
                         </td>
                         <td>
                             <label>
-                                <select class="form-control form-control-sm" v-model="detail.city_id" :class="'items.'+i+'.city_id' ? 'is-invalid' : ''">
+                                <select class="form-control form-control-sm" v-model="detail.city_id" :class="errors['items.'+i+'.city_id'] ? 'is-invalid' : ''">
                                     <option v-for="city in pool.cities" v-if="detail.province_id === city.province_id" :value="city.id">@{{ city.name }}</option>
                                 </select>
                             </label>
                         </td>
                         <td>
-                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.unit_price" :class="'items.'+i+'.unit_price' ? 'is-invalid' : ''"></label>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.unit_price" :class="errors['items.'+i+'.unit_price'] ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
-                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.delivery_fee" :class="'items.'+i+'.delivery_fee' ? 'is-invalid' : ''"></label>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.delivery_fee" :class="errors['items.'+i+'.delivery_fee'] ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
-                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.initial_fee" :class="'items.'+i+'.initial_fee' ? 'is-invalid' : ''"></label>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.initial_fee" :class="errors['items.'+i+'.initial_fee'] ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
-                            <label><input type="number" min="0" class="form-control form-control-sm" v-model="detail.initial_amount" :class="'items.'+i+'.initial_amount' ? 'is-invalid' : ''"></label>
+                            <label><input type="number" min="0" class="form-control form-control-sm" v-model="detail.initial_amount" :class="errors['items.'+i+'.initial_amount'] ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
-                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.rate" :class="'items.'+i+'.rate' ? 'is-invalid' : ''"></label>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.rate" :class="errors['items.'+i+'.rate'] ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
                             <button type="button" class="btn btn-sm btn-outline-danger" @click="delLogisticItem(i)">删</button>

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

@@ -25,7 +25,7 @@
         <strong>@{{ errors.name[0] }}</strong>
     </span>
 </div>
-<div class="row mt-3">
+<div class="row mt-3" v-if="model.operation.strategy == '特征'">
     <label class="col-2">特征:</label>
     <label class="col-8">
         <label v-if="model.operation.feature">@{{ model.operation.featureFormat }}</label><br>

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

@@ -2,7 +2,7 @@
     <div class="col-6" id="parent">
         <div class="card" id="storage-card">
             <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('storage')"><span class="fa fa-cubes"></span>&nbsp;仓储</span>
+                <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('storage')"><span class="fa fa-align-justify"></span>&nbsp;仓储</span>
             </div>
             <div class="card-body" id="storage">
                 <table class="table table-sm">
@@ -23,9 +23,9 @@
                         <td>@{{ item.using_type }}</td>
                         <td>@{{ item.minimum_area }}</td>
                         <td>@{{ item.price }}</td>
+                        <td>@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }}</td>
                         <td>@{{ item.discount_type }}</td>
                         <td>@{{ item.discount_value }}</td>
-                        <td>@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }}</td>
                         <td class="cursor-pointer" @click.stop="delStorage(item,i)"><span class="font-weight-bold text-danger">&times;</span></td>
                     </tr>
                 </table>
@@ -33,7 +33,7 @@
         </div>
         <div class="card" id="operation-card">
             <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('operation')"><span class="fa fa-suitcase"></span>&nbsp;作业</span>
+                <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('operation')"><span class="fa fa-align-justify"></span>&nbsp;作业</span>
             </div>
             <div class="card-body" id="operation">
                 <div class="container-fluid">
@@ -126,7 +126,7 @@
         </div>
         <div class="card" id="express-card">
             <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('express')"><span class="fa fa-cube"></span>&nbsp;快递</span>
+                <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('express')"><span class="fa fa-align-justify"></span>&nbsp;快递</span>
             </div>
             <div class="card-body" id="express">
                 <table class="table table-sm">
@@ -157,7 +157,7 @@
                         </tr>
                         <tr>
                             <td colspan="5">
-                                <div :id="'express-item-'+i" class="offset-3">
+                                <div :id="'express-item-'+i" class="offset-3 up">
                                     <table class="table table-sm col-10">
                                         <tr>
                                             <th>省份</th>
@@ -183,7 +183,7 @@
         </div>
         <div class="card" id="logistic-card">
             <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('logistic')"><span class="fa fa-truck"></span>&nbsp;物流</span>
+                <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('logistic')"><span class="fa fa-align-justify"></span>&nbsp;物流</span>
             </div>
             <div class="card-body" id="logistic">
                 <table class="table table-sm">
@@ -200,7 +200,7 @@
                         <th>详情</th>
                         <th></th>
                     </tr>
-                    <tbody v-for="(logistic,i) in selectedModel.logistic" @dblclick="editLogistic(i)">
+                    <tbody v-for="(logistic,i) in selectedModel.logistic" @dblclick="editLogistic(i)" style="cursor: pointer">
                         <tr>
                             <td>
                                 <div class="text-overflow-warp-100 small">
@@ -225,7 +225,7 @@
                         </tr>
                         <tr>
                             <td colspan="9">
-                                <div :id="'logistic-item-'+i" class="offset-1">
+                                <div :id="'logistic-item-'+i" class="offset-1 up">
                                     <table class="table table-sm">
                                         <tr>
                                             <th>省份</th>
@@ -263,20 +263,20 @@
         </div>
         <div class="card" id="directLogistic-card">
             <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('directLogistic')"><span class="fa fa-rocket"></span>&nbsp;直发</span>
+                <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('directLogistic')"><span class="fa fa-align-justify"></span>&nbsp;直发</span>
             </div>
             <div class="card-body" id="directLogistic" @dblclick="editDirectLogistic()" style="cursor: pointer">
                 <div class="row">
-                    <label class="col-4">名称:<b>@{{ selectedModel.directLogistic.name }}</b></label>
-                    <label class="col-4">起步数(KM):<b>@{{ selectedModel.directLogistic.base_km }}</b></label>
-                    <label class="col-1 offset-3" v-if="selectedModel.directLogistic.name">
+                    <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="cursor-pointer text-danger font-weight-bold" @click.stop="delDirectLogistic(selectedModel.directLogistic)">&times;</span>
-                    </label>
+                    </span>
                 </div>
                 <div class="row">
                     <div class="cursor-pointer text-primary col-2" @click.stop="show('directLogistic-item')">
                         <span class="fa" :class="upList['directLogistic-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span>&nbsp;详情</div>
-                    <div class="col-10" id="directLogistic-item">
+                    <div class="col-10 up" id="directLogistic-item">
                         <table class="table table-sm">
                             <tr>
                                 <th>车型</th>

+ 15 - 1
resources/views/maintenance/priceModel/storage/create.blade.php

@@ -24,6 +24,13 @@
                     <strong>@{{ errors.name[0] }}</strong>
                 </span>
             </div>
+            <div class="row mt-3">
+                <label class="col-2" for="owner_id">项目</label>
+                <select id="owner_id" class="selectpicker" multiple data-live-search="true" title="项目(多选)" v-model="model.owner_id">
+                    <option v-for="owner in owners" :value="owner.id">@{{ owner.name }}</option>
+                </select>
+                <label hidden><input :value="model.owner_id" name="owner_id"></label>
+            </div>
             <div class="row mt-3">
                 <label for="counting_type" class="col-2 text-info">计费类型</label>
                 <select id="counting_type" name="counting_type" class="col-3 form-control"
@@ -103,12 +110,14 @@
                 model : {
                     'id' : "{{isset($model) ? $model->id : ''}}",
                     'counting_type' : "{{old('counting_type') ?? (isset($model) ? $model->counting_type : '')}}",
+                    name : "{{old('name') ?? (isset($model) ? $model->name : '')}}",
                     'using_type' : "{{old('using_type') ?? (isset($model) ? $model->using_type : '')}}",
                     'minimum_area' : "{{old('minimum_area') ?? (isset($model) ? $model->minimum_area : '')}}",
                     'discount_value' : "{{old('discount_value') ?? (isset($model) ? $model->discount_value : '')}}",
                     'price' : "{{old('price') ?? (isset($model) ? $model->price : '')}}",
                     'discount_type' : "{{old('discount_type') ?? (isset($model) ? $model->discount_type : '')}}",
                     'unit_id' : "{{old('unit_id') ?? (isset($model) ? $model->unit_id : '')}}",
+                    owner_id:{!! old('owner_id') ? json_encode(old('owner_id')) : (isset($model) ? json_encode(array_column($model->owners->toArray(),"id")) : '[]') !!},
                 },
                 counting_type : ['包仓','灵活用仓','统单价'],
                 using_type : ['常温','恒温'],
@@ -118,7 +127,12 @@
                     {id:"{{$unit->id}}", name:"{{$unit->name}}"},
                     @endforeach
                 ],
-                errors:{!! $errors !!}
+                errors:{!! $errors !!},
+                owners:[
+                    @foreach($owners as $model)
+                    {id:"{{$model->id}}",name:"{{$model->name}}"},
+                    @endforeach
+                ],
             },
         });
     </script>

+ 5 - 0
resources/views/maintenance/priceModel/storage/index.blade.php

@@ -17,6 +17,7 @@
                 <th>计费类型</th>
                 <th>用仓类型</th>
                 <th>最低起租面积</th>
+                <th>项目</th>
                 <th>单价</th>
                 <th>减免类型</th>
                 <th>减免值</th>
@@ -29,6 +30,9 @@
                 <td>@{{ model.counting_type }}</td>
                 <td>@{{ model.using_type }}</td>
                 <td>@{{ model.minimum_area }}</td>
+                <td>
+                    <small v-for="owner in model.owners">@{{ owner.name }}<br></small>
+                </td>
                 <td>@{{ model.price }}/@{{ model.unit_name }}</td>
                 <td>@{{ model.discount_type }}</td>
                 <td>@{{ model.discount_value }}</td>
@@ -61,6 +65,7 @@
                         discount_value : "{{$model->discount_value}}",
                         unit_name : "{{$model->unit ? $model->unit->name : ''}}",
                         created_at : "{{$model->created_at}}",
+                        owners:{!! $model->owners !!},
                     },
                     @endforeach
                 ],

+ 48 - 0
resources/views/waybill/_batchUploadImg.blade.php

@@ -0,0 +1,48 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="batchUploadImg">
+    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="pull-left ml-2 small text-primary">
+                    选择文件时使用SHIFT键或CTRL键可多选
+                </div>
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <label hidden><input type="file" @change="uploadFiles($event)" multiple="multiple" id="uploadImg" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"></label>
+                <div class="container-fluid">
+                    <div class="text-center small row mb-1" v-if="batchUploadError.length>0">
+                        <div class="col-3 text-danger">部分上传失败:</div>
+                        <div class="col-8">
+                            <b v-for="err in batchUploadError">@{{ err }}<br></b>
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-8 text-center offset-2 border border-2 rounded" style="min-height: 100px;cursor: pointer"
+                        @click="selectedFile()" v-if="images.length<1">
+                            <div class="h1 text-secondary mt-3">
+                                <span class="fa fa-plus"></span>
+                            </div>
+                        </div>
+                        <div class="col-3 border border-2 rounded" v-for="(img,i) in images">
+                            <div class="w-100 h4 m-1" style="height: 10%;">
+                                <span class="text-danger font-weight-bold pull-right" style="cursor: pointer;" @click="delTempImg(i)"> &times;</span>
+                            </div>
+                            <div class="w-100 m-0 text-center" style="height: 60%">
+                                <img class="img-fluid" :src="img.src" alt="img.name">
+                            </div>
+                            <div class="w-100 text-center small" style="height: 25%;margin-top: 5%">
+                                <span class="text-wrap">@{{ img.name }}(<span class="text-info">@{{ img.size | size }}</span>)</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button class="btn btn-info text-white mr-1" @click="selectedFile()" v-if="images.length>1">
+                    <span class="fa fa-image"></span>
+                    继续添加</button>
+                <button class="btn btn-success" @click="batchUploadImages()">开始上传</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 84 - 14
resources/views/waybill/index.blade.php

@@ -8,6 +8,9 @@
     </div>
     <div class="container-fluid" style="min-width: 1500px;">
         <div class="d-none" id="list">
+
+            @include("waybill._batchUploadImg")
+
             <div class="container-fluid nav3">
                 <div class="card menu-third" >
                     <ul class="nav nav-pills">
@@ -37,6 +40,7 @@
                     <a class="dropdown-item" @click="waybillExport(true)" href="javascript:">导出所有页</a>
                 </div>
             </span>
+            @can('运输管理-图片上传')<button class="btn btn-sm btn-outline-info" data-target="#batchUploadImg" data-toggle="modal">批量上传图片</button>@endcan
             <div>
                 @if(Session::has('successTip'))
                     <div class="alert alert-success h1">{{Session::get('successTip')}}</div>
@@ -338,6 +342,8 @@
                 paginate : 50,
                 page : Number('{{$waybills->currentPage()}}'),
                 count : Number('{{$waybills->count()}}'),
+                images:[],
+                batchUploadError:[],
             },
             watch:{
                 checkData:{
@@ -373,6 +379,7 @@
                         {name:'carrier_bill',type:'input',tip:'承运商单号:可在左侧增加百分号(%)进行模糊搜索',placeholder: '承运商单号'},
                         {name:'status',type:'select',placeholder: '运单状态',data:this.status},
                         {name:'source_bill',type:'input',tip: '上游单号:可在左侧增加百分号(%)进行模糊搜索',placeholder: '上游单号'},
+                        {name:'recipient',type:'input',tip: '收货人姓名:可在左侧增加百分号(%)进行模糊搜索',placeholder: '收货人姓名'},
                     ],
                     [
                         {name:'wms_bill_number',type:'input',tip:'WMS单号:可在两侧增加百分号(%)进行模糊搜索',placeholder: 'WMS单号'},
@@ -380,6 +387,7 @@
                         {name:'destination',type:'input',tip:'目的地:可在两侧增加百分号(%)进行模糊搜索',placeholder: '目的地'},
                         {name:'waybill_number',type:'input',tip:'运单号:可在两侧增加百分号(%)进行模糊搜索',placeholder: '运单号'},
                         {name:'logistic_id',type:'select',placeholder: '承运商',data:this.logistics},
+                        {name:'recipient_mobile',type:'input',tip: '收货人电话:可在左侧增加百分号(%)进行模糊搜索',placeholder: '收货人电话'},
                     ],
                 ];
                 let param=[];
@@ -497,10 +505,6 @@
                         tempTip.show('审核失败,网络连接错误!'+err);
                     });
                 },
-                {{--waybillUpdate(id){--}}
-                {{--    location.href="{{url('waybill/waybillEdit')}}/"+id;--}}
-                {{--},--}}
-                // 软删除
                 waybillDestroy(id,waybill_number,index){
                     if(!confirm('确定要删除运单号为:“'+waybill_number+'”的运单吗?')){return};
                     let url = '{{url('waybill')}}/'+id;
@@ -550,9 +554,6 @@
                         tempTip.show('审核驳回失败,网络连接错误!'+err);
                     });
                 },
-                {{--job(id){--}}
-                {{--    location.href="{{url('waybill')}}/"+id+"/edit";--}}
-                {{--},--}}
                 waybillEndAudit(id,waybill_number){
                     if(!confirm('确定要通过“'+waybill_number+'”的终审吗?')){return};
                     let _this=this;
@@ -665,7 +666,7 @@
                         "<img src=\""+url+'-common.'+suffix+"\" style='position: relative;left:-50px;' >" +
                         "</a>" +
                         "</div>"+
-                            @can('运输管理-图片删除')"<button type='button' class='btn btn-sm btn-danger' onclick='vueList.btnDeleteImg(this)' value='"+id+"' style='position: relative;float: right;margin-right: 51px;margin-top: -30px;' >删除</button>" +@endcan
+                            @can('运输管理-图片删除')"<button type='button' class='btn btn-sm btn-danger' onclick='vue.btnDeleteImg(this)' value='"+id+"' style='position: relative;float: right;margin-right: 51px;margin-top: -30px;' >删除</button>" +@endcan
                             "</div>"+
                         "</div>");
                 },
@@ -787,10 +788,6 @@
                         }
                     })
                 },
-
-
-
-
                 // 运费修改
                 waybillFeeCheck:function (e) {
                     let target = $(e.target);
@@ -961,7 +958,73 @@
                         tempTip.setDuration(3000);
                         tempTip.show('刷新计重失败,网络连接错误!'+err);
                     });
-                }
+                },
+                //选择文件
+                selectedFile(){
+                    $("#uploadImg").click();
+                },
+                //上传文件
+                uploadFiles(event){
+                    let images = event.target.files;
+                    for(let i=0;i<images.length;i++){
+                        images[i]['src'] = window.URL.createObjectURL(images[i]);
+                        this.images.push(images[i]);
+                    }
+                },
+                //删除图片
+                delTempImg(index){
+                    this.$delete(this.images,index);
+                },
+                //上传图片
+                batchUploadImages(){
+                    if (this.images.length<1){
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("未选择图片");
+                        return;
+                    }
+                    let formData = new FormData();
+                    this.images.forEach(image=>{
+                        formData.append("images[]",image);
+                    });
+                    window.tempTip.setIndex(1099);
+                    window.tempTip.setDuration(9999);
+                    window.tempTip.waitingTip("上传中,请稍等......");
+                    window.axios.post('{{url('waybill/batchUploadImages')}}',formData,{
+                        'Content-Type':'multipart/form-data'
+                    }).then(res=>{
+                        if (res.data.success){
+                            let result = res.data.data.data;
+                            let errors = res.data.data.errors;
+                            if (errors.length>0)this.batchUploadError =  errors;
+                            console.log(result);
+                            result.forEach(r=>{
+                                this.waybills.some(waybill=> {
+                                    if (waybill.id==r.id){
+                                        waybill.url=r.upload_file.url;
+                                        waybill.suffix=r.upload_file.type;
+                                        setTimeout(()=> {
+                                            this.imgs.push(document.getElementById('img_'+waybill.id));
+                                            this.lazy();
+                                        },1);
+                                        return true;
+                                    }
+                                });
+                            });
+                            this.$forceUpdate();
+                            window.tempTip.cancelWaitingTip();
+                            window.tempTip.setDuration(2000);
+                            window.tempTip.showSuccess("上传成功!");
+                            return;
+                        }
+                        window.tempTip.cancelWaitingTip();
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show(res.data.data);
+                    }).catch(err=>{
+                        window.tempTip.cancelWaitingTip();
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show('网络错误:'+err);
+                    });
+                },
             },
             filters:{
                 km:function(value){
@@ -979,12 +1042,19 @@
                     value=value.replace(/(\.[1-9])0$/,'$1');
                     return value;
                 },
+                size:function (val) {
+                    if (!val)return '';
+                    val = Number(parseInt(val/1024));
+                    if (val >= 1024){
+                        return  parseInt(val/1024)+"MB";
+                    }
+                    return val+"KB";
+                }
             }
         });
         // modal 隐藏时修改 input 为空
         $("#exampleModal").on('hide.bs.modal',function(e){
             $('#remark').val('');
         });
-
     </script>
 @endsection

+ 1 - 0
routes/web.php

@@ -248,6 +248,7 @@ Route::group(['prefix'=>'waybill'],function(){
     Route::any('waybillEndAudit','WaybillController@waybillEndAudit');
     Route::any('export','WaybillController@export');
     Route::any('waybillUpdate/{id}','WaybillController@waybillUpdate');
+    Route::post('batchUploadImages','WaybillController@batchUploadImages');
 
     Route::resource('waybillFinancialSnapshot','WaybillFinancialSnapshotsController');
     Route::resource('waybillFinancialExcepted','WaybillFinancialExceptedController');

+ 6 - 3
tests/Services/OwnerPriceExpressService/OwnerPriceExpressServiceTest.php

@@ -121,16 +121,19 @@ class OwnerPriceExpressServiceTest extends  TestCase
         $owner = factory(Owner::class)->create([
             "user_owner_group_id" => 1,
         ]);
+        $logistic = factory(Logistic::class)->create();
         /** @var OwnerPriceExpress $model */
         $model = OwnerPriceExpress::query()->find($this->data["models"][0]["id"]);
         $model->owners()->sync([$owner->id]);
-        $result = $this->service->getExistOwnerName([$owner->id],$this->data["models"][0]["id"]);
+        $model->logistics()->sync([$logistic->id]);
+        $result = $this->service->getExistOwnerName([$owner->id],$logistic->id,$this->data["models"][0]["id"]);
         $this->assertCount(0,$result);
-        $result = $this->service->getExistOwnerName([$owner->id]);
+        $result = $this->service->getExistOwnerName([$owner->id],$logistic->id);
         $this->assertCount(1,$result);
-        $this->assertEquals($owner->name,$result[0]);
+        $this->assertStringContainsString($owner->name,$result[0]);
         Owner::destroy($owner->id);
         $model->owners()->sync([]);
+        $model->logistics()->sync([]);
     }
     /**
      * @group customer

+ 11 - 11
tests/Services/OwnerOutStorageRuleService/OwnerOutStorageRuleServiceTest.php → tests/Services/OwnerPriceOperationItemService/OwnerPriceOperationItemServiceTest.php

@@ -1,25 +1,25 @@
 <?php
 
 
-namespace Tests\Services\OwnerOutStorageRuleService;
+namespace Tests\Services\OwnerPriceOperationItemService;
 
 
-use App\OwnerOutStorageRule;
 use App\OwnerPriceOperation;
-use App\Services\OwnerOutStorageRuleService;
+use App\OwnerPriceOperationItem;
+use App\Services\OwnerPriceOperationItemService;
 use App\Unit;
 use Tests\TestCase;
 
-class OwnerOutStorageRuleServiceTest extends  TestCase
+class OwnerPriceOperationItemServiceTest extends  TestCase
 {
-    /** @var OwnerOutStorageRuleService */
+    /** @var OwnerPriceOperationItemService */
     public $service;
     public $data;
 
     protected function setUp(): void
     {
         parent::setUp();
-        $this->service = app(OwnerOutStorageRuleService::class);
+        $this->service = app(OwnerPriceOperationItemService::class);
 
         $this->data["units"] = [];
         $unit1 = Unit::query()->where("name","件")->first();
@@ -41,11 +41,11 @@ class OwnerOutStorageRuleServiceTest extends  TestCase
 
         $this->data["ownerPriceOperations"] = [$ownerPriceOperation->toArray()];
         $this->data["models"] = [];
-        $this->data["models"][] = factory(OwnerOutStorageRule::class)->create([
+        $this->data["models"][] = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id" => $ownerPriceOperation->id,
             "unit_id" => $unit1->id,
         ])->toArray();
-        $this->data["models"][] = factory(OwnerOutStorageRule::class)->create([
+        $this->data["models"][] = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id" => $ownerPriceOperation->id,
             "unit_id" => $unit2->id,
         ])->toArray();
@@ -71,7 +71,7 @@ class OwnerOutStorageRuleServiceTest extends  TestCase
             "amount" => 50
         ]);
         $this->assertEquals(1,$result);
-        $expected = OwnerOutStorageRule::query()->find($model["id"]);
+        $expected = OwnerPriceOperationItem::query()->find($model["id"]);
         $this->assertEquals(99,$expected->priority);
         $this->assertEquals(1.33,$expected->unit_price);
         $this->assertEquals(50,$expected->amount);
@@ -98,7 +98,7 @@ class OwnerOutStorageRuleServiceTest extends  TestCase
      */
     public function testFindUpdate()
     {
-        $model = OwnerOutStorageRule::query()->find($this->data["models"][0]["id"]);
+        $model = OwnerPriceOperationItem::query()->find($this->data["models"][0]["id"]);
         $result = $this->service->findUpdate($model,[
             "unit_price" => 0.566,
         ]);
@@ -129,7 +129,7 @@ class OwnerOutStorageRuleServiceTest extends  TestCase
     {
         Unit::destroy(array_column($this->data["units"],"id"));
         OwnerPriceOperation::destroy(array_column($this->data["ownerPriceOperations"],"id"));
-        OwnerOutStorageRule::destroy(array_column($this->data["models"],"id"));
+        OwnerPriceOperationItem::destroy(array_column($this->data["models"],"id"));
         parent::tearDown();
     }
 }

+ 65 - 49
tests/Services/OwnerPriceOperationService/OwnerPriceOperationServiceTest.php

@@ -5,9 +5,8 @@ namespace Tests\Services\OwnerPriceOperationService;
 
 use App\Commodity;
 use App\Owner;
-use App\OwnerInStorageRule;
-use App\OwnerOutStorageRule;
 use App\OwnerPriceOperation;
+use App\OwnerPriceOperationItem;
 use App\Services\FeatureService;
 use App\Services\OwnerPriceOperationService;
 use App\Unit;
@@ -59,58 +58,86 @@ class OwnerPriceOperationServiceTest extends  TestCase
         ]);
         $this->data["models"] = [$model1->toArray(),$model2->toArray(),$model3->toArray(),$model4->toArray()];
 
-        $in1 = factory(OwnerInStorageRule::class)->create([
-            "owner_price_operation_id"  => $model1->id, //作业计费ID
-            "amount"                    => 5,                   //计量
-            "unit_id"                   => $pieces->id,//单位ID
-            "unit_price"                => 2.22,               //单价
-        ]);
-        $in2 = factory(OwnerInStorageRule::class)->create([
-            "owner_price_operation_id"  => $model2->id, //作业计费ID
-            "amount"                    => 5,                   //计量
-            "unit_id"                   => $box->id,//单位ID
-            "unit_price"                => 3.22,               //单价
-        ]);
-        $out1 = factory(OwnerOutStorageRule::class)->create([
-            "owner_price_operation_id"          => $model3->id,
-            "strategy"                          =>"起步",
-            "amount"                            =>6,
+        $item1 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model1->id,
+            "strategy"                          => "默认",
+            "amount"                            => 6,
             "unit_id"                           => $box->id,
             "unit_price"                        => 2.22,
         ]);
-        $out4 = factory(OwnerOutStorageRule::class)->create([
+        $item2 = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id"          => $model3->id,
-            "strategy"                          => "默认",
+            "strategy"                          => "特征",
+            "amount"                            => 6,
             "unit_id"                           => $box->id,
             "unit_price"                        => 3.22,
         ]);
-        $out5 = factory(OwnerOutStorageRule::class)->create([
+        $item3 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model2->id,
+            "strategy"                          =>"默认",
+            "amount"                            => 6,
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 4.22,
+        ]);
+        $item4 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model2->id,
+            "strategy"                          =>"特征",
+            "amount"                            => 6,
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.1,
+        ]);
+        $item5 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model3->id,
+            "strategy"                          => "起步",
+            "amount"                            => 6,
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.2,
+        ]);
+        $item6 = factory(OwnerPriceOperationItem::class)->create([
+            "owner_price_operation_id"          => $model3->id,
+            "strategy"                          =>"默认",
+            "amount"                            => 6,
+            "unit_id"                           => $box->id,
+            "unit_price"                        => 5.3,
+        ]);
+        $item7 = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id"          => $model3->id,
             "strategy"                          =>"特征",
+            "amount"                            => 6,
             "unit_id"                           => $box->id,
-            "unit_price"                        => 4.22,
+            "unit_price"                        => 5.4,
         ]);
-        $out6 = factory(OwnerOutStorageRule::class)->create([
+        $item8 = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id"          => $model4->id,
-            "strategy"                          =>"起步",
+            "strategy"                          => "起步",
             "amount"                            => 6,
             "unit_id"                           => $box->id,
-            "unit_price"                        => 5.1,
+            "unit_price"                        => 5.5,
         ]);
-        $out7 = factory(OwnerOutStorageRule::class)->create([
+        $item9 = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id"          => $model4->id,
-            "strategy"                          => "默认",
+            "strategy"                          =>"默认",
+            "amount"                            => 6,
             "unit_id"                           => $box->id,
-            "unit_price"                        => 5.2,
+            "unit_price"                        => 5.6,
         ]);
-        $out8 = factory(OwnerOutStorageRule::class)->create([
+        $item10 = factory(OwnerPriceOperationItem::class)->create([
             "owner_price_operation_id"          => $model4->id,
             "strategy"                          =>"特征",
+            "amount"                            => 6,
             "unit_id"                           => $box->id,
-            "unit_price"                        => 5.3,
+            "unit_price"                        => 5.7,
         ]);
-        $this->data["in"] = [$in1->toArray(),$in2->toArray()];
-        $this->data["out"] = [$out1->toArray(),$out4->toArray(),$out5->toArray(),$out6->toArray(),$out7->toArray(),$out8->toArray()];
+        $this->data["item"] = [$item1->toArray(),
+            $item2->toArray(),
+            $item3->toArray(),
+            $item4->toArray(),
+            $item5->toArray(),
+            $item6->toArray(),
+            $item7->toArray(),
+            $item8->toArray(),
+            $item9->toArray(),
+            $item10->toArray()];
         $owner = factory(Owner::class)->create([
             "user_owner_group_id" => 1,
         ]);
@@ -131,26 +158,16 @@ class OwnerPriceOperationServiceTest extends  TestCase
     /**
      * @group customer
      */
-    public function testMatchRule()
+    public function testMatching()
     {
         $this->partialMock(FeatureService::class,function ($mock){
             /** @var Mock $mock */
             $mock->shouldReceive("matchFeature")->andReturn(true);
         });
-        $result = $this->service->matchRule(["packages"=>[["commodity"=>"测试","amount"=>55,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"入库");
-        $this->assertEquals(12.88,$result);
-        $result = $this->service->matchRule(["packages"=>[["commodity"=>"测试","amount"=>57,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"出库");
-        $this->assertEquals(99.5,$result);
-    }
-    /**
-     * @group customer
-     */
-    public function testMatchRule1()
-    {
-        $result = $this->service->matchRule(["packages"=>[["commodity"=>"测试","amount"=>56,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"入库");
-        $this->assertEquals(26.64,$result);
-        $result = $this->service->matchRule(["packages"=>[["commodity"=>"测试","amount"=>58,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"出库");
-        $this->assertEquals(58.4,$result);
+        $result = $this->service->matching(["packages"=>[["commodity"=>"测试","amount"=>55,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"入库");
+        $this->assertEquals(96.9,$result);
+        $result = $this->service->matching(["packages"=>[["commodity"=>"测试","amount"=>57,"sku"=>$this->data["commodities"][0]["sku"]]]],[],$this->data["owners"][0]["id"],"出库");
+        $this->assertEquals(107.1,$result);
     }
 
     public function tearDown(): void
@@ -162,8 +179,7 @@ class OwnerPriceOperationServiceTest extends  TestCase
             $model->id = $d["id"];
             $model->ownerPriceOperationOwners()->sync([]);
         }
-        OwnerInStorageRule::destroy(array_column($this->data["in"],"id"));
-        OwnerOutStorageRule::destroy(array_column($this->data["out"],"id"));
+        OwnerPriceOperationItem::destroy(array_column($this->data["item"],"id"));
         Owner::destroy(array_column($this->data["owners"],"id"));
         Commodity::destroy(array_column($this->data["commodities"],"id"));
         parent::tearDown();