Parcourir la source

Merge branch 'master' into zengjun

ajun il y a 5 ans
Parent
commit
31138ad5b0
100 fichiers modifiés avec 2299 ajouts et 1360 suppressions
  1. 2 3
      app/Commodity.php
  2. 26 0
      app/Components/ApiProcurementResponse.php
  3. 8 0
      app/Console/Commands/CreateProcurementTotalBill.php
  4. 1 0
      app/Console/Commands/SyncBatchTask.php
  5. 2 0
      app/Console/Commands/SyncOrderPackageLogisticRouteTask.php
  6. 3 0
      app/Console/Kernel.php
  7. 2 1
      app/Exceptions/Exception.php
  8. 27 2
      app/Feature.php
  9. 15 2
      app/Http/Controllers/Auth/RegisterController.php
  10. 5 2
      app/Http/Controllers/CommodityController.php
  11. 3 0
      app/Http/Controllers/ConfigurationController.php
  12. 0 1
      app/Http/Controllers/LogisticController.php
  13. 0 1
      app/Http/Controllers/LogisticNumberFeatureController.php
  14. 4 2
      app/Http/Controllers/MaterialController.php
  15. 3 2
      app/Http/Controllers/OwnerMaterialController.php
  16. 5 6
      app/Http/Controllers/PackageLogisticController.php
  17. 43 77
      app/Http/Controllers/PriceModelController.php
  18. 31 21
      app/Http/Controllers/ProcessController.php
  19. 35 19
      app/Http/Controllers/ProcessStatisticController.php
  20. 56 46
      app/Http/Controllers/ProcurementController.php
  21. 2 0
      app/Http/Controllers/RejectedController.php
  22. 40 42
      app/Http/Controllers/SupplierController.php
  23. 51 453
      app/Http/Controllers/TestController.php
  24. 25 3
      app/Http/Controllers/UserController.php
  25. 0 61
      app/Http/Controllers/api/procurement/wechat/AuthController.php
  26. 6 2
      app/Http/Controllers/api/thirdPart/goodscan/PackageController.php
  27. 6 1
      app/Http/Controllers/api/thirdPart/haiq/PickStationController.php
  28. 21 8
      app/Http/Controllers/api/thirdPart/haiq/StorageController.php
  29. 0 1
      app/Http/Controllers/api/thirdPart/jianshang/RejectedController.php
  30. 5 7
      app/Http/Controllers/api/thirdPart/weight/PackageController.php
  31. 86 0
      app/Http/Controllers/api/thirdPart/weixin/AuthController.php
  32. 22 16
      app/Http/Controllers/api/thirdPart/weixin/ProcurementController.php
  33. 3 1
      app/Http/Requests/ForeignHaiRobotic_taskUpdateRequest.php
  34. 65 0
      app/Http/Requests/Material/MaterialRequest.php
  35. 74 0
      app/Http/Requests/OwnerMaterial/OwnerMaterialRequest.php
  36. 91 0
      app/Http/Requests/Supplier/SupplierRequest.php
  37. 46 81
      app/Imports/ExpressImport.php
  38. 1 1
      app/Imports/UpdatePickZone.php
  39. 0 2
      app/Imports/WaybillPriceModelsImport.php
  40. 78 0
      app/Jobs/ProcurementCheckConfirmInform.php
  41. 81 0
      app/Jobs/ProcurementConfirmInform.php
  42. 68 0
      app/Jobs/ProcurementEnquiry.php
  43. 37 0
      app/Jobs/ProcurementReceive.php
  44. 82 0
      app/Jobs/ProcurementWaitConfirmInform.php
  45. 43 0
      app/Jobs/RejectedBillCreateInstantBill.php
  46. 1 1
      app/Jobs/WeightUpdateInstantBill.php
  47. 0 12
      app/Order.php
  48. 6 0
      app/OwnerPriceExpress.php
  49. 4 0
      app/OwnerPriceExpressProvince.php
  50. 4 0
      app/OwnerPriceOperation.php
  51. 5 0
      app/OwnerStoragePriceModel.php
  52. 1 1
      app/Process.php
  53. 1 5
      app/ProcessStatistic.php
  54. 8 6
      app/Procurement.php
  55. 7 1
      app/ProcurementTotalBill.php
  56. 4 0
      app/Providers/AppServiceProvider.php
  57. 4 3
      app/Services/BatchService.php
  58. 17 4
      app/Services/CommodityService.php
  59. 37 0
      app/Services/ConfigurationService.php
  60. 70 78
      app/Services/FeatureService.php
  61. 63 19
      app/Services/ForeignHaiRoboticsService.php
  62. 1 0
      app/Services/InventoryAccountService.php
  63. 2 1
      app/Services/OrderPackageReceivedSyncService.php
  64. 13 26
      app/Services/OrderService.php
  65. 25 3
      app/Services/OwnerPriceExpressService.php
  66. 1 1
      app/Services/OwnerPriceLogisticService.php
  67. 205 200
      app/Services/OwnerPriceOperationService.php
  68. 8 1
      app/Services/OwnerStoragePriceModelService.php
  69. 2 2
      app/Services/PackageService.php
  70. 1 1
      app/Services/ProcessService.php
  71. 4 10
      app/Services/ProcessStatisticService.php
  72. 16 20
      app/Services/ProcurementService.php
  73. 67 0
      app/Services/ProcurementWeiXinSendMessageService.php
  74. 37 0
      app/Services/RejectedBillService.php
  75. 2 2
      app/Services/StationRuleBatchService.php
  76. 5 2
      app/Services/StationService.php
  77. 2 1
      app/Services/StationTaskBatchService.php
  78. 5 0
      app/Services/StationTaskMaterialBoxService.php
  79. 2 3
      app/Services/StationTaskService.php
  80. 2 3
      app/Services/StoreService.php
  81. 45 0
      app/Services/UnitService.php
  82. 0 22
      app/Services/WaybillService.php
  83. 1 15
      app/Store.php
  84. 3 0
      app/User.php
  85. 1 1
      app/UserDetail.php
  86. 2 2
      config/api.php
  87. 1 1
      config/api_logistic.php
  88. 16 0
      config/weiXin.php
  89. 1 1
      database/migrations/2020_11_30_140958_create_stations_table.php
  90. 1 1
      database/migrations/2021_02_19_110139_change_owner_operation_owner_table.php
  91. 2 2
      database/migrations/2021_02_26_152744_change_owner_fee_details_table_change_volume_column.php
  92. 32 0
      database/migrations/2021_03_19_134619_add_openid_column_to_user_details.php
  93. 39 0
      database/migrations/2021_03_23_140544_add_configurations_data.php
  94. 32 0
      database/migrations/2021_03_24_131737_change_table_process_add_column_designate_id.php
  95. 11 1
      database/seeds/ConfigurationSeeder.php
  96. 5 5
      laravel-echo-server.json
  97. 44 0
      laravel-echo-server.json.configed
  98. BIN
      public/images/QRCodeIMG/1.png
  99. 16 1
      resources/sass/text.scss
  100. 211 38
      resources/views/customer/project/create.blade.php

+ 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);

+ 26 - 0
app/Components/ApiProcurementResponse.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Components;
+
+use Illuminate\Support\Facades\Gate;
+use Maatwebsite\Excel\Facades\Excel;
+
+trait ApiProcurementResponse{
+
+    public function success($data = null,$message = null): \Illuminate\Http\JsonResponse
+    {
+        $status_code=200;
+        $result = ['status'=>1];
+        if ($data)$result["data"] = $data;
+        if ($message)$result["message"] = $message;
+        return response()->json($result,$status_code);
+    }
+
+    public function error($message = null): \Illuminate\Http\JsonResponse
+    {
+        $status_code=401;
+        $result = ['status'=>0,'message'=>$message];
+        if ($message)$result["message"] = $message;
+        return response()->json($result,$status_code);
+    }
+}

+ 8 - 0
app/Console/Commands/CreateProcurementTotalBill.php

@@ -2,7 +2,9 @@
 
 namespace App\Console\Commands;
 
+use App\Jobs\ProcurementCheckConfirmInform;
 use App\ProcurementCheckSheet;
+use App\ProcurementTotalBill;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
@@ -61,6 +63,12 @@ class CreateProcurementTotalBill extends Command
         if (count($totalBill)>0){
             DB::table("procurement_total_bills")->insert($totalBill);
             app('LogService')->log(__METHOD__,"采购管理-生成月账单报表",json_encode($totalBill));
+            $procurementTotalBills=ProcurementTotalBill::query()
+                ->withCount('procurement')
+                ->with(['supplier.user.userDetail'])
+                ->where('counting_month',$date.'-01')
+                ->get();
+            dispatch(new ProcurementCheckConfirmInform($procurementTotalBills));
         }
     }
 

+ 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 - 0
app/Console/Commands/SyncOrderPackageLogisticRouteTask.php

@@ -2,6 +2,7 @@
 
 namespace App\Console\Commands;
 
+use App\Services\LogService;
 use App\Services\OrderPackageReceivedSyncService;
 use Illuminate\Console\Command;
 
@@ -38,6 +39,7 @@ class SyncOrderPackageLogisticRouteTask extends Command
      */
     public function handle()
     {
+        LogService::log(__CLASS__,"同步快递信息",'');
         ini_set('memory_limit','2226M');
         (new OrderPackageReceivedSyncService)->syncLogisticRoute();
     }

+ 3 - 0
app/Console/Kernel.php

@@ -4,6 +4,7 @@ namespace App\Console;
 
 use App\Console\Commands\BeforeCreateOwnerReport;
 use App\Console\Commands\ClearCancelledOrderTask;
+use App\Console\Commands\CreateProcurementTotalBill;
 use App\Console\Commands\CreateWeightStatistic;
 use App\Console\Commands\FluxOrderFix;
 use App\Console\Commands\InventoryDailyLoggingOwner;
@@ -46,6 +47,7 @@ class  Kernel extends ConsoleKernel
         WasSyncWmsAsnInformation::class,
         CreateWeightStatistic::class,
         BeforeCreateOwnerReport::class,
+        CreateProcurementTotalBill::class,
     ];
 
     /**
@@ -72,6 +74,7 @@ class  Kernel extends ConsoleKernel
         $schedule->command('clear:cancelledOrder')->everyTenMinutes();
         $schedule->command('WasSyncWmsAsnInformation')->everyMinute();
         $schedule->command('create:weightStatistic')->dailyAt("00:30");
+        $schedule->command('createProcurementTotalBill')->monthlyOn(1);
     }
 
     /**

+ 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',
+        ]
+    ];
 }

+ 15 - 2
app/Http/Controllers/Auth/RegisterController.php

@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
 
 use App\User;
 use App\Http\Controllers\Controller;
+use App\UserDetail;
+use Carbon\Carbon;
 use Illuminate\Auth\Events\Registered;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
@@ -75,17 +77,28 @@ class RegisterController extends Controller
     }
     public function register(Request $request)
     {
-
         $headTo=$request->input('headTo')??'';
         $this->validator($request->all())->validate();
 
         event(new Registered($user = $this->create($request->all())));
-
+        $phone=$request->input('phone');
+        if ($phone) UserDetail::query()->create([
+            'user_id'=>$user['id'],
+            'full_name'=>$user['name'],
+            'mobile_phone'=>$phone,
+            'created_at'=>Carbon::now()->toDateTimeString(),
+            'updated_at'=>Carbon::now()->toDateTimeString(),
+        ]);
         $rolesIds=$request->input('role')??'';
         if($rolesIds){
             $roleIdArr=explode(',',$rolesIds);
             $user->roles()->sync($roleIdArr);
         }
+        $supplierIds=$request->input('supplier')??'';
+        if($supplierIds){
+            $supplierIdArr=explode(',',$supplierIds);
+            $user->suppliers()->sync($supplierIdArr);
+        }
 //        $this->guard()->login($user);
         $carrierIds=$request->input('carrier')??'';
         if ($carrierIds){

+ 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;

+ 3 - 0
app/Http/Controllers/ConfigurationController.php

@@ -7,6 +7,7 @@ use App\Configuration;
 use App\Filters\ConfigurationFilters;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
 
 class ConfigurationController extends Controller
 {
@@ -24,6 +25,7 @@ class ConfigurationController extends Controller
         $params = $request->all();
         $params['operator'] = Auth::user()['id'];
         $configuration = Configuration::query()->create($params);
+        Cache::put($params['name'],$configuration);
         if($configuration)$this->success($configuration->loadMissing('operator'));
         $this->error('创建失败');
     }
@@ -36,6 +38,7 @@ class ConfigurationController extends Controller
         $params = $request->only(['name','value','description']);
         $params['operator'] = Auth::user()['id'];
         $configuration->update($params);
+        Cache::put($params['name'],$configuration);
         $this->success($configuration->loadMissing('operator'));
     }
 

+ 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;

+ 4 - 2
app/Http/Controllers/MaterialController.php

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
 use App\Components\AsyncResponse;
 use App\Exceptions\WarningException;
 use App\Filters\MaterialFilters;
+use App\Http\Requests\Material\MaterialRequest;
 use App\Material;
 use Illuminate\Http\Request;
 
@@ -19,7 +20,7 @@ class MaterialController extends Controller
         return view('maintenance/material/index',compact('materials'));
     }
 
-    public function storeApi(Request $request):array
+    public function storeApi(MaterialRequest $request):array
     {
         $this->gate('耗材类型-编辑');
         $material = Material::query()->where('code',$request['code'])->first();
@@ -32,9 +33,10 @@ class MaterialController extends Controller
         }
     }
 
-    public function updateApi(Request $request):array
+    public function updateApi(MaterialRequest $request):array
     {
         $this->gate('耗材类型-编辑');
+        /** @var Material $material */
         $material = Material::query()->find($request['id']);
         try {
             $material->update($request->all(['code', 'name']));

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

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
 use App\Components\AsyncResponse;
 use App\Exceptions\Exception;
 use App\Filters\OwnerMaterialFilters;
+use App\Http\Requests\OwnerMaterial\OwnerMaterialRequest;
 use App\Material;
 use App\OwnerMaterial;
 use App\Services\OwnerService;
@@ -28,7 +29,7 @@ class OwnerMaterialController extends Controller
         return view('/maintenance/ownerMaterial/index',compact('ownerMaterials','owners','materials'));
     }
 
-    public function storeApi(Request  $request):array
+    public function storeApi(OwnerMaterialRequest  $request):array
     {
         $this->gate('项目耗材-编辑');
         $params = $request->all(['owner_id', 'material_id', 'material_code', 'size', 'special', 'specification']);
@@ -42,7 +43,7 @@ class OwnerMaterialController extends Controller
         }
     }
 
-    public function updateApi(Request $request)
+    public function updateApi(OwnerMaterialRequest $request)
     {
         $this->gate('项目耗材-编辑');
         $material = OwnerMaterial::query()->find($request['id']);

+ 5 - 6
app/Http/Controllers/PackageLogisticController.php

@@ -19,18 +19,17 @@ class PackageLogisticController extends Controller
         $this->middleware('auth');
     }
 
-    public function index(Request $request,OrderPackageFilters $filters)
+    public function index(Request $request, OrderPackageFilters $filters)
     {
         /** @var UserService $userService */
         $userService = app('UserService');
         $owner_ids = $userService->getPermittingOwnerIds(auth()->user());
         $paginateParams = $request->input();
-        $orderPackages = OrderPackage::query()->filter($filters)
-            ->whereIn('owner_id',$owner_ids)->with(['order' => function ($query) {
-            $query->with(['logistic', 'owner', 'packages.commodities']);
-        }])->orderByDesc('id')->paginate($request->paginate ?? 50);
+        $orderPackages = OrderPackage::query()
+            ->filter($filters)
+            ->whereIn('owner_id', $owner_ids)->with(['order.logistic', 'order.owner'])->orderByDesc('id')->paginate($request->paginate ?? 50);
         $logistics = Logistic::all();
         $owners = Owner::find($owner_ids);
-        return view('package.logistic.index', compact('orderPackages', 'logistics', 'owners','paginateParams'));
+        return view('package.logistic.index', compact('orderPackages', 'logistics', 'owners', 'paginateParams'));
     }
 }

+ 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,"二次加工统计记录");
     }
 }

+ 56 - 46
app/Http/Controllers/ProcurementController.php

@@ -10,19 +10,26 @@ use App\Http\Requests\Procurement\EnquiryRequest;
 use App\Http\Requests\Procurement\ProcurementAmountRequest;
 use App\Http\Requests\Procurement\ProcurementRequest;
 use App\Http\Requests\Procurement\ProofRequest;
+use App\Jobs\ProcurementConfirmInform;
+use App\Jobs\ProcurementEnquiry;
+use App\Jobs\ProcurementReceive;
+use App\Jobs\ProcurementWaitConfirmInform;
 use App\Material;
 use App\Procurement;
 use App\ProcurementCheckSheet;
 use App\ProcurementDeliverie;
 use App\ProcurementTotalBill;
 use App\Services\common\ExportService;
+use App\Services\ConfigurationService;
 use App\Services\OwnerMaterialService;
 use App\Services\ProcurementService;
 use App\Services\ProcurementTotalBillService;
 use App\Supplier;
 use Carbon\Traits\Date;
 use Illuminate\Http\Request;
+use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Gate;
 use Matrix\Builder;
 
@@ -47,8 +54,10 @@ class ProcurementController extends Controller
         $procurement_code .= date ("ymd").str_pad($number_id>99999?$number_id%99999:$number_id,4,"0",STR_PAD_LEFT);
         /** @var ProcurementService $procurementService*/
         $procurementService=app(ProcurementService::class);
-        $deadline=$procurementService->computeDeadline($procurement->created_at);
+        $deadline=$procurementService->computeDeadline(Carbon::now()->toDateTimeString());
         $procurement->update(['code'=>$procurement_code,'deadline'=>$deadline]);
+        if ($procurement->type==0)  dispatch(new ProcurementEnquiry($procurement))->delay(Carbon::parse($deadline)); //采购单创建时 推送到队列中
+        dispatch(new ProcurementConfirmInform($procurement));  //推送发送订单通知消息模板  队列
         return $procurement;
     }
 
@@ -62,7 +71,11 @@ class ProcurementController extends Controller
             ->filter($filters)
             ->with(['initiator','ownerMaterial.file','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
                 $query->with('customer')->whereIn('id',$owner_ids);
-            }])->paginate($param['paginate'] ?? 50);
+            },'procurementDeliveries'])->paginate($param['paginate'] ?? 50);
+        foreach ($procurements as $procurement){
+            if (empty($procurement->procurementDeliveries))continue;
+            $procurement->deliver_amount=$procurement->procurementDeliveries->sum('amount');
+        }
         /** @var OwnerMaterialService $ownerMaterialService*/
         $ownerMaterialService=app(OwnerMaterialService::class);
         $owners=$ownerMaterialService->getOwnerPermittingWithMaterial();
@@ -92,6 +105,7 @@ class ProcurementController extends Controller
     }
     public function createProcurement(ProcurementRequest $request): array
     {
+
         $this->gate('采购管理-采购-新建');
         $request->validated();
         $param=$request->all(['owner_material_id','quantity','amount','unit_price']);
@@ -129,6 +143,7 @@ class ProcurementController extends Controller
             $procurementService=app(ProcurementService::class);
             $deadline=$procurementService->computeDeadline($procurement->created_at);
             $procurement->update(['code'=>$procurement_code,'deadline'=>$deadline]);
+            dispatch(new ProcurementConfirmInform($procurement));  //推送发送订单通知消息模板  队列
             $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer','ownerMaterial.file']);
             if ($procurement) return ['success' => true,'data' => $procurement];
             else return ['success' => false, 'message' => '添加失败'];
@@ -160,6 +175,7 @@ class ProcurementController extends Controller
             $procurementService=app(ProcurementService::class);
             $deadline=$procurementService->computeDeadline($procurement->created_at);
             $procurement->update(['code'=>$procurement_code,'deadline'=>$deadline]);
+            dispatch(new ProcurementConfirmInform($procurement));  //推送发送订单通知消息模板  队列
             $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer','ownerMaterial.file']);
             if ($procurement) return ['success' => true,'data' => $procurement];
             else return ['success' => false, 'message' => '添加失败'];
@@ -187,13 +203,15 @@ class ProcurementController extends Controller
         $this->gate('采购管理-采购-编辑');
         $request->validated();
         $param=$request->all();
+        /**@var ConfigurationService $configurationService */
+        $configurationService=app(ConfigurationService::class);
+        $receive_time=$configurationService->getReceiveTime();
+        $priceCoefficient=$configurationService->getPriceCoefficient();
         try {
+            /** @var Procurement $procurement */
             $procurement=Procurement::query()->find($param['id']);
             $unit_price=$param['unit_price'];
-            if (!$unit_price){
-                $priceCoefficient=Configuration::query()->where('name','价格系数')->value('value');
-                $unit_price=$priceCoefficient*$param['offer'];
-            }
+            if (!$unit_price) $unit_price=$priceCoefficient*$param['offer'];
             $procurement->update([
                 'type'=>0,
                 'status'=>2,
@@ -202,7 +220,10 @@ class ProcurementController extends Controller
                 'unit_price'=>$unit_price,
                 'cost_price'=>$param['offer'],
                 'supplier_id'=>$param['supplier_id'],
+                'deadline'=>Carbon::parse(Carbon::now()->toDateTimeString())->subHours(-$receive_time)->toDateTimeString(),
             ]);
+            dispatch(new ProcurementReceive($procurement))->delay(now()->addHours($receive_time)); //可从系统配置获取
+            dispatch(new ProcurementWaitConfirmInform($procurement));
             $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer','ownerMaterial.file']);
             if ($procurement) return ['success' => true,'data' => $procurement];
             else return ['success' => false, 'message' => '发起采购失败'];
@@ -258,31 +279,6 @@ class ProcurementController extends Controller
         if (!empty($collect)) return ['success' => true,'data' => $collect];
     }
 
-
-
-    public function show(Procurement $procurement)
-    {
-        //
-    }
-
-
-    public function edit(Procurement $procurement)
-    {
-        //
-    }
-
-
-    public function update(Request $request, Procurement $procurement)
-    {
-        //
-    }
-
-
-    public function destroy(Procurement $procurement)
-    {
-        //
-    }
-
     public function checkBill(Request $request,ProcurementCheckSheetFilters $filters)
     {
         if(!Gate::allows('采购管理-财务-对账单')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
@@ -295,7 +291,8 @@ class ProcurementController extends Controller
         $materials=Material::query()->select('id','name')->get();
         return view('procurement/finance/checkBill',compact('procurementCheckSheets','suppliers','paginateParams','materials'));
     }
-    public function fillInvoice(Request $request){
+    public function fillInvoice(Request $request): array
+    {
         $this->gate('采购管理-财务-对账单');
         $id=$request->input('procurementCheckSheetId');
         $invoice_number=$request->input('invoice_number');
@@ -321,12 +318,14 @@ class ProcurementController extends Controller
             ->with(['initiator','supplier','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
                 /** @var Builder $query */
                 $query->with('customer')->whereIn('id',$owner_ids);
-            },'procurementDeliveries'=>function($builder){
-                /** @var Builder $builder */
-                $builder->orderByDesc('id')->first();
-            }])
+            },'procurementDeliveries'])
             ->where('type',0) //只取采购单
             ->paginate($param['paginate'] ?? 50);
+        foreach ($procurements as $procurement){
+            if (empty($procurement->procurementDeliveries))continue;
+            $procurement->deliver_amount=$procurement->procurementDeliveries->sum('amount');
+            $procurement->signed_at=$procurement->procurementDeliveries->first()['signed_at'];
+        }
         return view('procurement/finance/procurementBill',compact('suppliers','materials','owners','paginateParams','procurements'));
     }
 
@@ -348,8 +347,11 @@ class ProcurementController extends Controller
             ->filter($filters)
             ->with(['initiator','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
                 $query->with('customer')->whereIn('id',$owner_ids);
-            }])->get();
-
+            },'procurementDeliveries'])->get();
+        foreach ($procurements as $procurement){
+            if (empty($procurement->procurementDeliveries))continue;
+            $procurement->deliver_amount=$procurement->procurementDeliveries->sum('amount');
+        }
         $procurementStatus=Procurement::status;
         $procurementType=Procurement::type;
         $row = ['采购编号','项目','单据类型','采购公司','耗材编号','耗材','尺寸大小','特殊要求','材质规格','采购数量','销售单价(元)','送货数量','销售总价(元)','采购单状态','联系方式'];
@@ -367,7 +369,7 @@ class ProcurementController extends Controller
                 $procurement->ownerMaterial ? $procurement->ownerMaterial->specification :'',
                 $procurement->quantity,
                 $procurement->unit_price,
-                '',//送货数量
+                $procurement->deliver_amount ?  $procurement->deliver_amount :'',//送货数量
                 $procurement->unit_price*$procurement->amount,//销售总价=销售数量*销售单价
                 is_null($procurement->status) ? '' :$procurementStatus[$procurement->status],
                 $procurement->ownerMaterial->owner->customer ? $procurement->ownerMaterial->owner->customer->phone :'',
@@ -410,9 +412,17 @@ class ProcurementController extends Controller
         $owner_ids=app('UserService')->getPermittingOwnerIds(auth()->user());
         $procurements = Procurement::query()
             ->filter($filters)
-            ->with(['initiator','supplier','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+            ->with(['supplier','initiator','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+                /** @var Builder $query */
                 $query->with('customer')->whereIn('id',$owner_ids);
-            }])->get();
+            },'procurementDeliveries'])
+            ->where('type',0) //只取采购单
+            ->get();
+        foreach ($procurements as $procurement){
+            if (empty($procurement->procurementDeliveries))continue;
+            $procurement->receive_amount=$procurement->procurementDeliveries->sum('receipt_amount');
+            $procurement->signed_at=$procurement->procurementDeliveries->first()['signed_at'];
+        }
 
         $procurementStatus=Procurement::status;
         $row = ['采购编号','采购日期','接单日期','签收日期','项目名称','采购公司','供应商','耗材编号','耗材','尺寸大小','特殊要求',
@@ -422,8 +432,8 @@ class ProcurementController extends Controller
             $list[] = [
                 $procurement->code,
                 $procurement->created_at,
-                '',//接单日期
-                '',//签收日期
+                $procurement->deadline ? $procurement->deadline : '',//接单日期
+                $procurement->signed_at ? $procurement->signed_at : '',//签收日期
                 $procurement->ownerMaterial->owner ? $procurement->ownerMaterial->owner->name :'',
                 $procurement->ownerMaterial->owner->customer ? $procurement->ownerMaterial->owner->customer->company_name :'',
                 $procurement->supplier ? $procurement->supplier->name :'',
@@ -434,11 +444,11 @@ class ProcurementController extends Controller
                 $procurement->ownerMaterial ? $procurement->ownerMaterial->specification :'',
                 $procurement->quantity,
                 $procurement->amount,
-                '',//收货数量
+                $procurement->receive_amount ? $procurement->receive_amount : '',//收货数量
                 $procurement->cost_price,
                 $procurement->unit_price,
-                '',//应收金额
-                '',//应付金额
+                $procurement->amount*$procurement->cost_price,//应收金额
+                $procurement->quantity*$procurement->unit_price,//应付金额
                 is_null($procurement->status) ? '' :$procurementStatus[$procurement->status],
             ];
         }

+ 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'];

+ 40 - 42
app/Http/Controllers/SupplierController.php

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use App\Components\AsyncResponse;
 use App\Filters\SupplierFilters;
+use App\Http\Requests\Supplier\SupplierRequest;
 use App\Material;
 use App\MaterialSupplier;
 use App\Supplier;
@@ -12,76 +13,73 @@ use Illuminate\Http\Request;
 class SupplierController extends Controller
 {
     use AsyncResponse;
-    public function index(Request $request,SupplierFilters $filters)
+
+    public function index(Request $request, SupplierFilters $filters)
     {
         $this->gate('供应商');
-        $suppliers = Supplier::query()->with('material')->orderByDesc('id')->filter($filters)->paginate($request['paginate']??50);
-        $materials=Material::query()->select('id','name')->get();
-        return view('/maintenance/supplier/index',compact('suppliers','materials'));
+        $suppliers = Supplier::query()->with('material')->orderByDesc('id')->filter($filters)->paginate($request['paginate'] ?? 50);
+        $materials = Material::query()->select('id', 'name')->get();
+        return view('/maintenance/supplier/index', compact('suppliers', 'materials'));
     }
 
-    public function storeApi(Request $request)
+    public function storeApi(SupplierRequest $request)
     {
         $this->gate('供应商-编辑');
-        $supplier = Supplier::query()->create($request->addSupplier);
-        $material_supplier=[];
-        foreach ($request->material_id as $item){
-            $material_supplier[]=[
-              'material_id'=>$item,
-              'supplier_id'=>$supplier->id,
+        $supplier = Supplier::query()->create($request->all());
+        $material_supplier = [];
+        foreach ($request['material_id'] as $item) {
+            $material_supplier[] = [
+                'material_id' => $item,
+                'supplier_id' => $supplier['id'],
             ];
         }
         MaterialSupplier::query()->insert($material_supplier);
+        $supplier->loadMissing('material');
         $this->success($supplier);
     }
 
-    public function updateApi(Request $request)
+    public function updateApi(SupplierRequest $request)
     {
         $this->gate('供应商-编辑');
-        $editSupplier=$request->input('editSupplier');
-        $material_ids=$request->input('material_id');
-        $material_suppliers=MaterialSupplier::query()->where('supplier_id',$editSupplier['id'])->get();
-        $this->updateMaterial($material_suppliers,$material_ids,$editSupplier['id']);
-        $supplier = Supplier::query()->find($editSupplier['id']);
-        $bool= $supplier->update([
-            'name'=>$editSupplier['name'],
-            'contact_man'=>$editSupplier['contact_man'],
-            'phone'=>$editSupplier['phone'],
-            'invoice_title'=>$editSupplier['invoice_title'],
-            'bank'=>$editSupplier['bank'],
-            'bank_account'=>$editSupplier['bank_account'],
-            'opening_bank'=>$editSupplier['opening_bank']
-        ]);
-        if($bool)$this->success($supplier->loadMissing('material'));
+        $material_suppliers = MaterialSupplier::query()->where('supplier_id', $request['id'])->get();
+        $this->updateMaterial($material_suppliers, $request['material_id'], $request['id']);
+        /** @var Supplier $supplier */
+        $supplier = Supplier::query()->find($request['id']);
+        $bool = $supplier->update($request->all());
+        if ($bool) $this->success($supplier->loadMissing('material'));
         $this->error('更新异常');
     }
 
     public function destroyApi($id)
     {
         $this->gate('供应商-删除');
+        /** @var Supplier $supplier */
         $supplier = Supplier::query()->find($id);
         $supplier->delete();
         $this->success();
     }
-    private function updateMaterial($material_suppliers,$material_ids,$supplier_id){
-        $exist=[]; $adds=[];$addMaterial=[];
-        foreach ($material_suppliers as $material_supplier){
-            $exist[]=$material_supplier['material_id'];
+
+    private function updateMaterial($material_suppliers, $material_ids, $supplier_id)
+    {
+        $exist = [];
+        $adds = [];
+        $addMaterial = [];
+        foreach ($material_suppliers as $material_supplier) {
+            $exist[] = $material_supplier['material_id'];
         }
-        $deletes=array_diff($exist,$material_ids);
-        foreach ($material_ids as $id){
-            if (empty($material_suppliers->where('material_id',$id)->first()))$adds[]=$id;
+        $deletes = array_diff($exist, $material_ids);
+        foreach ($material_ids as $id) {
+            if (empty($material_suppliers->where('material_id', $id)->first())) $adds[] = $id;
         }
-        foreach ($adds as $add){
-            $addMaterial[]=[
-                'material_id'=>$add,
-                'supplier_id'=>$supplier_id,
+        foreach ($adds as $add) {
+            $addMaterial[] = [
+                'material_id' => $add,
+                'supplier_id' => $supplier_id,
             ];
         }
-        if (count($addMaterial)>0) MaterialSupplier::query()->insert($addMaterial);
-        foreach ($deletes as $delete){
-            MaterialSupplier::query()->where('material_id',$delete)
-                ->where('supplier_id',$supplier_id)->delete();
+        if (count($addMaterial) > 0) MaterialSupplier::query()->insert($addMaterial);
+        foreach ($deletes as $delete) {
+            MaterialSupplier::query()->where('material_id', $delete)->where('supplier_id', $supplier_id)->delete();
         }
     }
 }

+ 51 - 453
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;
@@ -99,11 +101,13 @@ use App\Services\OrderTrackingOwnerService;
 use App\Services\OrderTrackingService;
 use App\Services\OwnerPriceOperationService;
 use App\Services\OwnerService;
+use App\Services\ProcurementWeiXinSendMessageService;
 use App\Services\RegionService;
 use App\Services\RejectedBillService;
 use App\Services\ShopService;
 use App\Services\StoreService;
 use App\Services\WarehouseService;
+use App\Station;
 use App\StationRuleBatch;
 use App\StationTask;
 use App\StationTaskMaterialBox;
@@ -155,55 +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');
-        dd($a= $response->json());
-        dd(config('api.haiq.storage.moveBin'));
-        $a=Http::post(config('api.haiq.storage.moveBin'), [
-  "taskMode"=> 2,
-  "bins"=> [
-    [
-        "taskCode"=> 65,
-      "binCode"=> "H01-001-3",
-      "fromLocCode"=> "",
-      "toLocCode"=> ""
-    ]
-  ],
-  "groupCode"=> "1761616223042.4121",
-  "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,11 +270,37 @@ sql;
         return "cacheing get:'$cache'<script>document.write('<br>localStorage:'+localStorage.getItem('storedTest'))</script>";
     }
 
-    function t1(Request $request)
+    function hProcessed(Request $request)
     {
-
-        $re = OracleDOCWaveDetails::query()->where('orderno', 'SO201230003574')->get('seqno')->first()['seqno'];
-        dd($re);
+        app('ForeignHaiRoboticsService')->markBinProcessed(
+            '1',
+            'IDE0005680',
+            true,
+            "2021-56-24 05-03-15",
+            '',
+            true
+        );
+    }
+    function hBatch(Request $request)
+    {
+        $a=[
+            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);
     }
 
     function packageT(Request $request)
@@ -583,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();
@@ -596,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)
     {/**/
@@ -915,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()
     {
@@ -955,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()
     {
 
@@ -1210,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();

+ 25 - 3
app/Http/Controllers/UserController.php

@@ -3,9 +3,13 @@
 namespace App\Http\Controllers;
 
 use App\Role;
+use App\Supplier;
 use App\User;
+use App\UserDetail;
 use App\UserWorkgroup;
+use Doctrine\DBAL\Configuration;
 use Exception;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Auth;
@@ -23,7 +27,8 @@ class UserController extends Controller
     public function index(Request $request)
     {
         if(!Gate::allows('用户-查询')){ return redirect(url('/'));  }
-        $query = User::with(['roles','logistics','userWorkgroups']);
+        $userDetailQuery = UserDetail::query()->select('user_id')->where('type','临时工');
+        $query = User::with(['roles','logistics','userWorkgroups','suppliers','userDetail'])->whereNotIn('id',$userDetailQuery);
         if($request->has('user')){
            $query->where('name','like',$request->input('user'));
         }
@@ -51,7 +56,8 @@ class UserController extends Controller
         $roles=Role::all();
         $logistics=app('LogisticService')->getSelection(["id","name"],"物流");
         $userWorkgroups=UserWorkgroup::query()->get();
-        return view('maintenance.user.create',['rolesAll'=>$roles,'logistics'=>$logistics,'userWorkgroups'=>$userWorkgroups]);
+        $suppliers=Supplier::query()->get();
+        return view('maintenance.user.create',['rolesAll'=>$roles,'logistics'=>$logistics,'userWorkgroups'=>$userWorkgroups,'suppliers'=>$suppliers]);
     }
 
 
@@ -78,13 +84,16 @@ class UserController extends Controller
     public function edit(User $user)
     {
         if(!Gate::allows('用户-编辑')){ return redirect(url('/'));  }
+        $user=$user->loadMissing('userDetail');
         $rolesAll=Role::all();
         $roles=$user->roles()->get();
         $logistics=app('LogisticService')->getSelection(["id","name"],"物流");
         $logisticUser=$user->logistics()->get();
         $userWorkgroups=UserWorkgroup::query()->get();
         $userWorkgroup=$user->userWorkgroups()->first();
-        return view('maintenance.user.edit',compact('user','rolesAll','roles','logistics','logisticUser','userWorkgroups','userWorkgroup'));
+        $supplierUser=$user->suppliers()->get();
+        $suppliers=Supplier::query()->get();
+        return view('maintenance.user.edit',compact('user','rolesAll','roles','logistics','logisticUser','userWorkgroups','userWorkgroup','suppliers','supplierUser'));
     }
 
     /**
@@ -96,6 +105,7 @@ class UserController extends Controller
      */
     public function update(Request $request, User $user)
     {
+
         if(!Gate::allows('用户-编辑')){ return redirect(url('/'));  }
         $this->validatorUpdate($request->all())->validate();
         $user->fill($request->all());
@@ -107,6 +117,13 @@ class UserController extends Controller
         }else{
             $user->roles()->sync([]);
         }
+        $supplierIds=$request->input('supplier')??'';
+        if($supplierIds){
+            $supplierIdArr=explode(',',$supplierIds);
+            $user->suppliers()->sync($supplierIdArr);
+        }else{
+            $user->suppliers()->sync([]);
+        }
         $carrierIds=$request->input('logistic')??'';
         if($carrierIds){
             $carrierIds=explode(',',$carrierIds);
@@ -120,6 +137,11 @@ class UserController extends Controller
         }else{
             $user->userWorkgroups()->sync([]);
         }
+        $phone=$request->input('phone');
+        $user=$user->loadMissing('userDetail');
+        if ($phone && $user->userDetail){
+            if ($phone!=$user->userDetail->mobile_phone) UserDetail::query()->where('user_id',$user->id) ->update(['mobile_phone'=>$phone]);
+        }
         app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/user/')->with('successTip',"成功修改用户“{$user['name']}”!");
     }

+ 0 - 61
app/Http/Controllers/api/procurement/wechat/AuthController.php

@@ -1,61 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\api\procurement\wechat;
-
-use App\User;
-use Firebase\JWT\JWT;
-use App\Http\Controllers\Controller;
-use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Support\Facades\Hash;
-
-class AuthController extends Controller
-{
-
-    public function login()
-    {
-        $phone=request('phone');
-        $password = request("password");
-        $user=User::query()->with('roles')
-            ->whereHas('userDetail',function ($query)use($phone){
-            /** @var Builder $query */
-            $query->where('mobile_phone',$phone);
-        })->whereHas('roles',function ($builder){
-                /** @var Builder $builder */
-            $builder->whereIn('name',['供应商','收货员']);
-            })
-            ->first();
-        if (!$user)return response()->json(['status'=>0,'message' => '当前用户不存在!'], 401);
-        if (!Hash::check($password,$user->password)) return response()->json(['status'=>0,'message' => '很抱歉,您的手机号和密码不匹配'], 401);
-
-        $credentials = [
-            'id'=>$user->id,
-            'name'=>$user->name,
-        ];
-        $token = $this->getJWTToken($credentials);
-        $userType=0;
-        foreach ($user->roles as $role){
-            if ($role->name=='供应商')$userType=1;
-            if ($role->name=='收货员')$userType=2;
-        }
-        return response()->json(['status'=>1,'message' => $userType,'data'=>$token], 200);
-    }
-
-    public function getJWTToken($value)
-    {
-        $time = time();
-        $payload = [
-            'iat' => $time,
-            'nbf' => $time,
-            'exp' => $time+7200,
-            'data' => [
-                'id' => $value['id'],
-                'name' => $value['name']
-            ]
-        ];
-        $key =  env('JWT_SECRET');
-        $alg = 'HS256';
-        $token = JWT::encode($payload,$key,$alg);
-        return $token;
-    }
-
-}

+ 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'){   // 称重异常校验
@@ -69,8 +71,10 @@ class PackageController
         }
         $orderPackage->loadMissing('measuringMachine');
         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;
     }
 

+ 21 - 8
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),
@@ -114,9 +115,15 @@ class StorageController
                 [
                 "taskCode"  =>'t'.Uuid::uuid4(),
                 "binCode"   => "IDE0005711",
-                "fromLocCode" => "HAIB2-03-03", //B1是面对架货右手,从右往左数列,第三个数字从下往上数行
+                "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'],

+ 86 - 0
app/Http/Controllers/api/thirdPart/weixin/AuthController.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Http\Controllers\api\thirdPart\weixin;
+
+use App\Components\ApiProcurementResponse;
+use App\User;
+use App\UserDetail;
+use Firebase\JWT\JWT;
+use App\Http\Controllers\Controller;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Http;
+
+class AuthController extends Controller
+{
+    use ApiProcurementResponse;
+
+    public function login(): \Illuminate\Http\JsonResponse
+    {
+        $phone=request('phone');
+        $password = request("password");
+        $user=User::query()->with('roles')
+            ->whereHas('userDetail',function ($query)use($phone){
+            /** @var Builder $query */
+            $query->where('mobile_phone',$phone);
+        })->whereHas('roles',function ($builder){
+                /** @var Builder $builder */
+            $builder->whereIn('name',['供应商','收货员']);
+            })
+            ->first();
+        if (!$user)return $this->error('当前用户不存在');
+        if (!Hash::check($password,$user->password))return $this->error('很抱歉,您的手机号和密码不匹配');
+
+        $credentials = [
+            'id'=>$user->id,
+            'name'=>$user->name,
+        ];
+        $token = $this->getJWTToken($credentials);
+        $userType=0;
+        foreach ($user->roles as $role){
+            if ($role->name=='供应商')$userType=1;
+            if ($role->name=='收货员')$userType=2;
+        }
+        return $this->success($token,$userType);
+    }
+
+    public function getJWTToken($value): string
+    {
+        $time = time();
+        $payload = [
+            'iat' => $time,
+            'nbf' => $time,
+            'exp' => $time+7200,
+            'data' => [
+                'id' => $value['id'],
+                'name' => $value['name']
+            ]
+        ];
+        $key =  env('JWT_SECRET');
+        $alg = 'HS256';
+        $token = JWT::encode($payload,$key,$alg);
+        return $token;
+    }
+
+    public function banding(Request $request): \Illuminate\Http\JsonResponse
+    {
+        if (!$request->input('code'))return $this->error('code 不能为空!');
+        $requests= [
+            'appid'=>config('weiXin.xiaoChengXu.appId'), //小程序appid
+            'secret'=>config('weiXin.xiaoChengXu.appSecret'), //小程序appsecret
+            'js_code'=>$request->input('code'),
+            'grant_type'=>'authorization_code',
+        ];
+        $url='https://api.weixin.qq.com/sns/jscode2session?';
+        $get=Http::get($url,$requests);
+        $resp=$get->json();
+        if (!$resp['openid']) return $this->error('授权失败,无法获取openid');
+        UserDetail::query()
+            ->where('user_id',Auth::user()['id'])
+            ->update(['procurement_wechat_open_id'=>$resp['openid'],]);
+        return $this->success($resp['openid'],'获取openID成功');
+    }
+
+}

+ 22 - 16
app/Http/Controllers/api/procurement/wechat/ProcurementController.php → app/Http/Controllers/api/thirdPart/weixin/ProcurementController.php

@@ -1,7 +1,8 @@
 <?php
 
-namespace App\Http\Controllers\api\procurement\wechat;
+namespace App\Http\Controllers\api\thirdPart\weixin;
 
+use App\Components\ApiProcurementResponse;
 use App\Http\Controllers\Controller;
 use App\Procurement;
 use App\ProcurementCheckSheet;
@@ -16,6 +17,7 @@ use Illuminate\Support\Facades\Auth;
 
 class ProcurementController extends Controller
 {
+    use ApiProcurementResponse;
 
     public function getWaitQuotation(Request $request): \Illuminate\Http\JsonResponse
     {
@@ -26,14 +28,18 @@ class ProcurementController extends Controller
             ->where('status',$status)
             ->get();
         $keys = [];
+        $now=Carbon::now();
         foreach ($procurements as $key=>$procurement){
             if ($procurement->procurement_quotations_count>0 && $status==0 )$keys[]= $key;
             if ($procurement->type==2 && $procurement->supplier_id )$keys[]= $key;
-            if($status==0)$procurement->deadline=Carbon::parse($procurement->deadline)->diffInMilliseconds(Carbon::now()); //待报价倒计时4小时
+            if($status==0){
+                if ($procurement->deadline>$now) $procurement->deadline=Carbon::parse($procurement->deadline)->diffInMilliseconds(); //待报价倒计时4小时
+                else $procurement->deadline=0;
+            }
             if($status==2)$procurement->deadline=Carbon::parse($procurement->deadline)->subHours(-24)->diffInMilliseconds(Carbon::now()); //待接单倒计时24小时
         }
         $procurements = $procurements->diffKeys($keys);
-        if (!empty($procurements))return response()->json(['status'=>1,'data'=>$procurements], 200);
+        if (!empty($procurements)) return $this->success($procurements);
     }
 
     public function getQuotationDetailById(Request $request): \Illuminate\Http\JsonResponse
@@ -43,7 +49,7 @@ class ProcurementController extends Controller
             ->with(['ownerMaterial.material','ownerMaterial.owner','ownerMaterial.file'])
             ->find($id);
         $procurement->deadline=Carbon::parse($procurement->deadline)->diffInMilliseconds(Carbon::now());
-        if ($procurement) return response()->json(['status'=>1,'data'=>$procurement], 200);
+        if ($procurement) return $this->success($procurement);
     }
     //报价
     public function setOffer(Request $request): \Illuminate\Http\JsonResponse
@@ -64,7 +70,7 @@ class ProcurementController extends Controller
             'status'=>1,//2:已报价
         ]);
         $procurement->update(['status'=>1]);//1:已报价
-        if ($procurementQuotation) return response()->json(['status'=>1,'data'=>$procurementQuotation], 200);
+        if ($procurementQuotation) return $this->success($procurementQuotation);
     }
     //接单
     public function accept(Request $request): \Illuminate\Http\JsonResponse
@@ -81,7 +87,7 @@ class ProcurementController extends Controller
         }else{
             $procurement->update(['status'=>4,'deadline'=>Carbon::now()->toDateTimeString()]);//4:生产中
         }
-        if ($procurement) return response()->json(['status'=>1,'data'=>$procurement], 200);
+        if ($procurement) return $this->success($procurement);
     }
     //生产中的订单
     public function getProductionProcurement(): \Illuminate\Http\JsonResponse
@@ -91,14 +97,14 @@ class ProcurementController extends Controller
             ->whereIn('type',[0,2])
             ->where('status',4) //4:生产中
             ->get();
-        if ($procurements) return response()->json(['status'=>1,'data'=>$procurements], 200);
+        if ($procurements) return $this->success($procurements);
     }
     //结束生产
     public function finishProductionProcurement(Request $request): \Illuminate\Http\JsonResponse
     {
         $id=$request->input('id');
         $procurement=Procurement::query()->find($id)->update(['status'=>5]);
-        if ($procurement) return response()->json(['status'=>1,'data'=>$procurement], 200);
+        if ($procurement) return $this->success($procurement);
     }
 
     public function getProcurementDeliveries(): \Illuminate\Http\JsonResponse
@@ -107,7 +113,7 @@ class ProcurementController extends Controller
             ->with('procurement.ownerMaterial.material')
             ->whereIn('status',[0,1])//1:待送货,2:送货中
             ->get();
-        if ($procurementDeliveries) return response()->json(['status'=>1,'data'=>$procurementDeliveries], 200);
+        if ($procurementDeliveries) return $this->success($procurementDeliveries);
     }
     public function makeProcurementDelivery(Request $request): \Illuminate\Http\JsonResponse
     {
@@ -138,20 +144,20 @@ class ProcurementController extends Controller
         $procurementDelivery->loadMissing( 'procurement.ownerMaterial.material');
         //当前采购单不是打样单生成对账单
         if ($procurement->type!=2)ProcurementCheckSheet::query()->create(['procurement_delivery_id'=>$procurementDelivery->id,'account_payable'=>$procurementDelivery->receipt_amount*$procurement->cost_price,'auditor'=>0]);
-        if ($procurementDelivery) return response()->json(['status'=>1,'data'=>$procurementDelivery], 200);
+        if ($procurementDelivery) return $this->success($procurementDelivery);
     }
     public function getProcurementDeliveryById(Request $request): \Illuminate\Http\JsonResponse
     {
         $procurementDelivery=ProcurementDeliverie::query()
             ->with(['procurement.ownerMaterial.material','receiver.userDetail','procurement.ownerMaterial.owner.customer','procurement.supplier','procurement.ownerMaterial.file'])
             ->find($request->input('id'));
-        if ($procurementDelivery) return response()->json(['status'=>1,'data'=>$procurementDelivery], 200);
+        if ($procurementDelivery) return $this->success($procurementDelivery);
     }
     public function updateProcurementDeliveryAmount(Request $request): \Illuminate\Http\JsonResponse
     {
         $param=$request->all(['id','delivernum']);
         $procurementDelivery=ProcurementDeliverie::query()->where('id',$param['id'])->update(['amount'=>$param['delivernum']]);
-        if ($procurementDelivery)return response()->json(['status'=>1,'data'=>$procurementDelivery], 200);
+        if ($procurementDelivery)return $this->success($procurementDelivery);
     }
 
     public function getProcurementTotalBill(): \Illuminate\Http\JsonResponse
@@ -162,13 +168,13 @@ class ProcurementController extends Controller
             /** @var  ProcurementTotalBill $procurementTotalBill */
             $procurementTotalBill->setCurrentMothProcurements();
         }
-        if ($procurementTotalBills) return response()->json(['status'=>1,'data'=>$procurementTotalBills], 200);
+        if ($procurementTotalBills) return $this->success($procurementTotalBills);
     }
     public function markProcurementTotalBillStatus(Request $request): \Illuminate\Http\JsonResponse//供应商提交对账单
     {
         $id=$request->input('id');
         $procurementTotalBill=ProcurementTotalBill::query()->find($id)->update(['status'=>1]);//1:已出账
-        return response()->json(['status'=>1,'data'=>$procurementTotalBill], 200);
+        return $this->success($procurementTotalBill);
     }
     //收货员确认收货
     public function makeReceipt(Request $request): \Illuminate\Http\JsonResponse
@@ -177,7 +183,7 @@ class ProcurementController extends Controller
         $procurementDelivery=ProcurementDeliverie::query()->with('procurement')->find($param['id']);
         $procurementDelivery ->update(['status'=>1,'receipt_amount'=>$param['delivernum'],'created_at'=>Carbon::now()->toDateTimeString(),'signed_at'=>Carbon::now()->toDateString()]);
         $procurementDelivery->procurement->update(['status'=>6]);
-        if ($procurementDelivery) return response()->json(['status'=>1,'data'=>$procurementDelivery], 200);
+        if ($procurementDelivery) return $this->success($procurementDelivery);
     }
     public function supplierDeliverConfirm(Request $request): \Illuminate\Http\JsonResponse
     {
@@ -190,6 +196,6 @@ class ProcurementController extends Controller
             && $procurementCheckSheet)
         $procurementCheckSheet->update(['status'=>1,'account_payable'=>($procurementDelivery->receipt_amount*$procurementDelivery->procurement->cost_price)]);
         $procurementDelivery->procurement->update(['status'=>7]);//待出账
-        if ($procurementDelivery) return response()->json(['status'=>1,'data'=>$procurementDelivery], 200);
+        if ($procurementDelivery) return $this->success($procurementDelivery);
     }
 }

+ 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));

+ 65 - 0
app/Http/Requests/Material/MaterialRequest.php

@@ -0,0 +1,65 @@
+<?php
+
+
+namespace App\Http\Requests\Material;
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Route;
+
+
+class MaterialRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    protected $storeApiRules =[
+        'name' => 'required',
+        'code' => 'required',
+    ];
+    protected $storeApiMessage = [
+        'name.required' => '耗材类型名称为必填项',
+        'code.required' => '编号为必填项'
+    ];
+
+    protected $updateApiRules = [
+        'name' => 'required',
+        'code' => 'required',
+        'id' =>  'required'
+    ];
+
+    protected $updateApiMessage = [
+        'name.required' => '名称不能为空',
+        'code.required' => '编号不能为空',
+        'id.required' => '未选中耗材类型',
+    ];
+
+
+    public function rules():array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName){
+            case 'material.storeApi':
+                return $this->storeApiRules;
+            case 'material.updateApi':
+                return $this->updateApiRules;
+            default:
+                return [];
+        }
+    }
+    public function messages():array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName){
+            case 'material.storeApi':
+                return $this->storeApiMessage;
+            case 'material.updateApi':
+                return $this->updateApiMessage;
+            default:
+                return [];
+        }
+    }
+}

+ 74 - 0
app/Http/Requests/OwnerMaterial/OwnerMaterialRequest.php

@@ -0,0 +1,74 @@
+<?php
+
+
+namespace App\Http\Requests\OwnerMaterial;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Route;
+
+class OwnerMaterialRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+
+    use RequestApiFormValidation;
+
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+
+    protected $storeApiRules = [
+        'owner_id' => 'required',       // 货主
+        'material_id' => 'required',    // 耗材
+        'size' => 'required',    // size
+        'material_code' => 'required',  // 耗材编码
+    ];
+    protected $storeApiMessage = [
+        'owner_id.required' => '货主为必选项',
+        'material_id.required' => '耗材为必选项',
+        'size.required' => '尺寸为必填项',
+        'material_code.required' => '耗材编码为必填项',
+    ];
+
+    protected $updateApiRules = [
+        'owner_id' => 'required',       // 货主
+        'material_id' => 'required',    // 耗材
+        'size' => 'required',    // size
+        'material_code' => 'required',  // 耗材编码
+    ];
+    protected $updateApiMessage = [
+        'owner_id.required' => '货主为必选项',
+        'material_id.required' => '耗材为必选项',
+        'size.required' => '尺寸为必填项',
+        'material_code.required' => '耗材编码为必填项',
+    ];
+
+    public function rules(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'ownerMaterial.storeApi':
+                return $this->storeApiRules;
+            case 'ownerMaterial.updateApi':
+                return $this->updateApiRules;
+            default:
+                return [];
+        }
+    }
+
+    public function messages(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'ownerMaterial.storeApi':
+                return $this->storeApiMessage;
+            case 'ownerMaterial.updateApi':
+                return $this->updateApiMessage;
+            default:
+                return [];
+        }
+    }
+
+}

+ 91 - 0
app/Http/Requests/Supplier/SupplierRequest.php

@@ -0,0 +1,91 @@
+<?php
+
+
+namespace App\Http\Requests\Supplier;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Route;
+
+class SupplierRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+
+    protected $storeApiRules = [
+        'name' => 'required',
+        'contact_man' => 'required',
+        'phone' => 'required|numeric',
+        'invoice_title' => 'required',
+        'bank' => 'required',
+        'bank_account' => 'required',
+        'opening_bank' => 'required',
+        'material_id'=> 'required'
+    ];
+    protected $storeApiMessage = [
+        'name.required' => '供应商能为必填项',
+        'contact_man.required' => '联系人为必填项',
+        'phone.required' => '联系电话为必填项',
+        'phone.numeric' => '联系电话必须由数字组成',
+        'invoice_title.required' => '发票抬头为必填项',
+        'bank.required' =>  '账户银行为必填项',
+        'bank_account.required' => '收款账号为必填项',
+        'opening_bank.required' => '开户银行为必填项',
+        'material_id.required' => '耗材类型为必选项',
+    ];
+
+    protected $updateApiRules = [
+        'name' => 'required',
+        'contact_man' => 'required',
+        'phone' => 'required|numeric',
+        'invoice_title' => 'required',
+        'bank' => 'required',
+        'bank_account' => 'required',
+        'opening_bank' => 'required',
+        'material_id'=> 'required'
+
+    ];
+    protected $updateMessage = [
+        'name.required' => '供应商能为必填项',
+        'contact_man.required' => '联系人为必填项',
+        'phone.required' => '联系电话为必填项',
+        'phone.numeric' => '联系电话必须由数字组成',
+        'invoice_title.required' => '发票抬头为必填项',
+        'bank.required' =>  '账户银行为必填项',
+        'bank_account.required' => '收款账号为必填项',
+        'opening_bank.required' => '开户银行必填项',
+        'material_id.required' => '耗材类型为必选项',
+    ];
+
+
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+
+    public function rules(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'supplier.storeApi':
+                return $this->storeApiRules;
+            case 'supplier.updateApi':
+                return $this->updateApiRules;
+            default:
+                return [];
+        }
+    }
+
+    public function messages(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'supplier.storeApi':
+                return $this->storeApiMessage;
+            case 'supplier.updateApi':
+                return $this->updateMessage;
+            default:
+                return [];
+        }
+    }
+}

+ 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;

+ 78 - 0
app/Jobs/ProcurementCheckConfirmInform.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Services\ProcurementWeiXinSendMessageService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Collection;
+
+class ProcurementCheckConfirmInform implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $procurementTotalBills;
+    /**
+     * Create a new job instance.
+     *
+     * @param Collection $procurementTotalBills
+     */
+    public function __construct(Collection $procurementTotalBills)
+    {
+        $this->procurementTotalBills=$procurementTotalBills;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        if (empty($this->procurementTotalBills)) return;
+        foreach ($this->procurementTotalBills as $procurementTotalBill){
+            foreach ($procurementTotalBill->supplier as $supplier) {
+                foreach ($supplier->user as $user){
+                   if($user->userDetail->procurement_wechat_open_id){
+                       $param['touser'] =$user->userDetail->procurement_wechat_open_id;
+                       $param['mp_template_msg'] =[
+                           "appid"=>config('weiXin.fuWuHao.appId'),
+                           "template_id"=>config('weiXin.fuWuHaoTemplate.check_sheet_inform'),
+                           "url"=>"http://weixin.qq.com/download",
+                           "miniprogram"=>[
+                               "appid"=>config('weiXin.appId.appId'),
+                               "pagepath"=>"pages/login/login"
+                           ],
+                           'data'=>[
+                               'first' => [
+                                   "value"=>"您好,您的对账单已生成。",
+                               ],
+                               'keyword1' => [
+                                   "value"=>$procurementTotalBill->created_at ?? '',
+                                   "color"=>"#173177"
+                               ],
+                               'keyword2' => [
+                                   "value"=>$procurementTotalBill->procurement_count ?? '',
+                                   "color"=>"#173177"
+                               ],
+                               'keyword3' => [
+                                   "value"=>$procurementTotalBill->total_payable ?? '',
+                                   "color"=>"#173177"
+                               ],
+                               'remark' => [
+                                   "value"=>'点击查看详情。',
+                               ],
+                           ]
+                       ];
+                       app(ProcurementWeiXinSendMessageService::class)->sendWenChantTemplate($param);
+                   }
+                }
+            }
+
+        }
+
+    }
+}

+ 81 - 0
app/Jobs/ProcurementConfirmInform.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Procurement;
+use App\Services\ProcurementWeiXinSendMessageService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class ProcurementConfirmInform implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $procurement;
+
+    /**
+     * Create a new job instance.
+     *
+     * @param Procurement $procurement
+     */
+    public function __construct(Procurement $procurement)
+    {
+        $this->procurement=$procurement;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $pro=$this->procurement->loadMissing(['ownerMaterial.material.supplier.user.userDetail','ownerMaterial.owner.customer']);
+        if (empty($pro->ownerMaterial->material->supplier))return;
+        $suppliers=$pro->ownerMaterial->material->supplier;
+        $open_ids=[];
+        foreach ($suppliers as $supplier) {
+            foreach ($supplier->user as $user){
+                $open_id = $user->userDetail->procurement_wechat_open_id ?? false;
+                if($open_id)$open_ids[]=$open_id;
+            }
+        }
+        $open_ids=array_unique($open_ids);
+        foreach ($open_ids as $open_id){
+            $param['touser'] =$open_id;
+            $param['mp_template_msg'] =[
+                "appid"=>config('weiXin.fuWuHao.appId'),
+                "template_id"=>config('weiXin.fuWuHaoTemplate.order_confirm_inform'),
+                "url"=>"http://weixin.qq.com/download",
+                "miniprogram"=>[
+                    "appid"=>config('weiXin.appId.appId'),
+                    "pagepath"=>"pages/login/login"
+                ],
+                'data'=>[
+                    'first' => [
+                        "value"=>"尊敬的供应商,你好!",
+                    ],
+                    'keyword1' => [
+                        "value"=>$pro->code ?? '',
+                        "color"=>"#173177"
+                    ],
+                    'keyword2' => [
+                        "value"=>$pro->ownerMaterial->owner->customer->company_name ?? '',
+                        "color"=>"#173177"
+                    ],
+                    'remark' => [
+                        "value"=>'请及时确认,谢谢。',
+                    ],
+                ]
+            ];
+            app(ProcurementWeiXinSendMessageService::class)->sendWenChantTemplate($param);
+        }
+
+    }
+
+
+
+}

+ 68 - 0
app/Jobs/ProcurementEnquiry.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Configuration;
+use App\Procurement;
+use App\Services\ConfigurationService;
+use App\Services\LogService;
+use App\Services\ProcurementService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Cache;
+
+class ProcurementEnquiry implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $procurement;
+    private $unit_price;
+    /**
+     * Create a new job instance.
+     *
+     * @param Procurement $procurement
+     */
+    public function __construct(Procurement $procurement)
+    {
+        $this->procurement=$procurement;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        /** @var ProcurementService $procurementService*/
+        /**@var ConfigurationService $configurationService */
+        $configurationService=app(ConfigurationService::class);
+        $receive_time=$configurationService->getReceiveTime();
+        $priceCoefficient=$configurationService->getPriceCoefficient();
+        $procurementService=app(ProcurementService::class);
+        $procurementQuotation=$procurementService->screenLowestQuotation($this->procurement->id);
+        if (!$procurementQuotation){
+            $this->procurement->update(['status'=>3]);
+            return;
+        }
+        if(!$this->procurement->unit_price)$this->unit_price=$priceCoefficient*$procurementQuotation['offer'];
+        try{
+           $this->procurement->update([
+               'status'=>2,
+               'unit_price'=>$this->unit_price,
+               'cost_price'=>$procurementQuotation['offer'],
+               'supplier_id'=>$procurementQuotation['supplier_id'],
+               'deadline'=>Carbon::parse(Carbon::now()->toDateTimeString())->subHours(-$receive_time)->toDateTimeString(),
+           ]);
+            dispatch(new ProcurementReceive($this->procurement))->delay(now()->addHours($receive_time)); //可从系统配置获取
+            dispatch(new ProcurementWaitConfirmInform($this->procurement));
+
+        }catch (\Exception $e){
+            LogService::log(__METHOD__,"ERROR-采购延时选定最低报价供应商",$this->procurement->toJson()." | ".$e->getMessage());
+        }
+    }
+}

+ 37 - 0
app/Jobs/ProcurementReceive.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Procurement;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class ProcurementReceive implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+    protected $procurement;
+
+    /**
+     * Create a new job instance.
+     *
+     * @param Procurement $procurement
+     */
+    public function __construct(Procurement $procurement)
+    {
+        $this->procurement=$procurement;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $procurement=Procurement::query()->find($this->procurement->id);
+        if ($procurement->status==2) $procurement->update(['status'=>3]);
+    }
+}

+ 82 - 0
app/Jobs/ProcurementWaitConfirmInform.php

@@ -0,0 +1,82 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Procurement;
+use App\Services\ProcurementWeiXinSendMessageService;
+use App\User;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Carbon;
+
+class ProcurementWaitConfirmInform implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $procurement;
+    /**
+     * Create a new job instance.
+     *
+     * @param Procurement $procurement
+     */
+    public function __construct(Procurement $procurement)
+    {
+        $this->procurement=$procurement;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $pro=$this->procurement->loadMissing(['supplier.user.userDetail']);
+        $initiator='';
+        if ($pro->initiator)$initiator=User::query()->where('id',$pro->initiator)->value('name');
+            foreach ($pro->supplier->user as $user){
+               if ($user->userDetail->procurement_wechat_open_id){
+                   $param['touser'] =$user->userDetail->procurement_wechat_open_id;
+                   $param['mp_template_msg'] =[
+                       "appid"=>config('weiXin.fuWuHao.appId'),
+                       "template_id"=>config('weiXin.fuWuHaoTemplate.wait_procurement_inform'),
+                       "url"=>"http://weixin.qq.com/download",
+                       "miniprogram"=>[
+                           "appid"=>config('weiXin.appId.appId'),
+                           "pagepath"=>"pages/login/login"
+                       ],
+                       'data'=>[
+                           'first' => [
+                               "value"=>"采购申请等待处理。",
+                           ],
+                           'keyword1' => [
+                               "value"=>$pro->code ?? '',
+                               "color"=>"#173177"
+                           ],
+                           'keyword2' => [
+                               "value"=> $initiator,
+                               "color"=>"#173177"
+                           ],
+                           'keyword3' => [
+                               "value"=>$pro->cost_price*$pro->quantity>0 ? $pro->cost_price*$pro->quantity.'元' :0 .'元',
+                               "color"=>"#173177"
+                           ],
+                           'keyword4' => [
+                               "value"=>Carbon::now()->toDateString(),
+                               "color"=>"#173177"
+                           ],
+                           'remark' => [
+                               "value"=>'请及时确认,谢谢。',
+                               "color"=>"#173177"
+                           ],
+                       ]
+                   ];
+                   app(ProcurementWeiXinSendMessageService::class)->sendWenChantTemplate($param);
+               }
+            }
+
+    }
+}

+ 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','质量验收');
-    }*/
 }

+ 8 - 6
app/Procurement.php

@@ -55,23 +55,25 @@ class Procurement extends Model
         }
     }
 
-    public  function ownerMaterial(){
+    public  function ownerMaterial(): \Illuminate\Database\Eloquent\Relations\HasOne
+    {
         return $this->hasOne('App\OwnerMaterial','id','owner_material_id');
     }
 
-    public  function supplier(){
+    public  function supplier(): \Illuminate\Database\Eloquent\Relations\HasOne
+    {
         return $this->hasOne('App\Supplier','id','supplier_id');
     }
 
-    public function initiator()
+    public function initiator(): \Illuminate\Database\Eloquent\Relations\BelongsTo
     {
         return $this->belongsTo(User::class,'initiator','id');
     }
-    public function procurementDeliveries()
+    public function procurementDeliveries(): \Illuminate\Database\Eloquent\Relations\HasMany
     {
-        return $this->hasMany('App\ProcurementDeliverie','procurement_id','id');
+        return $this->hasMany('App\ProcurementDeliverie','procurement_id','id')->orderByDesc('id');
     }
-    public function procurementQuotations()
+    public function procurementQuotations(): \Illuminate\Database\Eloquent\Relations\HasMany
     {
         return $this->hasMany('App\ProcurementQuotation','procurement_id','id');
     }

+ 7 - 1
app/ProcurementTotalBill.php

@@ -24,9 +24,15 @@ class ProcurementTotalBill extends Model
     protected $fillable=[
         'counting_month','supplier_id','status','total_payable'
     ];
-    public function supplier(){
+    public function supplier(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+    {
         return $this->belongsTo('App\Supplier','supplier_id','id');
     }
+    public function procurement()
+    {
+        return $this->hasMany('App\Procurement','supplier_id','supplier_id')
+            ->whereNotIn('status',[3,10]);
+    }
 
     //截取账单日期为月
     public function getCountingMonthAttribute($value)

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -10,6 +10,7 @@ use App\Services\CommodityService;
 use App\Services\common\BatchUpdateService;
 use App\Services\CommodityBarcodeService;
 use App\Services\common\DataHandlerService;
+use App\Services\ConfigurationService;
 use App\Services\CustomerLogService;
 use App\Services\CustomerLogStatusService;
 use App\Services\CustomerService;
@@ -64,6 +65,7 @@ use App\Services\ProcessService;
 use App\Services\ProcessStatisticService;
 use App\Services\ProcurementService;
 use App\Services\ProcurementTotalBillService;
+use App\Services\ProcurementWeiXinSendMessageService;
 use App\Services\ProvinceService;
 use App\Services\RealtimePendingOrdersService;
 use App\Services\RejectedBillItemService;
@@ -162,6 +164,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
         app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
         app()->singleton('CustomerService',CustomerService::class);
+        app()->singleton('ConfigurationService',ConfigurationService::class);
         app()->singleton('DataHandlerService',DataHandlerService::class);
         app()->singleton('DeliveryAppointment',DeliveryAppointment::class);
         app()->singleton('DeliveryAppointmentService',DeliveryAppointmentService::class);
@@ -217,6 +220,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('ProcessesContentService',ProcessesContentService::class);
         app()->singleton('ProcurementService',ProcurementService::class);
         app()->singleton('ProcurementTotalBillService',ProcurementTotalBillService::class);
+        app()->singleton('ProcurementWeiXinSendMessageService',ProcurementWeiXinSendMessageService::class);
         app()->singleton('ProvinceService',ProvinceService::class);
         app()->singleton('RealtimePendingOrdersService',RealtimePendingOrdersService::class);
         app()->singleton('RegionService',RegionService::class);

+ 4 - 3
app/Services/BatchService.php

@@ -55,13 +55,14 @@ class BatchService
 
     /**
      * 为波次附加任务,已附加的重复任务不影响
-     * @param Collection $batches
+     * @param $batches
      * @throws Exception
      */
-    public function assignTasks(Collection $batches)
+    public function assignTasks($batches)
     {
         try{
             LogService::log(__METHOD__,'assignTasks','波次任务分配1:'.json_encode($batches));
+            $batches = collect($batches);
 
             $this->instant($this->stationTaskBatchService,'StationTaskBatchService');
             $this->instant($this->stationRuleBatchService,'StationRuleBatchService');
@@ -78,7 +79,7 @@ class BatchService
             $stationTaskBatches=$this->stationTaskBatchService->createByBatches($batches_shouldProcess,$stationTasks); //注册波次任务
             LogService::log(__METHOD__,'assignTasks','波次任务分配4:'.json_encode($batches));
             $stationTaskMaterialBoxes=$this->stationTaskMaterialBoxService->createByBatches($batches_shouldProcess,$stationTasks); //注册料箱任务
-            LogService::log(__METHOD__,'assignTasks','波次任务分配5:'.json_encode($batches));
+            LogService::log(__METHOD__,'assignTasks','波次任务分配5:'.json_encode($stationTaskMaterialBoxes).json_encode($batches));
             $stationTaskCommodities=$this->stationTaskCommodityService->createByBatches($batches_shouldProcess,$stationTasks); //注册商品任务
             LogService::log(__METHOD__,'assignTasks','波次任务分配6:'.json_encode($batches));
 

+ 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],

+ 37 - 0
app/Services/ConfigurationService.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Services;
+
+use App\CarType;
+use App\Configuration;
+use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\Cache;
+
+
+class ConfigurationService
+{
+    use ServiceAppAop;
+    protected $modelClass=Configuration::class;
+
+    public function getEnquiryTime()
+    {
+        return Cache::remember('询价延时时间',null,function (){
+            return Configuration::query()->where('name','询价延时时间')->value('value');
+        });
+    }
+
+    public function getReceiveTime()
+    {
+        return Cache::remember('接单延时时间',null,function (){
+            return Configuration::query()->where('name','接单延时时间')->value('value');
+        });
+    }
+    public function getPriceCoefficient()
+    {
+        return Cache::remember('价格系数',null,function (){
+            return Configuration::query()->where('name','价格系数')->value('value');
+        });
+    }
+
+
+}

+ 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 - 19
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,13 +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('海柔请求','runMany','波次任务分配6.r5f2c1.51:');
+            $a = json_encode($dataToPost);
             $response = Http::post(config('api.haiq.storage.moveBin'), $dataToPost);
+            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){
-            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 = '错误: ';
@@ -291,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 ?? ''

+ 1 - 0
app/Services/InventoryAccountService.php

@@ -338,6 +338,7 @@ class InventoryAccountService
     //盘点库存
     public function stockInventory($id,$location,$barcode,$count,$inventoryAccountId){
         $inventoryAccountMission=InventoryAccountMission::with(['commodity.barcodes','stockInventoryPersons'])->find($id);
+        if (!$inventoryAccountMission)return null;
         $this->盘点($inventoryAccountId,$count,$inventoryAccountMission);
         $request=[
             'location'=>$location,

+ 2 - 1
app/Services/OrderPackageReceivedSyncService.php

@@ -104,7 +104,8 @@ class OrderPackageReceivedSyncService
         if (Carbon::now()->lte($initDate)) {//当前时间小于等于初始化时间
             //初始化查询一个月的数据,exception为否
             $query = $query->where('created_at', '>=', $initDate->subDays((int)config('api_logistic.days'))->toDateTimeString())
-                ->where('exception', '否');
+                ->where('exception', '否')
+                ->whereNull('received_at');
         } else {//当前时间大于初始化时间,exception为否且未收货
             $query = $query->where('created_at', '>=', $initDate->toDateTimeString())
                 ->where('exception', '否')

+ 13 - 26
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;
@@ -1007,7 +1008,7 @@ class OrderService
     {
         if (!$logistics)$logistics = app("OwnerPriceExpressService")->getBuildLogistic($owner);
         $query = DB::raw(<<<sql
-SELECT COUNT(1) count,logistic_id FROM orders WHERE wms_status = '订单完成' 
+SELECT COUNT(1) count,logistic_id FROM orders WHERE wms_status = '订单完成'
 AND owner_id = ?
 AND wms_edittime like ? GROUP BY logistic_id
 sql
@@ -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];
     }
 }

+ 2 - 2
app/Services/PackageService.php

@@ -39,8 +39,8 @@ class PackageService
             'batch_number' => ['like' => ''],
             'created_at_start' => ['alias' => 'created_at','startDate' => " 00:00:00"],
             'created_at_end' => ['alias' => 'created_at','endDate' => " 23:59:59"],
-            'weighed_at_start' => ['alias' => 'weighed_at','startDate' => " 00:00:00"],
-            'weighed_at_end' => ['alias' => 'weighed_at','endDate' => " 23:59:59"],
+            'weighed_at_start' => ['alias' => 'weighed_at', 'startDate' => ':00'],
+            'weighed_at_end' => ['alias' => 'weighed_at','endDate' => ":59"],
             'id' => ['multi' => ','],
         ];
         $packages = app(QueryService::class)->query($params,$packages,$columnQueryRules,"order_packages");

+ 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();
     }
 
 }

+ 16 - 20
app/Services/ProcurementService.php

@@ -20,35 +20,31 @@ class ProcurementService
     //选中最低报价
     public function screenLowestQuotation($procurement_id){
         if (!$procurement_id) return null;
-        $procurementQuotation=ProcurementQuotation::query()
+        return ProcurementQuotation::query()
             ->with(['supplier','procurement'])
             ->select('procurement_id','supplier_id','offer')
             ->orderBy('offer','asc')
             ->where('procurement_id',$procurement_id)
             ->first();
-        return $procurementQuotation;
     }
 
-    public function pushEnquiryToSupplier($procurement_id){
-        $procurement=Procurement::query()->find($procurement_id);
-        $procurement->loadMissing(['ownerMaterial.material.supplier']);
-        if (!empty($procurement->ownerMaterial->material->supplier))$suppliers=$procurement->ownerMaterial->material->supplier;
-        foreach ($suppliers as $supplier){
-            $procurementQuotation= new ProcurementQuotation([
-                'procurement_id'=>$procurement_id,
-                'supplier_id'=>$supplier->id,
-            ]);
-            $procurementQuotation->save();
-            //TODO 推送给指定耗材类型供应商
-        }
-    }
-    public function computeDeadline($time)
+    public function computeDeadline($time): string
     {
+        /**@var ConfigurationService $configurationService */
+        $configurationService=app(ConfigurationService::class);
+        $enquiry_time=$configurationService->getEnquiryTime();
         $date=Carbon::parse($time)->toDateString();
-        if ($time<$date." 09:00:00")$deadline=Carbon::parse($date." 09:00:00")->subHours(-4)->toDateTimeString();
-        if($time>=$date." 09:00:00" && $time<$date." 14:00:00") $deadline=Carbon::parse($time)->subHours(-4)->toDateTimeString();
-        if ($time>=$date." 14:00:00")$deadline=Carbon::parse($time)->subHours(-15-4)->toDateTimeString();
-        if ($deadline) return $deadline;
+        $date_tom=Carbon::parse($time)->subDays(-1)->toDateString();
+        $hour=Carbon::parse($time)->format('H');
+        if ($hour < 9)return Carbon::parse($date." 09:00:00")->subHours(-$enquiry_time)->toDateTimeString();
+        if ($hour >=9 && $hour <12)return Carbon::parse($time)->subHours(-$enquiry_time-1)->toDateTimeString();
+        if ($hour ==12)return Carbon::parse($date." 13:00:00")->subHours(-$enquiry_time)->toDateTimeString();
+        if ($hour >12 && $hour < 18){
+            if (18-$hour>=$enquiry_time) return Carbon::parse($date." ".$hour.":00:00")->subHours(-$enquiry_time)->toDateTimeString();
+            return Carbon::parse($date_tom." 09:00:00")->subHours(-$enquiry_time+(18-$hour))->toDateTimeString();
+        }
+        if ($hour>=18)return Carbon::parse($date_tom." 09:00:00")->subHours(-$enquiry_time)->toDateTimeString();
+
     }
     public function screenSupplier($user,$material)
     {

+ 67 - 0
app/Services/ProcurementWeiXinSendMessageService.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Services;
+
+
+use App\Components\AsyncResponse;
+
+class ProcurementWeiXinSendMessageService
+{
+    use AsyncResponse;
+    //获取access_token
+    public  function get_access_token($appId = '', $appSecret = ''){
+        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret";
+        $result = file_get_contents($url);
+        $result = json_decode($result,true);
+        if (array_key_exists("access_token", $result)) return $result['access_token'];
+        return null;
+    }
+    //发送微信模版消息通知
+    public function sendWenChantTemplate($param)
+    {
+        try {
+            $params['touser'] = $param['touser'];
+            $params['mp_template_msg'] = $param['mp_template_msg'];
+            $res = $this -> send_message($params);
+        } catch (\Exception $e) {
+            LogService::log(__METHOD__,"发送模板消息失败",$params." | ".$e->getMessage());
+        }
+        LogService::log(__METHOD__,"发送模板消息成功",$params);
+    }
+
+    /**
+     * @desc 发送微信消息
+     * param     string
+     * $type
+     * $param['title'] 消息标题
+     * $param['reason'] 消息内容或者消息原因
+     */
+    public function send_message($param)
+    {
+
+        $appId=config('weiXin.xiaoChengXu.appId');
+        $appSecret=config('weiXin.xiaoChengXu.appSecret');
+        $data = [
+            "touser" => $param['touser'],
+            "mp_template_msg" => $param['mp_template_msg'],
+        ];
+        $json = json_encode($data, JSON_UNESCAPED_UNICODE);
+        $access_token = self::get_access_token($appId, $appSecret);
+        $url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=" . $access_token;
+
+        //以'json'格式发送post的https请求
+        $curl = curl_init();
+        curl_setopt($curl, CURLOPT_URL, $url);
+        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
+        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
+        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
+        if (!empty($json)) {
+            curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
+        }
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+        $output = curl_exec($curl);
+        curl_close($curl);
+        return $output;
+    }
+
+}

+ 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",
+            ]);
+        }
+    }
 }

+ 2 - 2
app/Services/StationRuleBatchService.php

@@ -17,12 +17,12 @@ class StationRuleBatchService
 {
     use ServiceAppAop;
     protected $modelClass=StationRuleBatch::class;
-    function getByBatch(Batch $batch): ?StationRuleBatch
+    function getByBatch(?Batch $batch): ?StationRuleBatch
     {
         $batchType = $batch['type'] ?? 'null';
         $ownerId = $batch['owner_id'] ?? 'null';
         $batch->loadMissing('stationTaskBatch');
-        if($batch['stationTaskBatch'])return null;
+//        if($batch['stationTaskBatch'])return null;//? 这行有啥用?
         return Cache::remember('stationRuleBatch_batchType_'.$batchType.'_ownerId_'.$ownerId, config('cache.expirations.rarelyChange'),function()use($batch){
             $builder= StationRuleBatch::query()->with('stationType')
                 ->where('owner_id',$batch['owner_id']);

+ 5 - 2
app/Services/StationService.php

@@ -38,10 +38,10 @@ class StationService
 
     function getULineEntrance(Station $station):?Station{
         $station->loadMissing(['stationType','child']);
-        if ($station['stationType']['name']??''=='料箱出货口'){
+        if (($station['stationType']['name']??'')=='料箱出货口'){
             return $station;
         }
-        if ($station['child']['stationType']['name']??''=='料箱出货口'){
+        if (($station['child']['stationType']['name']??'')=='料箱出货口'){
             return $station['child'];
         }
         return null;
@@ -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));
     }
 
 }

+ 2 - 1
app/Services/StationTaskBatchService.php

@@ -87,7 +87,6 @@ class StationTaskBatchService
             $stationTasks_toAttach,
             data_get($stationTaskBatches_toCreate,'*.station_id')
         );
-
         return $stationTaskBatches_toCreate;
     }
 
@@ -103,6 +102,8 @@ class StationTaskBatchService
             return StationTaskBatch::query()
                 ->whereIn('status',data_get($stationTaskBatches,'*.status'))
                 ->whereIn('batch_id',data_get($stationTaskBatches,'*.batch_id'))
+                ->orderByDesc('id')
+                ->limit(count($stationTaskBatches))
                 ->get();
         });
     }

+ 5 - 0
app/Services/StationTaskMaterialBoxService.php

@@ -45,6 +45,7 @@ class StationTaskMaterialBoxService
     function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection
     {
         $this->instant($this->stationTaskService,'StationTaskService');
+        LogService::log(__METHOD__,'assignTasks','波次任务分配4.c1:'.json_encode($batches));
         $stationTaskMaterialBoxes_byBatch = (function () use ($batches) {
             $stationTaskMaterialBoxes_listByBatch = new Collection();
             foreach ($batches as $batch) {
@@ -54,6 +55,7 @@ class StationTaskMaterialBoxService
             }
             return $stationTaskMaterialBoxes_listByBatch;
         })();
+        LogService::log(__METHOD__,'assignTasks','波次任务分配4.c2:'.json_encode($batches));
          $this->stationTaskService
             ->registerSubTasks(
                 $stationTasks_toAttach,
@@ -106,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;
-//    }
+    }
 }

+ 3 - 0
app/User.php

@@ -92,6 +92,9 @@ class User extends Authenticatable
     function userWorkgroups(){
         return $this->belongsToMany('App\UserWorkgroup','user_workgroup_user','user_id','user_workgroup_id');
     }
+    function suppliers(){
+        return $this->belongsToMany('App\Supplier','supplier_user','user_id','supplier_id');
+    }
 
     function authorities(){
         $authorities = new Collection([]);

+ 1 - 1
app/UserDetail.php

@@ -17,7 +17,7 @@ class UserDetail extends Model
     public $incrementing=false;
 
     protected $fillable=[
-        'user_id','full_name','gender','identity_number','mobile_phone','type'
+        'user_id','full_name','gender','identity_number','mobile_phone','type','procurement_wechat_open_id'
     ];
     protected $appends=[
         'user_labor_company'

+ 2 - 2
config/api.php

@@ -46,8 +46,8 @@ return [
     'haiq'=>[
         'storage'=>[
 //            'relocate' => "http://59.37.126.227:65448/api/haiqEss/gr/relocate",
-            'moveBin' => "http://58.33.243.164/ess/api/haiqEss/gr/relocate",  //移动料箱
-            'light' => "http://58.33.243.164/ess/api/haiqEss/ctlPTL",  //控灯
+            'moveBin' => "http://58.33.243.164:2011/api/haiqEss/gr/relocate",  //移动料箱
+            'light' => "http://58.33.243.164:2011/api/haiqEss/ctlPTL",  //控灯
         ],
     ],
 

+ 1 - 1
config/api_logistic.php

@@ -106,6 +106,6 @@ return [
         'x-appKey' => 'c51c718eb899e9f706979',
         'appSecret' => '9f664e3ab08049874aa417720840161a',
     ],
-    'init_date' => '2021-01-25 23:59:59',
+    'init_date' => '2021-03-19 23:59:59',
     'days' => 7,
 ];

+ 16 - 0
config/weiXin.php

@@ -0,0 +1,16 @@
+<?php
+
+return [
+    "xiaoChengXu" => [
+        "appId" => "wxe1fbb56a49af3618",
+        "appSecret" => "ed27727f5152b094581a6bd6826907e5",
+    ],
+    "fuWuHao" => [
+        "appId" => "wxbe276d9de7304ef3",
+    ],
+    "fuWuHaoTemplate" => [
+        "check_sheet_inform" => "YAa5LNgLHtGUQeU0742sDQ0CT6hSsbyQ_qa0ZWKQEd0",
+        "order_confirm_inform" => "fL5KbX45ETWEtY6sJ77F9xF7u0u4fJqCSIXLBLxe_B8",
+        "wait_procurement_inform" => "k6QhyPbjKTPuJoQ7JxBqf-VVTWubgdmdDIA1uXqLZuE",
+    ],
+];

+ 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_19_134619_add_openid_column_to_user_details.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddOpenidColumnToUserDetails extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('user_details', function (Blueprint $table) {
+            $table->string('procurement_wechat_open_id')->nullable()->comment('采购小程序绑定用户openid');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('user_details', function (Blueprint $table) {
+            $table->dropColumn('procurement_wechat_open_id');
+        });
+    }
+}

+ 39 - 0
database/migrations/2021_03_23_140544_add_configurations_data.php

@@ -0,0 +1,39 @@
+<?php
+
+use App\Configuration;
+use Illuminate\Database\Migrations\Migration;
+
+use Illuminate\Support\Facades\Auth;
+
+class AddConfigurationsData extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        $time=\Illuminate\Support\Carbon::now()->toDateTimeString();
+        $configurations = [];
+        $conf_one=['name'=>'价格系数','value'=>1.3,'description'=>'采购管理价格系数','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $conf_two=['name'=>'询价延时时间','value'=>4,'description'=>'报价需在询价发起延时时间之内有效','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $conf_three=['name'=>'接单延时时间','value'=>24,'description'=>'接单需在询价发起延时时间之内有效','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $configurations[]=$conf_one;
+        $configurations[]=$conf_two;
+        $configurations[]=$conf_three;
+        Configuration::query()->insert($configurations);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Configuration::query()->where('name','价格系数')->delete();
+        Configuration::query()->where('name','询价延时时间')->delete();
+        Configuration::query()->where('name','接单延时时间')->delete();
+    }
+}

+ 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");
+        });
+    }
+}

+ 11 - 1
database/seeds/ConfigurationSeeder.php

@@ -1,7 +1,10 @@
 <?php
 
+use Carbon\Carbon;
 use Illuminate\Database\Seeder;
 use App\Configuration;
+use Illuminate\Support\Facades\Auth;
+
 class ConfigurationSeeder extends Seeder
 {
     /**
@@ -11,7 +14,14 @@ class ConfigurationSeeder extends Seeder
      */
     public function run()
     {
-        $configurations = factory(Configuration::class)->times(100)->make()->toArray();
+        $time=Carbon::now()->toDateTimeString();
+        $configurations = [];
+        $conf_one=['name'=>'价格系数','description'=>'采购管理价格系数','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $conf_two=['name'=>'询价延时时间','description'=>'报价需在询价发起延时时间之内有效','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $conf_three=['name'=>'接单延时时间','description'=>'接单需在询价发起延时时间之内有效','operator'=>Auth::user()['id'],'created_at'=>$time,'updated_at'=>$time];
+        $configurations[]=$conf_one;
+        $configurations[]=$conf_two;
+        $configurations[]=$conf_three;
         Configuration::query()->insert($configurations);
     }
 }

+ 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"
+	}
+}

BIN
public/images/QRCodeIMG/1.png


+ 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===""){

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff