浏览代码

Merge branch 'master' into Haozi

# Conflicts:
#	app/Providers/AppServiceProvider.php
haozi 5 年之前
父节点
当前提交
98780affe0
共有 71 个文件被更改,包括 1527 次插入1383 次删除
  1. 2 3
      app/Commodity.php
  2. 1 0
      app/Console/Commands/SyncBatchTask.php
  3. 2 1
      app/Exceptions/Exception.php
  4. 27 2
      app/Feature.php
  5. 5 2
      app/Http/Controllers/CommodityController.php
  6. 0 1
      app/Http/Controllers/LogisticController.php
  7. 0 1
      app/Http/Controllers/LogisticNumberFeatureController.php
  8. 43 77
      app/Http/Controllers/PriceModelController.php
  9. 31 21
      app/Http/Controllers/ProcessController.php
  10. 35 19
      app/Http/Controllers/ProcessStatisticController.php
  11. 2 0
      app/Http/Controllers/RejectedController.php
  12. 45 461
      app/Http/Controllers/TestController.php
  13. 6 2
      app/Http/Controllers/api/thirdPart/goodscan/PackageController.php
  14. 6 1
      app/Http/Controllers/api/thirdPart/haiq/PickStationController.php
  15. 22 9
      app/Http/Controllers/api/thirdPart/haiq/StorageController.php
  16. 0 1
      app/Http/Controllers/api/thirdPart/jianshang/RejectedController.php
  17. 5 7
      app/Http/Controllers/api/thirdPart/weight/PackageController.php
  18. 3 1
      app/Http/Requests/ForeignHaiRobotic_taskUpdateRequest.php
  19. 46 81
      app/Imports/ExpressImport.php
  20. 1 1
      app/Imports/UpdatePickZone.php
  21. 0 2
      app/Imports/WaybillPriceModelsImport.php
  22. 43 0
      app/Jobs/RejectedBillCreateInstantBill.php
  23. 1 1
      app/Jobs/WeightUpdateInstantBill.php
  24. 0 12
      app/Order.php
  25. 6 0
      app/OwnerPriceExpress.php
  26. 4 0
      app/OwnerPriceExpressProvince.php
  27. 4 0
      app/OwnerPriceOperation.php
  28. 5 0
      app/OwnerStoragePriceModel.php
  29. 1 1
      app/Process.php
  30. 1 5
      app/ProcessStatistic.php
  31. 17 4
      app/Services/CommodityService.php
  32. 70 78
      app/Services/FeatureService.php
  33. 63 23
      app/Services/ForeignHaiRoboticsService.php
  34. 12 25
      app/Services/OrderService.php
  35. 25 3
      app/Services/OwnerPriceExpressService.php
  36. 1 1
      app/Services/OwnerPriceLogisticService.php
  37. 205 200
      app/Services/OwnerPriceOperationService.php
  38. 8 1
      app/Services/OwnerStoragePriceModelService.php
  39. 1 1
      app/Services/ProcessService.php
  40. 4 10
      app/Services/ProcessStatisticService.php
  41. 37 0
      app/Services/RejectedBillService.php
  42. 3 0
      app/Services/StationService.php
  43. 3 0
      app/Services/StationTaskMaterialBoxService.php
  44. 2 3
      app/Services/StationTaskService.php
  45. 2 3
      app/Services/StoreService.php
  46. 45 0
      app/Services/UnitService.php
  47. 0 22
      app/Services/WaybillService.php
  48. 1 15
      app/Store.php
  49. 1 1
      database/migrations/2020_11_30_140958_create_stations_table.php
  50. 1 1
      database/migrations/2021_02_19_110139_change_owner_operation_owner_table.php
  51. 2 2
      database/migrations/2021_02_26_152744_change_owner_fee_details_table_change_volume_column.php
  52. 32 0
      database/migrations/2021_03_24_131737_change_table_process_add_column_designate_id.php
  53. 5 5
      laravel-echo-server.json
  54. 44 0
      laravel-echo-server.json.configed
  55. 16 1
      resources/sass/text.scss
  56. 211 38
      resources/views/customer/project/create.blade.php
  57. 102 23
      resources/views/customer/project/part/_express.blade.php
  58. 31 130
      resources/views/customer/project/part/_operation.blade.php
  59. 46 10
      resources/views/customer/project/part/_storage.blade.php
  60. 47 10
      resources/views/customer/project/part/_three.blade.php
  61. 3 3
      resources/views/customer/project/part/_two.blade.php
  62. 21 17
      resources/views/process/create.blade.php
  63. 9 23
      resources/views/process/index.blade.php
  64. 2 0
      resources/views/process/statistic.blade.php
  65. 24 15
      resources/views/station/monitor/show.blade.php
  66. 74 0
      resources/views/test.blade.php
  67. 4 1
      resources/views/transport/waybill/index.blade.php
  68. 1 0
      routes/api/thirdPart/haiq.php
  69. 1 1
      tests/webApi/thirdPart/haiq/move.http
  70. 1 1
      tests/webApi/thirdPart/haiq/pickStation.http
  71. 3 0
      tests/webApi/thirdPart/haiq/storage.http

+ 2 - 3
app/Commodity.php

@@ -2,7 +2,6 @@
 
 namespace App;
 
-use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
 use App\Traits\ModelTimeFormat;
 
@@ -13,9 +12,9 @@ class Commodity extends Model
     use ModelLogChanging;
 
     use ModelTimeFormat;
-    protected $fillable=['name','sku','owner_id','created_at','length','width','height','volumn',"type","pack_spec",'updated_at'];
+    protected $fillable=['name','sku','owner_id','created_at','length',
+        'width','height','volumn',"type","pack_spec",'updated_at',"remark"];
     protected $appends=['barcode'];
-//    protected $appends=['barcode','owner_name','owner_code'];
 
     public function setNameAttribute($value){
         $this->attributes['name']=str_replace(PHP_EOL,'',$value);

+ 1 - 0
app/Console/Commands/SyncBatchTask.php

@@ -249,6 +249,7 @@ sql;
         if (count($updateOrder)>1){
             app("OrderService")->batchUpdate($updateOrder);//反向修改订单
             LogService::log(__METHOD__,"波次同步-修改订单波次号",json_encode($updateOrder));
+            LogService::log(__METHOD__,"修改过的波次_",json_encode($updateBatch));
             BatchTaskJob::dispatch($updateBatch);    //在这里为波次注册队列任务!
         }
 

+ 2 - 1
app/Exceptions/Exception.php

@@ -24,7 +24,8 @@ class Exception extends \Exception
             $className,
             $functionName,
             $tracesAll
-            )           =(function()use($exception){
+            )
+            =(function()use($exception){
             $traces=method_exists($exception,'getTraceAsString')
                 ?($exception->getTraceAsString()??'')
                 :'';

+ 27 - 2
app/Feature.php

@@ -16,14 +16,39 @@ class Feature extends Model
         "describe", //特征
     ];
 
-    const type = [
+    const TYPE = [
         0 => "商品名称",  //二级
         1 => "订单类型",
         2 => "承运商",
         3 => "店铺类型",
         4 => "波次类型",
-        5 => "商品备注",
+        5 => "商品备注",  //二级
         6 => "长",       //二级
         7 => "订单备注",
     ];
+    //额外定义 8:商品数量 9:商品
+    const TYPE_NODE = [0,5,6,8,9]; //标注二级类型
+    const MAPPING = [
+        "store" => [
+            0 => "storeItems.name",
+            1 => "stored_method",
+            5 => "storeItems.commodity.remark",
+            6 => "storeItems.commodity.length",
+            7 => "remark",
+            8 => "storeItems.amount",
+            9 => "storeItems.commodity",
+        ],
+        "order" => [
+            0 => "packages.commodities.commodity.name",
+            1 => "order_type",
+            2 => "logistic.name",
+            3 => "shop.name",
+            4 => "batch.wms_type",
+            5 => "packages.commodities.commodity.remark",
+            6 => "packages.commodities.commodity.length",
+            7 => "remark",
+            8 => 'packages.commodities.amount',
+            9 => 'packages.commodities.commodity',
+        ]
+    ];
 }

+ 5 - 2
app/Http/Controllers/CommodityController.php

@@ -232,7 +232,7 @@ class CommodityController extends Controller
         $commodities = $commodityService->getOwnerCommodities(['owner_id' => $owner_id, 'sku'=>$skus]);
         $updateCommodities = [];
         $updateCommodities[] = [
-            'id', 'sku', 'name', 'length', 'width', 'height', 'volumn',"pack_spec"
+            'id', 'sku', 'name', 'length', 'width', 'height', 'volumn',"pack_spec","remark"
         ];
         $barcodeMap = [];
         $commoditiesId = [];
@@ -254,6 +254,7 @@ class CommodityController extends Controller
                     'height' => $wms->skuhigh,
                     'volumn' => $wms->cube,
                     "pack_spec"  => $wms->packid == 'STANDARD' ? 0 : explode("/",$wms->packid)[1],
+                    'remark' => $wms->notes,
                 ];
             }
             if ($wms->alternate_sku1){
@@ -316,6 +317,7 @@ class CommodityController extends Controller
                 'height' => $wms->skuhigh,
                 'volumn' => $wms->cube,
                 "pack_spec"  => $wms->packid == 'STANDARD' ? 0 : explode("/",$wms->packid)[1],
+                'remark' => $wms->notes,
                 "created_at" => $today,
             ];
             $barcodeMap[$wms->sku] = [];
@@ -340,7 +342,7 @@ class CommodityController extends Controller
             $commodities = $commodityService->ownerBarcodeSeekCommodityGet(['id'=>$owner_id], $barcodes);
             $updateCommodities = [];
             $updateCommodities[] = [
-                'id', 'sku', 'name', 'length', 'width', 'height', 'volumn',
+                'id', 'sku', 'name', 'length', 'width', 'height', 'volumn','pack_spec','remark'
             ];
             foreach ($commodities as $commodity){
                 foreach ($commodity->barcodes as $code){
@@ -356,6 +358,7 @@ class CommodityController extends Controller
                             'height' => $goods['height'],
                             'volumn' => $goods['volumn'],
                             "pack_spec" => $goods["pack_spec"],
+                            'remark' => $goods["notes"],
                         ];
                         unset($createCommodities[$barcodeIndex[$code->code]]);
                         break;

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

@@ -3,7 +3,6 @@
 namespace App\Http\Controllers;
 
 use App\Logistic;
-use App\Services\UserService;
 use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;

+ 0 - 1
app/Http/Controllers/LogisticNumberFeatureController.php

@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
 
 use App\Logistic;
 use App\LogisticNumberFeature;
-use App\Rejected;
 use App\RejectedBill;
 use Carbon\Carbon;
 use Illuminate\Http\Request;

+ 43 - 77
app/Http/Controllers/PriceModelController.php

@@ -116,7 +116,8 @@ class PriceModelController extends Controller
             'using_type'=>['required'],
             'minimum_area'=>['nullable','numeric','min:0'],
             'discount_value'=>['nullable','numeric','min:0'],
-            'price'=>['required','numeric','min:0'],
+            'price.*'=>['required','numeric','min:0'],
+            'amount_interval.*'=>['required','integer','min:0'],
             'discount_type'=>['required'],
             'unit_id'=>['required','integer'],
             'time_unit_id'=>['required','integer'],
@@ -129,7 +130,8 @@ class PriceModelController extends Controller
             'counting_type' =>"计费类型",
             'using_type'    =>"用仓类型",
             'minimum_area'  =>"最低起租面积",
-            'price'         =>"单价",
+            'price.*'       =>"单价",
+            'amount_interval.*'=>"数量区间",
             'discount_type' =>"减免类型",
             'discount_value'=>"减免值",
             'unit_id'       =>"单位",
@@ -488,25 +490,9 @@ class PriceModelController extends Controller
         $this->success();
     }
 
-    public function expressImport(Request $request){
+    public function expressImport(){
         $this->gate("计费模型-快递-录入");
-        $fileSuffix=$request->file('file')->getClientOriginalExtension();
-        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
-            return ['success'=>false,'data'=>'不支持该文件类型'];
-        ini_set('max_execution_time',2500);
-        ini_set('memory_limit','1526M');
-        $fileSuffix = ucwords($fileSuffix);
-
-        if (!$request->has("id")){
-            Excel::import(new ExpressImport(null),$request->file('file')->path(),null,$fileSuffix);
-        }else{
-            /** @var OwnerPriceExpress $model */
-            $model = app('OwnerPriceExpressService')->find($request->input("id"),["details"]);
-            Excel::import(new ExpressImport($model),$request->file('file')->path(),null,$fileSuffix);
-        }
-
-        if (Cache::has('express'))return Cache::pull('express');
-        return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
+        $this->importExcel(new ExpressImport(request("id") ? app('OwnerPriceExpressService')->find(request("id"),["details"]) : null));
     }
 
     public function expressCreate(){
@@ -574,20 +560,19 @@ class PriceModelController extends Controller
     private function expressValidator(array $params, $id=null)
     {
         return Validator::make($params,[
-            'name'=>['required',$id?"unique:owner_price_expresses,name,$id":'unique:owner_price_expresses,name'],
+            'name'=>['required'],
             'initial_weight'=>['required','numeric','min:0'],
             'additional_weight'=>['required','numeric','min:0'],
             'owner_id'=>[function ($attribute, $value, $fail)use($id,$params) {
                 $owners = app("OwnerPriceExpressService")->getExistOwnerName($value,$params["logistic_id"] ?? [],$id);
                 if ($owners)$fail("(".implode(',',$owners).') 已经绑定计费模型');
             }],
-            /*'logistic_id'=>[function ($attribute, $value, $fail)use($id) {
-                $logistics = app("OwnerPriceExpressService")->getExistLogisticName($value,$id);
-                if ($logistics)$fail("(".implode(',',$logistics).') 已经绑定计费模型');
-            }],*/
-            'items.*.province_id'=>['sometimes','required'],
-            'items.*.additional_weight_price'=>['sometimes','required','numeric',"min:0"],
-            'items.*.initial_weight_price'=>['sometimes','required','numeric',"min:0"],
+            'amount_interval.*'=>['required','integer','min:0'],
+            'weight_interval.*'=>['array'],
+            'weight_interval.*.*'=>['required','numeric','min:0'],
+            'items.*.province_id'=>['required'],
+            'items.*.additional_weight_price.*.*'=>['required','numeric',"min:0"],
+            'items.*.initial_weight_price.*.*'=>['required','numeric',"min:0"],
         ],[
             'required'=>':attribute 为必填项',
             'unique' => ':attribute 已存在',
@@ -596,9 +581,12 @@ class PriceModelController extends Controller
             'name' =>"名称",
             'initial_weight'  =>"首重",
             'additional_weight'  =>"续重",
+            'amount_interval.*'  =>"数量区间",
+            'weight_interval.*'  =>"重量区间",
+            'weight_interval.*.*'  =>"重量区间",
             "items.*.province_id"=>"省份",
-            "items.*.additional_weight_price"=>"首重价格",
-            "items.*.initial_weight_price"=>"续重价格",
+            "items.*.additional_weight_price.*.*"=>"续重价格",
+            "items.*.initial_weight_price.*.*"=>"首重价格",
         ]);
     }
 
@@ -1144,6 +1132,7 @@ class PriceModelController extends Controller
             "discount_value"    => request("discount_value") ?? 0,
             "unit_id"           => request("unit_id"),
             "time_unit_id"      => request("time_unit_id"),
+            "amount_interval"   => request("amount_interval") ?? null,
         ];
         if (request("id")){
             $model = app('OwnerStoragePriceModelService')->find(request("id"));
@@ -1162,16 +1151,7 @@ class PriceModelController extends Controller
     public function apiStoreOperation()
     {
         $this->gate("项目管理-项目-录入");
-
         $params = request()->input();
-        if (request("operation_type") == '入库'){
-            foreach ($params["items"] as $index => $it){
-                if (!$it || $it['strategy'] == '起步'){
-                    unset($params["items"][$index]);
-                    break;
-                }
-            }
-        }
 
         $params["owner_id"] = [$params["owner_id"]];
         $errors = $this->operationValidator($params,request("id"))->errors();
@@ -1183,6 +1163,7 @@ class PriceModelController extends Controller
             "operation_type"    => request("operation_type"),
             "strategy"          => request("strategy"),
             "feature"           => request("feature"),
+            "type_mark"         => request()->has("type_mark") ? \request("type_mark") : null,
             "remark"            => request("remark"),
             "discount_count"    => implode(",",request("discount_count")),
             "total_price"       => request("total_price"),
@@ -1219,24 +1200,20 @@ class PriceModelController extends Controller
                 if ($delete)app("OwnerPriceOperationItemService")->destroy($delete);
                 if (count($update) > 1)app(BatchUpdateService::class)->batchUpdate("owner_price_operation_items",$update);
                 if ($insert)app("OwnerPriceOperationItemService")->insert($insert);
-            }else{
-                foreach ($params["items"] as &$item){
-                    unset($item["id"]);
-                    $item["feature"] = $item["feature"] ?? null;
-                    $item["discount_price"] = implode(",",$item["discount_price"] ?? []);
-                }
-                $model = app("OwnerPriceOperationService")->copy($model,$operation,null,$params["items"],false);
-            }
+            }else $model = app("OwnerPriceOperationService")->copy($model,$operation,null,$params["items"],false);
         }else{
             DB::transaction(function ()use(&$model,$params,$operation){
                 $model = app('OwnerPriceOperationService')->create($operation);
                 foreach ($params["items"] as &$item){
-                    $item["discount_price"]  = implode(",",$item["discount_price"] ?? []);
-                    $item["owner_price_operation_id"] = $model->id;
-                    if (!isset($item["feature"]))$item["feature"] = null;
-                    unset($item["features"]);
-                    unset($item["featureFormat"]);
-                    unset($item["type"]);
+                    $temp = [];
+                    $temp["discount_price"]  = implode(",",$item["discount_price"] ?? []);
+                    $temp["owner_price_operation_id"] = $model->id;
+                    $temp["feature"] = $item["feature"] ?? null;
+                    $temp["strategy"] = $item["strategy"];
+                    $temp["amount"] = $item["amount"];
+                    $temp["unit_id"] = $item["unit_id"];
+                    $temp["unit_price"] = $item["unit_price"];
+                    $item = $temp;
                 }
                 app("OwnerPriceOperationItemService")->insert($params["items"]);
                 DB::insert(DB::raw("INSERT INTO owner_price_operation_owner(owner_price_operation_id,owner_id) VALUES(?,?)"),[$model->id,request("owner_id")]);
@@ -1266,6 +1243,8 @@ class PriceModelController extends Controller
             "name"              => request("name"),
             "initial_weight"    => request("initial_weight"),
             "additional_weight" => request("additional_weight"),
+            "amount_interval"   => request("amount_interval"),
+            "weight_interval"   => request("weight_interval"),
         ];
         if (request("id")){
             /** @var \stdClass $model */
@@ -1305,7 +1284,11 @@ class PriceModelController extends Controller
         }else{
             DB::transaction(function ()use(&$model,$params,$obj){
                 $model = app('OwnerPriceExpressService')->create($obj);
-                foreach ($params["items"] as &$item)$item["owner_price_express_id"] = $model->id;
+                foreach ($params["items"] as &$item){
+                    $item["owner_price_express_id"] = $model->id;
+                    $item["initial_weight_price"] = json_encode($item["initial_weight_price"]);
+                    $item["additional_weight_price"] = json_encode($item["additional_weight_price"]);
+                }
                 OwnerPriceExpressProvince::query()->insert($params["items"]);
                 DB::insert(DB::raw("INSERT INTO owner_price_express_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
                 app("OwnerService")->refreshRelevance(request("owner_id"),2);
@@ -1464,6 +1447,7 @@ class PriceModelController extends Controller
 
     public function getPriceModel()
     {
+        /** @var Owner|\stdClass $owner */
         $owner = new Owner();
         $owner->id = request("id");
         $owner->load(["ownerStoragePriceModels","ownerPriceOperations"=>function($query){
@@ -1485,11 +1469,10 @@ class PriceModelController extends Controller
         OwnerPriceOperationItem::$features = $features;
         foreach ($owner->ownerPriceOperations as &$operation){
             $operation["featureFormat"] = $operation->featureFormat;
+            $operation["isRejected"] = $operation->type_mark === 0 ? true : false;
             foreach ($operation->items as &$item){
                 $item["featureFormat"] = $item->featureFormat;
-                if ($operation["operation_type"]==='出库' && $item["strategy"] == "起步"){
-                    $item["type"] = $item["amount"] ? 0 : 1;
-                }
+                if ($item["strategy"] == "起步")$item["type"] = $item["amount"] ? 0 : 1;
             }
         }
         $this->success($owner);
@@ -1549,9 +1532,10 @@ class PriceModelController extends Controller
         $models = $models->get();
         foreach ($models as &$operation){
             $operation["featureFormat"] = $operation->featureFormat;
-            $items = [[],[]];
+            $operation["isRejected"] = $operation->type_mark === 0 ? true : false;
+            $items = [];
             foreach ($operation->items as $item){
-                $obj = [
+                $items[] = [
                     "strategy" => $item["strategy"],
                     "amount" => $item["amount"],
                     "unit_id" => $item["unit_id"],
@@ -1560,25 +1544,7 @@ class PriceModelController extends Controller
                     "feature" => $item["feature"],
                     "featureFormat" => $item->featureFormat,
                 ];
-                if ($item["strategy"] == '起步')$items[0] = $obj;
-                if ($item["strategy"] == '默认')$items[1] = $obj;
-                if ($item["strategy"] == '特征')$items[] = $obj;
             }
-            if (!$items[0])$items[0] = [
-                "strategy" => "起步",
-                "amount" => "",
-                "unit_id" => "",
-                "unit_price" => "",
-                "feature" => "",
-            ];
-            if (!$items[1])$items[1] = [
-                "strategy" => "默认",
-                "amount" => "",
-                "unit_id" => "",
-                "unit_price" => "",
-                "feature" => "",
-            ];
-            unset($operation["items"]);
             $operation["items"] = $items;
         }
         $this->success($models);

+ 31 - 21
app/Http/Controllers/ProcessController.php

@@ -17,6 +17,7 @@ use App\Services\OwnerService;
 use App\Services\ProcessService;
 use App\Sign;
 use App\Tutorial;
+use App\User;
 use App\UserDetail;
 use App\UserDutyCheck;
 use App\UserLabor;
@@ -174,11 +175,13 @@ class ProcessController extends Controller
     }
     //接单
     public function receive($id){
-        if(!Gate::allows('二次加工管理-接单与驳回')){ return redirect(url('/'));  }
-        $process=Process::select('id','status','amount')->find($id);
+        if(!Gate::allows('二次加工管理-接单与驳回')){ return ["success"=>false,"data"=>"无权操作"];  }
+        /** @var Process|\stdClass $process */
+        $process=Process::query()->select('id','status','amount','designate_id')->find($id);
+        if ($process && $process->designate_id && $process->designate_id!=Auth::id())return ["success"=>false,"data"=>"无权操作"];
         $amount=$process->amount;
         $today=Carbon::now()->format('Y-m-d');
-        $processDaily=ProcessDaily::where('date',$today)->where('process_id',$id)->first();
+        $processDaily=ProcessDaily::query()->where('date',$today)->where('process_id',$id)->first();
         if (!$processDaily){
             $processDaily=new ProcessDaily([
                 'process_id'=>$id,
@@ -191,8 +194,7 @@ class ProcessController extends Controller
         $process->status="待加工";
         $process->update();
         $process->createOperatorLog('接单');
-        app('LogService')->log(__METHOD__,"接单二次加工单_".__FUNCTION__,json_encode($process),Auth::user()['id']);
-        return $process;
+        return ["success"=>true,"data"=>$process->status];
     }
     //完成
     public function accomplish(Request $request){
@@ -513,14 +515,21 @@ class ProcessController extends Controller
      */
     public function create()
     {
-        if(!Gate::allows('二次加工管理-录入')){ return redirect(url('/'));  }
-        $processMethods=ProcessMethod::get();
-        return view('process/create',['processMethods'=>$processMethods,'process'=>null]);
+        if(!Gate::allows('二次加工管理-录入')){ return view("exception.authority");  }
+        $processMethods=ProcessMethod::query()->get();
+        $users = User::query()->whereNotNull("email")->whereHas("roles",function ($query){
+            /** @var Builder $query */
+            $query->whereHas("authorities",function($query){
+                /** @var Builder $query */
+                $query->where("alias_name","二次加工管理-接单与驳回");
+            });
+        })->orWhereIn("name",config("users.superAdmin"))->get();
+        return view('process/create',['processMethods'=>$processMethods,'process'=>null,"users"=>$users]);
     }
 
     //货主ID获取教程
     public function ownerGetTutorials($owner_id){
-        $tutorials=Tutorial::where('owner_id',$owner_id)->get();
+        $tutorials=Tutorial::query()->where('owner_id',$owner_id)->get();
         return $tutorials;
     }
 
@@ -544,6 +553,7 @@ class ProcessController extends Controller
             'remark'=>$request->input('remark'),
             'balance_remark'=>$request->input('balance_remark'),
             'amount'=>$request->input('amount'),
+            'designate_id'=>$request->input('designate_id'),
             'status'=>'待审核',
         ]);
         $process->save();
@@ -645,11 +655,7 @@ class ProcessController extends Controller
             DB::beginTransaction();
             if ($signUnitPrice){
                 $process->update(['unit_price' => $signUnitPrice->mark]);
-                $result = $this->statistic($process);
-//                if (!$result['success']){
-//                    DB::rollBack();
-//                    return $result['data'];
-//                }
+                $this->statistic($process);
             }
             $process->createSign('财务确认');
             $process->destroySign();
@@ -661,11 +667,7 @@ class ProcessController extends Controller
             DB::beginTransaction();
             if ($signUnitPrice){
                 $process->update(['unit_price' => $signUnitPrice->mark]);
-                $result = $this->statistic($process);
-//                if (!$result['success']){
-//                    DB::rollBack();
-//                    return $result['data'];
-//                }
+                $this->statistic($process);
             }
             $process->createSign('二次加工组确认');
             $process->destroySign();
@@ -679,7 +681,7 @@ class ProcessController extends Controller
     //审核
     function audit(Request $request){
         if(!Gate::allows('二次加工管理-审核')){ return ['success'=>false,'data'=>'您无权进行该操作!'];  }
-        $process=Process::find($request->id);
+        $process=Process::query()->find($request->id);
         if (!$process)return ['success'=>false];
         $process->update(['status'=>'待接单']);
         $process->createOperatorLog('审核');
@@ -702,7 +704,14 @@ class ProcessController extends Controller
             }]);
         }])->find($id);
         $processMethods=ProcessMethod::get();
-        return view('process.create',['process'=>$process,'processMethods'=>$processMethods]);
+        $users = User::query()->whereNotNull("email")->whereHas("roles",function ($query){
+            /** @var Builder $query */
+            $query->whereHas("authorities",function($query){
+                /** @var Builder $query */
+                $query->where("alias_name","二次加工管理-接单与驳回");
+            });
+        })->orWhereIn("name",config("users.superAdmin"))->get();
+        return view('process.create',['process'=>$process,'processMethods'=>$processMethods,"users"=>$users]);
     }
 
     public function show($id){
@@ -741,6 +750,7 @@ class ProcessController extends Controller
             $process->remark=$request->input('remark');
             $process->balance_remark=$request->input('balance_remark');
             $process->amount=$request->input('amount');
+            $process->designate_id=$request->input('designate_id');
             if ($process->status=='已驳回')$process->status='待接单';
             $process->update();
             $process->createOperatorLog('编辑');

+ 35 - 19
app/Http/Controllers/ProcessStatisticController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Process;
+use App\Services\common\ExportService;
 use App\Services\ProcessStatisticService;
 use Exception;
 use Illuminate\Http\Request;
@@ -20,29 +21,44 @@ class ProcessStatisticController extends Controller
         return view('process.statistic',['processStatistics'=>$processStatistics,'params'=>$request->input(),'owners'=>$owners,'processMethods'=>$processMethods]);
     }
 
-    public function export(Request $request){
+    public function export(){
         if(!Gate::allows('二次加工管理-查询')){ return '没有权限';  }
-        if ($request->checkAllSign){
-            $params = $request->input();
-            unset($params['checkAllSign']);
-            $sql = app('ProcessStatisticService')->getSql($params);
-        }else $sql = app('ProcessStatisticService')->getSql(["process_id"=>$request->data]);
+        if (request("checkAllSign")){
+            \request()->offsetUnset("checkAllSign");
+            $processes = app('ProcessStatisticService')->get(\request()->input());
+        }else $processes = app('ProcessStatisticService')->get(["process_id"=>\request("data")]);
 
-        $row = ["任务号", "货主", "开始日期", "完成日期","创建日期", "单价", "预期数量", "完成数量", "收入合计",
+        $row = ["任务号","接单人", "货主", "开始日期", "完成日期","创建日期", "单价", "预期数量", "完成数量", "收入合计",
             "完成时间(天)'", "总工时", "加工类型", "最高日产能", "最低日产能", "日均产能", "合计成本", "毛利润",
             "毛利率", "状态","加工备注","结算备注"];
-        $column = ["process_code", "owner_name", "started_at", "ended_at","process_created_at", "process_unit_price", "process_amount", "process_completed_amount", "revenue",
-		"duration_days", "duration_man_hours", "process_method_name", "top_capacity", "bottom_capacity",
-		"average_capacity", "total_cost", "gross_profit", "gross_profit_rate", "process_status", "process_remark", "process_balance_remark"];
-        $rule = ["gross_profit_rate"=> "percent", "started_at"=>"mysqlDate", "ended_at"=>"mysqlDate", "process_created_at"=>"mysqlDate"];
-        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
-            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
-        if ($post->status() == 500){
-            throw new Exception($post->header("Msg"));
+        $list = [];
+
+        foreach ($processes as $process){
+            $list[] = [
+                $process->process->code ?? "",
+                $process->operatorLog->user->name ?? "",
+                $process->process->owner->name ?? "",
+                $process->started_at,
+                $process->ended_at,
+                $process->process->created_at ?? "",
+                $process->process->unit_price ?? "",
+                $process->process->amount ?? "",
+                $process->process->completed_amount ?? "",
+                $process->revenue,
+                $process->duration_days,
+                $process->duration_man_hours,
+                $process->process->method->name ?? "",
+                $process->top_capacity,
+                $process->bottom_capacity,
+                $process->average_capacity,
+                $process->total_cost,
+                $process->gross_profit,
+                ($process->gross_profit_rate*100)."%",
+                $process->process->status ?? "",
+                $process->process->remark ?? "",
+                $process->process->balance_remark ?? "",
+            ];
         }
-        return response($post,200, [
-            "Content-type"=>"application/octet-stream",
-            "Content-Disposition"=>"attachment; filename=二次加工统计记录-".date('ymdHis').'.xlsx',
-        ]);
+        return app(ExportService::class)->json($row,$list,"二次加工统计记录");
     }
 }

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

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Imports\RejectedImport;
+use App\Jobs\RejectedBillCreateInstantBill;
 use App\Logistic;
 use App\Owner;
 use App\QualityLabel;
@@ -307,6 +308,7 @@ class RejectedController extends Controller
             if (!$re){
                 return ['success'=>'false','fail_info'=>"数据 {$rejected['id']} 更新失败"];
             }
+            dispatch(new RejectedBillCreateInstantBill($rejected));
         });
         app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true'];

+ 45 - 461
app/Http/Controllers/TestController.php

@@ -25,6 +25,7 @@ use App\Exceptions\ErrorException;
 use App\Events\CancelOrder;
 use App\Events\SendEmailEvent;
 use App\Exceptions\Exception;
+use App\Http\Controllers\api\thirdPart\haiq\PickStationController;
 use App\Http\Requests\ForeignHaiRobotic_taskUpdateRequest;
 use App\Http\Requests\TestAaRequest;
 use App\Imports\OrderTrackingImport;
@@ -60,6 +61,7 @@ use App\Owner;
 use App\OwnerFeeDetail;
 use App\OwnerFeeDetailLogistic;
 use App\OwnerPriceExpress;
+use App\OwnerPriceExpressProvince;
 use App\OwnerPriceOperation;
 use App\OwnerPriceOperationItem;
 use App\OwnerReport;
@@ -157,53 +159,27 @@ class TestController extends Controller
         return call_user_func([$this, $method], $request);
     }
 
-    public function bindOrder()
+    public function test()
     {
-        ini_set('max_execution_time', 2500);
-        ini_set('memory_limit', '1526M');
-        $models = Waybill::query()->whereNotNull("wms_bill_number")->whereNotIn("status", ['已完结', '无模型'])->get();
-        foreach ($models as $model) {
-            $order = Order::query()->where("code", $model->wms_bill_number)->first();
-            if ($order) $model->update(["order_id" => $order->id]);
-        }
-    }
-
-    public function tt1()
-    {
-//        $response = Http::post('https://was.baoshi56.com/api/thirdPart/haiq/pickStation/processed');
-        $a=Http::post(config('api.haiq.storage.moveBin'), [
-  "taskMode"=> 2,
-  "bins"=> [
-    [
-        "taskCode"=> 6,
-      "binCode"=> "H01-001-3",
-      "fromLocCode"=> "",
-      "toLocCode"=> ""
-    ]
-  ],
-  "groupCode"=> 'g'.microtime(true),
-  "priority"=> 10,
-  "sequenceFlag"=> 1
-]);
-        dd($a);
+        return view("test");
     }
     public function assignBatch(){
         $batches = collect([
-  [
-    "id"=> 87255,
-    "code"=> "W210312000317",
-    "status"=> "\u672a\u5904\u7406",
-    "type"=> null,
-    "wms_type"=> "09.[BAOSHI]\u622a\u5355\u6ce2\u6b21\u3010\u65e0\u5907\u6ce8\u3011",
-    "wms_status"=> "\u90e8\u5206\u6536\u8d27",
-    "wms_created_at"=> "0000-00-00 00=>00=>00",
-    "created_at"=> "2021-03-12T09=>10=>44.000000Z",
-    "updated_at"=> "2021-03-12T09=>10=>44.000000Z",
-    "remark"=> null,
-    "owner_id"=> "42",
-    "station_task_batch"=> null
-  ]
-]);
+            [
+                "id"=> 87255,
+                "code"=> "W210312000317",
+                "status"=> "\u672a\u5904\u7406",
+                "type"=> null,
+                "wms_type"=> "09.[BAOSHI]\u622a\u5355\u6ce2\u6b21\u3010\u65e0\u5907\u6ce8\u3011",
+                "wms_status"=> "\u90e8\u5206\u6536\u8d27",
+                "wms_created_at"=> "0000-00-00 00=>00=>00",
+                "created_at"=> "2021-03-12T09=>10=>44.000000Z",
+                "updated_at"=> "2021-03-12T09=>10=>44.000000Z",
+                "remark"=> null,
+                "owner_id"=> "42",
+                "station_task_batch"=> null
+            ]
+        ]);
         $batches=Batch::query()->where('id',data_get($batches,'*.id'))->get();
         app('BatchService')->assignTasks($batches);
     }
@@ -231,110 +207,6 @@ class TestController extends Controller
         ];*/
     }
 
-    public function syncWeight()
-    {
-        $pack = OrderPackageCountingRecord::query()->get();
-        foreach ($pack as $p) {
-            $yesterday = $p->targeted_at;
-            Cache::pull("weight." . $yesterday);
-            OrderPackageCountingRecord::query()->where("targeted_at", $yesterday)->delete();
-            $sql = <<<sql
-SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,
-SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
-COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id WHERE orders.wms_status != '订单取消'
-AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date
-sql;
-            $result = DB::selectOne(DB::raw($sql));
-            if (!$result) $obj = [
-                "targeted_at" => $yesterday,
-                "un_weigh_count" => 0,
-                "total_count" => 0
-            ]; else $obj = [
-                "targeted_at" => $result->date,
-                "un_weigh_count" => $result->count,
-                "total_count" => $result->total,
-            ];
-            /** @var \stdClass $model */
-            $model = OrderPackageCountingRecord::query()->create($obj);
-            Cache::put("weight." . $yesterday, [
-                "date" => $yesterday,
-                "total" => $model->total_count,
-                "count" => $model->un_weigh_count,
-                "value" => $model->total_count ? intval(($model->un_weigh_count / $model->total_count) * 100) : 0
-            ]);
-        }
-    }
-
-    public function sync()
-    {
-        ini_set('max_execution_time', 2500);
-        ini_set('memory_limit', '1526M');
-        foreach (Batch::query()->with("orders")->where("created_at", ">", "2021-01-20 15:00:00")->get() as $batch) {
-            $order = [];
-            $map = [];
-            foreach ($batch->orders as $o) {
-                $order[] = $o->code;
-                $map[$o->code] = $o->id;
-            }
-            $sql = <<<sql
-SELECT ORDERNO,WAVENO,SEQNO,EDITTIME FROM DOC_WAVE_DETAILS WHERE WAVENO = ? AND ORDERNO IN (''
-sql;
-            foreach ($order as $o) {
-                $sql .= ",'" . $o . "'";
-            }
-            $sql .= ")";
-            $re = DB::connection("oracle")->select(DB::raw($sql), [$batch->code]);
-            foreach ($re as $r) {
-                OrderBin::query()->firstOrCreate([
-                    'order_id' => $map[$r->orderno],
-                    'number' => $r->seqno,
-                ]);
-            }
-        }
-    }
-
-    public function mergeCarrier()
-    {
-        $carriers = Carrier::query()->get();
-        $logistics = [];
-        $map = [];
-        foreach ($carriers as $carrier) {
-            $map[$carrier->name] = $carrier->id;
-            $lo = Logistic::query()->where("name", $carrier->name)->first();
-            if ($lo) {
-                if ($lo->type == '快递') {
-//                    $lo->update(["type"=>"全部"]);$lo->save();
-                }
-                continue;
-            };
-            $logistics[] = [
-                "name" => $carrier->name,
-                'mobile' => $carrier->mobile,
-                'delivery_fee' => $carrier->delivery_fee,
-                'remark' => $carrier->remark,
-                "type" => "物流"
-            ];
-        }
-        Logistic::query()->insert($logistics);
-        $ls = Logistic::query()->where("type", "物流")->get();
-        $result = [];
-        foreach ($ls as $l) {
-            if (isset($map[$l->name])) $result[$map[$l->name]] = $l->id;
-        }
-        LogService::log(__METHOD__, "同步承运商", json_encode($result));
-        foreach ($result as $tag => $val) {
-            Waybill::query()->where("logistic_id", $tag)->update([
-                "logistic_id" => $val
-            ]);
-            WaybillPriceModel::query()->where("logistic_id", $tag)->update([
-                "logistic_id" => $val
-            ]);
-            DB::table("logistic_user")->where("logistic_id", $tag)->update([
-                "logistic_id" => $val
-            ]);
-        }
-    }
-
     public function updateLaborRemark()
     {
         $laborReports = LaborReport::query()->with(['remarks' => function ($query) {
@@ -385,11 +257,6 @@ sql;
         dd($uploaded . '/' . $count);
     }
 
-    function tlog(Request $request)
-    {
-        app('LogService')->log(__METHOD__, 'cczdelme' . __FUNCTION__, json_encode($request->all()), null);
-    }
-
     function setCache(Request $request)
     {
         $today = now();
@@ -403,22 +270,34 @@ sql;
         return "cacheing get:'$cache'<script>document.write('<br>localStorage:'+localStorage.getItem('storedTest'))</script>";
     }
 
-    function t1(Request $request)
+    function hProcessed(Request $request)
+    {
+        app('ForeignHaiRoboticsService')->markBinProcessed(
+            '1',
+            'IDE0005680',
+            true,
+            "2021-56-24 05-03-15",
+            '',
+            true
+        );
+    }
+    function hBatch(Request $request)
     {
         $a=[
-            new Batch([
-                "id"=> 89906,
-                "code"=> "W210322000262",
-                "status"=> "\u5904\u7406\u4e2d",
-                "type"=> null,
-                "wms_type"=> "09.[BAOSHI]\u622a\u5355\u6ce2\u6b21\u3010\u65e0\u5907\u6ce8\u3011",
-                "wms_status"=> "\u90e8\u5206\u6536\u8d27",
-                "wms_created_at"=> "0000-00-00 00:00:00",
-                "created_at"=> "2021-03-22T10:35:44.000000Z",
-                "updated_at"=> "2021-03-22T10:35:46.000000Z",
-                "remark"=> null,
-                "owner_id"=> "42"
-            ])
+            new Batch(
+                [
+                    "id"=> 91045,
+                    "code"=> "W210325000388",
+                    "status"=> "\u672a\u5904\u7406",
+                    "type"=> null,
+                    "wms_type"=> "09.[BAOSHI]\u622a\u5355\u6ce2\u6b21\u3010\u65e0\u5907\u6ce8\u3011",
+                    "wms_status"=> "\u90e8\u5206\u6536\u8d27",
+                    "wms_created_at"=> "0000-00-00 00:00:00",
+                    "created_at"=> "2021-03-25T10:58:46.000000Z",
+                    "updated_at"=> "2021-03-25T10:58:46.000000Z",
+                    "remark"=> null,
+                    "owner_id"=> "42"
+                ]            )
         ];
         app('BatchService')->assignTasks($a);
         dd($a);
@@ -597,12 +476,6 @@ sql;
         return "OK";
     }
 
-    public function tNull()
-    {
-        User::query()->get()->toArray();
-        User::query()->get()->toJson();
-    }
-
     public function deletePackageAuthority()
     {
         $authorities = Authority::where('name', 'like', '%包裹信息%')->get();
@@ -610,240 +483,6 @@ sql;
             $authority->delete();
         });
     }
-
-    function test()
-    {
-        $ids = [];
-        $logs = Log::query()->select('description')->where('type', '同步时WMS中未找到这些订单')->get();
-        foreach ($logs as $log) {
-            $arr = [];
-            eval("\$arr = " . $log->description . '; ');
-            if (count($arr) < 1) continue;
-            $ids = array_merge($ids, $arr);
-        }
-        $ids = array_unique($ids);
-        $error = [];
-        foreach ($ids as $id) {
-            $package = Package::query()->find($id);
-            /** @var OrderPackageService */
-            $orderPackage = app('OrderPackageService')->firstOrCreate($package->logistic_number,
-                ['batch_number' => $package->batch_number,
-                    'batch_rule' => $package->batch_rule,
-                    'bulk' => $package->bulk,
-                    'weight' => $package->weight,
-                    'length' => $package->length,
-                    'width' => $package->width,
-                    'height' => $package->height,
-                    'paper_box_id' => $package->paper_box_id,
-                    'measuring_machine_id' => $package->measuring_machine_id,
-                    'weighed_at' => $package->weighed_at,
-                    'status' => $package->status]);
-            if (!$orderPackage) array_push($error, $package->id);
-        }
-        if (count($error) > 0) app('LogService')->log(__METHOD__, "同步时WMS中未找到这些订单_two", json_encode($error));
-    }
-
-    public function test5()
-    {
-        ini_set('max_execution_time', 2500);
-        ini_set('memory_limit', '1526M');
-        //清理冗余条码
-//        $this->cleanBarcode();
-
-        while (true) {
-            $toDay = Carbon::now();
-            $skus = DB::select(DB::raw('select sku from commodities group by sku,owner_id having count(*)>1 limit 500 '));
-            $skus = array_column($skus, 'sku');
-
-            $commodities = Commodity::query()->with('barcodes')->whereNotNull('owner_id')->whereIn('sku', $skus)->get();
-
-
-            if (count($commodities) < 1) return "SUCCESS";
-            $commodityMap = [];
-            $commodityDel = [];
-            $commodityTag = [];
-            $commodityBar = [];
-            $createBarcodes = [];
-            $logs = [];
-            foreach ($commodities as $commodity) {
-                if ($commodityMap[$commodity->sku . '_' . $commodity->owner_id] ?? false) {
-                    $codes = $commodity->barcodes ? array_column($commodity->barcodes->toArray(), 'code') : [];
-                    $logs[] = [
-                        'id' => $commodity->id,
-                        'sku' => $commodity->sku,
-                        'owner_id' => $commodity->owner_id,
-                        'code' => $codes,
-                    ];
-                    $commodityDel[] = $commodity->id;
-                    $commodityTag[$commodity->id] = $commodityMap[$commodity->sku . '_' . $commodity->owner_id];
-
-                    $arr = array_diff($codes, $commodityBar[$commodity->sku . '_' . $commodity->owner_id]);
-                    foreach ($arr as $code) {
-                        if (!$code) continue;
-                        $createBarcodes[] = [
-                            'code' => $code,
-                            'commodity_id' => $commodityMap[$commodity->sku . '_' . $commodity->owner_id],
-                            'created_at' => $toDay,
-                        ];
-                    }
-                } else {
-                    $commodityMap[$commodity->sku . '_' . $commodity->owner_id] = $commodity->id;
-                    $commodityBar[$commodity->sku . '_' . $commodity->owner_id] = $commodity->barcodes ? array_column($commodity->barcodes->toArray(), 'code') : [];
-                }
-            }
-            dd($commodityMap, $commodityDel, $commodityTag);
-            app('LogService')->log(__METHOD__, '清理商品', json_encode($logs, JSON_UNESCAPED_UNICODE));
-            app('LogService')->log(__METHOD__, '重新分配商品', json_encode($commodityTag, JSON_UNESCAPED_UNICODE));
-
-            app('InventoryAccountMissionService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新库存盘点任务
-            app('InventoryCompareService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新库存对比
-            app('InventoryDailyLogService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新库存每日记录
-            app('ProcessesContentService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新二次加工内容单
-            app('StoreCheckingReceiveItemService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新入库盘收一体
-            app('OrderPackageCommoditiesService')->batchUpdateItself('commodity_id', $commodityTag);//批量更新订单商品
-
-            app('LogService')->log(__METHOD__, '删除商品与对应条码', json_encode($commodityDel, JSON_UNESCAPED_UNICODE));
-            CommodityBarcode::query()->whereIn('commodity_id', $commodityDel)->delete();
-            Commodity::destroy($commodityDel);
-        }
-    }
-
-    private function cleanBarcode()
-    {
-
-        $logCommodityBarcodes = CommodityBarcode::query()->where('code', "")->get();
-        if (count($logCommodityBarcodes) > 0) app('LogService')->log(__METHOD__, "纠正商品-删除空条码", json_encode($logCommodityBarcodes, JSON_UNESCAPED_UNICODE));
-
-        CommodityBarcode::query()->where('code', "")->delete();
-        $barcodes = DB::select(DB::raw('select * from commodity_barcodes c
-where (c.code,c.commodity_id) in (select code,commodity_id from commodity_barcodes group by code,commodity_id having count(*) > 1) order by commodity_id'));
-        $barcodeMap = [];
-        $barcodeDelete = [];
-        foreach ($barcodes as $barcode) {
-            if (isset($barcodeMap[$barcode->code . '_' . $barcode->commodity_id])) $barcodeDelete[] = $barcode->id;
-            else $barcodeMap[$barcode->code . '_' . $barcode->commodity_id] = $barcode->id;
-        }
-
-        $logCommodityBarcodes = CommodityBarcode::query()->whereIn('id', $barcodeDelete)->get();
-        if (count($logCommodityBarcodes) > 0) app('LogService')->log(__METHOD__, "纠正商品-删除重复条码", json_encode($logCommodityBarcodes, JSON_UNESCAPED_UNICODE));
-
-        CommodityBarcode::destroy($barcodeDelete);
-    }
-
-    private function multiCodes()
-    {
-
-        $barcode = 'BG10B1014C002100';
-        $commodity = Commodity::whereHas('barcodes', function (Builder $query) use ($barcode) {
-            $query->where('code', $barcode);
-        })->where('owner_id', 4)->first();
-        $codes = $commodity->barcodes->map(function ($barcode) {
-            return $barcode->code ?? '';
-        });
-        foreach ($codes as $code) {
-            $commodity = Commodity::whereHas('barcodes', function (Builder $query) use ($barcode) {
-                $query->where('code', $barcode);
-            })->where('owner_id', 4)->get();
-            dump($commodity);
-        }
-        die();
-        $commodityBuilder = Commodity::query();
-        $commodityBuilder->where('owner_id', 4)->first();
-        $commodityBuilder->whereHas('barcodes', function (Builder $query) use ($barcode, $codes) {
-            foreach ($codes as $code) {
-                $query->orWhere('code', $code);
-            }
-        });
-        dd($commodity, $codes, $commodityBuilder->get());
-    }
-
-    public function correctCommodity()
-    {
-        ini_set('max_execution_time', 2500);
-        ini_set('memory_limit', '1526M');
-        //清理冗余条码
-        //$this->cleanBarcode();
-
-        //获取重复条码
-        $commodities = DB::select(DB::raw('select commodities.name,commodities.sku,commodities.owner_id,commodity_barcodes.id as barcode_id,commodity_barcodes.code as barcode_code,commodity_barcodes.commodity_id from commodities LEFT JOIN commodity_barcodes on commodities.id = commodity_barcodes.commodity_id
-where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owner_id,commodity_barcodes.code from commodities LEFT JOIN commodity_barcodes on commodities.id = commodity_barcodes.commodity_id group by commodities.owner_id,commodity_barcodes.code having count(*) > 1) order by commodities.owner_id,commodity_barcodes.code'));
-
-        //对比map池
-        $commodityMap = [];
-        //需要删除项
-        $commodityDelete = [];
-        foreach ($commodities as $index => $commodity) {
-            $commodity->barcode_code = strtolower(trim($commodity->barcode_code));
-            //货主+条码 为唯一key值 设想正常数据下同货主不应该有同条码
-            $key = $commodity->owner_id . '_' . $commodity->barcode_code;
-            //使用map池对比为重复数据
-            if (isset($commodityMap[$key])) {
-                //获取下标指针指向的源数据
-                $c = $commodities[$commodityMap[$key]];
-                //源数据不符合规范,当前数据替换掉它
-                if (($c->sku == null || $c->sku == "") && ($commodity->sku != null && $commodity->sku != "")) {
-                    $commodityDelete[] = $commodityMap[$key];
-                    $commodityMap[$key] = $index;
-                } else {
-                    //当前数据比源数据更符合预期,替换掉
-                    if (($c->sku == $commodity->sku) && (strlen($c->name) < strlen($commodity->name))) {
-                        $commodityDelete[] = $commodityMap[$key];
-                        $commodityMap[$key] = $index;
-                    } else {
-                        //扔进处理池
-                        $commodityDelete[] = $index;
-                    }
-                }
-                //第一次出现的新数据,val为下标,当作指针指向源数据
-            } else $commodityMap[$key] = $index;
-        }
-        $createBarcodes = []; //批量生成条码
-        $deleteCommodities = []; //批量删除商品及商品条码
-
-        $updateCommodities = [];
-        foreach ($commodityDelete as $index) {
-            //获取到被处理数据 与 目标数据
-            $del = $commodities[$index];
-            $target = $commodities[$commodityMap[$del->owner_id . '_' . $del->barcode_code]];
-
-            //记录ID删除商品与条码
-            $deleteCommodities[] = $del->commodity_id;
-
-            //有效条码合并
-            $barcodes = DB::select(DB::raw("select * from
-            (select * from commodity_barcodes where commodity_id = " . $del->commodity_id . ")a
-            where (select count(1) as num from commodity_barcodes b
-            where commodity_id = " . $target->commodity_id . " and b.code = a.code) = 0"));
-            if (count($barcodes) > 0) {
-                foreach ($barcodes as $barcode) {
-                    $createBarcodes[] = ['code' => $barcode->code, 'commodity_id' => $target->commodity_id];
-                }
-            }
-            $updateCommodities[$del->commodity_id] = $target->commodity_id;
-        }
-        if (count($updateCommodities) > 0) {
-            app('InventoryAccountMissionService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新库存盘点任务
-            app('InventoryCompareService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新库存对比
-            app('InventoryDailyLogService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新库存每日记录
-            app('ProcessesContentService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新二次加工内容单
-            app('StoreCheckingReceiveItemService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新入库盘收一体
-            app('OrderPackageCommoditiesService')->batchUpdateItself('commodity_id', $updateCommodities);//批量更新订单商品
-        }
-
-        if (count($createBarcodes) > 0) app('LogService')->log(__METHOD__, "纠正商品-录入合并条码", json_encode(data_get($createBarcodes, '*.id'), JSON_UNESCAPED_UNICODE));
-
-        CommodityBarcode::query()->insert($createBarcodes);
-        $logCommodityBarcodes = CommodityBarcode::query()->whereIn('commodity_id', $deleteCommodities)->get();
-        if (count($logCommodityBarcodes) > 0) app('LogService')->log(__METHOD__, "纠正商品-删除无用商品条码", json_encode(data_get($logCommodityBarcodes, '*.id'), JSON_UNESCAPED_UNICODE));
-
-        CommodityBarcode::query()->whereIn('commodity_id', $deleteCommodities)->delete();
-
-//        $logCommodities = Commodity::query()->whereIn('id',$deleteCommodities)->get();
-        if (count($deleteCommodities) > 0) app('LogService')->log(__METHOD__, "纠正商品-删除无用商品", json_encode($deleteCommodities, JSON_UNESCAPED_UNICODE));
-
-        Commodity::destroy($deleteCommodities);
-    }
-
     /*1*/
     function socket(Request $request)
     {/**/
@@ -929,16 +568,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 //        ]))->save();
     }
 
-    public function usage()
-    {
-        dd(Request::all());
-    }
-
-    public function relating()
-    {
-        dd(OrderIssue::query()->where('id', 182)->paginate()->total());
-    }
-
 
     public function changeOrder()
     {
@@ -969,13 +598,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 //      orderService  getCreateOrderModelsByWMSOrderHeaders
     }
 
-
-
-    public function view()
-    {
-        return view('test');
-    }
-
     public function cleanOrderRepeat()
     {
 
@@ -1224,44 +846,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         if (count($updateParams) > 0) app(BatchUpdateService::class)->batchUpdate('store_items', $updateParams);
     }
 
-    function testUpdateStores()
-    {
-        $stores = Store::query()->where('stored_method', '快速入库')->get();
-        $updated_at = Carbon::now()->toDateTimeString();
-        $updateParams = [[
-            'id', 'is_fast_stored', 'updated_at'
-        ]];
-        foreach ($stores as $store) {
-            if ($store->stored_method != '快速入库') continue;
-            $updateParams[] = [
-                'id' => $store->id,
-                'is_fast_stored' => '快速入库',
-                'updated_at' => $updated_at,
-            ];
-        }
-        if (count($updateParams) > 1) app(BatchUpdateService::class)->batchUpdate('stores', $updateParams);
-    }
-
-    public function testSyncAsn()
-    {
-//        dump('hendle...');
-        dump((string)Carbon::now());
-//        dump(memory_get_usage() / 1024 / 1024);
-        $task = new WasSyncWmsAsnInformation();
-        $task->handle();
-        dump((string)Carbon::now());
-//        dump('hendle...end');
-//        dump(memory_get_usage() / 1024 / 1024);
-//        dump(memory_get_peak_usage() / 1024 / 1024);
-//        return view('test');
-    }
-
-    public function editOrderSyncAt()
-    {
-        ValueStore::query()->where('name', 'order_last_created_sync_at')->update(['value' => '2020-12-22 09:00:00']);
-        ValueStore::query()->where('name', 'order_last_updated_sync_at')->update(['value' => '2020-12-22 09:00:00']);
-    }
-
     public function syncOrderTrackingTask()
     {
         $service = new OrderTrackingService();

+ 6 - 2
app/Http/Controllers/api/thirdPart/goodscan/PackageController.php

@@ -5,10 +5,12 @@ namespace App\Http\Controllers\api\thirdPart\goodscan;
 
 use App\Events\WeighedEvent;
 use App\Http\Controllers\LogisticNumberFeatureController;
+use App\Jobs\WeightUpdateInstantBill;
 use App\MeasuringMachine;
 use App\OracleDOCOrderHeader;
 use App\Order;
 use App\OrderPackage;
+use App\Services\LogService;
 use App\Services\OrderService;
 use App\Waybill;
 use Carbon\Carbon;
@@ -19,12 +21,12 @@ class PackageController
 {
     public function new_(Request $request)
     {
+        app('LogService')->log(__METHOD__,'GoodScan weightApi add'.__FUNCTION__,json_encode($request->getContent()));
         $requestInput = [];
         foreach ($request->input() as $key=>$item) {
             $requestInput[strtolower($key)] = $item;
         }
 
-        app('LogService')->log(__METHOD__,'GoodScan weightApi add'.__FUNCTION__,json_encode($request->getContent()));
         $errors = $this->validatorWeight($requestInput)->errors(); // 参数校验
         $weight = $requestInput['weight']??'';
         if($weight == '-9.9'){   // 称重异常校验
@@ -68,8 +70,10 @@ class PackageController
             Waybill::setWeightByOrderCode($orderPackage->order->code,$orderPackage->weight);
         }
         event(new WeighedEvent($orderPackage));
+        dispatch(new WeightUpdateInstantBill($orderPackage));
         $response=["code"=>0,'error'=>'upload success'];
-        app('LogService')->log(__METHOD__,__FUNCTION__,"下发写入包裹成功:".json_encode($request->getContent()).'||'.json_encode($response),null);
+        app('LogService')->log(__METHOD__,__FUNCTION__,"异方下发写入包裹成功:".json_encode($request->getContent()).'||'.json_encode($response),null);
+
         return json_encode($response,JSON_UNESCAPED_UNICODE);
     }
 

+ 6 - 1
app/Http/Controllers/api/thirdPart/haiq/PickStationController.php

@@ -8,6 +8,7 @@ namespace App\Http\Controllers\api\thirdPart\haiq;
 
 use App\Http\Requests\ForeignHaiRobotic_processedRequest;
 use App\Services\ForeignHaiRoboticsService;
+use App\Services\LogService;
 
 class PickStationController
 {
@@ -20,6 +21,8 @@ class PickStationController
 
     public function processed(ForeignHaiRobotic_processedRequest $request): array
     {
+        LogService::log('海柔请求','processed1',
+            json_encode($request->all()));
         $failed=
             ($processedResult=
                 $this->service->markBinProcessed(
@@ -33,9 +36,11 @@ class PickStationController
 
         $result = ["code" => 200, "data" => json_encode($request->all())];
         if($failed){
-            $result["code"] = 500;
+            $result["code"] = 400;
             $result["errMsg"] = $processedResult;
         }
+        LogService::log('海柔请求','processed2',
+            json_encode($result));
         return $result;
     }
 

+ 22 - 9
app/Http/Controllers/api/thirdPart/haiq/StorageController.php

@@ -6,6 +6,7 @@ namespace App\Http\Controllers\api\thirdPart\haiq;
 
 use App\Http\Requests\ForeignHaiRobotic_taskUpdateRequest;
 use App\Services\ForeignHaiRoboticsService;
+use App\Services\LogService;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Http;
 use Ramsey\Uuid\Uuid;
@@ -42,20 +43,20 @@ class StorageController
             "taskMode"      => 1,
             "bins"=>[[
                 "taskCode"  =>'t'.microtime(true),
-                "binCode"   => "IDE0000130",
+                "binCode"   => "IDE0005682",
                 "fromLocCode" => "BIN-IN1",
-                "toLocCode" => "BIN-OUT1",
+                "toLocCode" => "",
             ],],
             "groupCode"     => 'g'.microtime(true),
             "priority"      => 20,
             "sequenceFlag"  => 1,
         ]];
         $this->post2 = [[
-            "taskMode"      => 1,
+            "taskMode"      => 2,
             "bins"=>[[
                 "taskCode"  =>'t'.microtime(true),
-                "binCode"   => "IDE0004975",
-                "fromLocCode" => "BIN-IN1",
+                "binCode"   => "IDE0005714",
+                "fromLocCode" => "",
                 "toLocCode" => "BIN-OUT1",
             ],],
             "groupCode"     => 'g'.microtime(true),
@@ -113,10 +114,16 @@ class StorageController
             "bins"=>[
                 [
                 "taskCode"  =>'t'.Uuid::uuid4(),
-                "binCode"   => "IDE0015711",
-                "fromLocCode" => "HAIB2-03-03", //B1是面对架货右手,从右往左数列,第三个数字从下往上数行
+                "binCode"   => "IDE0005711",
+                "fromLocCode" => "HAIB1-01-02", //B1是面对架货右手,从右往左数列,第三个数字从下往上数行
                 "toLocCode" => "",
-            ]
+            ],
+                [
+                "taskCode"  =>'t'.Uuid::uuid4(),
+                "binCode"   => "IDE0005680",
+                "fromLocCode" => "HAIB1-02-02", //B1是面对架货右手,从右往左数列,第三个数字从下往上数行
+                "toLocCode" => "",
+            ],
 //                ,[
 //                "taskCode"  =>'t'.Uuid::uuid4(),
 //                "binCode"   => "IDE0005680",
@@ -246,6 +253,9 @@ class StorageController
     public function moveBinOut(Request $request){
         return $this->relocate($request,$this->post);
     }
+    public function postBin1(Request $request){
+        return $this->relocate($request,$this->post);
+    }
     public function postBin2(Request $request){
         return $this->relocate($request,$this->post2);
     }
@@ -269,10 +279,13 @@ class StorageController
         return $this->light($request,$this->lightOff);
     }
     public function taskUpdate(ForeignHaiRobotic_taskUpdateRequest $request){
+        LogService::log('海柔请求','taskUpdate',
+            json_encode($request->all()));
         try{
+            $stationTaskMaterialBox_id = explode('_',$request['taskCode'])[0];
             $this->service->taskUpdate(
 //                $request['groupCode']
-                $request['taskCode']
+                $stationTaskMaterialBox_id
                 ,$request['updateEventType']
                 ,$request['status']
                 ,$request['binCode']

+ 0 - 1
app/Http/Controllers/api/thirdPart/jianshang/RejectedController.php

@@ -9,7 +9,6 @@ use App\Logistic;
 use App\QualityLabel;
 use App\RejectedBill;
 use App\RejectedBillItem;
-use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;

+ 5 - 7
app/Http/Controllers/api/thirdPart/weight/PackageController.php

@@ -298,8 +298,10 @@ class PackageController extends Controller
         }
         if(!empty($package->order))
             Waybill::setWeightByOrderCode($package->order->code,$package->weight);
-        event(new WeighedEvent($package));
-        dispatch(new WeightUpdateInstantBill($package));
+        if ($package){
+            event(new WeighedEvent($package));
+            dispatch(new WeightUpdateInstantBill($package));
+        }
         $response=["msg"=>"保存成功",
             "code"=>200,
             "data"=>true,
@@ -316,11 +318,7 @@ class PackageController extends Controller
 
     public function validatorWeight(array $request){
         $validator=Validator::make($request,[
-            'id'=>['nullable','max:30',/*function ($attribute, $value, $fail) {
-                $measuringMachine=MeasuringMachine::where('code',$value)->first();
-                if (!$measuringMachine) {
-                    $fail($attribute.' 设备未录入在系统中!');
-            }}*/],
+            'id'=>['nullable','max:30'],
             'barcode'=>['required','max:191'],
             'weight'=>['required','numeric','min:0'],
             'length'=>['nullable','numeric','min:0'],

+ 3 - 1
app/Http/Requests/ForeignHaiRobotic_taskUpdateRequest.php

@@ -30,7 +30,7 @@ class ForeignHaiRobotic_taskUpdateRequest extends FormRequest
            'taskCode'=>'required',
            'updateEventType'=>'required|in:0,1',
            'status'=>'required|in:0,1',
-           'binCode'=>'required',
+//           'binCode'=>'required',
            'kubotId'=>'required',
            'description'=>'nullable',
         ];
@@ -38,6 +38,8 @@ class ForeignHaiRobotic_taskUpdateRequest extends FormRequest
     public function withValidator(Validator $validator)
     {
         $validator->after(function (Validator $validator) {
+            LogService::log('海柔请求','valideate',
+                json_encode($validator));
             if($validator->errors()->isNotEmpty()){
                 $validator->errors()->add('code','422');
                 $validator->errors()->add('errMsg', json_encode($validator->errors()->messages(),JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));

+ 46 - 81
app/Imports/ExpressImport.php

@@ -2,22 +2,20 @@
 
 namespace App\Imports;
 
+use App\Components\AsyncResponse;
 use App\OwnerPriceExpress;
 use App\OwnerPriceExpressProvince;
 use App\Province;
 use App\Services\common\BatchUpdateService;
 use App\Services\LogService;
-use Illuminate\Support\Collection;
-use Illuminate\Support\Facades\Cache;
-use Maatwebsite\Excel\Concerns\ToCollection;
-use Maatwebsite\Excel\Concerns\WithHeadingRow;
+use Maatwebsite\Excel\Concerns\ToArray;
 use Maatwebsite\Excel\Concerns\WithMultipleSheets;
-use Maatwebsite\Excel\Imports\HeadingRowFormatter;
 
-HeadingRowFormatter::default('none');
-class ExpressImport implements ToCollection,WithHeadingRow,WithMultipleSheets
+class ExpressImport implements WithMultipleSheets,ToArray
 {
 
+    use AsyncResponse;
+
     public function sheets(): array
     {
         return [
@@ -25,83 +23,49 @@ class ExpressImport implements ToCollection,WithHeadingRow,WithMultipleSheets
         ];
     }
 
+    /** @var OwnerPriceExpress|\stdClass $express */
     protected $express;
+    /** @var array $errors */
+    private $errors = [];
+
     public function __construct(OwnerPriceExpress $express = null)
     {
         $this->express = $express;
     }
 
-    /**
-    * @param Collection $collection
-    * @return bool
-    */
-    public function collection(Collection $collection)
+    public function array(array $array)
     {
-        $row = $collection->first();
-        $header = [
-            "省","首重价格","续重价格"
-        ];
-        foreach ($header as $str){
-            if (!isset($row[$str])){
-                Cache::put("express",["success"=>false, "data"=>"表头不存在“".$str."”"],86400);
-                return false;
-            }
-        }
+        if (isset($array[0][0]) && $array[0][0]=='省')array_splice($array,0,1);
+        $array = $this->filter($array);
+        if (!$this->express)$this->success(["data"=>$array,"errors"=>$this->errors]);
 
-        //省份map
-        $map = [];
-        $provinces = Province::query()->get();
-        foreach ($provinces as $province){
-            $map[mb_substr($province->name,0,2)] = $province->id;
-        }
-
-        if (!$this->express){
-            return $this->readonly($collection,$map);
-        }
+        if (!$this->express->operation)$this->express = app("OwnerPriceExpressService")->copy($this->express);
 
-        if (!$this->express->operation){
-            $this->express = app("OwnerPriceExpressService")->copy($this->express);
-        }
         //已存在的计费
         $existDetails = [];
         foreach ($this->express->details as $detail){
             $existDetails[$detail->province_id] = $detail->id;
         }
-
         //导入的数据整理,存在更新
         $id = $this->express->id;
-        $errors = [];
         $insert = [];
         $update = [["id","initial_weight_price","additional_weight_price","updated_at"]];
         $date = date('Y-m-d H:i:s');
-        foreach ($collection as $index => $item){
-            $province = mb_substr($item["省"],0,2);
-            if (!isset($map[$province])){
-                $errors[] = "第“".($index+2)."”行未知省份";
-                continue;
-            }
-            if (!is_numeric($item["首重价格"]) || $item["首重价格"] <= 0){
-                $errors[] = "第“".($index+2)."”行非法首重价格";
-                continue;
-            }
-            if (!is_numeric($item["续重价格"]) || $item["续重价格"] <= 0){
-                $errors[] = "第“".($index+2)."”行非法续重价格";
-                continue;
-            }
-            if (isset($existDetails[$map[$province]])){
+        foreach ($array as $index => $item){
+            if (isset($existDetails[$item[0]])){
                 $update[] = [
-                    "id" => $existDetails[$map[$province]],
-                    "initial_weight_price" => $item["首重价格"],
-                    "additional_weight_price" => $item["续重价格"],
+                    "id" => $existDetails[$item[0]],
+                    "initial_weight_price" => $item[1],
+                    "additional_weight_price" => $item[2],
                     "updated_at" => $date,
                 ];
                 continue;
             }
             $insert[] = [
                 "owner_price_express_id" => $id,
-                "province_id" => $map[$province],
-                "initial_weight_price" => $item["首重价格"],
-                "additional_weight_price" => $item["续重价格"],
+                "province_id" => $item[0],
+                "initial_weight_price" => $item[1],
+                "additional_weight_price" => $item[2],
                 "created_at" => $date,
             ];
         }
@@ -115,35 +79,36 @@ class ExpressImport implements ToCollection,WithHeadingRow,WithMultipleSheets
         }
 
         $this->express->load("details.province");
-        Cache::put("express",["success"=>true,"data"=>$this->express->details,"errors"=>$errors],86400);
-        return true;
+        $this->success(["data"=>$this->express->details,"errors"=>$this->errors]);
     }
 
-    private function readonly(Collection $collection, array $map)
+    public function filter(array $array)
     {
-        $errors = [];
-        $data = [];
-        foreach ($collection as $index => $item){
-            $province = mb_substr($item["省"],0,2);
+        $result = [];
+        //省份map
+        $map = [];
+        $provinces = Province::query()->get();
+        foreach ($provinces as $province){
+            $map[mb_substr($province->name,0,2)] = $province->id;
+        }
+        foreach ($array as &$item){
+            if (count($item)<3 || (!$item[0] && !$item[1] && !$item[2]))continue;
+            $province = mb_substr($item[0],0,2);
             if (!isset($map[$province])){
-                $errors[] = "第“".($index+2)."”行未知省份";
-                continue;
-            }
-            if (!is_numeric($item["首重价格"]) || $item["首重价格"] <= 0){
-                $errors[] = "第“".($index+2)."”行非法首重价格";
-                continue;
-            }
-            if (!is_numeric($item["续重价格"]) || $item["续重价格"] <= 0){
-                $errors[] = "第“".($index+2)."”行非法续重价格";
+                $this->errors[] = "“".$province."”此省份未被记录";
                 continue;
+            }else $item[0] = $map[$province];
+            $sign = false;
+            for($i=1;$i<count($item);$i++){
+                if (($item[$i] && !is_numeric($item[$i]))||$item[$i]<=0){
+                    $this->errors[] = "“".$province."”非法价格";
+                    $sign = true;
+                    break;
+                }
             }
-            $data[] = [
-                "province_id" => $map[$province],
-                "initial_weight_price" => $item["首重价格"],
-                "additional_weight_price" => $item["续重价格"],
-            ];
+            if ($sign)continue;
+            $result[] = $item;
         }
-        Cache::put("express",["success"=>true,"data"=>$data,"errors"=>$errors],86400);
-        return true;
+        return $result;
     }
 }

+ 1 - 1
app/Imports/UpdatePickZone.php

@@ -181,7 +181,7 @@ class UpdatePickZone implements ToCollection,WithHeadingRow
                 ];
             }
         }
-        Cache::put("commodityAssign",["success"=>true,"data"=>$models,"errors"=>$errors]);
+        Cache::put("commodityAssign",["success"=>true,"data"=>$models,"errors"=>array_unique($errors)]);
     }
 
     private function matchingMax($lots, $amount)

+ 0 - 2
app/Imports/WaybillPriceModelsImport.php

@@ -4,9 +4,7 @@ namespace App\Imports;
 
 use App\Logistic;
 use App\WaybillPriceModel;
-use App\City;
 use App\Events\WaybillPriceModelEvent;
-use App\Province;
 use App\Unit;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;

+ 43 - 0
app/Jobs/RejectedBillCreateInstantBill.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace App\Jobs;
+
+use App\RejectedBill;
+use App\Services\LogService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class RejectedBillCreateInstantBill implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $rejected;
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     *
+     * @param RejectedBill $rejectedBill
+     */
+    public function __construct(RejectedBill $rejectedBill)
+    {
+        $this->rejected = $rejectedBill;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        try{
+            app("RejectedBillService")->buildInstantBill($this->rejected);
+        }catch(\Exception $exception){
+            LogService::log(__CLASS__,"退货单建立即时账单",$exception->getMessage()." | ".json_encode($this->rejected));
+        }
+    }
+}

+ 1 - 1
app/Jobs/WeightUpdateInstantBill.php

@@ -12,7 +12,7 @@ use Illuminate\Queue\SerializesModels;
 
 class WeightUpdateInstantBill implements ShouldQueue
 {
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+    use SerializesModels;
 
     /** @var \stdClass  */
     protected $package;

+ 0 - 12
app/Order.php

@@ -4,14 +4,11 @@ namespace App;
 
 use App\Traits\ModelTimeFormat;
 use Illuminate\Database\Eloquent\Model;
-
 use App\Traits\ModelLogChanging;
 
 class Order extends Model
 {
     use ModelLogChanging;
-
-    //
     use ModelTimeFormat;
 
     protected $fillable = [
@@ -44,11 +41,6 @@ class Order extends Model
      * 仓库                 warehouse_id=>DOC_ORDER_HEADER['WAREHOUSEID']
      */
 
-    protected $appends = [
-//        'logisticNumbers',
-//        'amount',
-//        'commodityPackages'
-    ];
     public function cancel(){
         $this['status'] = '取消';
         $this->update();
@@ -88,10 +80,6 @@ class Order extends Model
     }
     public function bin(){
         return $this->hasOne('App\OrderBin','order_id','id');
-//        $bin= $this->hasOne('App\OrderBin','order_id','id');
-//        if($bin->count()>0)return $bin;
-//        $this->batch()->first()->assignBins();
-//        return $this->hasOne('App\OrderBin','order_id','id');
     }
     public function batch(){
         return $this->belongsTo('App\Batch', 'batch_id','id');

+ 6 - 0
app/OwnerPriceExpress.php

@@ -17,6 +17,12 @@ class OwnerPriceExpress extends Model
         "additional_weight",//续重
         "operation",        //操作
         "target_id",        //目标ID
+        "amount_interval",  //数量区间
+        "weight_interval",  //重量区间
+    ];
+    protected $casts = [
+        "amount_interval" => "array",
+        "weight_interval" => "array"
     ];
 
     public function owners()

+ 4 - 0
app/OwnerPriceExpressProvince.php

@@ -16,6 +16,10 @@ class OwnerPriceExpressProvince extends Model
         "initial_weight_price",     //初始单价
         "additional_weight_price",  //续重单价
     ];
+    protected $casts = [
+        "initial_weight_price" => "array",
+        "additional_weight_price" => "array"
+    ];
 
     public function ownerPriceExpress()
     {   //快递计费

+ 4 - 0
app/OwnerPriceOperation.php

@@ -22,10 +22,14 @@ class OwnerPriceOperation extends Model
         "total_discount_price",//按单计价减免
         "operation",        //操作
         "target_id",        //目标ID
+        "type_mark",        //类型标记
     ];
     public static $features = null;
     public static $columnMapping = null;
 
+    const MARK=[
+        0 => "退货单",
+    ];
     public function items()
     {   //出库规则
         return $this->hasMany(OwnerPriceOperationItem::class,"owner_price_operation_id","id");

+ 5 - 0
app/OwnerStoragePriceModel.php

@@ -22,6 +22,11 @@ class OwnerStoragePriceModel extends Model
         "time_unit_id",     //计时单位ID
         "operation",        //操作
         "target_id",        //目标ID
+        "amount_interval",  //数量区间
+    ];
+    protected $casts = [
+        "amount_interval" => "array",
+        "price" => "array"
     ];
 
     public function unit()

+ 1 - 1
app/Process.php

@@ -16,7 +16,7 @@ class Process extends Model
     use ModelTimeFormat;
     use SoftDeletes;
     protected $fillable=[
-        'code','owner_id','process_method_id','unit_price','status','remark','balance_remark','amount','completed_amount','created_at','updated_at','deleted_at'
+        'code','owner_id','process_method_id','unit_price','status','remark','balance_remark','amount','completed_amount','created_at','updated_at','deleted_at',"designate_id"
     ];
     protected $appends=[
         'owner_name','process_method_name',

+ 1 - 5
app/ProcessStatistic.php

@@ -28,10 +28,6 @@ class ProcessStatistic extends Model
 
     public function operatorLog(){
         return $this->hasOne('App\OperatorLog','operator_logable_id','process_id')
-            ->where('operator_logable_type','processes');
+            ->where('operator_logable_type','processes')->where("operation",'接单');
     }
-    /*public function operatorLogSubmit(){
-        return $this->hasOne('App\OperatorLog','operator_logable_id','process_id')
-            ->where('operator_logable_type','processes')->where('operation','质量验收');
-    }*/
 }

+ 17 - 4
app/Services/CommodityService.php

@@ -138,6 +138,8 @@ class CommodityService
             "width" => $wmsCommodity->skuwidth,
             "height" => $wmsCommodity->skuhigh,
             "volumn" => $wmsCommodity->cube,
+            "pack_spec"  => $wmsCommodity->packid == 'STANDARD' ? 0 : explode("/",$wmsCommodity->packid)[1],
+            "remark" => $wmsCommodity->notes,
         ]);
         if ($wmsCommodity->alternate_sku1) app('CommodityBarcodeService')->first([
             'commodity_id' => $commodity->id,
@@ -233,7 +235,9 @@ class CommodityService
                 'length' => $bas_sku->skulength,
                 'width' => $bas_sku->skuwidth,
                 'height' => $bas_sku->skuhigh,
-                'volumn' => $bas_sku->cube
+                'volumn' => $bas_sku->cube,
+                "pack_spec"  => $bas_sku->packid == 'STANDARD' ? 0 : explode("/",$bas_sku->packid)[1],
+                "remark" => $bas_sku->notes,
             ];
         }
         if (count($insert_params) > 0) {
@@ -324,7 +328,9 @@ class CommodityService
                 'length' => $bas_sku->skulength,
                 'width' => $bas_sku->skuwidth,
                 'height' => $bas_sku->skuhigh,
-                'volumn' => $bas_sku->cube
+                'volumn' => $bas_sku->cube,
+                "pack_spec"  => $bas_sku->packid == 'STANDARD' ? 0 : explode("/",$bas_sku->packid)[1],
+                "remark" => $bas_sku->notes,
             ];
         });
         if (count($inner_params) > 0) {
@@ -388,7 +394,9 @@ class CommodityService
             'length' => $basSku['skulength'],
             'width' => $basSku['skuwidth'],
             'height' => $basSku['skuhigh'],
-            'volumn' => $basSku['cube']
+            'volumn' => $basSku['cube'],
+            "pack_spec"  => $basSku['packid'] == 'STANDARD' ? 0 : explode("/",$basSku['packid'])[1],
+            "remark" => $basSku['notes'],
         ];
     }
 
@@ -544,6 +552,7 @@ class CommodityService
                     'created_at' => $basSku->addtime,
                     'updated_at' => $basSku->edittime,
                     'pack_spec' => $basSku->packid == 'STANDARD' ? 0 : explode("/", $basSku->packid)[1],
+                    'remark' => $basSku->notes,
                 ];
             });
             return $map;
@@ -591,7 +600,7 @@ class CommodityService
             ->get();
         $commodities_map = $dataHandlerService->dataHeader(['owner_id', 'sku'], $commodities);
         $updateParams = [[
-            'id', 'name', 'sku', 'owner_id', 'length', 'width', 'height', 'volumn', 'pack_spec', 'updated_at', 'created_at'
+            'id', 'name', 'sku', 'owner_id', 'length', 'width', 'height', 'volumn', 'pack_spec', 'remark', 'updated_at', 'created_at'
         ]];
         $insert_params = [];
         $updateBasSkus=collect();
@@ -608,6 +617,7 @@ class CommodityService
                         'width' => $basSku->skuwidth,
                         'height' => $basSku->skuhigh,
                         'volumn' => $basSku->cube,
+                        'remark' => $basSku->notes,
                         'created_at' => $basSku->addtime,
                         'updated_at' => $basSku->edittime,
                         'pack_spec' => $basSku->packid == 'STANDARD' ? 0 : explode("/", $basSku->packid)[1],
@@ -620,6 +630,7 @@ class CommodityService
                   $commodity->width != $basSku->skuwidth ||
                   $commodity->height != $basSku->skuhigh ||
                   $commodity->volumn != $basSku->cube ||
+                  $commodity->remark != $basSku->notes ||
                   $commodity->created_at != $basSku->addtime ||
                   $commodity->pack_spec != $basSku->pickid ||
                   $commodity->updated_at != $basSku->edittime
@@ -634,6 +645,7 @@ class CommodityService
                     'width' => $basSku->skuwidth,
                     'height' => $basSku->skuhigh,
                     'volumn' => $basSku->cube,
+                    'remark' => $basSku->notes,
                     'created_at' => $basSku->addtime,
                     'updated_at' => $basSku->edittime,
                     'pack_spec' => $basSku->packid == 'STANDARD' ? 0 : explode("/", $basSku->packid)[1],
@@ -871,6 +883,7 @@ class CommodityService
                 'width' => $basSku->skuwidth,
                 'height' => $basSku->skuhigh,
                 'volumn' => $basSku->cube,
+                'remark' => $basSku->notes,
                 'created_at' => $basSku->addtime,
                 'updated_at' => $basSku->edittime,
                 'pack_spec' => $basSku->packid == 'STANDARD' ? 0 : explode("/", $basSku->packid)[1],

+ 70 - 78
app/Services/FeatureService.php

@@ -73,7 +73,7 @@ class FeatureService
             foreach ($m as $string){
                 if (is_numeric($string)){//填入特征信息
                     if (isset($featureMap[$string])){
-                        $arr["type"] = Feature::type[$features[$featureMap[$string]]->type];
+                        $arr["type"] = Feature::TYPE[$features[$featureMap[$string]]->type];
                         $arr["id"] = $features[$featureMap[$string]]->id;
                         $arr["logic"] = $features[$featureMap[$string]]->logic;
                         $arr["describe"] = $features[$featureMap[$string]]->describe;
@@ -128,7 +128,7 @@ class FeatureService
         $map = [];
         foreach ($features as &$feature){
             if (!$feature["type"] || !$feature["logic"] || !$feature["describe"])continue;
-            $typeMap = array_flip(Feature::type);
+            $typeMap = array_flip(Feature::TYPE);
             $f = Feature::query()->firstOrCreate([
                 "type"=>$typeMap[$feature["type"]],  //特征类型
                 "logic"=>$feature["logic"],  //特征逻辑
@@ -163,7 +163,7 @@ class FeatureService
         preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
         foreach ($result[0] as &$str){
             if (is_numeric($str) && isset($features[$str])){
-                $column = Feature::type[$features[$str]["type"]];
+                $column = Feature::TYPE[$features[$str]["type"]];
                 $logic = $features[$str]["logic"];
                 $describe = $features[$str]["describe"];
                 if ($columnMapping){
@@ -209,106 +209,96 @@ class FeatureService
     }
 
     /**
-     *  匹配特征
-     *      $vale : 特征简述 例: "1&2|(3|4)"
-     *      $columnMapping : 列映射 例:["商品名称"=>"commodity_name"]
-     *      $matchObject : 被匹配对象,必须存在列映射所指定字段 例:["commodity_name"=>"衣服"]
-     *      $isMultiMatching 是否开启多重匹配 开启将匹配对象视为二维数组深层寻找商品(入库需要)
-     *      bool true匹配成功 false匹配失败
+     *  匹配特征 true匹配成功 false匹配失败
      *
      * @param string $value
      * @param array $columnMapping
      * @param array $matchObject
-     * @param bool $isMultiMatching
+     *
      * @return bool
      */
-    public function matchFeature($value, $columnMapping, $matchObject, $isMultiMatching = false) :bool
+    public function matchFeature($value, $columnMapping, $matchObject) :bool
     {
         if (!$value)return true;
 
         preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
         if (implode("",$result[0]) != $value)return false;
 
-        $features = app(CacheService::class)->getOrExecute($value,function ()use($value){
+        foreach ($result[0] as &$str) {
+            switch ($str){
+                case "&":
+                    $str = "&&";
+                    break;
+                case "|":
+                    $str = "||";
+                    break;
+                default:
+                    $str = $this->match($str, $value, $columnMapping, $matchObject);
+            }
+        }
+        $is = implode("",$result[0]);
+        return eval("return $is;");
+    }
+
+    /**
+     * 匹配实例
+     *
+     * @param string|integer $id
+     * @param string $value
+     * @param array $columnMapping
+     * @param array $matchObject
+     *
+     * @return string
+     */
+    private function match($id, $value, $columnMapping, $matchObject):string
+    {
+        if (!is_numeric($id))return $id; //非特征返回本身
+
+        $features = app(CacheService::class)->getOrExecute("feature:".$value,function ()use($value){
             preg_match_all('/\d+/',$value,$ids);
             if ($ids[0])$fs = Feature::query()->whereIn("id",$ids[0])->get();
             else return false;
             $features = [];
-            foreach ($fs as $f){
-                $features[$f->id] = $f;
-            }
+            foreach ($fs as $f)$features[$f->id] = $f;
             return $features;
         });
 
-        foreach ($result[0] as &$str) {
-            if (is_numeric($str) && isset($features[$str])) {
-                $column = Feature::type[$features[$str]["type"]];
-                $logic = $features[$str]["logic"];
-                $describe = $features[$str]["describe"];
-                if (($column == '商品名称' || $column == '商品备注' || $column == '长') && $isMultiMatching){
-                    $packageColumn = $columnMapping["packages"] ?? "packages";
-                    $packages = $matchObject[$packageColumn] ?? [];
-                    $str = $this->multiMatching($packages,$logic,$describe,$columnMapping[$column] ?? '');
-                    continue;
-                }
-                $value = isset($columnMapping[$column]) ? ($matchObject[$columnMapping[$column]] ?? '') : '';
-                switch ($logic) {
-                    case "包含":
-                        $str = mb_strpos($value,$describe) === false ? 'false' : 'true';
-                        break;
-                    case "不包含":
-                        $str = mb_strpos($value,$describe) === false ? 'true' : 'false';
-                        break;
-                    case "等于":
-                        $str = $value == $describe ? 'true' : 'false';
-                        break;
-                    case "小于":
-                        $str = $value < $describe ? 'true' : 'false';
-                        break;
-                    case "大于":
-                        $str = $value > $describe ? 'true' : 'false';
-                        break;
-                    case "小于等于":
-                        $str = $value <= $describe ? 'true' : 'false';
-                        break;
-                    case "大于等于":
-                        $str = $value >= $describe ? 'true' : 'false';
-                        break;
-                    default:
-                        $str = 'false';
-                }
-                continue;
-            }
-            if ($str == "&") {
-                $str = '&&';
-                continue;
-            }
-            if ($str == "|") {
-                $str = '||';
-            }
-        }
-        $is = implode("",$result[0]);
-        return eval("return $is;");
+        if (!isset($features[$id]))return 'false'; //特征不存在返回 false
+        if (!($columnMapping[$features[$id]["type"]] ?? false))return 'false';
+        return $this->getMatchBool($features[$id],$matchObject,explode(".",$columnMapping[$features[$id]["type"]]));
     }
 
     /**
-     * 多重子项匹配
+     * 获取匹配结果
      *
-     * @param array $packages
-     * @param string $logic
-     * @param string $describe
-     * @param string $column
-     * @return string           //"true" || "false"
+     * @param array $feature
+     * @param array|\stdClass $matchObject
+     * @param array $column
+     *
+     * @return string
      */
-    private function multiMatching($packages, $logic, $describe, $column):string
+    private function getMatchBool($feature, $matchObject, $column)
     {
-        if(!$column)return 'false';
-
-        foreach ($packages as $package){
-            $value = $package[$column] ?? '';
+        /*递归: 1.列数组为空 对象不存在列 返回false
+                2.为数组时,递归数组内对象,任意一个符合返回true,全部不符合返回false
+                3.为正常值时,进入核心匹配,必然返回一个值
+                4.为对象时,向下递归,splice列数组
+        */
+        if (!$column)return 'false';
+        if (!isset($matchObject[$column[0]]))return 'false';
+        if (is_array($matchObject)){
+            foreach ($matchObject as $object){
+                if ($this->getMatchBool($feature,$object,$column) === 'true')return 'true';
+            }
+            return 'false';
+        }
+        $value = $matchObject[$column[0]];
+        if (count($column)==1 && (is_string($value) || is_numeric($value) || is_null($value))){
+            $logic = $feature["logic"];
+            $describe = $feature["describe"];
             switch ($logic) {
                 case "包含":
-                    if (mb_strpos($value,$describe)!==false)return 'true';
+                    if (mb_strpos($value,$describe) !== false)return 'true';
                     break;
                 case "不包含":
                     if (mb_strpos($value,$describe) === false)return 'true';
@@ -329,8 +319,10 @@ class FeatureService
                     if ($value >= $describe)return 'true';
                     break;
             }
-        }
-        return "false";
+            return 'false';
+        };
+        array_splice($column,0,1);
+        return $this->getMatchBool($feature, $value, $column);
     }
 
 }

+ 63 - 23
app/Services/ForeignHaiRoboticsService.php

@@ -5,11 +5,8 @@ namespace App\Services;
 
 
 use App\Exceptions\ErrorException;
-use App\Exceptions\PanicException;
 use App\MaterialBox;
 use App\StationTaskMaterialBox;
-use Illuminate\Http\Request;
-use Illuminate\Http\Response;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Http;
 use App\Traits\ServiceAppAop;
@@ -70,19 +67,19 @@ class ForeignHaiRoboticsService
         })();
         $bins=$taskMaterialBoxes->map(function (StationTaskMaterialBox $taskMaterialBox)use($timestampSuffix,$fromLocation,$toLocation){
             return [
-                "taskCode"  =>$taskMaterialBox['id'],
+                "taskCode"  =>$taskMaterialBox['id'].'_'.$timestampSuffix,
                 "binCode"   => $taskMaterialBox['materialBox']['code'],
                 "fromLocCode" => $fromLocation??'',
                 "toLocCode" => $toLocation??'',
             ];
         });
-        return [
+        return [[
             "taskMode"  =>$taskMode,
             "bins"=>$bins,
-            "groupCode"=>$groupId.$timestampSuffix,
+            "groupCode"=>$groupId.'_'.$timestampSuffix,
             "priority"=>$priority,
             "sequenceFlag"=>$isSequenced,
-        ];
+        ]];
     }
 
     public function fetchGroup($toLocation, Collection $taskMaterialBoxes, $groupIdPrefix=''): bool
@@ -113,20 +110,31 @@ class ForeignHaiRoboticsService
         $is_in_plan
     ): bool
     {
+        LogService::log('海柔请求','markBinProcessed1.1',
+            '');
         $this->instant($this->stationService,'StationService');
         $this->instant($this->materialBoxService,'MaterialBoxService');
         $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
         $this->instant($this->stationTaskCommoditiesService,'StationTaskCommodityService');
         try{
+            LogService::log('海柔请求','markBinProcessed1.2',
+                json_encode([$binCode,$success,$exception,$is_in_plan]));
             if($failed
                 =!$success)
                 throw new ErrorException('海柔任务失败:'.$exception);
-            if($NotInPlan
-                =!$is_in_plan)
-                throw new ErrorException('海柔认为是计划外的料箱:'.$exception);
+            LogService::log('海柔请求','markBinProcessed1.3',
+                $failed);
+//            if($NotInPlan
+//                =!$is_in_plan)
+//                throw new ErrorException('海柔认为是计划外的料箱:'.$exception);
+
+            LogService::log('海柔请求','markBinProcessed1.4',
+                '$NotInPlan');
 
             $materialBox=
                 $this->materialBoxService->get(['code'=>$binCode])->first();
+            LogService::log('海柔请求','markBinProcessed1.5',
+                json_encode($materialBox));
             $stationTaskMaterialBox
                 =(function()use($materialBox){
                 return $stationTaskMaterialBox=
@@ -138,6 +146,8 @@ class ForeignHaiRoboticsService
                             ]
                         )->first();
             })();
+            LogService::log('海柔请求','markBinProcessed1.6',
+                json_encode($stationTaskMaterialBox));
             if(!$stationTaskMaterialBox){
                 throw new ErrorException('该料箱没有安排在处理队列中');
             }
@@ -146,11 +156,15 @@ class ForeignHaiRoboticsService
                 :(function(){throw new ErrorException('呼叫机器人回收U型线料箱失败');})();
             $this->stationTaskMaterialBoxService
                 ->markProcessed($stationTaskMaterialBox);
+            LogService::log('海柔请求','markBinProcessed1.7',
+                json_encode($stationTaskMaterialBox));
             $stationTaskMaterialBox_next=
                 $this->stationTaskMaterialBoxService
                     ->processNextQueued($stationTaskMaterialBox); //找到队列中下一个料箱,并标记为处理中
             $this->stationTaskCommoditiesService
                 ->markProcessed($stationTaskMaterialBox['stationTaskCommodities']);
+            LogService::log('海柔请求','markBinProcessed1.8',
+                json_encode($stationTaskMaterialBox));
             if($stationTaskMaterialBox_next)
                 $this->stationTaskCommoditiesService
                     ->markProcessing($stationTaskMaterialBox_next['stationTaskCommodities']);//因为上边商品任务被标记完成了,所以这里要将队列中找出正在处理的料箱对应的标记为“处理中”
@@ -158,7 +172,11 @@ class ForeignHaiRoboticsService
                 $this->instant($this->stationTaskService,'StationTaskService');
                 $this->stationTaskService->markProcessed($stationTaskMaterialBox['stationTask']);
             }
+            LogService::log('海柔请求','markBinProcessed1.9',
+                json_encode($stationTaskMaterialBox_next));
             $this->stationService->broadcastBinMonitor($stationTaskMaterialBox['station_id'],$stationTaskMaterialBox['stationTask']);
+            LogService::log('海柔请求','markBinProcessed1.99',
+                json_encode($stationTaskMaterialBox_next));
             return true;
         }catch (\Exception $e){
             $stationTaskMaterialBox = $stationTaskMaterialBox??$materialBox??null;
@@ -178,14 +196,20 @@ class ForeignHaiRoboticsService
 
     public function putBinToStore(?StationTaskMaterialBox $stationTaskMaterialBox): bool
     {
+        LogService::log('海柔请求','putBinToStore1',
+            '');
+        LogService::log('海柔请求','putBinToStore2',
+            json_encode($stationTaskMaterialBox));
         $this->instant($this->stationService,'StationService');
         $dataToPost=$this->makeJson_move(
             collect([$stationTaskMaterialBox]),
-            '缓存架入立架',
-            $this->stationService->getULineExit($stationTaskMaterialBox['station'])['name']??'',
+            '输送线入立架',
+            'BIN-IN1',//TODO:这里应该是动态取得,参考出立架getULineExit()方法,不然不能从站获得对应的出口,而且要改Station的child为children
             '',
             $stationTaskMaterialBox['stationTaskBatch']['id']
         );
+        LogService::log('海柔请求','putBinToStore3',
+            json_encode($dataToPost));
         return $this->controlHaiRobot($dataToPost);
     }
 
@@ -196,6 +220,13 @@ class ForeignHaiRoboticsService
         $status,            //0:任务成功1:任务失败
         $binCode
     ):bool{
+        LogService::log('海柔请求','taskUpdateIn',
+            json_encode([
+                $stationTaskMaterialBox_id,
+                $updateEventType,
+                $status,
+                $binCode
+            ]));
         $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
         try{
             if(($failed
@@ -209,19 +240,24 @@ class ForeignHaiRoboticsService
                     if($stationTaskMaterialBox['materialBox']['code']==$binCode)return $stationTaskMaterialBox;
                     return null;
                 })()){
-                throw new ErrorException('发回的料箱和任务号(ID)不匹配');
+                throw new ErrorException('发回的料箱和任务号(ID)不匹配:$stationTaskMaterialBox_id:'
+                    .$stationTaskMaterialBox_id.' $binCode:'.$binCode. ' '.
+                    StationTaskMaterialBox::query()
+                        ->where('id', $id=$stationTaskMaterialBox_id)
+                        ->get()
+                        ->toJson());
             }
             ($标记已放置在库外=
                 function()use($updateEventType,$stationTaskMaterialBox){
                     if(($isPut
-                            =$updateEventType)==0){
+                            =$updateEventType)==1){
                         $this->stationTaskMaterialBoxService->markHasTaken($stationTaskMaterialBox);
                     }
                 })();
             ($标记已入立架=
                 function()use($updateEventType,$stationTaskMaterialBox){
                     if(($isGet
-                            =$updateEventType)==1){
+                            =$updateEventType)==0){
                         $this->stationTaskMaterialBoxService->markPutStored($stationTaskMaterialBox);
                     }
                 })();
@@ -262,17 +298,21 @@ class ForeignHaiRoboticsService
      */
     public function controlHaiRobot(array $dataToPost): bool
     {
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1:'.json_encode($dataToPost));
+        LogService::log('海柔请求','runMany','波次任务分配6.r5f2c1:'.json_encode($dataToPost));
         try{
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1.51:');
+            LogService::log('海柔请求','runMany','波次任务分配6.r5f2c1.51:');
+            $a = json_encode($dataToPost);
             $response = Http::post(config('api.haiq.storage.moveBin'), $dataToPost);
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1.52:');
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1.53:'.json_encode($response));
+            if(isset($response->json()['code'])&&$response->json()['code']==500)
+                throw new ErrorException('机器人500错误:'.json_encode($response->json()));
+            $b=json_encode($response->json());
+            LogService::log('海柔请求','runMany','波次任务分配6.r5f2c1.52:');
+            LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1.53:'.json_encode($response->json()));
         }catch (\Exception $e){
-            LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c1.54:');
-            throw new ErrorException('海柔机器人任务执行失败:'.json_encode($dataToPost));
+            LogService::log('海柔请求','runMany','波次任务分配6.r5f2c1.54:'.json_encode($dataToPost).$e->getMessage());
+            throw new ErrorException('海柔机器人任务执行失败:'.json_encode($dataToPost).$e->getMessage());
         }
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c2:'.json_encode($dataToPost));
+        LogService::log('海柔请求','runMany','波次任务分配6.r5f2c2:'.json_encode($dataToPost));
         $errMsg = (function () use ($response) {
             if ($response->ok()) return '';
             $errMsg = '错误: ';
@@ -295,7 +335,7 @@ class ForeignHaiRoboticsService
                 . ' response:' . json_encode($response->headers());
             return $errMsg . $responseDetails;
         })();
-        LogService::log(__METHOD__,'runMany','波次任务分配6.r5f2c3:'.json_encode($errMsg));
+        LogService::log('海柔请求','runMany','波次任务分配6.r5f2c3:'.json_encode($errMsg));
 
         LogService::log(__METHOD__, __FUNCTION__,
             $errMsg ?? ''

+ 12 - 25
app/Services/OrderService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Feature;
 use App\Jobs\OrderCreateInstantBill;
 use App\Jobs\OrderFreeze;
 use App\Log;
@@ -1087,7 +1088,6 @@ sql
         /** @var OwnerPriceExpressService $service */
         $service = app("OwnerPriceExpressService");
         $logistic_fee = 0;
-        $commodities = [];
         $amount = 0;
         $volume = 0;
         $weight = 0;
@@ -1095,23 +1095,17 @@ sql
 
         if (!$order->logistic || $order->logistic->type == "物流")$logistic_fee = null;
 
-
-
         $items = [];
         foreach ($order->packages as &$package){
             $logistic_bill .= $package->logistic_number.",";
             $volume += $package->bulk;
             $weight += $package->weight;
 
-            // 四维转二维
             $partAmount = 0;
-            foreach($package->commodities as &$commodity){
-                $commodity["commodity_name"] = $commodity->commodity ? $commodity->commodity->name : '';
-                $commodity["sku"] = $commodity->commodity ? $commodity->commodity->sku : '';
+            foreach($package->commodities as $commodity){
                 $partAmount += $commodity->amount;
             }
             $amount += $partAmount;
-            $commodities = array_merge($commodities,$package->commodities->toArray());
 
             $provinceName = mb_substr($order->province,0,2);
             $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
@@ -1138,19 +1132,9 @@ sql
         }
         if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
 
-        $object = ["commodities"=>$commodities,
-            "logistic_name"=>($order->logistic ? $order->logistic->name : ''),
-            "shop_name"=>($order->shop ? $order->shop->name : ''),
-            "order_type"=>$order->order_type,
-            "batch_type" => $order->batch ? $order->batch->wms_type : '',
-            "owner_id"=>$order->owner_id];
-        $mapping = ["packages"=>"commodities","商品名称"=>"commodity_name",
-            "承运商"=>"logistic_name","店铺类型"=>"shop_name","订单类型"=>"order_type",
-            "波次类型"=>"batch_type"];
-
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
-        $result = $service->matching($object,$mapping,$order->owner_id,"出库");
+        $result = $service->matching($order,Feature::MAPPING["order"],$order->owner_id,"出库");
 
         $detail = app("OwnerFeeDetailService")->create([
             "owner_id"          => $order->owner_id,
@@ -1282,16 +1266,19 @@ sql
             $weight += $package->weight;
 
             $provinceName = mb_substr($order->province,0,2);
-            $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
-                return Province::query()->where("name","like",$provinceName."%")->first();
-            },86400);
-            if (!$province)$logistic_fee = null;
+            $fee = null;
+            if ($provinceName){
+                $province = app(CacheService::class)->getOrExecute("province_".$provinceName,function ()use($provinceName){
+                    return Province::query()->where("name","like",$provinceName."%")->first();
+                },86400);
+                if (!$province)$logistic_fee = null;
+                $fee = app("OwnerPriceExpressService")->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
+            }
 
-            $fee = app("OwnerPriceExpressService")->matching($package->weight, $order->owner_id, $order->logistic_id, $province->id);
             OwnerFeeDetailLogistic::query()->where("owner_fee_detail_id",$feeBill->id)->where("logistic_bill",$package->logistic_number)->update([
                 "volume"=>$package->bulk,
                 "weight"=>$package->weight,
-                "logistic_fee" => $fee>0 ? $fee : null,
+                "logistic_fee" => $fee,
             ]);
             if ($logistic_fee!==null){
                 if ($fee<0)$logistic_fee = null;

+ 25 - 3
app/Services/OwnerPriceExpressService.php

@@ -82,11 +82,15 @@ class OwnerPriceExpressService
                     unset($obj["id"]);
                 }
                 $obj["owner_price_express_id"] = $copyModel->id;
+                $obj["initial_weight_price"] = json_encode($obj["initial_weight_price"]);
+                $obj["additional_weight_price"] = json_encode($obj["additional_weight_price"]);
                 $insert[] = $obj;
             }
         }else{
             foreach ($items as $item){
                 $item["owner_price_express_id"] = $copyModel->id;
+                $item["initial_weight_price"] = json_encode($item["initial_weight_price"]);
+                $item["additional_weight_price"] = json_encode($item["additional_weight_price"]);
                 $insert[] = $item;
             }
         }
@@ -120,7 +124,7 @@ class OwnerPriceExpressService
 
     public function create(array $params)
     {
-        $params["operation"] = "U";
+        $params["operation"] = "C";
         return OwnerPriceExpress::query()->create($params);
     }
 
@@ -183,6 +187,7 @@ class OwnerPriceExpressService
 
     public function destroy($id)
     {
+        if (!$id)return 0;
         if (!is_array($id))$id = [$id];
         OwnerPriceExpressProvince::query()->whereIn("owner_price_express_id",$id)->delete();
 
@@ -254,8 +259,25 @@ sql
             $query->whereNull("operation")->orWhere("operation","");
         })->first();
         if (!$model || count($model->details)<1)return -1;
-        if ($weight <= $model->initial_weight)return $model->details[0]->initial_weight_price;
+
+        if ($model->amount_interval){
+            $total = app("OrderService")->getOrderQuantity($owner_id);//获取该货主本月C端单量
+            for ($i=count($model->amount_interval);$i<0;$i--){
+                if ($total>=$model->amount_interval[$i]){$to1 = $i;break;}
+            }
+            if (isset($to1) && isset($model->weight_interval[$to1])){
+                for ($i=count($model->weight_interval[$to1]);$i<0;$i--){
+                    if ($weight>=$model->weight_interval[$to1][$i]){$to2 = $i;break;}
+                }
+            }
+        }
+        if (!isset($to1))$to1 = 0;
+        if (!isset($to2))$to2 = 0;
+
+        $initPrice = $model->details[0]->initial_weight_price[$to1][$to2];
+        $additionalPrice = $model->details[0]->additional_weight_price[$to1][$to2];
+        if ($weight <= $model->initial_weight)return $initPrice;
         $weight -= $model->initial_weight;
-        return (ceil($weight/$model->additional_weight)*$model->details[0]->additional_weight_price)+$model->details[0]->initial_weight_price;
+        return (ceil($weight/$model->additional_weight)*$additionalPrice)+$initPrice;
     }
 }

+ 1 - 1
app/Services/OwnerPriceLogisticService.php

@@ -22,7 +22,7 @@ class OwnerPriceLogisticService
 
     public function create(array $params)
     {
-        $params["operation"] = "U";
+        $params["operation"] = "C";
         return OwnerPriceLogistic::query()->create($params);
     }
 

+ 205 - 200
app/Services/OwnerPriceOperationService.php

@@ -2,12 +2,13 @@
 
 namespace App\Services;
 
+use App\Feature;
 use App\OwnerFeeDetail;
 use App\OwnerPriceOperation;
 use App\OwnerPriceOperationItem;
 use App\Services\common\QueryService;
-use App\Unit;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\DB;
@@ -43,10 +44,10 @@ class OwnerPriceOperationService
     }
 
 
-    private function ownerGetIds(string $owner_id)
+    private function ownerGetIds(string $ownerId)
     {
-        if (!$owner_id)return [];
-        $arr = DB::select(DB::raw("SELECT owner_price_operation_id AS id FROM owner_price_operation_owner WHERE owner_id in (".$owner_id.")"));
+        if (!$ownerId)return [];
+        $arr = DB::select(DB::raw("SELECT owner_price_operation_id AS id FROM owner_price_operation_owner WHERE owner_id in (".$ownerId.")"));
         return array_column($arr,"id");
     }
 
@@ -99,9 +100,16 @@ class OwnerPriceOperationService
             }
         }else{
             foreach ($items as $item){
-                $item["owner_price_operation_id"] = $copyModel->id;
-                $item["discount_price"] = implode(",",($item["discount_price"] ? $item["discount_price"] : [])) ?? null;
-                $insert[] = $item;
+                $arr = [];
+                $arr["owner_price_operation_id"] = $copyModel->id;
+                $arr["strategy"] = $item["strategy"];
+                $arr["amount"] = $item["amount"] ?? null;
+                $arr["unit_id"] = $item["unit_id"];
+                $arr["unit_price"] = $item["unit_price"];
+                $arr["feature"] = $item["feature"] ?? null;
+                $arr["priority"] = $item["priority"] ?? 0;
+                $arr["discount_price"] = isset($item["discount_price"]) ? (is_array($item["discount_price"]) ? implode(",",$item["discount_price"]) : $item["discount_price"]) : null;
+                $insert[] = $arr;
             }
         }
         if ($insert)OwnerPriceOperationItem::query()->insert($insert);
@@ -121,6 +129,8 @@ class OwnerPriceOperationService
         $result = app(QueryService::class)->priceModelAuditOrRecoverQuery($isAudit,OwnerPriceOperation::query(),$ownerId,$ids);
         if ($result["delete"])$this->destroy($result["delete"]);
         if ($result["update"])OwnerPriceOperation::query()->whereIn("id",$result["update"])->update(["operation"=>null,"target_id"=>null]);
+        if (!is_array($ownerId))$ownerId = [$ownerId];
+        foreach ($ownerId as $ow)Cache::tags("operationFeeOwner:".$ow)->flush();
     }
 
     public function destroy($id)
@@ -180,6 +190,97 @@ class OwnerPriceOperationService
         return $model->update($params);
     }
 
+    /**
+     *  获取计费模型缓存
+     *
+     * @param integer $owner
+     * @param string $type
+     * @param int|null $typeMark
+     *
+     * @return array|Collection
+     *
+     */
+    public function getOwnerPriceOperation($owner, $type, $typeMark)
+    {
+        return Cache::tags("operationFeeOwner:".$owner)->remember("operationFee:".$owner.$type.$typeMark,config("cache.expirations.rarelyChange"),
+            function ()use($owner,$type,$typeMark){
+                $query = 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");
+                }])->where("operation_type",$type)->whereHas("owners",function ($query)use($owner){
+                    /** @var Builder $query */
+                    $query->where("id",$owner);
+                })->where(function(Builder $query){
+                    $query->whereNull("operation")->orWhere("operation","");
+                })->orderByRaw("strategy desc,priority desc");
+
+                if ($typeMark!==null)$query->where("type_mark",$typeMark);
+                else $query->whereNull("type_mark");
+
+                return $query->get();
+        });
+    }
+
+    /**
+     * 获取满减信息
+     *
+     * @param null|string $discount
+     * @param integer $total
+     *
+     * @return bool|array
+     */
+    public function getDiscount($discount, $total)
+    {
+        if ($discount){
+            foreach (array_reverse(explode(",",$discount),true) as $index=>$discount){
+                if ($total >= $discount)return [$index=>$discount];
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 处理折扣单
+     *
+     * @param object $rule
+     * @param integer $owner
+     * @param bool|array $result
+     */
+    public function handleDiscount($rule, $owner, $result)
+    {
+        $sign = false;
+        //入口仅在此处存在 缓存1000s
+        $key = "pivot_".$rule->id."_".$owner;
+        $discountIndex = key($result);
+        $targetValue = $result[$discountIndex];
+        $pivot = app(CacheService::class)->getOrExecute($key,function ()use($key,$targetValue,&$sign,$rule,$owner){
+            try{
+                DB::beginTransaction();
+                //此处暂时未使用cache的互斥锁 使用sql行锁代替下 防止缓存击穿
+                $pivot = DB::selectOne(DB::raw("SELECT * FROM owner_price_operation_owner WHERE owner_price_operation_id = ? AND owner_id = ? for update"),[$rule->id,$owner]);
+                if ($pivot && (!$pivot->discount_date || substr($pivot->discount_date,0,7)!=date("Y-m") || $pivot->target_value < $targetValue)){
+                    //未被标记过处理时间或处理时间不为本月,或上次处理值过期,处理历史即时账单
+                    $sign = true;
+                }
+                if ($sign){
+                    //先标记成功 这将在后续推进历史单处理流程,防止程序在此堵塞
+                    DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
+                        [date("Y-m-d"),$targetValue,$rule->id,$owner]);
+                    $pivot->discount_date = date("Y-m-d");
+                    $pivot->target_value = $targetValue;
+                    Cache::put($key,$pivot,1000);
+                }
+                DB::commit();
+            }catch (\Exception $exception){
+                DB::rollBack();
+                LogService::log(__CLASS__,"即时账单满减处理失败",$exception->getMessage());
+            }
+            return $pivot ?? null;
+        },1000);
+        //进入历史单处理
+        if ($pivot && $sign)$this->handlePastBill($rule,$owner,$discountIndex,$pivot);
+    }
+
     /** 参数顺序: 数量 匹配对象 列映射 货主ID 单位ID 类型 SKU .
      *  匹配顺序: 类型 货主 策略 单位 特征                    ..多对多匹配规则废弃,1对1,设单位必定为件,对应规则必然只有一项存在
      *  单位匹配: 件,箱 由小到大,依次换算匹配           .
@@ -188,8 +289,10 @@ class OwnerPriceOperationService
      *
      * @param array|object $matchObject  key-val
      * @param array $columnMapping       key-val
-     * @param string $owner_id
+     * @param string $ownerId
      * @param string $type
+     * @param int|null $typeMark
+     *
      * @return double|array
      * 错误代码: -1:无匹配对象 -2:无计费模型 -3:未知单位 -4:sku为空 -5:货主未找到 -6:无箱规 -7:未匹配到计费模型
      *
@@ -200,83 +303,32 @@ class OwnerPriceOperationService
      *      增加按订单计价策略:主匹配模型增加字段量价,该字段存在时视为按单计价,价格为该值
      * 四. 2021-02-18 zzd
      *      满减多阶段匹配 满减字段由单值改为字符串多值 匹配时转数组寻找最相近
+     * 五. 2021-03-18 zzd
+     *      区分单据类型,增加字段
+     * 六. 2021-03-23 zzd
+     *      不严格区分入库出库差异 统一模型
      */
-    public function matching($matchObject, $columnMapping, $owner_id, $type = '出库')
+    public function matching($matchObject, $columnMapping, $ownerId, $type = '出库', $typeMark = null)
     {
-        $unitModels = Unit::query()->whereIn("name",["件","箱"])->get();
-        $units = [];
-        foreach ($unitModels as $unitModel)$units[$unitModel->id] = $unitModel->name;
-
-        $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");
-        }])->where("operation_type",$type)->whereHas("owners",function ($query)use($owner_id){
-                /** @var Builder $query */
-                $query->where("id",$owner_id);
-        })->where(function(Builder $query){
-            $query->whereNull("operation")->orWhere("operation","");
-        })->orderByRaw("strategy desc,priority desc")->get(); //货主下的全部规则
-
+        $units = app("UnitService")->getUnitMapping(["件","箱"]); //获取单位映射集
+        $rules = $this->getOwnerPriceOperation($ownerId,$type,$typeMark);//货主下的全部规则
         if (!$rules)return -2;  //规则不存在跳出
-
-        $total = app("OrderService")->getOrderQuantity($owner_id);//获取该货主本月C端单量
+        $total = app("OrderService")->getOrderQuantity($ownerId);//获取该货主本月C端单量
         foreach ($rules as $rule){
             if (!$rule->items)continue; //不存在子规则跳出
-            $isDiscount = false;    //是否存在满减
-            $discountIndex = 0;
-            $targetValue = 0;
-            if ($type=='出库' && $rule->discount_count){
-                foreach (array_reverse(explode(",",$rule->discount_count),true) as $index=>$discount){
-                    if ($total >= $discount){
-                        $isDiscount = true; //第一个满足满减条件
-                        $discountIndex = $index;
-                        $targetValue = $discount;
-                        break;
-                    }
-                }
-            }
-            //满减存在
-            if ($isDiscount){
-                $sign = false;
-                //入口仅在此处存在 缓存1000s
-                $key = "pivot_".$rule->id."_".$owner_id;
-                $pivot = app(CacheService::class)->getOrExecute($key,function ()use($key,$targetValue,&$sign,$rule,$owner_id){
-                    try{
-                        DB::beginTransaction();
-                        //此处暂时未使用cache的互斥锁 使用sql行锁代替下 防止缓存击穿
-                        $pivot = DB::selectOne(DB::raw("SELECT * FROM owner_price_operation_owner WHERE owner_price_operation_id = ? AND owner_id = ? for update"),[$rule->id,$owner_id]);
-                        if ($pivot && (!$pivot->discount_date || substr($pivot->discount_date,0,7)!=date("Y-m") || $pivot->target_value < $targetValue)){
-                            //未被标记过处理时间或处理时间不为本月,或上次处理值过期,处理历史即时账单
-                            $sign = true;
-                        }
-                        if ($sign){
-                            //先标记成功 这将在后续推进历史单处理流程,防止程序在此堵塞
-                            DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
-                                [date("Y-m-d"),$targetValue,$rule->id,$owner_id]);
-                            $pivot->discount_date = date("Y-m-d");
-                            $pivot->target_value = $targetValue;
-                            Cache::put($key,$pivot,1000);
-                        }
-                        DB::commit();
-                    }catch (\Exception $exception){
-                        DB::rollBack();
-                        LogService::log(__CLASS__,"即时账单满减处理失败",$exception->getMessage());
-                    }
-                    return $pivot ?? null;
-                },1000);
-                //进入历史单处理
-                if ($pivot && $sign)$this->handlePastBill($rule,$owner_id,$units,$discountIndex,$pivot);
-            }
-            if ($rule->strategy == '特征'){//特征策略匹配
-                $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);
-                if ($bool === true){
-                    if ($rule->total_price)return ["id"=>$rule->id,"money"=>$isDiscount ? explode(",",$rule->total_discount_price)[$discountIndex] : $rule->total_price]; //按单计价存在,直接返回单总价或减免总价
-                    $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false,$isDiscount,$discountIndex);
+
+            $result = $this->getDiscount($rule->discount_count,$total); //满减信息
+            if ($result)$this->handleDiscount($rule,$ownerId,$result);//满减存在
+
+            if ($rule->strategy == '特征'){
+                if (app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject)){
+                    if ($rule->total_price)return ["id"=>$rule->id,"money"=>$result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price];//按单计价存在,直接返回单总价或减免总价
+                    $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$ownerId,$result);
                     if ($money>0)return ["id"=>$rule->id,"money"=>$money];
                 };
-            }else{//默认策略匹配
-                if ($rule->total_price)return ["id"=>$rule->id,"money"=>$isDiscount ? explode(",",$rule->total_discount_price)[$discountIndex] : $rule->total_price]; //按单计价存在,直接返回单总价或减免总价
-                $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false,$isDiscount,$discountIndex);
+            }else{
+                if ($rule->total_price)return ["id"=>$rule->id,"money"=>$result ? explode(",",$rule->total_discount_price)[key($result)] : $rule->total_price]; //按单计价存在,直接返回单总价或减免总价
+                $money = $this->matchItem($rule->items,$columnMapping,$matchObject,$units,$ownerId,$result);
                 if ($money>0)return ["id"=>$rule->id,"money"=>$money];
             };
         }
@@ -287,19 +339,48 @@ class OwnerPriceOperationService
      *      不满一箱视为一箱
      *
      * @param integer $amount
-     * @param integer $owner_id
-     * @param string $sku
+     * @param integer $ownerId
+     * @param null|object $commodity
      *
      * @return int
      */
-    private function changeUnit($amount,$owner_id,$sku)
+    private function changeUnit($amount,$ownerId,$commodity)
     {
-        if (!$sku)return -4;
-        $pack = app("CommodityService")->getPack($owner_id,$sku);
+        if (!$commodity)return -4;
+        if ($commodity->pack_spec)return ceil($amount/$commodity->pack_spec);
+        $pack = app("CommodityService")->getPack($ownerId,$commodity->sku);
         if (!$pack)return -6;
         return ceil($amount/$pack);
     }
 
+    /**
+     * 重置子节点的映射对象  将无限极数组扁平化为二维 以Feature中定义的8:商品数量 key为基准
+     *
+     * @param object|array $matchObject
+     * @param array $columnMapping
+     *
+     * @return array
+     */
+    private function resetChildNodeMapping($matchObject,&$columnMapping)
+    {
+        $need = "";
+        foreach (Feature::TYPE_NODE as $index){
+            if (!$need)$need=strstr($columnMapping[$index],".",true);
+            $columnMapping[$index] = ltrim(strstr($columnMapping[$index],"."),".");
+        }
+        $nextObj = strstr($columnMapping[8],".",true);
+        $first = $matchObject[$need] ?? false;
+        if ($first && is_array($first))$first = reset($first);
+        else return $matchObject;
+        if (!$first)return $matchObject;
+        if (is_array($first[$nextObj])){
+            $result = [];
+            foreach ($matchObject[$need] as $arr)$result = array_merge($result,$arr[$nextObj]);
+            return $this->resetChildNodeMapping($result,$columnMapping);
+        }
+        return $matchObject[$need];
+    }
+
     /**
      * 匹配子策略
      *
@@ -307,108 +388,50 @@ class OwnerPriceOperationService
      * @param array $columnMapping 映射对象
      * @param array $matchObject 被匹配对象
      * @param array $units 单位集
-     * @param integer $owner_id 货主ID
-     * @param bool $isIn 是否为入库单
-     * @param bool $isDiscount 是否为满减单
-     * @param int $discountIndex 阶梯满减所处下标  满减价格此处应为 1,2,3 解析为数组后根据此下标寻找对应值
+     * @param integer $ownerId 货主ID
+     * @param bool|array $result 满减信息
      *
      * @return double
      */
-    private function matchItem($rules, $columnMapping, $matchObject, $units, $owner_id, $isIn, $isDiscount, $discountIndex)
+    private function matchItem($rules, $columnMapping, $matchObject, $units, $ownerId, $result)
     {
-        $amountColumn = $columnMapping["amount"] ?? "amount";
-        $packageColumn = $columnMapping["packages"] ?? "packages";
-        $packages = $matchObject[$packageColumn] ?? false;
-        $commodityColumn = $columnMapping["商品名称"] ?? 'commodity';
-        if (!$packages)return -1;
+        /** @var Collection $matchObject */
+        $matchObject = $this->resetChildNodeMapping($matchObject->toArray(),$columnMapping);
+        if (!$matchObject)return -1;
 
         $unitName = "";
         foreach ($rules as $rule){
-            if ($isDiscount)$rule->unit_price = explode(",",$rule->discount_price)[$discountIndex]; //满足满减条件,单价调整为满减单价
-            switch ($rule->strategy){
-                case "特征":
-                    $inMoney = 0;
-                    foreach ($packages as &$package){
-                        if ($package["price"] ?? false)continue;
-                        if (!app("FeatureService")->matchFeature($rule->feature,["商品名称"=>$commodityColumn],$package)) continue;
-
-                        if (!$unitName)$unitName = $units[$rule->unit_id];
-                        else {
-                            if ($unitName != $units[$rule->unit_id]) return -3;
-                        }
-                        $package["price"] = $rule->unit_price;
-                        if (!isset($units[$rule->unit_id]))return -3;
-                        if ($units[$rule->unit_id] == '箱'){ //为箱时同步商品寻找箱规
-                            $sumTemp = 0;
-                            $packageColumn = $columnMapping["packages"] ?? "packages";
-                            foreach ($matchObject[$packageColumn] as $commodity){
-                                $sumTemp += $this->changeUnit($package[$amountColumn],$owner_id,$commodity["sku"]);
-                            }
-                            $amount = $sumTemp;
-                            if ($amount<0)return $amount;
-                            $package[$amountColumn] = $amount;
-                        }
-                        $inMoney += $package[$amountColumn] * $package["price"];
-                    }
-                    if ($isIn && $inMoney !== 0){
-                        return $inMoney;
-                    }
-                    break;
-                case "默认":
-                    $inMoney = 0;
-                    foreach ($packages as &$package){
-                        if ($package["price"] ?? false)continue; //校验是否已匹配到
-                        if (!$unitName)$unitName = $units[$rule->unit_id]; //校验单位是否一致
-                        else {
-                            if ($unitName != $units[$rule->unit_id])
-                                return -3;
-                        }
-
-                        $package["price"] = $rule->unit_price;
-                        if (!isset($units[$rule->unit_id]))return -3;
-                        if ($units[$rule->unit_id] == '箱'){ //为箱时同步商品寻找箱规
-                            $sumTemp = 0;
-                            $packageColumn = $columnMapping["packages"] ?? "packages";
-                            foreach ($matchObject[$packageColumn] as $commodity){
-                                $sumTemp += $this->changeUnit($package[$amountColumn],$owner_id,$commodity["sku"]);
-                            }
-                            $amount = $sumTemp;
-                            if ($amount<0)return $amount;
-                            $package[$amountColumn] = $amount;
-                        }
-                        $inMoney += $package[$amountColumn] * $package["price"];
-                    }
-                    if ($isIn && $inMoney !== 0){
-                        return $inMoney;
-                    }
-                    break;
-                default:
-                    if ($isIn)break;    //入库不计算起步
-
-                    if ($rule->amount){ //起步数+起步费
-                        if ($unitName && $unitName != $units[$rule->unit_id])return -3; //校验单位是否一致
-
-                        $money = $rule->unit_price;
-                        $startNumber = $rule->amount;
-                        $packages = $this->settingCount($packages,$amountColumn,$startNumber);
-                        if ($packages){
-                            foreach ($packages as $package){
-                                $money += $package[$amountColumn] * $package["price"];
-                            }
-                        }
-                    }else{//单起步费
-                        $money = 0;
-                        if ($packages){
-                            foreach ($packages as $package){
-                                $money += $package[$amountColumn] * $package["price"];
-                            }
-                        }
-                        if ($money<$rule->unit_price)$money = $rule->unit_price;
-                    }
-                    return $money;
+            if ($result)$rule->unit_price = explode(",",$rule->discount_price)[key($result)]; //满足满减条件,单价调整为满减单价
+
+            if ($rule->strategy=='起步'){
+                if ($unitName && $unitName != $units[$rule->unit_id])return -3; //校验单位是否一致
+                $money = $rule->unit_price;
+                $startNumber = $rule->amount;
+                if ($startNumber)$matchObject=$this->settingCount($matchObject,$columnMapping[8],$startNumber);
+                if ($matchObject)foreach ($matchObject as $package)$money += $package[$columnMapping[8]] * $package["price"];
+                if (!$startNumber && $money<$rule->unit_price)$money = $rule->unit_price;
+                return $money;
+            }
+            foreach ($matchObject as &$package){
+                if ($package["price"] ?? false)continue;
+                if (!isset($units[$rule->unit_id]))return -3;
+                if (!$unitName)$unitName = $units[$rule->unit_id];
+                else if ($unitName != $units[$rule->unit_id]) return -3;
+                if ($rule->strategy=='特征')if (!app("FeatureService")->matchFeature($rule->feature,$columnMapping,$package)) continue;
+                $package["price"] = $rule->unit_price;
             }
+            if ($units[$rule->unit_id] == '箱'){ //为箱时同步商品寻找箱规
+                $amount = 0;
+                foreach ($matchObject as $commodity)$amount += $this->changeUnit($commodity[$columnMapping[8]],$ownerId,$commodity[$columnMapping[9]]);
+                if ($amount<0)return $amount;
+                $package[$columnMapping[8]] = $amount;
+            }
+        }
+        if ($matchObject){
+            $money = 0;
+            foreach ($matchObject as $package)if ($package["price"])$money += $package[$columnMapping[8]] * $package["price"];
         }
-        return -7;
+        return $money ?? -7;
     }
     //递归式重新设置数量
     private function settingCount($packages,$amountColumn,$startNumber)
@@ -439,44 +462,26 @@ class OwnerPriceOperationService
      * 处理历史账单
      *
      * @param object $rule
-     * @param int $owner_id
-     * @param array $units
+     * @param int $owner
      * @param int $discountIndex
      * @param object $pivot
      */
-    public function handlePastBill($rule, $owner_id, $units, $discountIndex, $pivot)
+    public function handlePastBill($rule, $owner, $discountIndex, $pivot)
     {
         try{
             DB::beginTransaction();
             $month = date("Y-m");
             $day = date("t",strtotime($month));
+            $units = app("UnitService")->getUnitMapping(["件","箱"]); //获取单位映射集
             foreach (OwnerFeeDetail::query()->with(["order.logistic","order.shop","order.packages.commodities.commodity","order.batch"])
-                         ->where("owner_id",$owner_id)
+                         ->where("owner_id",$owner)
                          ->whereBetween("worked_at",[$month."-01",$month."-".$day])->get() as $detail){
                 $order = $detail->order;
 
                 $logistic_fee = 0;
-                $commodities = [];
-                foreach ($order->packages as &$package){
-                    // 四维转二维
-                    foreach($package->commodities as &$commodity){
-                        $commodity["commodity_name"] = $commodity->commodity ? $commodity->commodity->name : '';
-                        $commodity["sku"] = $commodity->commodity ? $commodity->commodity->sku : '';
-                    }
-                    $commodities = array_merge($commodities,$package->commodities->toArray());
-                }
                 if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
 
-                $object = ["commodities"=>$commodities,
-                    "logistic_name"=>($order->logistic ? $order->logistic->name : ''),
-                    "shop_name"=>($order->shop ? $order->shop->name : ''),
-                    "order_type"=>$order->order_type,
-                    "batch_type" => $order->batch ? $order->batch->wms_type : '',
-                    "owner_id"=>$order->owner_id];
-                $mapping = ["packages"=>"commodities","商品名称"=>"commodity_name",
-                    "承运商"=>"logistic_name", "店铺类型"=>"shop_name",
-                    "订单类型"=>"order_type","波次类型"=>"batch_type"];
-                $money = $this->matchItem($rule->items,$mapping,$object,$units,$owner_id,false,true,$discountIndex);
+                $money = $this->matchItem($rule->items,Feature::MAPPING["order"],$order,$units,$owner,[$discountIndex=>true]);
                 if ($money>0)$detail->update(["work_fee"=>$money]);
                 else LogService::log(__CLASS__,"处理历史即时账单时发生匹配错误","账单主键:".$detail->id."; 错误代码".$money);
             };
@@ -485,7 +490,7 @@ class OwnerPriceOperationService
             DB::rollBack();
             //处理失败回退标记
             DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
-                [$pivot->discount_date,$pivot->target_value,$rule->id,$owner_id]);
+                [$pivot->discount_date,$pivot->target_value,$rule->id,$owner]);
             LogService::log(__CLASS__,"处理历史即时账单时发生系统错误","计费模型主键:".$rule->id."; 错误信息".$e->getMessage());
         }
     }

+ 8 - 1
app/Services/OwnerStoragePriceModelService.php

@@ -147,6 +147,13 @@ class OwnerStoragePriceModelService
                 }
                 break;
         }
-        return $area*$model->price;
+        $index = 0;
+        if ($model->amount_interval){
+            $total = app("OrderService")->getOrderQuantity($owner_id);
+            for ($i=count($model->amount_interval);$i<0;$i--){
+                if ($total>=$model->amount_interval[$i])$model->price = $index;
+            }
+        }
+        return $area*$model->price[$index];
     }
 }

+ 1 - 1
app/Services/ProcessService.php

@@ -18,7 +18,7 @@ class ProcessService
      * @return Builder
      */
     private function conditionQuery(array $params){
-        $processes=Process::filterAuthorities()->with(['owner','processMethod','tutorials'=>function($query){$query->with('owner');},'signs','operatorLogs'=>function($query){$query->with('user');},
+        $processes=Process::filterAuthorities()->with(['owner','processMethod','tutorials.owner','signs','operatorLogs.user',
             'signUnitPrice','processesContents'=>function($query){
             return $query->with(['signCommodityName','signCommoditySku','signCommodityBarcode','commodity'=>function($query){
                 return $query->with('barcodes');

+ 4 - 10
app/Services/ProcessStatisticService.php

@@ -13,7 +13,7 @@ class ProcessStatisticService
     use ServiceAppAop;
     protected $modelClass=ProcessStatistic::class;
     private function conditionQuery(array $params){
-        $query = ProcessStatistic::with(['process'/*,'operatorLogSubmit'*/])->orderBy('process_statistics.process_id','DESC')
+        $query = ProcessStatistic::with(['process.owner','operatorLog.user'])->orderBy('process_statistics.process_id','DESC')
             ->has('process');
         if ($params["owner_id"] ?? false){
             $owner_id=$params["owner_id"];
@@ -56,15 +56,9 @@ class ProcessStatisticService
         return $this->conditionQuery($params)->paginate($params["paginate"] ?? 50);
     }
 
-    public function getSql(array $params){
-        return $this->conditionQuery($params)->selectRaw('process_statistics.*')
-            ->leftJoin('processes','process_statistics.process_id','processes.id')
-                ->selectRaw('processes.created_at process_created_at,processes.code process_code,processes.unit_price process_unit_price,processes.amount process_amount,processes.completed_amount process_completed_amount,processes.status process_status,processes.remark process_remark,processes.balance_remark process_balance_remark')
-            ->leftJoin('owners','processes.owner_id','owners.id')
-                ->selectRaw('owners.name owner_name')
-            ->leftJoin('process_methods','processes.process_method_id','process_methods.id')
-                ->selectRaw('process_methods.name process_method_name')
-            ->sql();
+    public function get(array $params)
+    {
+        return $this->conditionQuery($params)->get();
     }
 
 }

+ 37 - 0
app/Services/RejectedBillService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Feature;
 use App\OracleActAllocationDetails;
 use App\OracleDOCASNHeader;
 use App\OracleDOCOrderHeader;
@@ -9,10 +10,12 @@ use App\Order;
 use App\OrderIssue;
 use App\OrderIssueRejectedBill;
 use App\OrderPackage;
+use App\OwnerFeeDetail;
 use App\Owner;
 use App\RejectedBill;
 use App\Services\common\BatchUpdateService;
 use App\Services\common\DataHandlerService;
+use App\Store;
 use App\StoreRejected;
 use Carbon\Carbon;
 use App\Traits\ServiceAppAop;
@@ -330,4 +333,38 @@ class RejectedBillService
         }
         return null;
     }
+
+    /**
+     * 建立即时账单,已存在覆盖,不存在补录
+     *
+     * @param RejectedBill $rejectedBill
+     *
+     */
+    public function buildInstantBill(RejectedBill $rejectedBill)
+    {
+        /** @var \stdClass $rejectedBill */
+        $number = array_column(StoreRejected::query()->where("logistic_number_return",$rejectedBill->logistic_number_return)->get()->toArray(),"store_id");
+
+        foreach (Store::query()->with("storeItems")->whereIn("id",$number)->get() as $store){
+            /** @var OwnerPriceOperationService $service */
+            $service = app("OwnerPriceOperationService");
+            $result = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库",0);
+            $bill = OwnerFeeDetail::query()->where("outer_id",$store->id)->where("outer_table_name","stores")->first();
+            if ($bill) $bill->update([
+                    "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
+                    "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+            ]); else app("OwnerFeeDetailService")->create([
+                "owner_id" => $store->owner_id,
+                "worked_at" => $store->created_at,
+                "type" => "收货",
+                "operation_bill" => $store->asn_code,
+                "commodity_amount" => array_sum(array_column($store->storeItems->toArray(), "amount")),
+                "work_fee" => is_array($result) ? ($result["money"]>0 ? $result["money"] : null) : null,
+                "owner_price_operation_id" => is_array($result) ? $result["id"] : null,
+                "created_at" => date('Y-m-d H:i:s'),
+                "outer_id" => $store->id,
+                "outer_table_name" => "stores",
+            ]);
+        }
+    }
 }

+ 3 - 0
app/Services/StationService.php

@@ -58,6 +58,7 @@ class StationService
         return null;
     }
 
+
     function broadcast($station_id, StationTask $stationTask){
         if($stationTask)
             $json = $stationTask->toJson();
@@ -78,6 +79,8 @@ class StationService
                 "stationTaskMaterialBoxes.materialBox",
             ]);
         $this->broadcast($station_id, $stationTask);
+        LogService::log('海柔请求','broadcastBinMonitor',
+            json_encode($stationTask));
     }
 
 }

+ 3 - 0
app/Services/StationTaskMaterialBoxService.php

@@ -108,7 +108,10 @@ class StationTaskMaterialBoxService
         $this->instant($this->stationTaskService,'StationTaskService');
         $this->instant($this->stationService,'StationService');
         try{
+            LogService::log('海柔请求','markHasTaken1','');
             $taskType=$this->getServingTaskType($stationTaskMaterialBox);
+            LogService::log('海柔请求','markHasTaken2',
+                json_encode($taskType));
             switch ($taskType){
                 case '分波次':
                     $this->markProcessing($stationTaskMaterialBox);

+ 2 - 3
app/Services/StationTaskService.php

@@ -109,6 +109,7 @@ class StationTaskService
     }
     function markProcessed($stationTask_orCollection)
     {
+        $this->instant($this->batchService, 'BatchService');
         if (get_class($stationTask_orCollection)==StationTask::class){
             $stationTask_orCollection = collect([$stationTask_orCollection]);
         }
@@ -117,8 +118,6 @@ class StationTaskService
             $ids_stationTasks
         );
         $stationTaskBatches=StationTaskBatch::query()->whereIn('station_task_id',$ids_stationTasks);
-        $this->batchService->updateWhereIn('id', data_get($stationTaskBatches, '*.batch_id'), ['status' => '已处理']);
+        $this->batchService->updateWhereIn('id', data_get($stationTaskBatches, '*.batch_id')??[], ['status' => '已处理']);
     }
-
-
 }

+ 2 - 3
app/Services/StoreService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Feature;
 use App\Jobs\StoreCreateInstantBill;
 use App\Order;
 use App\OwnerFeeDetail;
@@ -326,9 +327,7 @@ class StoreService
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
 
-        $mapping = ["packages" => "storeItems", "商品名称" => "name", "订单类型" => "stored_method", "订单数"=>"amount"];
-
-        $result = $service->matching($store, $mapping, $store->owner_id, "入库");
+        $result = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库");
 
         if (app("OwnerFeeDetailService")->create([
             "owner_id" => $store->owner_id,

+ 45 - 0
app/Services/UnitService.php

@@ -4,6 +4,7 @@ namespace App\Services;
 
 use App\Unit;
 use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\Cache;
 
 
 class UnitService
@@ -21,4 +22,48 @@ class UnitService
         return Unit::query()->orderBy("sequence")->select($column)->get();
     }
 
+    /**
+     * 设置/刷新 单位缓存
+     */
+    public function setUnitCache()
+    {
+        $units = Unit::query()->get();
+        Cache::forever("units",$units);
+    }
+
+    /**
+     * 获取单位缓存
+     *
+     * @return mixed
+     */
+    public function getUnitCache()
+    {
+        if (!Cache::has("units")){
+            $units = Unit::query()->get();
+            Cache::forever("units",$units);
+        }
+        return Cache::get("units");
+    }
+
+    /**
+     * 获取单位集的映射
+     *
+     * @param null|array $targets
+     *
+     * @return array
+     */
+    public function getUnitMapping($targets = null)
+    {
+        return Cache::remember("unitMapping:".json_encode($targets,JSON_UNESCAPED_UNICODE),config("cache.expirations.rarelyChange"),function ()use($targets){
+            $result = [];
+            $units = $this->getUnitCache();
+            if (!$units)return [];
+            foreach ($units as $unit){
+                if (!$targets)$result[$unit->id] = $unit->name;
+                else if (array_search($unit->name,$targets)!==false)$result[$unit->id] = $unit->name;
+            }
+            return $result;
+        });
+    }
+
 }

+ 0 - 22
app/Services/WaybillService.php

@@ -155,28 +155,6 @@ class WaybillService
             $request->offsetSet('dispatch_remark', str_replace(["\n","\r"], ' ', $request->dispatch_remark));
         }
         if (!$request->destination) $request->offsetSet('destination', $waybill->destination);
-        /*if ($request->destination_city_id && $waybill->destination_city_id != $request->destination_city_id) {
-            $city = app(CityService::class)->find($request->destination_city_id);
-            if ($city && $city->province_name && (mb_strpos($request->destination, $city->name) === false || mb_strpos($request->destination, $city->province_name) === false)) {
-                if (mb_strpos($request->destination, $city->name) === false && mb_strpos($request->destination, $city->province_name) === false) {
-                    $request->offsetSet('destination', $city->province_name . $city->name . $request->destination);
-                    goto sign;
-                }
-                if (mb_strpos($request->destination, $city->province_name) === false) {
-                    $request->offsetSet('destination', $city->province_name . $request->destination);
-                }
-                if (mb_strpos($request->destination, $city->name) === false) {
-                    $province_name = $city->province_name;
-                    $start_index = mb_strpos($request->destination, $city->province_name . '省');
-                    if ($start_index === false) $start_index = mb_strpos($request->destination, $city->province_name);
-                    else $province_name = $province_name . '省';
-                    $strBefore = mb_substr($request->destination, $start_index, mb_strlen($province_name));
-                    $strAfter = mb_substr($request->destination, $start_index + mb_strlen($province_name));
-                    $request->offsetSet('destination', $strBefore . $city->name . $strAfter);
-                }
-            }
-        }
-        sign:*/
         $waybill->fill($request->input());
         $waybill->update();
         return $waybill;

+ 1 - 15
app/Store.php

@@ -19,10 +19,6 @@ class Store extends Model
         'asn_code','warehouse_id','owner_id','stored_method','status','remark','deleted_at','is_fast_stored'
     ];
 
-//    protected $appends=[
-//        'owner_name','warehouse_name'
-//    ];
-
     public function owner(){
         return $this->belongsTo('App\Owner','owner_id','id');
     }
@@ -32,15 +28,5 @@ class Store extends Model
     }
     public function storeItems(){
         return $this->hasMany('App\StoreItem','store_id','id');
-}
-
-//    public function getOwnerNameAttribute()
-//    {
-//        return $this['owner']? $this['owner']['name']:null;
-//    }
-//
-//    public function getWarehouseNameAttribute()
-//    {
-//        return $this['warehouse']?$this['warehouse']['name']:null;
-//    }
+    }
 }

+ 1 - 1
database/migrations/2020_11_30_140958_create_stations_table.php

@@ -27,7 +27,7 @@ class CreateStationsTable extends Migration
         $stationType= StationType::query()->firstOrCreate(['name'=>'料箱出货口']);
         $station料箱监视器01= StationType::query()->firstOrCreate(['name'=>'料箱监视器01']);
         $station= Station::query()->firstOrCreate(['name'=>'U型线入货口01'
-            ,'code'=>'BIN-OUT01'
+            ,'code'=>'BIN-OUT1'
             ,'station_type_id'=>$stationType['id']
             ,'parent_id'=>$station料箱监视器01['id']
         ]);

+ 1 - 1
database/migrations/2021_02_19_110139_change_owner_operation_owner_table.php

@@ -31,7 +31,7 @@ class ChangeOwnerOperationOwnerTable extends Migration
     {
         Schema::table('owner_price_operation_owner', function (Blueprint $table) {
             $table->dropColumn("discount_date");
-            $table->dropColumn("discount_date");
+            $table->dropColumn("target_value");
         });
         Schema::table('owner_price_operations', function (Blueprint $table) {
             $table->date("discount_date")->nullable()->comment("满减标记日");

+ 2 - 2
database/migrations/2021_02_26_152744_change_owner_fee_details_table_change_volume_column.php

@@ -29,10 +29,10 @@ class ChangeOwnerFeeDetailsTableChangeVolumeColumn extends Migration
     public function down()
     {
         Schema::table('owner_fee_details', function (Blueprint $table) {
-            $table->decimal('volume',8,3)->nullable()->comment('体积');
+            $table->decimal('volume',8,3)->nullable()->comment('体积')->change();
         });
         Schema::table('owner_fee_detail_logistics', function (Blueprint $table) {
-            $table->decimal('volume',8,3)->nullable()->comment('体积');
+            $table->decimal('volume',8,3)->nullable()->comment('体积')->change();
         });
     }
 }

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

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeTableProcessAddColumnDesignateId extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('processes', function (Blueprint $table) {
+            $table->bigInteger("designate_id")->nullable()->index()->comment("指派人");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('processes', function (Blueprint $table) {
+            $table->dropColumn("designate_id");
+        });
+    }
+}

+ 5 - 5
laravel-echo-server.json

@@ -1,5 +1,5 @@
 {
-	"authHost": "http://localhost",
+	"authHost": "https://localhost",
 	"authEndpoint": "/broadcasting/auth",
 	"clients": [
 		{
@@ -21,14 +21,14 @@
 			"databasePath": "/database/laravel-echo-server.sqlite"
 		}
 	},
-	"devMode": true,
+	"devMode": false,
 	"host": null,
 	"port": "6001",
-	"protocol": "http",
+	"protocol": "https",
 	"socketio": {},
 	"secureOptions": 67108864,
-	"sslCertPath": "",
-	"sslKeyPath": "",
+	"sslCertPath": "/etc/letsencrypt/live/was.baoshi56.com/fullchain.pem",
+	"sslKeyPath": "/etc/letsencrypt/live/was.baoshi56.com/privkey.pem",
 	"sslCertChainPath": "",
 	"sslPassphrase": "",
 	"subscribers": {

+ 44 - 0
laravel-echo-server.json.configed

@@ -0,0 +1,44 @@
+{
+	"authHost": "https://localhost",
+	"authEndpoint": "/broadcasting/auth",
+	"clients": [
+		{
+			"appId": "3ce79ec696215d04",
+			"key": "e68440520697de422639b451f760f208"
+		},
+		{
+			"appId": "wcs",
+			"key": "62c8838fa8546ad1f1784327a6d25df2"
+		}
+	],
+	"database": "redis",
+	"databaseConfig": {
+		"redis": {
+            "port": "6379",
+            "host": "127.0.0.1"
+        },
+		"sqlite": {
+			"databasePath": "/database/laravel-echo-server.sqlite"
+		}
+	},
+	"devMode": false,
+	"host": null,
+	"port": "6001",
+	"protocol": "https",
+	"socketio": {},
+	"secureOptions": 67108864,
+	"sslCertPath": "/etc/letsencrypt/live/was.baoshi56.com/fullchain.pem",
+	"sslKeyPath": "/etc/letsencrypt/live/was.baoshi56.com/privkey.pem",
+	"sslCertChainPath": "",
+	"sslPassphrase": "",
+	"subscribers": {
+		"http": true,
+		"redis": true
+	},
+	"apiOriginAllow": {
+        "allowCors" : true,
+        "allowOrigin" : "http://127.0.0.1",
+        "allowMethods" : "GET, POST",
+        "allowHeaders" : "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
+	}
+}

+ 16 - 1
resources/sass/text.scss

@@ -138,7 +138,7 @@
 .scrollbar::-webkit-scrollbar {
     /*滚动条整体样式*/
     width : 10px;  /*高宽分别对应横竖滚动条的尺寸*/
-    height: 1px;
+    height: 10px;
 }
 .scrollbar::-webkit-scrollbar-thumb {
     /*滚动条里面小方块*/
@@ -206,3 +206,18 @@
     z-index:100;
     position:relative;
 }
+
+//超高滚动 200px
+.overflow-scrollbar-200{
+    max-height: 200px;
+    max-width: 100%;
+    overflow: auto;
+    border: RGB(204,204,204) solid 1px;
+    border-radius: 5px
+}
+.overflow-y-scrollbar-200{
+    max-height: 200px;
+    overflow-y: auto;
+    border: RGB(204,204,204) solid 1px;
+    border-radius: 5px
+}

+ 211 - 38
resources/views/customer/project/create.blade.php

@@ -139,7 +139,8 @@
                         counting_type : "",
                         using_type : "",
                         minimum_area : "",
-                        price : "",
+                        price : [""],
+                        amount_interval : [""],
                         discount_type : "无减免",
                         discount_value : "",
                         unit_id : "",
@@ -150,6 +151,8 @@
                         name:"",
                         initial_weight:"",
                         additional_weight:"",
+                        amount_interval:[""],
+                        weight_interval:[[]],
                         items:[],
                         logistics:[],
                     },
@@ -173,7 +176,7 @@
                     discount_type:[
                         "无减免","按单减免","固定减免"
                     ],
-                    feature_type:{!! json_encode(\App\Feature::type,JSON_UNESCAPED_UNICODE) !!},
+                    feature_type:{!! json_encode(\App\Feature::TYPE,JSON_UNESCAPED_UNICODE) !!},
                     logic : ['包含','不包含','等于',"大于","大于等于","小于","小于等于"],
                 },
                 poolMapping:{},//基础数据选择池的映射对象 供展示使用
@@ -232,6 +235,7 @@
                             strategy:"默认",
                             discount_count:[''],
                             name:"",
+                            isRejected:false,
                             feature:"",
                             total_discount_price:[''],
                             items : [
@@ -266,7 +270,7 @@
                     if (!this.owner.id)return;
                     if (base === this.base)return;
                     if (base === 'three') this._loadStorage();
-                    if (base === 'two')this._getTaxRates()
+                    if (base === 'two')this._getTaxRates();
                     this.base = base;
                 },
                 //切换类型
@@ -287,6 +291,7 @@
                         case "express":
                             this._loadExpress();
                             dom = $("#express-card");
+                            $("#expressImport").tooltip();
                             break;
                         case "logistic":
                             this._loadLogistic();
@@ -311,7 +316,7 @@
                     switch (this.base) {
                         case "one":
                             this._verifyOne(()=>{
-                                this.base = "two";
+                                this.switchBase('two');
                             });
                             break;
                         case "two":
@@ -449,6 +454,7 @@
                         if (item.discount_price) operation.items[j].discount_price = item.discount_price.split(",");
                     });
                     if (operation.total_price)operation.isSingle = true;
+                    if (operation.type_mark===0 || operation.type_mark==='0')operation.isRejected = true;
                     return operation;
                 },
                 //重载快递费
@@ -456,6 +462,10 @@
                     express.logistics.forEach((logistic,j)=>{
                         express.logistics[j] = logistic.id;
                     });
+                    if (!express.amount_interval || !express.weight_interval){
+                        express.amount_interval = [""];
+                        express.weight_interval = [[]];
+                    }else express.isInterval = true;
                     return JSON.parse(JSON.stringify(express).replace(/details/g,"items"));
                 },
                 //重载物流费
@@ -621,14 +631,35 @@
                     if (!this.model.storage.counting_type)error["counting_type"] = ["未选择计费类型"];
                     if (!this.model.storage.name)error["name"] = ["未填写名称"];
                     if (!this.model.storage.using_type)error["using_type"] = ["未选择用仓类型"];
-                    if (!this.model.storage.price)error["price"] = ["未输入单价"];
+                    if (!this.model.storage.price[0])error["price.0"] = ["未输入单价"];
                     if (!this.model.storage.discount_type)error["discount_type"] = ["未选择减免类型"];
                     if (!this.model.storage.unit_id)error["unit_id"] = ["未选择单位"];
                     if (!this.model.storage.time_unit_id)error["time_unit_id"] = ["未选择计时单位"];
+                    if (this.model.storage.isInterval){
+                        if (this.model.storage.amount_interval.length<1 || this.model.storage.price.length<1){
+                            error["amount_interval.0"] = ["未设定数量区间"];
+                            error["price.0"] = ["未输入单价"];
+                        }else{
+                            this.model.storage.amount_interval.forEach((amount,i)=>{
+                                if (!amount)error["amount_interval."+i] = ["未设定数量区间"];
+                                else if (i!==0 && amount<=this.model.storage.amount_interval[i-1])
+                                    error["amount_interval."+i] = ["阶梯区间应大于上一区间值"];
+                                this.model.storage.amount_interval[i] = Number(this.model.storage.amount_interval[i]);
+                            });
+                            this.model.storage.price.forEach((price,i)=>{
+                                if (!price)error["price."+i] = ["未输入单价"];
+                                this.model.storage.price[i] = Number(this.model.storage.price[i]);
+                            });
+                        }
+                    }
                     if (JSON.stringify(error) !== "{}"){
                         this.errors = error;
                         return;
                     }
+                    if (!this.model.storage.isInterval){
+                        this.model.storage.amount_interval = null;
+                        this.model.storage.price = [Number(this.model.storage.price[0])];
+                    }
                     let url = "{{url('maintenance/priceModel/apiStoreStorage')}}";
                     let params = this.model.storage;
                     params.owner_id = this.ownerTemp.id;
@@ -649,7 +680,8 @@
                             counting_type : "",
                             using_type : "",
                             minimum_area : "",
-                            price : "",
+                            price : [""],
+                            amount_interval : [""],
                             discount_type : "无减免",
                             discount_value : "",
                             unit_id : "",
@@ -689,6 +721,10 @@
                             return;
                         }
                     }
+                    if (this.model.operation.strategy === '特征' && !this.model.operation.feature){
+                        this.$set(this.errors,"feature",["特征未填写"]);
+                        return;
+                    }
                     if (this.model.operation.isSingle && !this.model.operation.total_price){
                         this.$set(this.errors,"total_price",["按单价格不存在"]);
                         return;
@@ -703,11 +739,8 @@
                         })
                     }
                     if (!this.model.operation.isSingle){
-                        if ((this.model.operation.operation_type === '出库' && this._verifyOperationItem(0)) || this._verifyOperationItem(1))return;
-                        if (this.model.operation.items.length>2){
-                            for (let i=2;i<this.model.operation.items.length;i++){
-                                if (this._verifyOperationItem(i))return;
-                            }
+                        for (let i=0;i<this.model.operation.items.length;i++){
+                            if (this._verifyOperationItem(i))return;
                         }
                         this.model.operation.total_price = "";
                     }else this.$set(this.model.operation,"items",[]);
@@ -715,6 +748,7 @@
                         this.model.operation.discount_count = [""];
                         this.model.operation.total_discount_price = [""];
                     }
+                    if (this.model.operation.isRejected)this.model.operation.type_mark = 0;
                     let url = "{{url('maintenance/priceModel/apiStoreOperation')}}";
                     let params = this.model.operation;
                     params.owner_id = this.ownerTemp.id;
@@ -729,20 +763,18 @@
                         }
                         res.features = this.model.operation.features;
                         res.featureFormat = this.model.operation.featureFormat;
-                        let sign = 0;
-                        if (res.operation_type === '入库') sign++;
                         for (let i=0;i<res.items.length;i++){
-                            res.items[i].features = this.model.operation.items[sign]['features'];
-                            res.items[i].featureFormat = this.model.operation.items[sign]['featureFormat'];
-                            res.items[i].type = this.model.operation.items[sign]['type'];
+                            res.items[i].features = this.model.operation.items[i]['features'];
+                            res.items[i].featureFormat = this.model.operation.items[i]['featureFormat'];
+                            res.items[i].type = this.model.operation.items[i]['type'];
                             res.items[i].discount_price = res.items[i].discount_price ? res.items[i].discount_price.split(",") : [""];
-                            sign++;
                         }
                         if (res.discount_count)res.isDiscount = true;
                         if (res.total_price)res.isSingle = true;
 
                         res.discount_count = res.discount_count ? res.discount_count.split(",") : [""];
                         res.total_discount_price = res.total_discount_price ? res.total_discount_price.split(",") : [""];
+                        res.isRejected = this.model.operation.type_mark==='0'||this.model.operation.type_mark===0;
 
                         if (params.id) this.selectedModel.operation[params.index] = res;
                         else this.selectedModel.operation.push(res);
@@ -791,14 +823,49 @@
                     if (this.model.express.items.length>0){
                         this.model.express.items.forEach((item,index)=>{
                             if (!item.province_id)error["item."+index+".province_id"] = ["不存在"];
-                            if (!item.initial_weight_price)error["item."+index+".initial_weight_price"] = ["不存在"];
-                            if (!item.additional_weight_price)error["item."+index+".additional_weight_price"] = ["不存在"];
+                            if (!this.model.express.isInterval){
+                                if (!item.initial_weight_price[0][0])error["item."+index+".initial_weight_price.0.0"] = ["不存在"];
+                                if (!item.additional_weight_price[0][0])error["item."+index+".additional_weight_price.0.0"] = ["不存在"];
+                            }else{
+                                item.initial_weight_price.forEach((arr,i)=>{
+                                    arr.forEach((price,j)=>{
+                                        if (!price)error["item."+index+".additional_weight_price."+i+"."+j] = ["不存在"];
+                                    });
+                                });
+                                item.additional_weight_price.forEach((arr,i)=>{
+                                    arr.forEach((price,j)=>{
+                                        if (!price)error["item."+index+".additional_weight_price."+i+"."+j] = ["不存在"];
+                                    });
+                                });
+                            }
+                        });
+                    }
+                    if (this.model.express.isInterval){
+                        this.model.express.amount_interval.forEach((amount,i)=>{
+                            if (amount==="") error["amount_interval."+i] = ["区间值不得为空"];
+                            else if (i!==0 && amount<=this.model.express.amount_interval[i-1])error["amount_interval."+i] = ["阶梯区间应大于上一区间值"];
+                            if (this.model.express.weight_interval[i].length>0){
+                                this.model.express.weight_interval[i].forEach((weight,j)=>{
+                                    if (weight==="") error["weight_interval."+i+"."+j] = ["区间值不得为空"];
+                                    else if (j!==0 && weight<=this.model.express.weight_interval[j-1])error["weight_interval."+i+"."+j] = ["阶梯区间应大于上一区间值"];
+                                })
+                            }
                         });
                     }
                     if (JSON.stringify(error) !== "{}"){
                         this.errors = error;
                         return;
                     }
+                    if (!this.model.express.isInterval){
+                        this.model.express.amount_interval = null;
+                        this.model.express.weight_interval = null;
+                        if (this.model.express.items.length>0){
+                            this.model.express.items.forEach((item,i)=>{
+                                this.model.express.items[i].initial_weight_price = [[Number(item.initial_weight_price[0][0])]];
+                                this.model.express.items[i].additional_weight_price = [[Number(item.additional_weight_price[0][0])]];
+                            });
+                        }
+                    }
                     let url = "{{url('maintenance/priceModel/apiStoreExpress')}}";
                     let params = this.model.express;
                     params.owner_id = this.ownerTemp.id;
@@ -808,6 +875,8 @@
                             if (res.errors.owner_id)window.tempTip.show(res.errors.owner_id[0]);
                             return;
                         }
+                        if (!this.model.express.amount_interval) this.model.express.amount_interval = [""];
+                        if (!this.model.express.weight_interval) this.model.express.weight_interval = [[]];
                         this.model.express.items.forEach((item,i)=>{
                             item.id = res.details[i].id;
                         });
@@ -820,10 +889,12 @@
                         }
                         this.model.express = {
                             name:"",
-                            logistics:[],
                             initial_weight:"",
                             additional_weight:"",
+                            amount_interval:[""],
+                            weight_interval:[[]],
                             items:[],
+                            logistics:[],
                         };
                         this.errors = {};
                         this.importError = [];
@@ -903,9 +974,13 @@
                     });
                 },
                 //增加作业费特征子项
-                addOperationItem(){
+                addOperationItem(strategy){
+                    if (strategy!=='特征' && !this.model.operation.items.every(item=>{
+                        if (item.strategy===strategy)return false;
+                        return true;
+                    }))return;
                     this.model.operation.items.push({
-                        strategy:"特征",
+                        strategy:strategy,
                         discount_price:new Array(this.model.operation.discount_count.length).fill(""),
                     });
                 },
@@ -1028,21 +1103,54 @@
                 },
                 //新增快递子项
                 addExpressItem(){
+                    let arr = [];
+                    this.model.express.amount_interval.forEach((amount,i)=>{
+                        if (this.model.express.weight_interval[i].length>0){
+                            let it = [];
+                            this.model.express.weight_interval[i].forEach(weight=>{
+                                it.push("");
+                            });
+                            arr.push(it);
+                        }else arr.push([""]);
+                    });
+                    let re=[];
+                    for(let i=0;i<arr.length;i++){
+                        re.push(arr[i].slice(0));
+                    }
                     this.model.express.items.unshift({
                         province_id : "",
-                        initial_weight_price:"",
-                        additional_weight_price:"",
+                        initial_weight_price:arr,
+                        additional_weight_price:re,
                     });
                 },
                 //删除快递子项
                 delExpressItem(index){
-                    this.$delete(this.model.express.items,index);
+                    window.tempTip.confirm("确定要删除该子项吗?",res=>{
+                        this.$delete(this.model.express.items,index);
+                    })
                 },
                 //选择文件
                 selectFile(id){
                     this.importError = [];
                     $("#"+id).click();
                 },
+                _getExpressImportData(index,data){
+                    let arr = [];
+                    this.model.express.amount_interval.forEach((amount,i)=>{
+                        if (this.model.express.weight_interval[i].length>0){
+                            let it = [];
+                            this.model.express.weight_interval[i].forEach(weight=>{
+                                it.push(data[index] ? data[index] : "");
+                                index++;
+                            });
+                            arr.push(it);
+                        }else {
+                            arr.push([data[index] ? data[index] : ""]);
+                            index++;
+                        }
+                    });
+                    return [arr,index];
+                },
                 //导入快递子项
                 importExpress(e){
                     let file=e.target.files[0];
@@ -1057,14 +1165,27 @@
                         'Content-Type':'multipart/form-data'
                     }).then(res=>{
                             if (res.data.success) {
-                                res.data.data.forEach(data=>{
-                                    let unique = this.model.express.items.every(item=>{
+                                res.data.data.data.forEach(data=>{
+                                    if(this.model.express.items.every(item=>{
                                         if (data.province_id === item.province_id)return false;
                                         return true;
-                                    });
-                                    if (unique)this.model.express.items.push(data);
+                                    })){
+                                        if (this.model.express.isInterval){
+                                            let result = this._getExpressImportData(1,data);
+
+                                            this.model.express.items.push({
+                                                province_id : data[0],
+                                                initial_weight_price:result[0],
+                                                additional_weight_price:this._getExpressImportData(result[1],data)[0],
+                                            });
+                                        }else this.model.express.items.push({
+                                                province_id : data[0],
+                                                initial_weight_price:[[data[1]]],
+                                                additional_weight_price:[[data[2]]],
+                                            });
+                                    }
                                 });
-                                this.importError = res.data.errors;
+                                this.importError = res.data.data.errors;
                                 window.tempTip.setDuration(2000);
                                 window.tempTip.showSuccess("导入成功!");
                                 return;
@@ -1243,6 +1364,8 @@
                                 price : model.price,
                                 discount_type : model.discount_type,
                                 discount_value : model.discount_value,
+                                amount_interval : model.amount_interval ? model.amount_interval : [""],
+                                isInterval:!!model.amount_interval,
                                 unit_id : model.unit_id,
                             };
                         });
@@ -1266,6 +1389,8 @@
                                 feature : model.feature,
                                 featureFormat : model.featureFormat,
                                 remark : model.remark,
+                                type_mark : model.type_mark,
+                                isRejected : model.type_mark==='0'||model.type_mark===0,
                                 items:model.items,
                             };
                         });
@@ -1299,6 +1424,9 @@
                                 name:model.name,
                                 initial_weight:model.initial_weight,
                                 additional_weight:model.additional_weight,
+                                amount_interval:model.amount_interval ? model.amount_interval : [""],
+                                weight_interval:model.weight_interval ? model.weight_interval : [[]],
+                                isInterval:!!model.amount_interval,
                                 items:items,
                             };
                         });
@@ -1512,15 +1640,7 @@
                 editOperation(index){
                     this.switchType("operation");
                     this.model.operation = JSON.parse(JSON.stringify(this.selectedModel.operation[index]));
-                    if (this.model.operation.operation_type==='入库') this.model.operation.items.unshift({});
                     this.model.operation.index = index;
-                    if (this.model.operation.items.length == 0){
-                        this.model.operation.items = [
-                            {strategy:"起步",type:"0"},
-                            {strategy:"默认"},
-                            {strategy:"特征"},
-                        ];
-                    }
                 },
                 //编辑快递
                 editExpress(index){
@@ -1642,6 +1762,59 @@
                         })
                     })
                 },
+                //增加数量区间
+                addStoreAmount(){
+                    this.model.storage.amount_interval.push("");
+                    this.model.storage.price.push("");
+                },
+                //删除数量区间
+                delStoreAmount(index){
+                    if (this.model.storage.amount_interval.length<2)return;
+                    this.$delete(this.model.storage.amount_interval,index);
+                    this.$delete(this.model.storage.price,index);
+                },
+                //增加快递数量区间
+                addExpressAmount(){
+                    this.model.express.amount_interval.push("");
+                    this.model.express.weight_interval.push([]);
+                    if (this.model.express.items.length>0){
+                        this.model.express.items.forEach((item,i)=>{
+                            this.$set(this.model.express.items[i],"initial_weight_price",[""]);
+                            this.$set(this.model.express.items[i],"additional_weight_price",[""]);
+                        })
+                    }
+                },
+                //增加快递重量区间
+                addExpressWeight(index){
+                    this.model.express.weight_interval[index].push("");
+                    if (!this.model.express.maxDom || this.model.express.weight_interval[index].length > this.model.express.maxDom)
+                        this.$set(this.model.express,'maxDom',this.model.express.weight_interval[index].length);
+                },
+                //删除快递数量区间
+                delExpressAmount(){
+                    let len = this.model.express.amount_interval.length;
+                    if (len>1){
+                        this.$delete(this.model.express.amount_interval,len-1);
+                        this.$delete(this.model.express.weight_interval,len-1);
+                        if (this.model.express.items.length>0){
+                            this.model.express.items.forEach((item,i)=>{
+                                this.$delete(this.model.express.items[i]["initial_weight_price"],len-1);
+                                this.$delete(this.model.express.items[i]["additional_weight_price"],len-1);
+                            })
+                        }
+                    }
+                },
+                //删除快递重量区间
+                delExpressWeight(index){
+                    let len = this.model.express.weight_interval[index].length;
+                    this.$delete(this.model.express.weight_interval[index],len-1);
+                    if (this.model.express.items.length>0){
+                        this.model.express.items.forEach((item,i)=>{
+                            this.$delete(this.model.express.items[i]["initial_weight_price"][index],len-1);
+                            this.$delete(this.model.express.items[i]["additional_weight_price"][index],len-1);
+                        })
+                    }
+                },
                 filterCustomer(e){
                     let value = $(e.target).val();
                     if (value===""){

+ 102 - 23
resources/views/customer/project/part/_express.blade.php

@@ -21,18 +21,63 @@
            v-model="model.express.additional_weight" :class="errors.additional_weight ? 'is-invalid' : ''"></label>
 </div>
 <div class="row mt-3">
-    <label class="col-3 cursor-pointer"><span @click="show('express-item')">详情&nbsp;
-        <span class="fa" :class="upList['express-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span></span></label>
+    <label for="isInterval" class="col-3"><b class="text-danger">* </b>设定区间</label>
+    <label class="col-7"><input id="isInterval" type="checkbox" class="switch"  v-model="model.express.isInterval"></label>
+</div>
+<div class="row mt-3" v-if="model.express.isInterval">
+    <label class="col-3">区间值</label>
+    <div class="col-8">
+        <div class="scrollbar overflow-scrollbar-200">
+            <div class="w-100 text-nowrap">
+                <div class="w-25 d-inline-block border border-1 border-secondary rounded rounded-5 font-weight-bold">
+                    <span class="pull-right">重量</span><br><span class="pull-left">数量</span>
+                </div>
+                <label class="w-25 d-inline-block m-0 text-center" v-for="index of model.express.maxDom">
+                    第@{{ index }}阶梯
+                </label>
+            </div>
+            <div class="w-100 text-nowrap" v-for="(amount,i) in model.express.amount_interval">
+                <label class="w-25 d-inline-block m-0">
+                    <input type="number" step="1" min="0" v-model="model.express.amount_interval[i]" class="form-control border-dark"
+                        :min="(model.express.amount_interval[i-1]) ? (Number(model.express.amount_interval[i-1])+1) : '0'"
+                        :class="errors['amount_interval.'+i] ? 'is-invalid' : ''"
+                        :placeholder="'数量:最小'+((model.express.amount_interval[i-1]) ? (Number(model.express.amount_interval[i-1])+1) : '0')">
+                </label>
+                <label class="w-25 d-inline-block m-0" v-for="(weight,j) in model.express.weight_interval[i]">
+                    <input type="number" v-model="model.express.weight_interval[i][j]" step="0.01" class="form-control"
+                    :class="errors['weight_interval.'+i+'.'+j] ? 'is-invalid' : ''"
+                    :min="(model.express.weight_interval[i][j-1]) ? (Number(model.express.weight_interval[i][j-1])+1) : 0"
+                    :placeholder="'重量:最小'+((model.express.weight_interval[i][j-1]) ? (Number(model.express.weight_interval[i][j-1])+1) : '0')">
+                </label>
+                <span class="fa fa-plus cursor-pointer" @click="addExpressWeight(i)"></span>
+                <span class="fa fa-times cursor-pointer text-danger" @click="delExpressWeight(i)"></span>
+            </div>
+            <div class="w-100 text-nowrap mt-0 mb-3">
+                <label style="width: 12.5%" class="d-inline-block mb-0 p-0 text-center border border-1 cursor-pointer border-info rounded rounded-5" @click="addExpressAmount()">
+                    <span class="fa fa-plus" style="font-size: 1rem"></span>
+                </label>
+                <label style="width: 12.5%" class="d-inline-block mb-0 p-0 text-center border border-1 cursor-pointer text-danger border-danger rounded rounded-5"
+                       @click="delExpressAmount()" v-if="model.express.amount_interval.length>1">
+                    <span class="fa fa-times" style="font-size: 1rem"></span>
+                </label>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="row mt-3">
+    <label class="col-3 cursor-pointer"><span>详情&nbsp;
+        <span @click="show('express-item')" class="fa" :class="upList['express-item'] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span></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)"/>
             <button type="button" class="btn btn-sm btn-outline-info w-25" @click="addExpressItem()">新增</button>
-            <button type="button" class="btn btn-sm btn-outline-primary w-25 ml-2" @click="selectFile('expressFile')" @mouseenter="hoverEffect('express',true)" @mouseleave="hoverEffect('express',false)">导入</button>
+            <button type="button" class="btn btn-sm btn-outline-primary w-25 ml-2" id="expressImport" data-toggle="tooltip" @click="selectFile('expressFile')"
+                    title="表头可不填写,会按照下方排列顺序读取数据" @mouseenter="hoverEffect('express',true)" @mouseleave="hoverEffect('express',false)">导入</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)"/>
+                <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">
@@ -44,30 +89,64 @@
                 </div>
             </div>
         </div>
-        <div class="row font-weight-bold" v-if="model.express.items.length>0 || hover.express"
+        <div class="font-weight-bold overflow-scrollbar-200" v-if="model.express.items.length>0 || hover.express"
              :class="hover.express ? 'text-danger font-weight-bold text-shadow-stress' : ''">
-            <label class="col-3">省</label>
-            <label class="col-3">首重价格</label>
-            <label class="col-3">续重价格</label>
-            <label class="col-3"></label>
-        </div>
-        <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>
+            <div class="w-100 text-nowrap">
+                <label class="w-25 d-inline-block m-0 text-center">省</label>
+                <label v-if="model.express.isInterval" class="d-inline-block m-0 text-center" v-for="(amount,i) in model.express.amount_interval" :style="{width:(model.express.weight_interval[i].length<1 ? 1 : model.express.weight_interval[i].length)*25+'%'}">
+                    首重价格(@{{ (model.express.amount_interval[i+1]) ? (model.express.amount_interval[i]+'-'+model.express.amount_interval[i+1]) : (model.express.amount_interval[i]+' +') }}单)
                 </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 v-if="model.express.isInterval" class="d-inline-block m-0 text-center" v-for="(amount,i) in model.express.amount_interval" :style="{width:(model.express.weight_interval[i].length<1 ? 1 : model.express.weight_interval[i].length)*25+'%'}">
+                    续重价格(@{{ (model.express.amount_interval[i+1]) ? (model.express.amount_interval[i]+'-'+model.express.amount_interval[i+1]) : (model.express.amount_interval[i]+' +') }}单)
                 </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 v-if="!model.express.isInterval" class="w-25 d-inline-block m-0 text-center">首重价格</label>
+                <label v-if="!model.express.isInterval" class="w-25 d-inline-block m-0 text-center">续重价格</label>
+            </div>
+            <div class="w-100 text-nowrap" v-if="model.express.isInterval">
+                <label class="w-25 d-inline-block m-0 text-center"></label>
+                <label class="d-inline-block m-0 text-center" v-for="(amount,i) in model.express.amount_interval" :style="{width:(model.express.weight_interval[i].length<1 ? 1 : model.express.weight_interval[i].length)*25+'%'}">
+                    <label v-if="model.express.weight_interval[i].length>0" v-for="(weight,j) in model.express.weight_interval[i]" :style="{width:100/model.express.weight_interval[i].length+'%'}">重(@{{ model.express.weight_interval[i][j+1] ? (model.express.weight_interval[i][j]+'-'+model.express.weight_interval[i][j+1]) : (model.express.weight_interval[i][j]+' +') }}kg)</label>
+                    <label v-if="model.express.weight_interval[i].length<=0" class="w-100">重(0 +kg)</label>
                 </label>
-                <label class="col-3 cursor-pointer h3 font-weight-bold text-danger" @click="delExpressItem(i)">
-                    &times;
+                <label class="d-inline-block m-0 text-center" v-for="(amount,i) in model.express.amount_interval" :style="{width:(model.express.weight_interval[i].length<1 ? 1 : model.express.weight_interval[i].length)*25+'%'}">
+                    <label v-if="model.express.weight_interval[i].length>0" v-for="(weight,j) in model.express.weight_interval[i]" :style="{width:100/model.express.weight_interval[i].length+'%'}">重(@{{ model.express.weight_interval[i][j+1] ? (model.express.weight_interval[i][j]+'-'+model.express.weight_interval[i][j+1]) : (model.express.weight_interval[i][j]+' +') }}kg)</label>
+                    <label v-if="model.express.weight_interval[i].length<=0" class="w-100">重(0 +kg)</label>
                 </label>
             </div>
+            <div class="w-100 text-nowrap" id="express-item">
+                <div class="w-100" v-for="(item,i) in model.express.items" v-if="!searchItem.express || (searchItem.express && searchItem.express.includes(i))">
+                    <label class="w-25 d-inline-block m-0 text-center">
+                        <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 v-if="model.express.isInterval" class="d-inline-block m-0 text-center" v-for="(amount,j) in model.express.amount_interval" :style="{width:(model.express.weight_interval[j].length<1 ? 1 : model.express.weight_interval[j].length)*25+'%'}">
+                        <label v-for="(weight,k) in model.express.weight_interval[j]" :style="{width:100/model.express.weight_interval[j].length+'%'}">
+                            <input type="number" step="0.01" min="0" :class="errors['items.'+i+'.initial_weight_price.'+j+'.'+k] ? 'is-invalid' : ''" class="form-control form-control-sm" v-model="item.initial_weight_price[j][k]">
+                        </label>
+                        <label v-if="model.express.weight_interval[j].length<1">
+                            <input type="number" step="0.01" min="0" :class="errors['items.'+i+'.initial_weight_price.'+j+'.0'] ? 'is-invalid' : ''" class="form-control form-control-sm" v-model="model.express.items[i]['initial_weight_price'][j][0]">
+                        </label>
+                    </label>
+                    <label v-if="model.express.isInterval" class="d-inline-block m-0 text-center" v-for="(amount,j) in model.express.amount_interval" :style="{width:(model.express.weight_interval[j].length<1 ? 1 : model.express.weight_interval[j].length)*25+'%'}">
+                        <label v-for="(weight,k) in model.express.weight_interval[j]" :style="{width:100/model.express.weight_interval[j].length+'%'}">
+                            <input type="number" :class="errors['items.'+i+'.additional_weight_price.'+j+'.'+k] ? 'is-invalid' : ''" step="0.01" min="0" class="form-control form-control-sm" v-model="item.additional_weight_price[j][k]">
+                        </label>
+                        <label v-if="model.express.weight_interval[j].length<1">
+                            <input type="number" :class="errors['items.'+i+'.additional_weight_price.'+j+'.0'] ? 'is-invalid' : ''" step="0.01" min="0" class="form-control form-control-sm" v-model="model.express.items[i]['additional_weight_price'][j][0]">
+                        </label>
+                    </label>
+                    <label v-if="!model.express.isInterval" class="w-25 d-inline-block m-0 text-center">
+                        <input type="number" step="0.01" min="0" :class="errors['items.'+i+'.initial_weight_price.0.0'] ? 'is-invalid' : ''" class="form-control form-control-sm" v-model="model.express.items[i]['initial_weight_price'][0][0]">
+                    </label>
+                    <label v-if="!model.express.isInterval" class="w-25 d-inline-block m-0 text-center">
+                        <input type="number" step="0.01" min="0" :class="errors['items.'+i+'.additional_weight_price.0.0'] ? 'is-invalid' : ''" class="form-control form-control-sm" v-model="model.express.items[i]['additional_weight_price'][0][0]">
+                    </label>
+                    <label class="w-25 d-inline-block m-0 text-center cursor-pointer h3 font-weight-bold text-danger">
+                        <span @click="delExpressItem(i)">&times;</span>
+                    </label>
+                </div>
+            </div>
         </div>
     </div>
-</div>
+</div>

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

@@ -25,14 +25,19 @@
         <strong>@{{ errors.name[0] }}</strong>
     </span>
 </div>
+<div class="row mt-3" v-if="model.operation.operation_type == '入库'">
+    <label class="col-2" for="isRejected">是退货</label>
+    <input content="col-3" id="isRejected" type="checkbox" class="switch" v-model="model.operation.isRejected">
+</div>
 <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>
+        <label v-if="errors.feature" class="text-danger small font-weight-bold">@{{ errors.feature[0] }}</label><br>
         <button type="button" class="btn btn-dark w-75 ml-2" @click="showAddFeatureModal(-1,model.operation.feature)">调整特征</button>
     </label>
 </div>
-<div class="row mt-3" v-if="model.operation.operation_type == '出库'">
+<div class="row mt-3">
     <label class="col-2" for="isDiscount">是否满减</label>
     <div class="col-2">
         <input type="checkbox" id="isDiscount" class="rounded mt-1" v-model="model.operation.isDiscount">
@@ -75,15 +80,28 @@
     </div>
 </div>
 <div class="row mt-3" v-if="!model.operation.isSingle">
-    {{--起步--}}
-    <div class="card row text-white offset-1 col-9 bg-dark" v-if="model.operation.operation_type === '出库'">
+    <div class="btn-group offset-1 col-9 mb-1">
+        <button type="button" class="btn btn-outline-dark" @click="addOperationItem('起步')">新增起步</button>
+        <button type="button" class="btn btn-outline-info" @click="addOperationItem('默认')">新增默认</button>
+        <button type="button" class="btn btn-outline-secondary" @click="addOperationItem('特征')">新增特征</button>
+    </div>
+    <div v-for="(item,i) in model.operation.items" class="card row text-white offset-1 col-9" :class="item.strategy=='特征' ? 'bg-secondary' : (item.strategy=='默认' ? 'bg-info' : 'bg-dark')">
         <div class="card-header" style="max-height: 50px">
             <div class="row">
-                <div class="col-6 offset-3 text-center">起&nbsp;&nbsp;&nbsp;&nbsp;步</div>
+                <div class="col-6 offset-3 text-center">
+                    @{{ item.strategy }}
+                </div>
+                <div class="col-3">
+                    <div class="pull-right cursor-pointer text-white" @click="delOperationItem(i)"><small>删除</small>&nbsp;<span class="fa fa-window-close-o"></span></div>
+                </div>
             </div>
         </div>
         <div class="card-body">
-            <div class="row">
+            <div class="row mt-2" v-if="item.strategy!='起步'">
+                <label class="col-3">数量</label>
+                <label class="col-6 mb-0"><input type="number" step="1" min="0" :class="errors['items.'+i+'.amount'] ? 'is-invalid' : ''" v-model="item.amount" class="form-control"></label>
+            </div>
+            <div class="row" v-if="item.strategy=='起步'">
                 <label class="col-3">
                     <select class="form-control mt-1" v-model="model.operation.items[0].type">
                         <option value="0">起步数</option>
@@ -92,132 +110,15 @@
                 </label>
                 <label class="col-6 mb-0">
                     <input id="amount" type="number" :class="errors['items.0.amount'] ? 'is-invalid' : ''" v-if="model.operation.items[0].type == 0"
-                       v-model="model.operation.items[0].amount" class="form-control" step="1">
+                           v-model="model.operation.items[0].amount" class="form-control" step="1">
                     <input v-else type="number" min="0" step="0.01" class="form-control" v-model="model.operation.items[0].unit_price"
                            :class="errors['items.0.unit_price'] ? 'is-invalid' : ''">
                 </label>
             </div>
-            <div class="row mt-0" v-if="errors['items.0.amount']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">起步数为必填项</small></div>
-            </div>
-            <div class="row mt-2" v-if="model.operation.items[0].type == 0">
-                <label class="col-3">单位</label>
-                <label class="col-6 mb-0"><select v-model="model.operation.items[0].unit_id" class="form-control" :class="errors['items.0.unit_id'] ? 'is-invalid' : ''">
-                        <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name=='件' || unit.name=='箱'">@{{ unit.name }}</option>
-                    </select></label>
-            </div>
-            <div class="row mt-0" v-if="errors['items.0.unit_id']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必选项</small></div>
-            </div>
-            <div class="row mt-2" v-if="model.operation.items[0].type == 0">
-                <label class="col-3">起步费</label>
-                <label class="col-6 mb-0 input-group">
-                    <input type="number" min="0" step="0.01" class="form-control" v-model="model.operation.items[0].unit_price"
-                                                 :class="errors['items.0.unit_price'] ? 'is-invalid' : ''">
-                    <span class="d-block input-group-append">
-                          <span class="input-group-text">元</span>
-                    </span>
-                </label>
-            </div>
-            <div class="row mt-0" v-if="errors['items.0.unit_price']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">起步费为必填项</small></div>
-            </div>
-            <div class="row mt-2" v-if="model.operation.isDiscount" v-for="(value,i) in model.operation.discount_count">
-                <label class="col-3">满减起步费@{{ i>0 ? i : '' }}</label>
-                <label class="col-6 mb-0 input-group">
-                    <input type="number" min="0" step="0.01"  class="form-control"
-                     v-model="model.operation.items[0].discount_price[i]" :class="errors['items.0.discount_price'] ? 'is-invalid' : ''">
-                    <span class="d-block input-group-append">
-                        <span class="input-group-text">元</span>
-                    </span>
-                </label>
-                <label class="col-4">@{{ value ? (model.operation.discount_count[i+1] ? value+'-'+(model.operation.discount_count[i+1]-1)+' 单' : value+'+ 单') : '' }}</label>
-            </div>
-        </div>
-    </div>
-
-    {{--默认--}}
-    <div class="card row text-white offset-1 col-9 bg-info">
-        <div class="card-header" style="max-height: 50px">
-            <div class="row">
-                <div class="col-3">
-                    <div class="pull-left cursor-pointer text-white" @click="addOperationItem()"><small>新增</small>&nbsp;<span class="fa fa-plus-square-o"></span></div>
-                </div>
-                <div class="col-6 text-center">
-                    默&nbsp;&nbsp;&nbsp;&nbsp;认
-                </div>
-            </div>
-        </div>
-        <div class="card-body">
-            <div class="row mt-2">
-                <label class="col-3">数量</label>
-                <label class="col-6 mb-0"><input id="amount" type="number" :class="errors['items.1.amount'] ? 'is-invalid' : ''"
-                       v-model="model.operation.items[1].amount" class="form-control" step="1">
-                </label>
-            </div>
-            <div class="row mt-0" v-if="errors['items.1.amount']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">数量为必填项</small></div>
-            </div>
-            <div class="row mt-2">
-                <label class="col-3">单位</label>
-                <label class="col-6 mb-0"><select v-model="model.operation.items[1].unit_id" class="form-control" :class="errors['items.1.unit_id'] ? 'is-invalid' : ''">
-                    <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name=='件' || unit.name=='箱'">@{{ unit.name }}</option>
-                </select></label>
-            </div>
-            <div class="row mt-0" v-if="errors['items.1.unit_id']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必填项</small></div>
-            </div>
-            <div class="row mt-2">
-                <label class="col-3">单价</label>
-                <label class="col-6 mb-0 input-group">
-                    <input type="number" min="0" step="0.01" class="form-control" v-model="model.operation.items[1].unit_price"
-                           :class="errors['items.1.unit_price'] ? 'is-invalid' : ''">
-                    <span class="d-block input-group-append">
-                          <span class="input-group-text">元</span>
-                    </span>
-                </label>
-            </div>
-            <div class="row mt-0" v-if="errors['items.1.unit_price']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">单价为必填项</small></div>
-            </div>
-            <div class="row mt-2" v-if="model.operation.isDiscount" v-for="(value,i) in model.operation.discount_count">
-                <label class="col-3">满减价@{{ i>0 ? i : '' }}</label>
-                <label class="col-6 mb-0 input-group">
-                    <input type="number" min="0" step="0.01" class="form-control" v-model="model.operation.items[1].discount_price[i]"
-                           :class="errors['items.1.discount_price'] ? 'is-invalid' : ''">
-                    <span class="d-block input-group-append">
-                          <span class="input-group-text">元</span>
-                    </span>
-                </label>
-                <label class="col-4">@{{ value ? (model.operation.discount_count[i+1] ? value+'-'+(model.operation.discount_count[i+1]-1)+' 单' : value+'+ 单') : '' }}</label>
-            </div>
-        </div>
-    </div>
-
-    {{--特征--}}
-    <div v-for="(item,i) in model.operation.items" class="card row text-white offset-1 col-9 bg-secondary" v-if="i>1">
-        <div class="card-header" style="max-height: 50px">
-            <div class="row">
-                <div class="col-3">
-                    <div class="pull-left cursor-pointer text-white" @click="addOperationItem()"><small>新增</small>&nbsp;<span class="fa fa-plus-square-o"></span></div>
-                </div>
-                <div class="col-6 text-center">
-                    特&nbsp;&nbsp;&nbsp;&nbsp;征
-                </div>
-                <div class="col-3">
-                    <div class="pull-right cursor-pointer text-white" @click="delOperationItem(i)"><small>删除</small>&nbsp;<span class="fa fa-window-close-o"></span></div>
-                </div>
-            </div>
-        </div>
-        <div class="card-body">
-            <div class="row mt-2">
-                <label class="col-3">数量</label>
-                <label class="col-6 mb-0"><input type="number" step="1" min="0" :class="errors['items.'+i+'.amount'] ? 'is-invalid' : ''" v-model="item.amount" class="form-control"></label>
-            </div>
             <div class="row mt-0" v-if="errors['items.'+i+'.amount']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">数量为必填项</small></div>
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3"><span v-if="item.strategy=='起步'">起步数</span><span v-else>数量</span>为必填项</small></div>
             </div>
-            <div class="row mt-2">
+            <div class="row mt-2" v-if="item.strategy!='起步' || (item.strategy=='起步' && item.type==0)">
                 <label class="col-3">单位</label>
                 <label class="col-6 mb-0"><select v-model="item.unit_id" class="form-control" :class="errors['items.'+i+'.unit_id'] ? 'is-invalid' : ''">
                     <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name=='件' || unit.name=='箱'">@{{ unit.name }}</option>
@@ -226,8 +127,8 @@
             <div class="row mt-0" v-if="errors['items.'+i+'.unit_id']">
                 <div class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必选项</small></div>
             </div>
-            <div class="row mt-2">
-                <label class="col-3">单价</label>
+            <div class="row mt-2" v-if="item.strategy!='起步' || (item.strategy=='起步' && item.type==0)">
+                <label class="col-3"><span v-if="item.strategy=='起步'">起步费</span><span v-else>单价</span></label>
                 <label class="col-6 mb-0 input-group">
                     <input type="number" min="0" step="0.01" class="form-control" v-model="item.unit_price"
                        :class="errors['items.'+i+'.unit_price'] ? 'is-invalid' : ''">
@@ -237,10 +138,10 @@
                 </label>
             </div>
             <div class="row mt-0" v-if="errors['items.'+i+'.unit_price']">
-                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">单价为必填项</small></div>
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3"><span v-if="item.strategy=='起步'">起步费</span><span v-else>单价</span>为必填项</small></div>
             </div>
             <div class="row mt-2" v-if="model.operation.isDiscount" v-for="(value,i) in model.operation.discount_count">
-                <label class="col-3">满减价@{{ i>0 ? i : '' }}</label>
+                <label class="col-3">满减<span v-if="item.strategy=='起步'">起步费</span><span v-else></span>@{{ i>0 ? i : '' }}</label>
                 <label class="col-6 mb-0 input-group">
                     <input type="number" min="0" step="0.01" class="form-control" v-model="item.discount_price[i]"
                        :class="errors['items.'+i+'.discount_price'] ? 'is-invalid' : ''">
@@ -250,7 +151,7 @@
                 </label>
                 <label class="col-4">@{{ value ? (model.operation.discount_count[i+1] ? value+'-'+(model.operation.discount_count[i+1]-1)+' 单' : value+'+ 单') : '' }}</label>
             </div>
-            <div class="row mt-2">
+            <div class="row mt-2" v-if="item.strategy=='特征'">
                 <label class="col-3">特征:</label>
                 <label class="col-8">
                     <label v-if="errors['items.'+i+'.feature']" class="text-danger">@{{ errors['items.'+i+'.feature'][0] }}</label>

+ 46 - 10
resources/views/customer/project/part/_storage.blade.php

@@ -33,18 +33,14 @@
         <strong>@{{ errors.minimum_area[0] }}</strong>
     </span>
 </div>
+<div class="row mt-3">
+    <label for="isInterval" class="col-2 text-info">设定区间</label>
+    <input id="isInterval" type="checkbox" class="switch"  v-model="model.storage.isInterval">
+</div>
 <div class="row mt-3">
     <div class="col-4 row">
-        <label for="price" class="col-4 text-info">单价</label>
-        <input id="price" type="number" min="0" step="0.001" class="offset-3 col-5 form-control"
-               :class="errors.price ? 'is-invalid' : ''" v-model="model.storage.price">
-        <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.price">
-            <strong>@{{ errors.price[0] }}</strong>
-        </span>
-    </div>
-    <div class="col-3 row m-0">
-        <label for="unit_id" class="col-5 offset-1 text-info">单位</label>
-        <select id="unit_id" class="col-6 form-control"
+        <label for="unit_id" class="col-4 text-info">单位</label>
+        <select id="unit_id" class="offset-3 col-5 form-control"
                 :class="errors.unit_id ? 'is-invalid' : ''" v-model="model.storage.unit_id">
             <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name == 'm²' || unit.name=='㎡' || unit.name == 'm³' || unit.name == '件'">
                 @{{ unit.name }}</option>
@@ -63,6 +59,46 @@
             <strong>@{{ errors.time_unit_id[0] }}</strong>
         </span>
     </div>
+    <div class="col-3 row m-0" v-if="!model.storage.isInterval">
+        <label for="price" class="col-5 offset-1 text-info">单价</label>
+        <input id="price" type="number" min="0" step="0.001" class="col-6 form-control"
+               :class="errors['price.0'] ? 'is-invalid' : ''" v-model="model.storage.price[0]">
+        <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors['price.0']">
+            <strong>@{{ errors['price.0'][0] }}</strong>
+        </span>
+    </div>
+</div>
+<div class="row mt-3" v-if="model.storage.isInterval">
+    <label for="amount_interval" class="col-2 text-info">数量区间</label>
+    <div class="col-8 scrollbar overflow-y-scrollbar-200">
+        <div class="row mt-0 text-muted">
+            <label class="col-4 offset-2 text-center">区间值</label>
+            <label class="col-5 text-center">单价</label>
+        </div>
+        <div class="row mt-1" v-for="(amount,i) in model.storage.amount_interval">
+            <label class="col-2">
+                <span class="fa fa-plus cursor-pointer" @click="addStoreAmount()">&nbsp;增加</span>
+            </label>
+            <label class="col-4">
+                <input type="number" class="form-control form-control-sm" :class="errors['amount_interval.'+i] ? 'is-invalid' : ''"
+                       step="1" :min="Number(model.storage.amount_interval[i-1] ? model.storage.amount_interval[i-1] : 0)+1" v-model="model.storage.amount_interval[i]">
+            </label>
+            <label class="col-5 text-center">
+                <input type="number" class="form-control form-control-sm"  step="0.01" v-model="model.storage.price[i]" :class="errors['price.'+i] ? 'is-invalid' : ''"
+                       :placeholder="model.storage.amount_interval[i] ?
+                       ('区间范围:'+model.storage.amount_interval[i]+(model.storage.amount_interval[i+1] ? '-'+(model.storage.amount_interval[i+1]-1) : ' +')) : ''">
+            </label>
+            <label class="col-1">
+                <span class="cursor-pointer text-danger font-weight-bold h4" @click="delStoreAmount(i)" v-if="i!=0">&times;</span>
+            </label>
+            <label class="small text-danger offset-2 col-4" role="alert" v-if="errors['amount_interval.'+i]">
+                <strong>@{{ errors['amount_interval.'+i][0] }}</strong>
+            </label>
+            <label class="small text-danger col-5" :class="!errors['amount_interval.'+i] ? 'offset-6' : ''" role="alert" v-if="errors['price.'+i]">
+                <strong>@{{ errors['price.'+i][0] }}</strong>
+            </label>
+        </div>
+    </div>
 </div>
 <div class="row mt-3">
     <label for="discount_type" class="col-2 text-info">减免类型</label>

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

@@ -18,7 +18,7 @@
                         <th>计费类型</th>
                         <th>用仓类型</th>
                         <th>起租面积</th>
-                        <th>单价</th>
+                        <th class="text-center">单价</th>
                         <th>单位</th>
                         <th>计时单位</th>
                         <th>减免类型</th>
@@ -30,7 +30,15 @@
                         <td>@{{ item.counting_type }}</td>
                         <td>@{{ item.using_type }}</td>
                         <td>@{{ item.minimum_area }}</td>
-                        <td>@{{ item.price }}</td>
+                        <td>
+                            <div v-if="item.amount_interval">
+                                <div v-for="(amount,i) in item.amount_interval" class="row text-nowrap">
+                                    <b class="col-4 offset-1 m-0">@{{ item.price[i] }}</b>
+                                    <label class="col-7 m-0">(@{{ item.amount_interval[i+1] ? amount+'-'+item.amount_interval[i+1] : amount+" +" }}单)</label>
+                                </div>
+                            </div>
+                            <div v-else><b>@{{ item.price[0] }}</b></div>
+                        </td>
                         <td>@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }}</td>
                         <td>@{{ poolMapping.units ? poolMapping.units[item.time_unit_id] : '' }}</td>
                         <td>@{{ item.discount_type }}</td>
@@ -48,7 +56,7 @@
                         @can("项目管理-项目-计费模型-审核")<button class="btn btn-sm btn-success" type="button" @click="auditOrRecoverModel('operation')">审核</button>
                         <button class="btn btn-sm btn-danger" type="button" @click="auditOrRecoverModel('operation',false)">恢复</button>@endcan
                     </div>
-                </div>
+                </div>  
                 <div class="col-3 pull-right small mb-0 text-secondary" v-if="selectedModel.operation.length>0">双击下方已添加内容可编辑</div>
             </div>
             <div class="card-body" id="operation">
@@ -65,7 +73,7 @@
                                         <span class="fa" :class="upList['operation-item-'+i] ? 'fa-caret-right' : 'fa-caret-down'"></span>
                                         &nbsp;@{{ operation.strategy }}:
                                     </label>
-                                    <label>@{{ operation.name }}</label>
+                                    <label>@{{ operation.name }}</label><span class="badge badge-pill badge-danger" v-if="operation.isRejected">退</span>
                                     <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
                                 </div>
                                 <div class="col-1">
@@ -197,18 +205,47 @@
                         </tr>
                         <tr>
                             <td colspan="5">
-                                <div :id="'express-item-'+i" class="offset-3 up">
-                                    <table class="table table-sm col-10">
+                                <div :id="'express-item-'+i" class="offset-3 up overflow-scrollbar-200">
+                                    <table class="table table-sm col-10 text-nowrap">
                                         <tr>
                                             <th>省份</th>
-                                            <th>首重价格</th>
-                                            <th>续重价格</th>
+                                            <template v-if="express.isInterval">
+                                                <th v-for="(amount,i) in express.amount_interval" class="text-center" :colspan="express.weight_interval[i] ? express.weight_interval[i].length : 1">
+                                                    首重价格(@{{ (express.amount_interval[i+1]) ? (express.amount_interval[i]+'-'+express.amount_interval[i+1]) : (express.amount_interval[i]+' +') }}单)
+                                                </th>
+                                                <th v-for="(amount,i) in express.amount_interval" class="text-center" :colspan="express.weight_interval[i] ? express.weight_interval[i].length : 1">
+                                                    续重价格(@{{ (express.amount_interval[i+1]) ? (express.amount_interval[i]+'-'+express.amount_interval[i+1]) : (express.amount_interval[i]+' +') }}单)
+                                                </th>
+                                            </template>
+                                            <template v-else>
+                                                <th>首重价格</th>
+                                                <th>续重价格</th>
+                                            </template>
+                                            <th></th>
+                                        </tr>
+                                        <tr v-if="express.isInterval">
                                             <th></th>
+                                            <template v-for="(amount,j) in express.amount_interval">
+                                                <th v-for="(weight,k) in express.weight_interval[j]">
+                                                    重(@{{ express.weight_interval[j][k+1] ? (express.weight_interval[j][k]+'-'+express.weight_interval[j][k+1]) : (express.weight_interval[j][k]+' +') }}kg)
+                                                </th>
+                                                <th v-if="express.weight_interval[j].length==0">重(0 +kg)</th>
+                                            </template>
+                                            <template v-for="(amount,j) in express.amount_interval">
+                                                <th v-for="(weight,k) in express.weight_interval[j]">
+                                                    重(@{{ express.weight_interval[j][k+1] ? (express.weight_interval[j][k]+'-'+express.weight_interval[j][k+1]) : (express.weight_interval[j][k]+' +') }}kg)
+                                                </th>
+                                                <th v-if="express.weight_interval[j].length==0">重(0 +kg)</th>
+                                            </template>
                                         </tr>
                                         <tr v-for="(item,j) in express.items">
                                             <td>@{{ poolMapping.provinces ? poolMapping.provinces[item.province_id] : '' }}</td>
-                                            <td>@{{ item.initial_weight_price }}</td>
-                                            <td>@{{ item.additional_weight_price }}</td>
+                                            <template v-for="arr in item.initial_weight_price">
+                                                <td v-for="init in arr">@{{ init }}</td>
+                                            </template>
+                                            <template v-for="arr in item.additional_weight_price">
+                                                <td v-for="add in arr">@{{ add }}</td>
+                                            </template>
                                             <td>
                                                 <span class="cursor-pointer text-danger font-weight-bold" @click.stop="deleteExpressItem(item,j,i)">&times;</span>
                                             </td>

+ 3 - 3
resources/views/customer/project/part/_two.blade.php

@@ -3,7 +3,7 @@
     <select id="customer_id" v-model="owner.customer_id" @change="selectOwner()" class="form-control form-control-sm col-4 mb-0" :class="errors.customer_id ? 'is-invalid' : ''">
         <option v-for="customer in filterCustomers" :value="customer.id">@{{ customer.name }}</option>
     </select>
-    <input type="text" class="form-control form-control-sm ml-1 col-2" placeholder="输入关键字定位客户" @change="filterCustomer($event)">
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字定位客户" @change="filterCustomer($event)"></label>
     <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.customer_id">
         <strong>@{{ errors.customer_id[0] }}</strong>
     </span>
@@ -13,7 +13,7 @@
     <select id="owner_group_id" v-model="owner.owner_group_id" @change="selectGroup()" class="form-control form-control-sm col-4 mb-0" :class="errors.owner_group_id ? 'is-invalid' : ''" >
         <option v-for="ownerGroup in filterOwnerGroups" :value="ownerGroup.id">@{{ ownerGroup.name }}</option>
     </select>
-    <input type="text" class="form-control form-control-sm ml-1 col-2" placeholder="输入关键字项目小组" @change="filterOwnerGroup($event)">
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字项目小组" @change="filterOwnerGroup($event)"></label>
     <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.owner_group_id">
         <strong>@{{ errors.owner_group_id[0] }}</strong>
     </span>
@@ -32,7 +32,7 @@
     <select id="user_workgroup_id" v-model="owner.user_workgroup_id" @change="selectGroup()" class="form-control form-control-sm col-4 mb-0" :class="errors.user_workgroup_id ? 'is-invalid' : ''" >
         <option v-for="userGroup in filterUserGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
     </select>
-    <input type="text" class="form-control form-control-sm ml-1 col-2" placeholder="输入关键字项目小组" @change="filterUserGroup($event)">
+    <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字项目小组" @change="filterUserGroup($event)"></label>
     <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.user_workgroup_id">
         <strong>@{{ errors.user_workgroup_id[0] }}</strong>
     </span>

+ 21 - 17
resources/views/process/create.blade.php

@@ -269,6 +269,13 @@
                         <strong>@{{ error.unit_price[0] }}</strong>
                     </span>
                 </div>
+                <div class="form-group row">
+                    <label for="designate_id" class="col-3 col-form-label text-right">指定接单人</label>
+                    <select id="designate_id" class="form-control col-5" v-model="process.designate_id">
+                        <option v-for="user in users" :value="user.id">@{{ user.name }}</option>
+                    </select>
+                    <label class="col-3"><input class="text form-control rounded-pill" placeholder="搜索人员" @input="seekUser($event)"></label>
+                </div>
                 <div class="form-group row">
                     <label class="col-3 col-form-label text-right" >加工备注(选填)</label>
                     <textarea :readonly="is_hide" v-model="process.remark" type="text" class="form-control col-8"></textarea>
@@ -277,20 +284,6 @@
                     <label class="col-3 col-form-label text-right" >结算备注(选填)</label>
                     <textarea :readonly="is_hide" v-model="process.balance_remark" type="text" class="form-control col-8"></textarea>
                 </div>
-                {{--<div class="form-group row">
-                    <label class="col-3 col-form-label text-right" >引用教程(选填)</label>
-                    <span class=" col-8 input-group p-0" style="max-height: 150px; overflow-y: scroll;border-radius:5px;opacity:0.7;text-align: center;">
-                        <ul class="list-group" style="width: 100%" onselectstart="return false;">
-                            <li v-for="tutorial in tutorials" :data-original-title="tutorial.style ? '双击删除教程' :'双击添加教程'"  :id="tutorial.id" class="tooltipTarget list-group-item list-group-item-action p-0 m-0"
-                                @dblclick="selectedTutorial(tutorial)" :class="tutorial.style ? 'active' :''" style="cursor: default;">
-                                @{{ tutorial.name }}</li>
-                        </ul>
-                        <div class="mt-0 form-inline" v-if="processContents.length>0">
-                            <button type="button" @click="addTutorial()"  class="btn btn-sm btn-outline-primary">新增教程</button>
-                            <button type="button" @click="refreshTutorial()" class="btn btn-sm btn-outline-secondary ml-2">刷新</button>
-                        </div>
-                    </span>
-                </div>--}}
                 <div class="form-group row">
                     <div class="col-8 offset-3 p-0">
                         <input type="button" @click="submit()" class="btn btn-success form-control" value="提交">
@@ -312,7 +305,7 @@
                     process_method_id:'{{old('process_method_id')??($process->process_method_id??'')}}',
                     unit_price:'{{old('unit_price')??($process->unit_price??'')}}',remark:'{{preg_replace("/\s/",' ',old('remark')??($process->remark??''))}}',
                     balance_remark:'{{preg_replace("/\s/",' ',old('remark')??($process->balance_remark??''))}}',
-                    wms_code_full:'',status:'{{$process->status??''}}'},
+                    wms_code_full:'',status:'{{$process->status??''}}',designate_id:"{{old('designate_id') ?? ($process->designate_id ?? '')}}"},
                 error:{wms_code:[],owner_id:[],process_method_id:[],unit_price:[],amount:[]},
                 processContents:[
                     @if($process)
@@ -331,7 +324,7 @@
                     {!! $processMethod !!},
                     @endforeach
                 ],
-                //tutorials:[],
+                users:[@foreach($users as $user) @json($user), @endforeach],
                 selectedTutorials:[],
                 msg:false,
                 commodityIds:[],
@@ -348,7 +341,6 @@
                     handler(){
                         if (this.processContents.length===1 && this.processContents[(this.processContents.length)-1].owner_id){
                             this.process.owner_id=this.processContents[(this.processContents.length)-1].owner_id;
-                            //this.getTutorial(this.processContents[(this.processContents.length)-1].owner_id);
                         }
                     }
                 },
@@ -368,6 +360,18 @@
                 }
             },
             methods:{
+                //搜索人员
+                seekUser(e){
+                    e.stopPropagation();
+                    let val = e.target.value;
+                    if (!val) this.process.designate_id = "";
+                    if (this.users.every(user=>{
+                        if (user.name.indexOf(val)!==-1){
+                            this.process.designate_id = user.id;
+                            return false;
+                        }return true;
+                    }))this.process.designate_id = "";
+                },
                 //添加标记商品
                 _addSignCommodity(wms_code,commodity_id,is_finished_product){
                     this.commodityIds.push(wms_code+"_"+commodity_id+"_"+is_finished_product);

+ 9 - 23
resources/views/process/index.blade.php

@@ -183,7 +183,7 @@
                     <button v-if="!processOne.openProcessHour && processOne.status=='待验收'" class="btn btn-sm btn-outline-success" @click="checkAndAccept(processOne)" @mouseenter="processOne.buttonTexts.质量验收='质量验收'" @mouseleave="processOne.buttonTexts.质量验收='验'">@{{processOne.buttonTexts.质量验收}}</button>@endcan
                     @can("二次加工管理-接单与驳回")
                     <button v-if="!processOne.openProcessHour && processOne.status=='待接单'" @click="processReject(processOne.id)" class="btn btn-sm btn-outline-dark" @mouseenter="processOne.buttonTexts.驳回='驳回'" @mouseleave="processOne.buttonTexts.驳回='驳'">@{{processOne.buttonTexts.驳回}}</button>
-                    <button v-if="!processOne.openProcessHour && processOne.status=='待接单'"  @click="processReceive(processOne.id)" class="btn btn-sm btn-outline-primary" @mouseenter="processOne.buttonTexts.接单='接单'" @mouseleave="processOne.buttonTexts.接单='接'">@{{processOne.buttonTexts.接单}}</button>@endcan
+                    <button v-if="(!processOne.openProcessHour && processOne.status=='待接单') && ((!processOne.designate_id) || processOne.designate_id==userId)"  @click="processReceive(processOne.id,i)" class="btn btn-sm btn-outline-primary" @mouseenter="processOne.buttonTexts.接单='接单'" @mouseleave="processOne.buttonTexts.接单='接'">@{{processOne.buttonTexts.接单}}</button>@endcan
                     @can("二次加工管理-登记工时")<button :style="[{opacity:processOne.status=='交接完成'?'0.7':''},{transform:processOne.status=='交接完成'?'scale(0.85)':''}]" v-if="(processOne.status!='待审核' && processOne.status!='已驳回' && processOne.status!='待接单') && !processOne.openProcessHour"
                             class="btn btn-sm btn-outline-info" @click="openProcessHour(processOne);processOne.openProcessHour=true;processOne.detailFolding=false" @mouseenter="processOne.buttonTexts.登记工时='登记工时'" @mouseleave="processOne.buttonTexts.登记工时='登'">@{{processOne.buttonTexts.登记工时}}</button>
                     <button v-if="processOne.openProcessHour" @click="closeProcessHour(processOne.id);processOne.openProcessHour=false" class="btn btn-sm btn-dark">收起登记工时</button>
@@ -479,12 +479,13 @@
                         ,tutorials:{!! $processOne->tutorials !!},processesContents:{!! $processOne->processesContents !!},unit_price:'{{$processOne->unit_price}}',created_at:'{{$processOne->created_at}}',
                         completed_amount:'{{$processOne->completed_amount}}',status:'{{$processOne->status}}',remark:'{{preg_replace("/\s/",' ',$processOne->remark)}}',
                         balance_remark:'{{preg_replace("/\s/",' ',$processOne->balance_remark)}}',
-
+                        designate_id:"{{$processOne->designate_id}}",
                         detailFolding:false,openProcessHour:false,is_multi_row:false,is_verifier_show:false,is_update_unit_price:false,
                         buttonTexts:{'审核':'审','回滚':'回','编辑':'编','接单':'接','驳回':'驳','质量验收':'验','完成':'完','交接完成':'交','查看单据':'查','登记工时':'登'},
                     },
                     @endforeach
                 ],
+                userId:"{{\Illuminate\Support\Facades\Auth::id()}}",
                 processesList:[],
                 owners:[
                         @foreach($owners as $owner)
@@ -852,31 +853,16 @@
                     })
                 },
                 //接单
-                processReceive(id) {
+                processReceive(id,index) {
                     let url = "{{url('process/receive')}}" + "/" + id;
-                    let _this = this;
-                    axios.post(url)
-                        .then(function (response) {
-                            _this.processes.every(function (process) {
-                                if (process.id == response.data.id) {
-                                    process.status = response.data.status;
-                                    return false;
-                                }
-                                return true;
-                            });
-                            tempTip.setDuration(3000);
-                            tempTip.showSuccess('接单成功!');
-                        }).catch(function (err) {
-                        tempTip.setDuration(5000);
-                        tempTip.show('接单时发生了一些严重错误:' + err);
-                    })
+                    window.tempTip.postBasicRequest(url,{},res=>{
+                        this.processes[index].status = res;
+                        return "接单成功";
+                    });
                 },
                 //完成
                 processAccomplish(process) {
-                    if (!confirm('确定标记为加工完成吗?')) {
-                        return
-                    }
-                    ;
+                    if (!confirm('确定标记为加工完成吗?'))return
                     axios.post('{{url('process/processAccomplish')}}', {id: process.id})
                         .then(function (response) {
                             if (response.data.success) {

+ 2 - 0
resources/views/process/statistic.blade.php

@@ -27,6 +27,7 @@
                 </th>
                 <th>序号</th>
                 <th>任务号</th>
+                <th>接单人</th>
                 <th>货主</th>
                 <th>开始日期</th>
                 <th>完成日期</th>
@@ -52,6 +53,7 @@
                 <td><input class="checkItem" type="checkbox" :value="processStatistic.process_id" v-model="checkData"></td>
                 <td>@{{ i+1 }}</td>
                 <td><span v-if="processStatistic.process">@{{ processStatistic.process.code }}</span></td>
+                <td><span v-if="processStatistic.operatorLog && processStatistic.operatorLog.user">@{{ processStatistic.operatorLog.user.name }}</span></td>
                 <td><span v-if="processStatistic.process">@{{ processStatistic.process.owner_name }}</span></td>
                 <td>@{{ processStatistic.started_at }}</td>
                 <td>@{{ processStatistic.ended_at }}</td>

+ 24 - 15
resources/views/station/monitor/show.blade.php

@@ -34,7 +34,7 @@
                         </div>
                         <div class="row">
                             <div class="col py-3 text-muted text-center">
-                                <img id="barcode" alt="">
+                                <img id="barcode" alt="" :data-refresh="batchCode">
                             </div>
                         </div>
                         <div class="row">
@@ -237,8 +237,8 @@
             color: #fff;
         }
         .box-spot-color.n1{
-            background: #1d0939;
-            fill: #1d0939;
+            background: #d7e3ff;
+            fill: #d7e3ff;
         }
         .box-spot-color.n2{
             background: #393409;
@@ -311,6 +311,7 @@
                         let json = JSON.parse(msg.json);
                         if(!json||json.length===0)return;
                         this.station['current_station_task']=json;
+                        console.log((new Date()).toTimeString(),json);
                     });
                 },
             },
@@ -319,6 +320,18 @@
                     if(!this.station['current_station_task'])return null;
                     return this.station['current_station_task'];
                 },
+                batchCode(){
+                    let batches = this.task.station_task_batches;
+                    if(batches
+                        && Array.isArray(batches)
+                        && batches.length>0
+                    ){
+                        setTimeout(function (){
+                            setBarcode(batches[0].batch.code,"#barcode",1,50,false);
+                        })
+                    }
+                    return batches[0].batch.code;
+                },
                 taskCommodities(){
                     if(!this.task)return [];
                     return this.station['current_station_task']['station_task_commodities'];
@@ -384,25 +397,21 @@
                 },
                 processedCommodities(){
                     if(!this.task)return 0;
-                    return this.task['station_task_commodities'].reduce(function (item, taskCommodity) {
-                        if (typeof (item) === 'object' && item.status === '完成') {
-                            return item.amount;
-                        }
-                        if (typeof (item) === 'object') {
-                            return 0;
-                        }
+                    let processedAmount=0;
+                    this.task['station_task_commodities'].forEach(function (taskCommodity) {
                         if (taskCommodity.status === '完成') {
-                            return item + taskCommodity.amount;
+                            processedAmount+=taskCommodity.amount;
                         }
-                        return item;
                     })
+                    return processedAmount;
                 },
                 totalCommodities(){
                     if(!this.task)return 0;
-                    return this.task['station_task_commodities'].reduce(function(item,taskCommodity){
-                        if(typeof(item)==='object')item=item.amount;
-                        return item+taskCommodity.amount;
+                    let amount=0;
+                    this.task['station_task_commodities'].forEach(function (taskCommodity) {
+                        amount+=taskCommodity.amount;
                     })
+                    return amount;
                 },
                 processingTaskMaterialBox(){
                     if(!this.task)return [];

+ 74 - 0
resources/views/test.blade.php

@@ -0,0 +1,74 @@
+@extends('layouts.app')
+
+@section('content')
+    <div>
+        <table class="table table-hover table-striped table-bordered">
+            <tr>
+               <th>11</th>
+               <th>22</th>
+               <th>33</th>
+               <th>44</th>
+               <th>55</th>
+               <th>66</th>
+               <th>77</th>
+               <th>88</th>
+               <th>99</th>
+               <th>100</th>
+               <th>110</th>
+               <th>120</th>
+               <th>130</th>
+               <th>140</th>
+               <th>150</th>
+               <th>160</th>
+               <th>170</th>
+               <th>180</th>
+               <th>190</th>
+               <th>200</th>
+            </tr>
+            <tr>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+            </tr>
+            <tr>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+                <td>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</td>
+            </tr>
+        </table>
+    </div>
+@endsection

+ 4 - 1
resources/views/transport/waybill/index.blade.php

@@ -53,7 +53,7 @@
             <table class="table table-striped table-sm table-bordered table-hover text-nowrap waybill-table" style="background: #fff;" id="headerParent">
                 <tr>
                     <th class="table-header-layer-1" colspan="4"></th>
-                    <th class="table-header-layer-1" colspan="12"><span class="fa fa-file-text-o"></span> 运单信息</th>
+                    <th class="table-header-layer-1" colspan="13"><span class="fa fa-file-text-o"></span> 运单信息</th>
                     <th class="table-header-layer-1" colspan="16"><span class="fa fa-truck"></span> 运输信息</th>
                     <th class="table-header-layer-1" colspan="5"><span class="fa fa-rmb"></span> 费用信息
                     @can('运输管理-运单-删除')
@@ -131,6 +131,7 @@
                         <span class="badge badge-pill badge-danger" v-if="waybill.is_cancel">取消</span>
                         @{{waybill.wms_bill_number}}
                     </td>
+                    <td class="td-warm">@{{ waybill.order_status }}</td>
                     <td class="td-warm">@{{waybill.waybill_number}}</td>
                     @can('运输管理-运单-运单编辑')
                     <td class="td-warm" >
@@ -350,6 +351,7 @@
                         province:'{{$waybill->order_province ?? ($waybill->destinationCity->parent->name ?? '')}}',
                         city:'{{$waybill->order_city ?? ($waybill->destinationCity->name ?? '')}}',
                         district:'{{$waybill->order_district ?? ($waybill->district->name ?? '')}}',
+                        order_status:'{{$waybill->order->wms_status ?? ''}}',
                     },
                     @endforeach
                 ],
@@ -453,6 +455,7 @@
                     {name:'owner',value: '货主', class:"td-warm"},
                     {name:'source_bill',value: '上游单号', class:"td-warm"},
                     {name:'wms_bill_number',value: 'WMS订单号', class:"td-warm"},
+                    {name:'order_status',value: '订单状态', class:"td-warm"},
                     {name:'waybill_number',value: '运单号', class:"td-warm"},
                     {name:'charge',value: '运输收费', neglect: true, class:"td-warm"},
                     {name:'other_charge',value: '其他收费', neglect: true, class:"td-warm"},

+ 1 - 0
routes/api/thirdPart/haiq.php

@@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Route;
 
 
 Route::group(['prefix'=>'storage'],function(){
+    Route::post('postBin1', "StorageController@postBin1");//出库
     Route::post('postBin2', "StorageController@postBin2");//出库
     Route::post('moveBin2', "StorageController@moveBin2");//出库
     Route::post('moveBinIn', "StorageController@moveBinIn");//移库

+ 1 - 1
tests/webApi/thirdPart/haiq/move.http

@@ -2,7 +2,7 @@
 POST http://192.168.1.201:2011/api/haiqEss/gr/relocate
 Content-Type: application/json
 
-{"groupCode":"1","taskMode":2,"priority":1,"sequenceFlag":1,"bins":[{"taskCode":"taskIDE0000034","binCode":"IDE0000034","toWorkStation":"bin-out01","fromWorkStation":"","fromLocCode":"","toLocCode":"","sequence":1,"stockInfo":[{"skuCode":"string","qty":1}]}]}
+{"groupCode":"1","taskMode":2,"priority":1,"sequenceFlag":1,"bins":[{"taskCode":"taskIDE0000034","binCode":"IDE0000034","toWorkStation":"BIN-OUT1","fromWorkStation":"","fromLocCode":"","toLocCode":"","sequence":1,"stockInfo":[{"skuCode":"string","qty":1}]}]}
 ###
 
 

+ 1 - 1
tests/webApi/thirdPart/haiq/pickStation.http

@@ -17,7 +17,7 @@
 POST https://was.baoshi56.com/api/thirdPart/haiq/pickStation/processed
 Content-Type: application/json
 
-{"workStation": "", "binCode":"8b839c28-f2e3-3d56-b34a-d9ac4fd81fa2", "success": true, "created_at":"", "exception": "", "is_in_plan":true}
+{"workStation": "1", "binCode":"IDE0005680", "success": true, "created_at":"2021-56-24 05-03-15", "exception": "", "is_in_plan":true}
 ###
 
 

+ 3 - 0
tests/webApi/thirdPart/haiq/storage.http

@@ -5,6 +5,9 @@
 ## * 'ptr' and 'ptrp' create a POST request with a simple or parameter-like body;
 ## * 'mptr' and 'fptr' create a POST request to submit a form with a text or file field (multipart/form-data);
 ### out to roller
+POST http://bswas/api/thirdPart/haiq/storage/postBin1
+
+###
 POST http://bswas/api/thirdPart/haiq/storage/postBin2
 
 ###