Jelajahi Sumber

Merge branch 'LD'

# Conflicts:
#	app/Exceptions/Exception.php
#	app/Http/Controllers/TestController.php
#	app/Services/StationTaskCommodityService.php
LD 5 tahun lalu
induk
melakukan
33118e19b1
61 mengubah file dengan 1747 tambahan dan 278 penghapusan
  1. 2 2
      .gitlab-ci.yml
  2. 1 3
      app/Console/Commands/MakeTestCommand.php
  3. 33 0
      app/Http/Controllers/TestController.php
  4. 19 6
      app/Http/Controllers/api/thirdPart/haiq/PickStationController.php
  5. 8 10
      app/Http/Controllers/api/thirdPart/haiq/StorageController.php
  6. 35 0
      app/Http/Requests/ForeignHaiRobotic_processedRequest.php
  7. 1 1
      app/Http/Requests/ForeignHaiRobotic_taskUpdateRequest.php
  8. 18 0
      app/Providers/AppServiceProvider.php
  9. 49 8
      app/Services/BatchService.php
  10. 167 67
      app/Services/ForeignHaiRoboticsService.php
  11. 5 3
      app/Services/MaterialBoxService.php
  12. 12 8
      app/Services/StationRuleBatchService.php
  13. 22 0
      app/Services/StationService.php
  14. 75 39
      app/Services/StationTaskBatchService.php
  15. 1 2
      app/Services/StationTaskBatchTypeService.php
  16. 73 20
      app/Services/StationTaskCommodityService.php
  17. 107 15
      app/Services/StationTaskMaterialBoxService.php
  18. 17 16
      app/Services/StationTaskService.php
  19. 9 0
      app/Services/StationTaskTypeService.php
  20. 9 0
      app/Services/StationTypeBinMonitorService.php
  21. 6 5
      app/Services/StationTypeService.php
  22. 6 3
      app/Station.php
  23. 3 2
      app/StationRuleBatch.php
  24. 27 3
      app/StationTask.php
  25. 7 6
      app/StationTaskBatch.php
  26. 1 1
      app/StationTaskChild.php
  27. 9 7
      app/StationTaskCommodity.php
  28. 21 4
      app/StationTaskMaterialBox.php
  29. 44 4
      app/Traits/TestMockSubServices.php
  30. 2 2
      config/api.php
  31. 1 1
      database/factories/MaterialBoxFactory.php
  32. 6 3
      database/factories/OwnerFactory.php
  33. 0 12
      database/factories/StationMissionBatchFactory.php
  34. 0 12
      database/factories/StationMissionCommodityFactory.php
  35. 1 1
      database/factories/StationRuleBatchFactory.php
  36. 0 0
      database/factories/StationTaskBatchTypeFactory.php
  37. 1 1
      database/factories/StationTaskFactory.php
  38. 1 1
      database/factories/StationTaskMaterialBoxFactory.php
  39. 1 1
      database/factories/StationTypeFactory.php
  40. 6 1
      database/migrations/2020_11_30_140958_create_stations_table.php
  41. 44 0
      database/migrations/2020_12_24_155647_add_column_material_task_type_drop_station_mission_tables.php
  42. 30 0
      database/migrations/2020_12_29_182249_change_station_rule_batch_column_default_batch_type.php
  43. 45 0
      database/migrations/2021_01_06_114158_create_station_task_children2.php
  44. 45 0
      database/migrations/2021_01_21_153513_add_column_station_task_id_for_all_sub_tasks.php
  45. 3 2
      public/t.php
  46. 1 1
      resources/lang/cn/validation.php
  47. 12 0
      tests/Controller/api/thirdPart/haiq/StorageController/TestStorageController.php
  48. 38 0
      tests/Services/BatchService/AssignTasksTest.php
  49. 40 0
      tests/Services/BatchService/TestAssignTasks.php
  50. 0 1
      tests/Services/BatchService/TestGetBatchByCodes.php
  51. 1 2
      tests/Services/CityService/FindByNameTest.php
  52. 77 0
      tests/Services/ForeignHaiRoboticsService/TaskUpdateTest.php
  53. 57 0
      tests/Services/StationRuleBatchService/GetBatches_shouldProcessTest.php
  54. 81 0
      tests/Services/StationTaskBatchService/CreateByBatchesTest.php
  55. 130 0
      tests/Services/StationTaskBatchService/RunManyTest.php
  56. 104 0
      tests/Services/StationTaskCommodityService/CreateByBatchTest.php
  57. 83 0
      tests/Services/StationTaskCommodityService/CreateByBatchesTest.php
  58. 84 0
      tests/Services/StationTaskMaterialBoxService/CreateByBatchesTest.php
  59. 37 0
      tests/Services/StationTaskService/CreateTest.php
  60. 27 0
      tests/Services/StationTaskService/TestRegisterSubTasks.php
  61. 2 2
      tests/Unit/EchoTest.php

+ 2 - 2
.gitlab-ci.yml

@@ -8,8 +8,8 @@ cache:
     - vendor/
 
 before_script:
-  - sudo cp ci/.envCi .env
-  - sudo bash ci/installEnv.sh
+#  - sudo cp ci/.envCi .env
+#  - sudo bash ci/installEnv.sh
 
 
 build:

+ 1 - 3
app/Console/Commands/MakeTestCommand.php

@@ -56,9 +56,7 @@ class MakeTestCommand extends \Illuminate\Foundation\Console\TestMakeCommand
     }
     protected function getModelNamePlural()
     {
-        $modelName=preg_replace('/s$/','ses',lcfirst($this->getModelName()));
-        $modelName=preg_replace('/ch$/','ches',$modelName);
-        $modelName=preg_replace('/sh$/','shes',$modelName);
+        $modelName=preg_replace('/(s|x|ch|sh)$/','ses',lcfirst($this->getModelName()));
         $modelName=preg_replace('/y$/','ies',$modelName);
         $modelName=preg_replace('/[cC]hild$/','children',$modelName);
         if(preg_match('/[cC]hildren$/',$modelName)==0){

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

@@ -16,6 +16,7 @@ use App\Console\Commands\SyncBatchTask;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\WasSyncWmsAsnInformation;
+use App\Exceptions\ErrorException;
 use App\Events\CancelOrder;
 use App\Events\SendEmailEvent;
 use App\Http\Requests\ForeignHaiRobotic_taskUpdateRequest;
@@ -83,6 +84,7 @@ use App\Services\RejectedBillService;
 use App\Services\ShopService;
 use App\Services\StoreService;
 use App\Services\WarehouseService;
+use App\StationRuleBatch;
 use App\Store;
 use App\StationTaskBatch;
 use App\StoreCheckingReceiveItem;
@@ -290,6 +292,37 @@ 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();
+        Cache::put('storedTest', $today);
+        return "cacheing:'$today'<script>localStorage.setItem('storedTest','{$today}')</script>";
+    }
+
+    function getCache(Request $request)
+    {
+        $cache = Cache::get('storedTest');
+        return "cacheing get:'$cache'<script>document.write('<br>localStorage:'+localStorage.getItem('storedTest'))</script>";
+    }
+
+    function t1(Request $request)
+    {
+        throw new ErrorException('eeeff');
+        DB::connection('oracle')->update(DB::raw("update BAS_SKU set HAZARD_FLAG= 'N' where SKU= '13564151055'"));
+//        DB::connection('oracle')->update(DB::raw("UPDATE DOC_ORDER_HEADER SET notes = CASE WHEN notes IS NULL THEN '停运' ELSE  notes||',停运' END where ORDERNO in ('','SO190628000050','SO190628000001')"));
+    }
+
+    function packageT(Request $request)
+    {
+        $package = Package::where('created_at', '<', '2020-07-08')->whereNotNull('logistic_number')->first();
+        $package->fetchLogistic();
+    }
+
     function injectJS(Request $request)
     {
         $items = RejectedBillItem::whereHas('rejectedBill', function ($query) {

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

@@ -18,12 +18,25 @@ class PickStationController
         $this->service=app('ForeignHaiRoboticsService');
     }
 
-    public function processed(Request $request){
-        $success = $request->input('success');
-        $code = $success?200:0;
-        $this->service->markBinProcessed();
-        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->all()));
-        return ['code'=>$code,'errMsg'=>'','data'=>$request->all()];
+    public function processed(Request $request): array
+    {
+        $failed=
+            ($processedResult=
+                $this->service->markBinProcessed(
+                    $request->input('workStation'),
+                    $request->input('binCode'),
+                    $request->input('success'),
+                    $request->input('created_at'),
+                    $request->input('exception'),
+                    $request->input('is_in_plan')
+                ))!==true;
+
+        $result = ["code" => 200, "data" => json_encode($request->all())];
+        if($failed){
+            $result["code"] = 500;
+            $result["errMsg"] = $processedResult;
+        }
+        return $result;
     }
 
 }

+ 8 - 10
app/Http/Controllers/api/thirdPart/haiq/StorageController.php

@@ -243,16 +243,15 @@ class StorageController
         return $this->light($request,$this->lightOff);
     }
     public function taskUpdate(ForeignHaiRobotic_taskUpdateRequest $request){
-        return $request->method();
         try{
             $this->service->taskUpdate(
-                $request['groupCode'],
-                $request['taskCode'],
-                $request['updateEventType'],
-                $request['status'],
-                $request['binCode'],
-                $request['kubotId'],
-                $request['description']
+//                $request['groupCode']
+                $request['taskCode']
+                ,$request['updateEventType']
+                ,$request['status']
+                ,$request['binCode']
+//                ,$request['kubotId']
+//                ,$request['description']
             );
             return ['code'=>200,'errMsg'=>'','data'=>$request->all()];
         }catch (\Exception $e){
@@ -260,8 +259,7 @@ class StorageController
         }
     }
     public function exception(Request $request){
-        $this->service->excepted();
-        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->all()));
+        $this->service->excepted('海柔异常','',json_encode($request));
         return ['code'=>200,'errMsg'=>'','data'=>$request->all()];
     }
 }

+ 35 - 0
app/Http/Requests/ForeignHaiRobotic_processedRequest.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ForeignHaiRobotic_processedRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'workStation'=>'nullable',
+            'binCode'=>'required',
+            'success'=>'required|bool',
+            'created_at'=>'nullable',
+            'exception'=>'nullable',
+            'is_in_plan'=>'required|bool',
+        ];
+    }
+}

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

@@ -28,7 +28,7 @@ class ForeignHaiRobotic_taskUpdateRequest extends FormRequest
         return [
            'groupCode'=>'required',
            'taskCode'=>'required',
-           'updateEventType'=>'required',
+           'updateEventType'=>'required|in:0,1',
            'status'=>'required|in:0,1',
            'binCode'=>'required',
            'kubotId'=>'required',

+ 18 - 0
app/Providers/AppServiceProvider.php

@@ -20,6 +20,7 @@ use App\Services\InventoryAccountMissionService;
 use App\Services\InventoryCompareService;
 use App\Services\LaborReportsCountingRecordService;
 use App\Services\LogService;
+use App\Services\MaterialBoxService;
 use App\Services\OracleBasCustomerService;
 use App\Services\OracleBasSkuService;
 use App\Services\OracleDocAsnDetailService;
@@ -63,9 +64,17 @@ use App\Services\RejectedBillItemService;
 use App\Services\RejectedBillService;
 use App\Services\ShopService;
 use App\Services\RejectedService;
+use App\Services\StationRuleBatchService;
 use App\Services\StationTaskBatchService;
 use App\Services\StationTaskBatchTypeService;
 use App\Services\StationService;
+use App\Services\StationTaskChildService;
+use App\Services\StationTaskCommodityService;
+use App\Services\StationTaskMaterialBoxService;
+use App\Services\StationTaskService;
+use App\Services\StationTaskTypeService;
+use App\Services\StationTypeBinMonitorService;
+use App\Services\StationTypeService;
 use App\Services\StoreCheckingReceiveItemService;
 use App\Services\StoreCheckingReceiveService;
 use App\Services\StoreItemService;
@@ -150,6 +159,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('LaborReportsCountingRecordService',LaborReportsCountingRecordService::class);
         app()->singleton('LogService',LogService::class);
         app()->singleton('LogisticService',LogisticService::class);
+        app()->singleton('MaterialBoxService',MaterialBoxService::class);
         app()->singleton('OracleActAllocationDetailService',OracleActAllocationDetailService::class);
         app()->singleton('OracleBasCustomerService',OracleBasCustomerService::class);
         app()->singleton('OracleBasSkuService',OracleBasSkuService::class);
@@ -191,11 +201,19 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('RejectedBillService',RejectedBillService::class);
         app()->singleton('RejectedService',RejectedService::class);
         app()->singleton('ShopService',ShopService::class);
+        app()->singleton('StationRuleBatchService',StationRuleBatchService::class);
         app()->singleton('StationService',StationService::class);
         app()->singleton('StationTaskBatchService',StationTaskBatchService::class);
         app()->singleton('StationTaskBatchTypeService',StationTaskBatchTypeService::class);
         app()->singleton('StoreCheckingReceiveItemService',StoreCheckingReceiveItemService::class);
         app()->singleton('StoreCheckingReceiveService',StoreCheckingReceiveService::class);
+        app()->singleton('StationTaskCommodityService',StationTaskCommodityService::class);
+        app()->singleton('StationTaskMaterialBoxService',StationTaskMaterialBoxService::class);
+        app()->singleton('StationTaskChildService',StationTaskChildService::class);
+        app()->singleton('StationTaskService',StationTaskService::class);
+        app()->singleton('StationTaskTypeService',StationTaskTypeService::class);
+        app()->singleton('StationTypeBinMonitorService',StationTypeBinMonitorService::class);
+        app()->singleton('StationTypeService',StationTypeService::class);
         app()->singleton('StoreItemService',StoreItemService::class);
         app()->singleton('StoreService',StoreService::class);
         app()->singleton('UnitService',UnitService::class);

+ 49 - 8
app/Services/BatchService.php

@@ -3,7 +3,13 @@
 namespace App\Services;
 
 use App\Batch;
+use App\OracleActAllocationDetails;
+use App\Order;
+use App\OrderCommodity;
+use App\Owner;
 use Exception;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Http;
 use App\Traits\ServiceAppAop;
 
 
@@ -51,28 +57,63 @@ Class BatchService
 
     /**
      * 为波次附加任务,已附加的重复任务不影响
-     * @param Batch[] $batches
+     * @param Collection $batches
      * @throws Exception
      */
-    public function assignTasks(array $batches)
+    public function assignTasks(Collection $batches)
     {
+//        $this->directTemp($batches);
         $this->instant($this->stationTaskBatchService,'StationTaskBatchService');
         $this->instant($this->stationRuleBatchService,'StationRuleBatchService');
         $this->instant($this->stationTaskService,'StationTaskService');
         $this->instant($this->stationTaskCommodityService,'StationTaskCommodityService');
         $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
 
-        $batches_canProcess = $this->stationRuleBatchService->getBatches_canProcess($batches); //按规则过滤需要的波次
-        if($batches_canProcess->isEmpty()) return;
+        $batches_shouldProcess = $this->stationRuleBatchService->getBatches_shouldProcess($batches); //按规则过滤需要的波次
+        if($batches_shouldProcess->isEmpty()) return;
 
-        $stationTasks =  $this->stationTaskService->create($batches_canProcess->count()); //生成总任务
-        $stationTaskBatches=$this->stationTaskBatchService->createByBatches($batches_canProcess,$stationTasks); //注册波次任务
-        $this->stationTaskCommodityService->createByBatches($batches_canProcess,$stationTasks); //注册商品任务
-        $this->stationTaskMaterialBoxService->createByBatches($batches_canProcess,$stationTasks); //注册料箱任务
+        $stationTasks =  $this->stationTaskService->create($batches_shouldProcess->count()); //生成总任务
+        $stationTaskBatches=$this->stationTaskBatchService->createByBatches($batches_shouldProcess,$stationTasks); //注册波次任务
+        $this->stationTaskCommodityService->createByBatches($batches_shouldProcess,$stationTasks); //注册商品任务
+        $this->stationTaskMaterialBoxService->createByBatches($batches_shouldProcess,$stationTasks); //注册料箱任务
 
         $this->stationTaskBatchService->runMany($stationTaskBatches);//执行波次任务
     }
 
+//    public function directTemp($batches){
+//        $ownerName='';
+//        $batches=$batches->map(function(Batch $batch)use($ownerName){
+//            $owner=Owner::query()->where('name',$ownerName)->get();
+//            if(!$owner) return false;
+//            if($batch['owner_id']==$owner['id'])return $batch;
+//            return false;
+//        });
+//        $bins=$batches->map(function (Batch $batch){
+//            $batch->loadMissing('orders.orderCommodities');
+//
+//            foreach ($batch['orders'] as $order){
+//                foreach ($order['orderCommodities'] as $orderCommodity){
+//                    return [
+//                        "taskCode"  =>'testTask'.microtime(),
+//                        "binCode"   => $orderCommodity['location'],
+//                        "toLocCode" => 'BIN-OUT1',
+//                    ];
+//                }
+//            }
+//            return null;
+//        });
+//
+//        $json= [
+//            "taskMode"  =>2,
+//            "bins"=>$bins,
+//            "groupCode"=>'testGroup'.microtime(),
+//            "priority"=>10,
+//            "sequenceFlag"=>1,
+//        ];
+//        $response = Http::post(config('api.haiq.storage.moveBin'),$json);
+//        LogService::log(__CLASS__,__METHOD__,$response->json());
+//    }
+
     public function getBatchByCodes($codes)
     {
         if(empty($codes))return collect();

+ 167 - 67
app/Services/ForeignHaiRoboticsService.php

@@ -10,14 +10,28 @@ use App\MaterialBox;
 use App\StationTaskMaterialBox;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Http;
-use Ramsey\Collection\Collection;
 use App\Traits\ServiceAppAop;
 
 
 class ForeignHaiRoboticsService
 {
     use ServiceAppAop;
+
+    /** @var  $stationTaskMaterialBoxService StationTaskMaterialBoxService */
+    private $stationTaskMaterialBoxService;
+    /** @var  $materialBoxService MaterialBoxService */
+    private $materialBoxService;
+    /** @var  $stationService StationService */
+    private $stationService;
+    public function __construct()
+    {
+        $this->stationTaskMaterialBoxService=null;
+        $this->materialBoxService=null;
+        $this->stationService=null;
+    }
+
     /**
      * @param string $modeName '输送线入立架'|'立架出至输送线'|'移动立架内位置'|'缓存架入立架'|'立架出至缓存架'
      * @param string $fromLocation
@@ -26,6 +40,7 @@ class ForeignHaiRoboticsService
      * @param string $groupId
      * @param int $priority
      * @param int $isSequenced
+     * @return array
      */
     private function makeJson_move(
         Collection $taskMaterialBoxes,
@@ -35,7 +50,8 @@ class ForeignHaiRoboticsService
         $groupId=''
         , $priority=10
         , $isSequenced=1
-    ){
+    ): array
+    {
         $timestampSuffix = microtime(true);
         $taskMode=(function()use($modeName){
             switch ($modeName){
@@ -47,113 +63,197 @@ class ForeignHaiRoboticsService
                 default: throw new \Exception('发至海柔的移料箱请求,模式不存在');
             }
         })();
-        $bins=$taskMaterialBoxes->map(function (StationTaskMaterialBox $taskMaterialBox)use($timestampSuffix){
+        $bins=$taskMaterialBoxes->map(function (StationTaskMaterialBox $taskMaterialBox)use($timestampSuffix,$fromLocation,$toLocation){
             return [
-                "taskCode"  =>"{$taskMaterialBox['id']}_{$taskMaterialBox['material_box_id']}_{$timestampSuffix}",
+                "taskCode"  =>$taskMaterialBox['id'],
                 "binCode"   => $taskMaterialBox['materialBox']['code'],
                 "fromLocCode" => $fromLocation??'',
                 "toLocCode" => $toLocation??'',
             ];
         });
-        $groupId .= $timestampSuffix;
         return [
             "taskMode"  =>$taskMode,
             "bins"=>$bins,
-            "groupCode"=>$groupId,
+            "groupCode"=>$groupId.$timestampSuffix,
             "priority"=>$priority,
             "sequenceFlag"=>$isSequenced,
         ];
     }
 
-    public function fetchGroupToProcessor($toLocation, Collection $taskMaterialBoxes, $groupIdPrefix=''): bool
+    public function fetchGroup($toLocation, Collection $taskMaterialBoxes, $groupIdPrefix=''): bool
     {
         $dataToPost=$this->makeJson_move(
             $taskMaterialBoxes,
             '立架出至输送线',
             '',
-            $toLocation,
+            $toLocation??'',
             $groupIdPrefix
         );
-        $response = Http::post(config('api.haiq.storage.moveBin'),$dataToPost);
-        $errMsg=(function()use($response){
-            if($response->ok())return '';
-            $errMsg = '错误: ';
-            if (!$response){
-                return $errMsg.'没有返回内容,检查连接或目标服务器';
-            }
-            switch (((string)$response["code"])[0]){
-                case 5: $errMsg.='目标服务器代码错误,请联系对方';break;
-                case 4: $errMsg.='权限不足以请求资源,请检查对方服务器规范';break;
-                default: $errMsg.='出现未知请求错误';break;
-            }
-            $responseDetails=' code:'.$response["code"]
-                .' header:'.$response->body()
-                .' response:'.json_encode($response->headers());
-            return $errMsg.$responseDetails;
-        })();
-
-        LogService::log(__METHOD__,__FUNCTION__,
-            $errMsg??''
-            .'请求:'.json_encode($dataToPost)
-            .'调用堆栈:'.json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),0,3))
-        );
-        return $isSuccess=!$errMsg;
+        return $this->controlHaiRobot($dataToPost);
     }
 
     public function moveBin(){
 
     }
 
-    public function markBinProcessed(){
+    public function markBinProcessed(
+        $workStation,
+        $binCode,
+        $success,
+        $created_at,
+        $exception,
+        $is_in_plan
+    ): bool
+    {
+        try{
+            if($failed
+                =!$success)
+                throw new ErrorException('海柔任务失败:'.$exception);
+            if($NotInPlan
+                =!$is_in_plan)
+                throw new ErrorException('海柔认为是计划外的料箱:'.$exception);
 
+            $materialBox=
+                $this->materialBoxService->get(['code'=>$binCode]);
+            if($stationTaskMaterialBox
+                =(function()use($materialBox){
+                return $stationTaskMaterialBox=
+                    $this->stationTaskMaterialBoxService
+                        ->get([
+                            'material_box_id'=>$materialBox['id'],
+                            'status'=>'处理中',
+                        ])->first();
+            })()){
+                throw new ErrorException('该料箱没有安排在处理队列中');
+            }
+            $this->putBinToStore($stationTaskMaterialBox)
+                ?true
+                :(function(){throw new ErrorException('呼叫机器人回收U型线料箱失败');})();
+            $this->stationTaskMaterialBoxService
+                ->markProcessed($stationTaskMaterialBox);
+            return true;
+        }catch (\Exception $e){
+            $this->stationTaskMaterialBoxService
+                ->excepted($stationTaskMaterialBox??$materialBox??null);
+            return $e->getMessage();
+        }
+    }
+
+    public function putBinToStore(StationTaskMaterialBox $stationTaskMaterialBox): bool
+    {
+        $this->instant($this->stationService,'StationService');
+        $dataToPost=$this->makeJson_move(
+            collect($stationTaskMaterialBox),
+            '缓存架入立架',
+            $this->stationService->getULineExit($stationTaskMaterialBox['station'])['name']??'',
+            '',
+            $stationTaskMaterialBox['stationTaskBatch']['id']
+        );
+        return $this->controlHaiRobot($dataToPost);
     }
+
     public function taskUpdate(
-        $groupCode,
+//        $groupCode,
         $taskCode,
         $updateEventType,   //0:task_begin(取货)1:task_end(放货)
         $status,            //0:任务成功1:任务失败
-        $binCode,
-        $robotId,
-        $description
+        $binCode
     ):bool{
-        if($status==1){
-            return $this->excepted();
-        }
-        switch ($updateEventType){
-            case 0:
-            case 1:
+        try{
+            if(($failed
+                    =$status)==1){
+                throw new ErrorException('海柔任务失败');
+            }
+            if($boxNotMatch=
+                !$stationTaskMaterialBox
+                =(function()use($taskCode,$binCode){
+                $stationTaskMaterialBox=StationTaskMaterialBox::query()->find($id=$taskCode);
+                if($stationTaskMaterialBox['code']==$binCode)return $stationTaskMaterialBox;
+                return null;
+            })()){
+                throw new ErrorException('发回的料箱和任务号(ID)不匹配');
+            }
+            ($标记已放置在库外=
+                function()use($updateEventType,$stationTaskMaterialBox){
+                if(($isPut
+                        =$updateEventType)==1){
+                    $this->stationTaskMaterialBoxService->markHasPut($stationTaskMaterialBox);
+                }
+            })();
+            ($标记已入立架=
+                function()use($updateEventType,$stationTaskMaterialBox){
+                    if(($isGet
+                            =$updateEventType)==0){
+                        $this->stationTaskMaterialBoxService->markTaken($stationTaskMaterialBox);
+                    }
+            })();
+        }catch (\Exception $e){
+            $this->excepted($taskCode, $binCode, $e->getMessage());
+            return false;
         }
-        $this->markHasGet();
-
+        return true;
     }
-    public function markHasPut(
-        $groupCode,
-        $taskCode,
-        $updateEventType,   //0:task_begin(取货)1:task_end(放货)
-        $status,            //0:任务成功1:任务失败
-        $binCode,
-        $robotId,
-        $description
-    ):bool{
-
 
-    }
-    public function markHasGet(
-        $groupCode,
-        $taskCode,
-        $updateEventType,   //0:task_begin(取货)1:task_end(放货)
-        $status,            //0:任务成功1:任务失败
-        $binCode,
-        $robotId,
-        $description
-    ):bool{
+//    public function markHasPut($taskCode,$binCode):bool{
+//        try{
+//            //标记料箱进入位置
+////            $taskMaterialBoxesService->markDone();//
+//        }catch (\Exception $e){
+//            switch ($e->getCode()){
+//                case 'taskBinNotMatch';
+//                case 'taskGetFailed';
+//            }
+//        }
+//
+//    }
 
 
+    public function excepted($taskCode='',$binCode='', $msg=''):bool{
+        try{
+            throw new ErrorException(
+                "taskCode任务号:$taskCode , binCode箱号:$binCode 海柔运行报错: $msg"
+            );
+        }catch (\Exception $e){
+            return true;
+        }
     }
 
+    /**
+     * @param array $dataToPost
+     * @return bool
+     */
+    public function controlHaiRobot(array $dataToPost): bool
+    {
+        $response = Http::post(config('api.haiq.storage.moveBin'), $dataToPost);
+        $errMsg = (function () use ($response) {
+            if ($response->ok()) return '';
+            $errMsg = '错误: ';
+            if (!$response) {
+                return $errMsg . '没有返回内容,检查连接或目标服务器';
+            }
+            switch (((string)$response["code"])[0]) {
+                case 5:
+                    $errMsg .= '目标服务器代码错误,请联系对方';
+                    break;
+                case 4:
+                    $errMsg .= '权限不足以请求资源,请检查对方服务器规范';
+                    break;
+                default:
+                    $errMsg .= '出现未知请求错误';
+                    break;
+            }
+            $responseDetails = ' code:' . $response["code"]
+                . ' header:' . $response->body()
+                . ' response:' . json_encode($response->headers());
+            return $errMsg . $responseDetails;
+        })();
 
-    public function excepted():bool{
-
+        LogService::log(__METHOD__, __FUNCTION__,
+            $errMsg ?? ''
+            . '请求:' . json_encode($dataToPost)
+            . '调用堆栈:' . json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 0, 3))
+        );
+        return $isSuccess = !$errMsg;
     }
 
 }

+ 5 - 3
app/Services/MaterialBoxService.php

@@ -5,6 +5,7 @@ namespace App\Services;
 
 
 use App\MaterialBox;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
 
@@ -13,7 +14,7 @@ class MaterialBoxService
 {
     use ServiceAppAop;
 
-    function get(array $kvPairs){
+    function get(array $kvPairs):?Collection{
         ksort($kvPairs);
         return Cache::remember('MaterialBox_'.md5(json_encode($kvPairs)), config('cache.expirations.rarelyChange'), function ()use($kvPairs) {
             $query = MaterialBox::query();
@@ -27,7 +28,8 @@ class MaterialBoxService
 
     function firstOrCreate(array $kvPairs){
         $materialBox=$this->get($kvPairs);
-        if(!$materialBox)
-            return MaterialBox::query()->create($kvPairs);
+        if($materialBox->isNotEmpty())
+            return $materialBox->first();
+        return MaterialBox::query()->create($kvPairs);
     }
 }

+ 12 - 8
app/Services/StationRuleBatchService.php

@@ -15,14 +15,18 @@ use App\Traits\ServiceAppAop;
 class StationRuleBatchService
 {
     use ServiceAppAop;
-    function getByBatch(Batch $batch): StationRuleBatch
+    function getByBatch(Batch $batch): ?StationRuleBatch
     {
         $batchType = $batch['type'] ?? 'null';
         $ownerId = $batch['owner_id'] ?? 'null';
-        return Cache::remember('stationType_type_'.$batchType.'_ownerId_'.$ownerId, config('cache.expirations.rarelyChange'),function($batch){
-            return StationRuleBatch::query()->with('stationType')->where('batch_type',$batch['type'])
-                ->where('owner_id',$batch['owner_id'])
-                ->first();
+        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']);
+            if($batch['type']
+                && $batch['type']!='无'){
+                $builder=$builder->where('batch_type',$batch['type']);
+            }
+            return $builder->first();
         });
     }
 
@@ -33,10 +37,10 @@ class StationRuleBatchService
     }
 
     /**
-     * @param Batch[] $batches
-     * @return Collection
+     * @param Collection $batches
+     * @return Collection Batches
      */
-    function getBatches_canProcess(array $batches): Collection
+    function getBatches_shouldProcess(Collection $batches): Collection
     {
         $batches_toProcess=collect();
         foreach ($batches as $batch){

+ 22 - 0
app/Services/StationService.php

@@ -33,6 +33,28 @@ class StationService
         return $station;
     }
 
+    function getULineEntrance(Station $station):?Station{
+        $station->loadMissing(['stationType','child']);
+        if ($station['stationType']['name']??''=='料箱出货口'){
+            return $station;
+        }
+        if ($station['child']['stationType']['name']??''=='料箱出货口'){
+            return $station['child'];
+        }
+        return null;
+    }
+
+    function getULineExit(Station $station):?Station{
+        $station->loadMissing(['stationType','child']);
+        if ($station['stationType']['name']??''=='料箱入货口'){
+            return $station;
+        }
+        if ($station['child']['stationType']['name']??''=='料箱入货口'){
+            return $station['child'];
+        }
+        return null;
+    }
+
     function broadcast($station_id, $json_data){
         broadcast(new BroadcastToStation($station_id,$json_data));
     }

+ 75 - 39
app/Services/StationTaskBatchService.php

@@ -4,12 +4,8 @@
 namespace App\Services;
 
 
-use App\Batch;
-use App\Log;
-use App\Station;
-use App\StationTask;
+use App\Exceptions\ErrorException;
 use App\StationTaskBatch;
-use App\StationTaskBatchType;
 use Exception;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
@@ -43,59 +39,77 @@ class StationTaskBatchService
     }
 
     /**
-     * @param $batches Batch[]
+     * @param Collection $batches Batch[]
      * @param Collection $stationTasks_toAttach
      * @return Collection
      * @throws Exception
      */
-    function createByBatches(array $batches, Collection $stationTasks_toAttach): Collection
+    function createByBatches(Collection $batches, Collection $stationTasks_toAttach): Collection
     {
         $this->stationService = app('StationService');
+        $this->stationTaskService = app('StationTaskService');
         $this->stationTypeService = app('StationTypeService');
         $this->stationTaskBatchTypeService = app('StationTaskBatchTypeService');
         $this->batchService = app('BatchService');
 
         $stationTaskBatches_toCreate = new Collection();
-        $id_stationTaskBatchType = $this->stationTaskBatchTypeService->firstByWhere('name', 'U型线分捡');
+        $stationTaskBatchType = $this->stationTaskBatchTypeService->firstByWhere('name', 'U型线分捡');
+        $id_stationTaskBatchType=$stationTaskBatchType['id']??'';
 
         $batches_handled = collect();
         foreach ($batches as $batch) {
             if ($batch['status'] == '未处理') {
                 $stationType = $this->stationTypeService->getByBatch($batch);
                 $station = $this->stationService->getStation_byType($stationType['name']);
-                $stationTaskBatches_toCreate->push([
-                    'batch_id' => $batch['id'],
-                    'station_id' => $station['id'],
-                    'station_task_batch_type_id' => $id_stationTaskBatchType,
-                    'status' => '待处理'
-                ]);
+                $stationTaskBatches_toCreate->push(
+                    new StationTaskBatch([
+                        'batch_id' => $batch['id'],
+                        'station_id' => $station['id'],
+                        'station_task_batch_type_id' => $id_stationTaskBatchType,
+                        'status' => '待处理'
+                    ])
+                );
                 $batches_handled->push($batch);
             }
         }
         $this->batchService->updateWhereIn('id', data_get($batches_handled, '*.id'), ['status' => '处理中']);
         $this->insert($stationTaskBatches_toCreate->toArray());
-        $this->stationTaskService->registerSubTasks($stationTasks_toAttach,
-            $stationTaskBatches_toCreate->map(function ($stationMissionBatch) {
-                return [$stationMissionBatch];
+        $stationTaskBatches_toCreate=$this->getAndAttachIds($stationTaskBatches_toCreate);
+        $this->stationTaskService->registerSubTasks(
+            $stationTasks_toAttach,
+            $stationTaskBatches_toCreate->map(function($taskBatch){
+                return [$taskBatch];
             })
         );
 
         return $stationTaskBatches_toCreate;
     }
 
+    function getAndAttachIds($stationTaskBatches): Collection
+    {
+        $md5=is_array($stationTaskBatches)
+            ?$md5=md5(json_encode($stationTaskBatches)):null;
+
+        return Cache::remember(
+            'StationTaskBatch_'.$md5??md5(json_encode($stationTaskBatches->toArray()))
+            ,config('cache.expirations.rarelyChange')
+            ,function()use($stationTaskBatches){
+            return StationTaskBatch::query()
+                ->whereIn('status',data_get($stationTaskBatches,'*.status'))
+                ->whereIn('batch_id',data_get($stationTaskBatches,'*.batch_id'))
+                ->get();
+        });
+    }
     function insert(array $stationMissionBatches): bool
     {
-        $inserted = StationTaskBatch::query()->insert($stationMissionBatches);
-        LogService::log(__METHOD__, __FUNCTION__, json_encode($stationMissionBatches) .
-            '||' . json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 0, 3)));
-        return $inserted;
+        return StationTaskBatch::query()->insert($stationMissionBatches);
     }
 
     function markManyExcepted(Collection $stationTaskBatches_failed)
     {
         foreach (
             $stationTaskBatches_failed
-                 as $stationTaskBatch) {
+            as $stationTaskBatch) {
             if($stationTaskBatch['status']!='异常')
                 $this->markExcepted($stationTaskBatch);
         }
@@ -103,10 +117,7 @@ class StationTaskBatchService
         ($logAtFailings_andWait =
             function ($stationTaskBatches_failed) {
                 if ($stationTaskBatches_failed->isEmpty()) return;
-                LogService::log(__METHOD__, __FUNCTION__,
-                    '任务波次异常失败的:' . $stationTaskBatches_failed->toJson()
-                    . '调用堆栈:' . json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 0, 3))
-                );
+                throw new ErrorException('任务波次异常失败的');
             })($stationTaskBatches_failed);
     }
 
@@ -114,7 +125,7 @@ class StationTaskBatchService
      * @param Collection $stationTaskBatches
      * @return Collection|\Tightenco\Collect\Support\Collection|null 返回执行失败的记录
      */
-    function runMany(Collection $stationTaskBatches)
+    function runMany(Collection $stationTaskBatches):?Collection
     {
         $stationTaskBatches_failed = null;
         ($execute =
@@ -146,14 +157,18 @@ class StationTaskBatchService
 
     function run(StationTaskBatch $stationTaskBatch): bool
     {
-        $toLocation         = $stationTaskBatch['station']['code'];
+        $this->instant($this->foreignHaiRoboticsService,'ForeignHaiRoboticsService');
+        $this->instant($this->stationService,'StationService');
+        $stationTaskBatch->loadMissing(['station','stationTask.stationTaskMaterialBoxes']);
+        $toLocation         = $this->stationService->getULineEntrance($stationTaskBatch['station'])['code'];
         $groupPrefix        = $stationTaskBatch['id'];
-        $taskMaterialBoxes  = $stationTaskBatch['stationTask']['taskMaterialBoxes'] ??
-            function () use ($stationTaskBatch) {
+        $taskMaterialBoxes  = $stationTaskBatch['stationTask']['stationTaskMaterialBoxes'] ??
+            (function () use ($stationTaskBatch) {
                 throw new Exception('找不到料箱:' . json_encode($stationTaskBatch));
-            };
-        $isFetchedFromRobotics          = $this->foreignHaiRoboticsService->
-                                    fetchGroupToProcessor($toLocation, $taskMaterialBoxes, $groupPrefix);
+            })();
+        $isFetchedFromRobotics
+            = $this->foreignHaiRoboticsService->
+        fetchGroup($toLocation, $taskMaterialBoxes, $groupPrefix);
         ($markNewStatus
             =function()use($isFetchedFromRobotics,$stationTaskBatch){
             $isFetchedFromRobotics?
@@ -163,15 +178,36 @@ class StationTaskBatchService
         return $isFetchedFromRobotics;
     }
 
-    function markProcessing(StationTaskBatch $stationTaskBatch)
+    function markProcessing($stationTaskBatches)
     {
-        $stationTaskBatch   ['status']                  = '处理中';
-        $stationTaskBatch   ->update();
-        $stationTaskBatch   ->loadMissing               ('stationTask');
-        $stationTaskBatch   ['stationTask']['status']   = '异常';
-        $stationTaskBatch   ['stationTask']             ->update();
+        if (get_class($stationTaskBatches)==StationTaskBatch::class){
+            $stationTaskBatches = collect($stationTaskBatches);
+        }
+        StationTaskBatch::query()
+            ->whereIn('id', data_get($stationTaskBatches, '*.id'))
+            ->update(['status'=>'处理中']);
+
+        $this->stationTaskService
+            ->markProcessing_byId(
+                data_get($stationTaskBatches, '*.station_id')
+            );
     }
 
+//    function markFinished($stationTaskBatches)
+//    {
+//        if (get_class($stationTaskBatches)==StationTaskBatch::class){
+//            $stationTaskBatches = collect($stationTaskBatches);
+//        }
+//        StationTaskBatch::query()
+//            ->whereIn('id', data_get($stationTaskBatches, '*.id'))
+//            ->update(['status'=>'完成']);
+//
+//        $this->stationTaskService
+//            ->markProcessing_byId(
+//                data_get($stationTaskBatches, '*.station_id')
+//            );
+//    }
+
     function markExcepted(StationTaskBatch $stationTaskBatch)
     {
         $stationTaskBatch['status'] = '异常';

+ 1 - 2
app/Services/StationTaskBatchTypeService.php

@@ -6,7 +6,6 @@ namespace App\Services;
 
 use App\Station;
 use App\StationTaskBatchType;
-use App\StationType;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
 
@@ -19,7 +18,7 @@ class StationTaskBatchTypeService
      * @param string $value
      * @return Station
      */
-    public function firstByWhere(string $key,string $value):Station{
+    public function firstByWhere(string $key,string $value):StationTaskBatchType{
         return Cache::remember('station_mission_batch_type_id_by_'.$key.$value, config('cache.expirations.rarelyChange'), function ()use($key,$value) {
             $stationMissionBatchType =StationTaskBatchType::query()->where($key, $value)->first();
             if(!$stationMissionBatchType)throw new \Exception("找不到 StationMissionBatchType,where $key = $value");

+ 73 - 20
app/Services/StationTaskCommodityService.php

@@ -6,6 +6,8 @@ namespace App\Services;
 
 use App\Batch;
 use App\OrderCommodity;
+use App\StationTask;
+use App\StationTaskBatch;
 use App\StationTaskCommodity;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
@@ -42,18 +44,50 @@ class StationTaskCommodityService
         });
     }
 
-    function createByBatches(array $batches,Collection $stationTasks_toAttach): Collection
+    function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection
     {
         $this->instant($this->stationTaskService,'StationTaskService');
         $stationTaskCommodities_listByBatch=new Collection();
+        $stationTaskCommodities=new Collection();
         foreach ($batches as $batch){
-            $stationTaskCommodities_listByBatch->push(
-                $this->createByBatch($batch)
-            );
+            $taskCommodities = $this->createByBatch($batch);
+            $stationTaskCommodities= $stationTaskCommodities->merge($taskCommodities);
+            $stationTaskCommodities_listByBatch->push($taskCommodities);
         }
-        $this->stationTaskService->registerSubTasks($stationTasks_toAttach,$stationTaskCommodities_listByBatch);
+//        $stationTaskCommodities=$this->getAndAttachIds($stationTaskCommodities);
+        $this->stationTaskService->registerSubTasks(
+            $stationTasks_toAttach,
+            $stationTaskCommodities_listByBatch);
+        return $stationTaskCommodities;
+
     }
 
+//    function getAndAttachIds($taskCommodities): Collection
+//    {
+//        $md5=is_array($taskCommodities)
+//            ?$md5=md5(json_encode($taskCommodities)):null;
+//
+//        return Cache::remember(
+//            'StationTaskCommodity_'.$md5??md5(json_encode($taskCommodities->toArray()))
+//            ,config('cache.expirations.rarelyChange')
+//            ,function()use($taskCommodities){
+//                $a=data_get($taskCommodities,'*.status');
+//                $a2=data_get($taskCommodities,'*.station_task_batch_id');
+//                $a3=data_get($taskCommodities,'*.commodity_id');
+//                $a4=StationTaskCommodity::query()
+//                    ->whereIn('status',data_get($taskCommodities,'*.status'))
+//                    ->whereIn('station_task_batch_id',data_get($taskCommodities,'*.station_task_batch_id'))
+//                    ->whereIn('commodity_id',data_get($taskCommodities,'*.commodity_id'))
+//                    ->get();
+//                $a5=1;
+//            return StationTaskCommodity::query()
+//                ->whereIn('status',data_get($taskCommodities,'*.status'))
+//                ->whereIn('station_task_batch_id',data_get($taskCommodities,'*.station_task_batch_id'))
+//                ->whereIn('commodity_id',data_get($taskCommodities,'*.commodity_id'))
+//                ->get();
+//        });
+//    }
+
     function createByBatch(Batch $batch): Collection
     {
         $this->instant($this->stationTypeService,'StationTypeService');
@@ -66,24 +100,43 @@ class StationTaskCommodityService
             $stationType=$this->stationTypeService->getForCommodity();
             $station=$this->stationService->getStation_byType($stationType['name']);
             $materialBox=$this->materialBoxService->firstOrCreate(['code' => $orderCommodity['location']]);
-            $stationTaskCommodities_toCreate->push([
-                'station_id'=>$station['id'],
-                'material_box_id'=>$materialBox['id'],
-                'commodity_id'=>$orderCommodity['commodity_id'],
-                'amount'=>$orderCommodity['amount'],
-                'bin_number'=>$orderCommodity['orderBin']['number']??'',
-                'order_id'=>$orderCommodity['order_id'],
-                'status'=>'待处理'
-            ]);
+            $stationTaskCommodities_toCreate->push(
+                new StationTaskCommodity([
+                    'station_id'=>$station['id'],
+                    'material_box_id'=>$materialBox['id'],
+                    'commodity_id'=>$orderCommodity['commodity_id'],
+                    'amount'=>$orderCommodity['amount'],
+                    'bin_number'=>$orderCommodity['orderBin']['number']??'',
+                    'order_id'=>$orderCommodity['order_id'],
+                    'station_task_batch_id'=>$batch['id'],
+                    'status'=>'待处理'
+                ])
+            );
         }
-        $this->insert($stationTaskCommodities_toCreate->toArray());
+        return $this->insert($stationTaskCommodities_toCreate->toArray());
     }
 
-    public function insert(array $stationTaskCommodities): bool
+    public function insert(array $taskCommodities): ?Collection
     {
-        $inserted = StationTaskCommodity::query()->insert($stationTaskCommodities);
-        LogService::log(__METHOD__,__FUNCTION__,json_encode($stationTaskCommodities).
-            '||'.json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),0,3)));
-        return $inserted;
+        StationTaskCommodity::query()->insert($taskCommodities);
+        return StationTaskCommodity::query()
+            ->whereIn('status', data_get($taskCommodities, '*.status'))
+            ->whereIn('station_task_batch_id', data_get($taskCommodities, '*.station_task_batch_id'))
+            ->whereIn('commodity_id', data_get($taskCommodities, '*.commodity_id'))
+            ->get();
+    }
+    function markProcessing($stationTaskCommodities)
+    {
+        if (get_class($stationTaskCommodities)==StationTaskCommodity::class){
+            $stationTaskCommodities = collect($stationTaskCommodities);
+        }
+        StationTaskCommodity::query()
+            ->whereIn('id',data_get($stationTaskCommodities,'*.id'))
+            ->update(['status'=>'处理中']);
+
+        $this->stationTaskService
+            ->markProcessing_byId(
+                data_get($stationTaskCommodities, '*.station_id')
+            );
     }
 }

+ 107 - 15
app/Services/StationTaskMaterialBoxService.php

@@ -5,7 +5,10 @@ namespace App\Services;
 
 
 use App\Batch;
+use App\Exceptions\ErrorException;
+use App\MaterialBox;
 use App\OrderCommodity;
+use App\StationTask;
 use App\StationTaskMaterialBox;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
@@ -21,6 +24,10 @@ class StationTaskMaterialBoxService
     private $stationTypeService;
     /** @var StationTaskService $stationTaskService */
     private $stationTaskService;
+    /** @var StationTaskBatchService $stationTaskBatchService */
+    private $stationTaskBatchService;
+    /** @var StationTaskCommodityService $stationTaskCommodityService */
+    private $stationTaskCommodityService;
     /** @var MaterialBoxService $materialBoxService */
     private $materialBoxService;
     public function __construct(){
@@ -28,20 +35,32 @@ class StationTaskMaterialBoxService
         $this->stationTypeService=null;
         $this->stationTaskService=null;
         $this->materialBoxService=null;
+        $this->stationTaskBatchService=null;
+        $this->stationTaskCommodityService=null;
     }
-    function createByBatches(array $batches,Collection $stationTasks_toAttach): Collection
+
+    function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection
     {
-        $stationTaskMaterialBoxes_listByBatch=new Collection();
-        foreach ($batches as $batch){
-            $stationTaskMaterialBoxes_listByBatch->push(
-                $this->createByBatch($batch)
-            );
-        }
-        $this->stationTaskService->registerSubTasks($stationTasks_toAttach,$stationTaskMaterialBoxes_listByBatch);
+        $this->instant($this->stationTaskService,'StationTaskService');
+        $stationTaskMaterialBoxes = (function () use ($batches) {
+            $stationTaskMaterialBoxes_listByBatch = new Collection();
+            foreach ($batches as $batch) {
+                $stationTaskMaterialBoxes_listByBatch=
+                    $stationTaskMaterialBoxes_listByBatch->merge(
+                    $this->createByBatch($batch)
+                );
+            }
+            return $stationTaskMaterialBoxes_listByBatch;
+        })();
+         $this->stationTaskService
+            ->registerSubTasks(
+                $stationTasks_toAttach,
+                [$stationTaskMaterialBoxes]);
+        return $stationTaskMaterialBoxes;
 
     }
 
-    function createByBatch(Batch $batch): Collection
+    function createByBatch(Batch $batch): ?Collection
     {
         $this->instant($this->materialBoxService,'MaterialBoxService');
         $this->instant($this->stationTypeService,'StationTypeService');
@@ -49,8 +68,9 @@ class StationTaskMaterialBoxService
         $stationMaterialBoxes_toCreate=new Collection();
         $order_ids=data_get($batch['orders'],'*.id');
         $orderCommodities=OrderCommodity::query()->with('orderBin')->whereIn('order_id',$order_ids)->get();
+        if($orderCommodities->isEmpty())return $stationMaterialBoxes_toCreate;
+        $stationType=$this->stationTypeService->getForMaterialBox_onBatchProcess();
         foreach ($orderCommodities as $orderCommodity){
-            $stationType=$this->stationTypeService->getForMaterialBox();
             $station=$this->stationService->getStation_byType($stationType['name']);
             $materialBox=$this->materialBoxService->firstOrCreate(['code' => $orderCommodity['location']]);
             $stationMaterialBoxes_toCreate->push([
@@ -59,7 +79,7 @@ class StationTaskMaterialBoxService
                 'status'=>'待处理'
             ]);
         }
-        $this->insert($stationMaterialBoxes_toCreate->toArray());
+        return $this->insert($stationMaterialBoxes_toCreate->toArray());
     }
 
     function get(array $kvPairs){
@@ -74,11 +94,83 @@ class StationTaskMaterialBoxService
         });
     }
 
-    public function insert(array $stationTaskMaterialBoxes): bool
+    public function insert(array $stationTaskMaterialBoxes): Collection
     {
-        $inserted = StationTaskMaterialBox::query()->insert($stationTaskMaterialBoxes);
-        LogService::log(__METHOD__,__FUNCTION__,json_encode($stationTaskMaterialBoxes).
-            '||'.json_encode(array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),0,3)));
+        $inserted=collect();
+        foreach ($stationTaskMaterialBoxes as $stationTaskMaterialBox){
+            $inserted->push(StationTaskMaterialBox::query()->create($stationTaskMaterialBox));
+        }
         return $inserted;
     }
+
+    function markHasPut(StationTaskMaterialBox $stationTaskMaterialBox){
+        try{
+            $taskType=$this->getServingTaskType($stationTaskMaterialBox);
+            switch ($taskType){
+                case '分波次':
+                    $this->markProcessing($stationTaskMaterialBox);
+                    $this->stationTaskBatchService->markProcessing($stationTaskMaterialBox['stationTaskBatch']);
+                    $this->stationTaskCommodityService->markProcessing($stationTaskMaterialBox['stationTaskCommodities']);
+                    break;
+                case '入立库':
+
+                    break;
+                case '入库':break;
+            }
+        }catch (\Exception $e){
+            throw new ErrorException('放置料箱出错');
+        }
+    }
+
+    function markTaken($stationTaskMaterialBox){
+        //TODO: 标记 料箱位置(需要其字段存在)$stationTaskMaterialBox['materialBox']['position']
+    }
+    function markProcessed(StationTaskMaterialBox $stationTaskMaterialBox){
+        $stationTaskMaterialBox['status'] = '完成';
+        $stationTaskMaterialBox->save();
+        $this->stationService->broadcastBinMonitor($stationTaskMaterialBox['station_id'],$stationTaskMaterialBox['stationTask']);
+    }
+
+    function markProcessing($stationTaskMaterialBox)
+    {
+        if (get_class($stationTaskMaterialBox)==StationTaskMaterialBox::class){
+            $stationTaskMaterialBox = collect($stationTaskMaterialBox);
+        }
+        StationTaskMaterialBox::query()
+            ->whereIn('id', data_get($stationTaskMaterialBox, '*.id'))
+            ->update(['status'=>'处理中']);
+        $this->stationTaskService
+            ->markProcessing_byId(
+                data_get($stationTaskMaterialBox, '*.station_id')
+            );
+    }
+
+    function excepted($stationTaskMaterialBox_orBox){
+        switch (get_class($stationTaskMaterialBox_orBox)){
+            case MaterialBox::class:
+            case StationTaskMaterialBox::class:
+            throw new ErrorException('料箱异常'.json_encode($stationTaskMaterialBox_orBox->toJson()));
+        }
+    }
+
+    function getServingTaskType(StationTaskMaterialBox $stationTaskMaterialBox): string
+    {
+        $stationTaskMaterialBox->loadMissing('station.stationType');
+        if($isBatching=(
+            $stationTaskMaterialBox['station_task_batch_id'] &&
+            $stationTaskMaterialBox['station']['stationType'] == '料箱监视器')
+        ){
+            return '分波次';
+        }
+        if($isPuttingBack=(
+            !$stationTaskMaterialBox &&
+            $stationTaskMaterialBox['station']['stationType'] == '立库')
+        ){
+            return '入立库';
+        }
+        if($isStoring=false){
+            return '入库';
+        }
+        throw new ErrorException('当前类型找不到');
+    }
 }

+ 17 - 16
app/Services/StationTaskService.php

@@ -34,37 +34,38 @@ class StationTaskService
     }
 
     /**
-     * 个列表一一对应,每个task注册一组子任务: [task,task...],[[subTask,subTask],[subTask,subTask]....]
+     * 个列表一一对应,每个task注册一组子任务: [task,task...],[[subTask,subTask],[subTask,subTask]....]
      * @param Collection $tasks
      * @param Collection $subTaskLists 二维数组,第一维是对应注册的任务
-     * @return array
      */
-    function registerSubTasks(Collection $tasks, Collection $subTaskLists): array
+    function registerSubTasks(Collection $tasks, iterable $subTaskLists)
     {
         $this->instant($this->stationTaskChildService,'StationTaskChildService');
         $taskChildren_toInsert=collect();
         foreach ($subTaskLists as $i=>$subTaskList){
             foreach ($subTaskList as $subTask){
-                $tableName=(function()use($subTask){
-                    switch (get_class($subTask)){
-                        case StationTaskBatch::class: return 'station_task_batches';
-                        case StationTaskCommodity::class: return 'station_task_commodities';
-                        case StationTaskMaterialBox::class: return 'station_task_material_boxes';
-                        default:
-                            throw new \Exception('任务类型没有定义相应的模型类');
-                    }
-                })();
                 $paramToInsert = [
                     'station_task_id' => $tasks[$i]['id'],
-                    'station_task_table_type' => $tableName,
-                    'station_task_table_id' => $subTask['id'],
+                    'station_taskable_type' => get_class($subTask),
+                    'station_taskable_id' => $subTask['id'],
                 ];
-                $taskChild=$this->stationTaskChildService->get($paramToInsert)->frist();
-                if(!$taskChild)
+                $taskChild_existed=$this->stationTaskChildService->get($paramToInsert)->first();
+                if(!$taskChild_existed){
                     $taskChildren_toInsert->push($paramToInsert);
+                    $subTask['station_task_id']=$tasks[$i]['id'];
+                    $subTask->save();
+                }
             }
         }
         $this->stationTaskChildService->insert($taskChildren_toInsert->toArray());
     }
 
+    function markProcessing_byId($stationTaskIds)
+    {
+        StationTask::query()
+            ->whereIn('id',$stationTaskIds)
+            ->update(['status'=>'处理中']);
+    }
+
+
 }

+ 9 - 0
app/Services/StationTaskTypeService.php

@@ -0,0 +1,9 @@
+<?php 
+
+namespace App\Services; 
+
+Class StationTaskTypeService
+{ 
+
+
+}

+ 9 - 0
app/Services/StationTypeBinMonitorService.php

@@ -0,0 +1,9 @@
+<?php 
+
+namespace App\Services; 
+
+Class StationTypeBinMonitorService
+{ 
+
+
+}

+ 6 - 5
app/Services/StationTypeService.php

@@ -19,20 +19,21 @@ class StationTypeService
     {
         $this->stationRuleBatchService=null;
     }
-
-    function getByBatch(Batch $batch): StationType
+    function getByBatch(Batch $batch)
     {
         $this->instant($this->stationRuleBatchService,'StationRuleBatchService');
-        $stationRuleBatch=$this->stationRuleBatchService->getByBatch($batch);
-        return $stationRuleBatch['stationType'];
+//        return $stationRuleBatch['stationType'];
+        return StationType::query()->where('name','料箱监视器')->first();
     }
+
     function getForCommodity(): StationType
     {
         /** @var StationType $stationType */
         $stationType= StationType::query()->firstOrCreate(['name'=>'料箱监视器']);
         return $stationType;
     }
-    function getForMaterialBox(): StationType
+
+    function getForMaterialBox_onBatchProcess(): StationType
     {
         /** @var StationType $stationType */
         $stationType= StationType::query()->firstOrCreate(['name'=>'料箱监视器']);

+ 6 - 3
app/Station.php

@@ -12,10 +12,13 @@ class Station extends Model
 
     protected $fillable=['name', 'code', 'station_type_id','sequence','parent_id'];
 
-    public function type(){
-        return $this->belongsTo(StationType::class,'station_type_id');
+    public function stationType(){
+        return $this->belongsTo(StationType::class);
     }
     public function parent(){
-        return $this->belongsTo(Station::class,'parent_id','id');
+        return $this->belongsTo(Station::class);
+    }
+    public function child(){
+        return $this->hasOne(Station::class,'parent_id');
     }
 }

+ 3 - 2
app/StationRuleBatch.php

@@ -3,6 +3,7 @@
 namespace App;
 
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\HasOne;
 
 use App\Traits\LogModelChanging;
@@ -13,8 +14,8 @@ class StationRuleBatch extends Model
 
     protected $fillable=['name','station_type_id','batch_type','owner_id'];
 
-    public function stationType(): HasOne
+    public function stationType(): BelongsTo
     {
-        return $this->hasOne(StationType::class);
+        return $this->belongsTo(StationType::class);
     }
 }

+ 27 - 3
app/StationTask.php

@@ -19,14 +19,38 @@ class StationTask extends Model
 
     public function stationTaskCommodities()
     {   //任务商品列表
-        return $this->morphTo()->where("station_task_table_type","station_task_commodities");
+        return $this->morphToMany(
+            StationTaskCommodity::class,
+            'station_taskable',
+            'station_task_children',
+            'station_task_id',
+            'station_taskable_id',
+            'id',
+            'id',
+            true);
     }
     public function stationTaskBatches()
     {   //任务波次 目前为单个,取值时应取第一个即可
-        return $this->morphTo()->where("station_task_table_type","station_task_batches");
+        return $this->morphToMany(
+            StationTaskBatch::class,
+            'station_taskable',
+            'station_task_children',
+            'station_task_id',
+            'station_taskable_id',
+            'id',
+            'id',
+            true);
     }
     public function stationTaskMaterialBoxes()
     {   //任务料箱
-        return $this->morphTo()->where("station_task_table_type","station_task_material_boxes");
+        return $this->morphToMany(
+            StationTaskMaterialBox::class,
+            'station_taskable',
+            'station_task_children',
+            'station_task_id',
+            'station_taskable_id',
+            'id',
+            'id',
+        true);
     }
 }

+ 7 - 6
app/StationTaskBatch.php

@@ -3,6 +3,7 @@
 namespace App;
 
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\HasOne;
 use Illuminate\Database\Eloquent\Relations\MorphOne;
 
@@ -14,17 +15,17 @@ class StationTaskBatch extends Model
 
     protected $fillable=['batch_id','station_id','station_task_batch_type_id','status'];
 
-    function station(): HasOne
+    function station(): BelongsTo
     {
-        return $this->hasOne(Station::class);
+        return $this->belongsTo(Station::class);
     }
-    function stationTask(): MorphOne
+    function stationTask(): BelongsTo
     {
-        return $this->morphOne(StationTask::class,'station_taskable');
+        return $this->belongsTo(StationTask::class);
     }
 
-    public function batch(): HasOne
+    public function batch(): BelongsTo
     {   //波次
-        return $this->hasOne(Batch::class,"id","batch_id");
+        return $this->belongsTo(Batch::class);
     }
 }

+ 1 - 1
app/StationTaskChild.php

@@ -10,5 +10,5 @@ class StationTaskChild extends Model
 {
     use LogModelChanging;
 
-    protected $fillable= ['station_task_id','station_task_table_type','station_task_table_id'];
+    protected $fillable= ['station_task_id','station_taskable_type','station_taskable_id'];
 }

+ 9 - 7
app/StationTaskCommodity.php

@@ -5,22 +5,24 @@ namespace App;
 use Illuminate\Database\Eloquent\Model;
 
 use App\Traits\LogModelChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
 class StationTaskCommodity extends Model
 {
     use LogModelChanging;
 
-    protected $fillable= ['station_id','material_box_id','commodity_id','amount','order_id','status',"bin_number"];
+    protected $fillable= ['station_id','material_box_id','commodity_id','amount','order_id','status',"bin_number","station_task_batch_id"];
 
-    public function commodity()
+    public function commodity(): BelongsTo
     {   //商品
-        return $this->hasOne(Commodity::class,"id","commodity_id");
+        return $this->belongsTo(Commodity::class);
     }
-    public function materialBox()
+    public function materialBox(): BelongsTo
     {   //料箱
-        return $this->hasOne(MaterialBox::class,"id","material_box_id");
+        return $this->belongsTo(MaterialBox::class);
     }
-    function parentTask(){
-        return $this->morphOne(StationTask::class,'station_taskable');
+    function stationTask(): BelongsTo
+    {
+        return $this->belongsTo(StationTask::class);
     }
 }

+ 21 - 4
app/StationTaskMaterialBox.php

@@ -3,6 +3,9 @@
 namespace App;
 
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasOne;
+use Illuminate\Database\Eloquent\Relations\MorphOne;
 
 use App\Traits\LogModelChanging;
 
@@ -12,11 +15,25 @@ class StationTaskMaterialBox extends Model
 
     protected $fillable=['station_id','material_box_id','status'];
 
-    public function materialBox()
-    {   //料箱
+    function materialBox(): HasOne
+    {
         return $this->hasOne(MaterialBox::class,"id","material_box_id");
     }
-    function parentTask(){
-        return $this->morphOne(StationTask::class,'station_taskable');
+    function station(): BelongsTo
+    {
+        return $this->belongsTo(Station::class,"id","station_id");
+    }
+    function stationTaskBatch(): BelongsTo
+    {
+        return $this->belongsTo(StationTaskBatch::class,"id","station_id");
+    }
+    function stationTask(): BelongsTo
+    {
+        return $this->belongsTo(StationTask::class);
+    }
+    function stationTaskCommodities(): HasOne
+    {
+        return $this->hasOne(StationTaskCommodity::class,"station_task_batch_id","station_task_batch_id")
+        ->where('material_box_id',$this['material_box_id']);
     }
 }

+ 44 - 4
app/Traits/TestMockSubServices.php

@@ -5,11 +5,13 @@ trait TestMockSubServices{
     function subMock(array $serviceDefinition){
         $mockingService=$this->createPartialMock(
             $serviceDefinition['class'],
-            array_keys($serviceDefinition['methods'])
+            isset($serviceDefinition['methods'])
+                ?array_keys($serviceDefinition['methods']):[]
         );
-        foreach ($serviceDefinition['methods'] as $mName=>$mVal){
-            $mockingService->method($mName)->willReturn($mVal);
-        }
+        if(isset($serviceDefinition['methods']))
+            foreach ($serviceDefinition['methods'] as $mName=>$mVal){
+                $mockingService->method($mName)->willReturn($mVal);
+            }
 
         if(isset($serviceDefinition['subServices']))
             foreach ($serviceDefinition['subServices'] as $subService){
@@ -31,4 +33,42 @@ trait TestMockSubServices{
         return $mockingService;
     }
 
+    function getTargetIdCirculately($targetArr, $additionMark='', $idName='id'){
+        $amount = count($targetArr);
+
+        $json_encode = json_encode($targetArr);
+        $iName = 'i_' . md5($json_encode . $additionMark);
+        if(!isset($this->data[$iName])){
+            $this->data[$iName]=$amount;
+        }
+        $this->data[$iName]++;
+        if($this->data[$iName]>=$this->batchAmount)
+            $this->data[$iName]=0;
+        return $targetArr[$this->data[$iName]][$idName];
+    }
+    function getIntegerIncreasely($markStr): int
+    {
+        $iName = 'i_' . $markStr;
+        if(!isset($this->data[$iName])){
+            $this->data[$iName]=-1;
+        }
+        $this->data[$iName]++;
+        return $this->data[$iName];
+    }
+    function makeArray($amount,$array)
+    {
+        $resultArrays=[];
+        for($i=0;$i<$amount;$i++){
+            $newArr=[];
+            foreach ($array as $key=>$item){
+                if(gettype($item)=='object'){
+                    $newArr[$key]=$item();
+                }else{
+                    $newArr[$key]=$item;
+                }
+            }
+            $resultArrays[]= $newArr;
+        }
+        return $resultArrays;
+    }
 }

+ 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://192.168.1.201:2011/api/haiqEss/gr/relocate",  //移动料箱
-            'light' => "http://192.168.1.201:40000/api/haiqEss/ctlPTL",  //控灯
+            'moveBin' => "http://58.33.243.164:10022/api/haiqEss/gr/relocate",  //移动料箱
+            'light' => "http://58.33.243.164:10022/api/haiqEss/ctlPTL",  //控灯
         ],
     ],
 

+ 1 - 1
database/factories/MaterialBoxFactory.php

@@ -7,6 +7,6 @@ use Faker\Generator as Faker;
 
 $factory->define(MaterialBox::class, function (Faker $faker) {
     return [
-        'code'=>md5(\Illuminate\Support\Str::random(5)).date('Ymd')
+        'code'=>md5(\Illuminate\Support\Str::random(5).microtime(true))
     ];
 });

+ 6 - 3
database/factories/OwnerFactory.php

@@ -1,19 +1,22 @@
 <?php
 
-/** @var \Illuminate\Database\Eloquent\Factory $factory */
+/** @var Factory $factory */
 
 use App\Owner;
+use App\UserOwnerGroup;
 use Faker\Generator as Faker;
+use Illuminate\Database\Eloquent\Factory;
+use Illuminate\Support\Str;
 
 $factory->define(Owner::class, function (Faker $faker) {
     return [
         'name' => $faker->name,                 //名称
-        'code' => \Illuminate\Support\Str::random(5).date('yymmdd'),                 //代码
+        'code' => Str::random(5).date('yymmdd'),                 //代码
         'checking_count' => mt_rand(0,5),       //审核数量
         "tax_rate" => mt_rand(0,100) / 10,             //税率
         "linkman" => $faker->name,              //联系人
         "phone_number" => $faker->phoneNumber,         //联系电话
-        "user_owner_group_id" => factory(\App\UserOwnerGroup::class),  //项目组ID
+        "user_owner_group_id" => factory(UserOwnerGroup::class),  //项目组ID
         "waring_line_on" => mt_rand(0,1000),       //月单量预警
         "description" => $faker->text           //描述
     ];

+ 0 - 12
database/factories/StationMissionBatchFactory.php

@@ -1,12 +0,0 @@
-<?php
-
-/** @var \Illuminate\Database\Eloquent\Factory $factory */
-
-use App\StationTaskBatch;
-use Faker\Generator as Faker;
-
-$factory->define(StationTaskBatch::class, function (Faker $faker) {
-    return [
-        //
-    ];
-});

+ 0 - 12
database/factories/StationMissionCommodityFactory.php

@@ -1,12 +0,0 @@
-<?php
-
-/** @var \Illuminate\Database\Eloquent\Factory $factory */
-
-use App\StationTaskCommodity;
-use Faker\Generator as Faker;
-
-$factory->define(StationTaskCommodity::class, function (Faker $faker) {
-    return [
-        //
-    ];
-});

+ 1 - 1
database/factories/StationRuleBatchFactory.php

@@ -7,6 +7,6 @@ use Faker\Generator as Faker;
 
 $factory->define(StationRuleBatch::class, function (Faker $faker) {
     return [
-        //
+        'name' => $faker->uuid,
     ];
 });

+ 0 - 0
database/factories/StationMissionBatchTypeFactory.php → database/factories/StationTaskBatchTypeFactory.php


+ 1 - 1
database/factories/StationTaskFactory.php

@@ -8,6 +8,6 @@ use Faker\Generator as Faker;
 $factory->define(StationTask::class, function (Faker $faker) {
     $status = ['待处理','挂起','处理中','完成','异常','取消'];
     return [
-        "status"=>$status[array_rand($status)],
+        "status"=>'待处理',
     ];
 });

+ 1 - 1
database/factories/StationMissionMaterialBoxFactory.php → database/factories/StationTaskMaterialBoxFactory.php

@@ -7,6 +7,6 @@ use Faker\Generator as Faker;
 
 $factory->define(StationTaskMaterialBox::class, function (Faker $faker) {
     return [
-        //
+        'status'=>'待处理'
     ];
 });

+ 1 - 1
database/factories/StationTypeFactory.php

@@ -7,6 +7,6 @@ use Faker\Generator as Faker;
 
 $factory->define(StationType::class, function (Faker $faker) {
     return [
-        //
+        'name'=>$faker->name
     ];
 });

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

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

+ 44 - 0
database/migrations/2020_12_24_155647_add_column_material_task_type_drop_station_mission_tables.php

@@ -0,0 +1,44 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddColumnMaterialTaskTypeDropStationMissionTables extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::dropIfExists('station_mission_batch_types');
+        Schema::dropIfExists('station_mission_batches');
+        Schema::dropIfExists('station_mission_commodities');
+        Schema::dropIfExists('station_mission_material_boxes');
+        Schema::table('station_task_material_boxes',function(Blueprint $table){
+            $table->enum('type',['取','放','移动']);
+            $table->bigInteger('station_task_batch_id')->index()->nullable();
+        });
+        Schema::table('station_task_commodities',function(Blueprint $table){
+            $table->bigInteger('station_task_batch_id')->index()->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('station_task_material_boxes',function(Blueprint $table){
+            $table->dropColumn('type');
+            $table->dropColumn('station_task_batch_id');
+        });
+        Schema::table('station_task_commodities',function(Blueprint $table){
+            $table->dropColumn('station_task_batch_id');
+        });
+    }
+}

+ 30 - 0
database/migrations/2020_12_29_182249_change_station_rule_batch_column_default_batch_type.php

@@ -0,0 +1,30 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeStationRuleBatchColumnDefaultBatchType extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('station_rule_batches',function(Blueprint $table){
+            $table->string('batch_type')->default('无')->change();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 45 - 0
database/migrations/2021_01_06_114158_create_station_task_children2.php

@@ -0,0 +1,45 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateStationTaskChildren2 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('station_task_children', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger('station_task_id')->index();
+            $table->string('station_taskable_type');
+            $table->bigInteger('station_taskable_id');
+            $table->index(['station_taskable_type','station_taskable_id'],'station_taskable_t_i');
+            $table->timestamps();
+        });
+        Schema::table('station_tasks', function (Blueprint $table) {
+            $table->dropColumn('station_taskable_type');
+            $table->dropColumn('station_taskable_id');
+            $table->dropIndex('station_taskable_type');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('station_task_children');
+        Schema::table('station_tasks', function (Blueprint $table) {
+            $table->string('station_taskable_type');
+            $table->integer('station_taskable_id');
+            $table->index(['station_taskable_id','station_taskable_id'],'station_taskable_type');
+        });
+    }
+}

+ 45 - 0
database/migrations/2021_01_21_153513_add_column_station_task_id_for_all_sub_tasks.php

@@ -0,0 +1,45 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddColumnStationTaskIdForAllSubTasks extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('station_task_batches', function (Blueprint $table) {
+            $table->integer('station_task_id')->index()->nullable();
+        });
+        Schema::table('station_task_commodities', function (Blueprint $table) {
+            $table->integer('station_task_id')->index()->nullable();
+        });
+        Schema::table('station_task_material_boxes', function (Blueprint $table) {
+            $table->integer('station_task_id')->index()->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('station_task_batches', function (Blueprint $table) {
+            $table->dropColumn('station_task_id');
+        });
+        Schema::table('station_task_commodities', function (Blueprint $table) {
+            $table->dropColumn('station_task_id');
+        });
+        Schema::table('station_task_material_boxes', function (Blueprint $table) {
+            $table->dropColumn('station_task_id');
+        });
+
+    }
+}

+ 3 - 2
public/t.php

@@ -1,4 +1,5 @@
 <?php
 
-$s = '434211kjk';
-var_dump(preg_match('/434/',$s));
+$failed=!$success=true;
+
+var_dump($failed,$success);

+ 1 - 1
resources/lang/cn/validation.php

@@ -57,7 +57,7 @@ return [
         'array' => ':attribute must have :value items or more.',
     ],
     'image' => ':attribute must be an image.',
-    'in' => 'selected :attribute is invalid.',
+    'in' => ' :attribute 不在合法值内.',
     'in_array' => ':attribute field does not exist in :other.',
     'integer' => ':attribute must be an integer.',
     'ip' => ':attribute must be a valid IP address.',

+ 12 - 0
tests/Controller/api/thirdPart/haiq/StorageController/TestStorageController.php

@@ -0,0 +1,12 @@
+<?php
+
+
+namespace Tests\Controller\api\thirdPart\haiq;
+
+
+use Tests\TestCase;
+
+class TestStorageController extends TestCase
+{
+
+}

+ 38 - 0
tests/Services/BatchService/AssignTasksTest.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace Tests\Services\BatchService;
+use App\Services\BatchService;
+use Tests\TestCase;
+use App\Batch;
+use App\Traits\TestMockSubServices;
+
+class AssignTasksTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var BatchService $service */
+    public $service;
+    private $data;
+    private $amount=2;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('BatchService');
+        $this->data['Batches']
+            = factory(Batch::class, $this->amount)
+            ->create();
+    }
+
+    public function testReturned()
+    {
+        $this->service->assignTasks($this->data['Batches']);
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        Batch::query()
+            ->whereIn('id',data_get($this->data['Batches'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 40 - 0
tests/Services/BatchService/TestAssignTasks.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Tests\Services\BatchService;
+
+use App\Batch;
+use App\Services\BatchService;
+use Tests\TestCase;
+
+class TestAssignTasks extends TestCase
+{
+//    use RefreshDatabase;
+
+    /** @var BatchService $service */
+    private $service;
+    private $data = [];
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('BatchService');
+        $batches = factory(Batch::class,3)->create();
+        $this->data['batches'] = $batches;
+    }
+
+    /**
+     * @test
+     */
+    public function gotShouldProcessingBatches()
+    {
+        $this->assertTrue(true);
+    }
+
+    public function tearDown(): void
+    {
+        Batch::query()
+            ->whereIn('id',data_get($this->data['batches'],'*.id'))
+            ->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+}

+ 0 - 1
tests/Services/BatchService/TestGetBatchByCodes.php

@@ -4,7 +4,6 @@ namespace Tests\Services\BatchService;
 
 use App\Batch;
 use App\Services\BatchService;
-use Illuminate\Foundation\Testing\RefreshDatabase;
 use Tests\TestCase;
 
 class TestGetBatchByCodes extends TestCase

+ 1 - 2
tests/Services/CityService/FindByNameTest.php

@@ -1,11 +1,10 @@
 <?php
 
-namespace Tests\Services\CityService\FindByNameTest;
+namespace Tests\Services\CityService;
 
 use App\City;
 use App\Services\CityService;
 use Illuminate\Foundation\Testing\RefreshDatabase;
-use Illuminate\Foundation\Testing\WithFaker;
 use Tests\TestCase;
 
 class FindByNameTest extends TestCase

+ 77 - 0
tests/Services/ForeignHaiRoboticsService/TaskUpdateTest.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace Tests\Services\ForeignHaiRoboticsService;
+use App\MaterialBox;
+use App\Services\ForeignHaiRoboticsService;
+use App\Station;
+use App\StationTaskMaterialBox;
+use Tests\TestCase;
+use App\Traits\TestMockSubServices;
+
+class TaskUpdateTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var ForeignHaiRoboticsService $service */
+    public $service;
+    private $data;
+    private $amount=2;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('ForeignHaiRoboticsService');
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+        $this->data['stationTaskMaterialBox'] = factory(StationTaskMaterialBox::class)->create([
+            'station_id' => 1,
+            'material_box_id' => $this->data['materialBox']['id'],
+
+        ]);
+        $this->data['task']=[
+            'taskCode'=>md5(microtime(true)),
+            'updateEventType' => 0,
+            'status'=>0,
+            'binCode'=>$this->data['materialBox']['code']
+        ];
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    public function testMissionFailed()
+    {
+        $this->data['task']['status']=1;
+        $this->assertFalse($this->service->taskUpdate(
+            $this->data['task']['taskCode'],
+            $this->data['task']['updateEventType'],
+            $this->data['task']['status'],
+            $this->data['task']['binCode']
+        ));
+    }
+
+    public function testMissionFailed2()
+    {
+        $this->data['task']['status']=1;
+        $this->assertFalse($this->service->taskUpdate(
+            $this->data['task']['taskCode'],
+            $this->data['task']['updateEventType'],
+            $this->data['task']['status'],
+            $this->data['task']['binCode']
+        ));
+    }
+
+    function tearDown(): void
+    {
+        Station::query()
+            ->whereIn('id',[$this->data['task']['station']['id']??''])
+            ->delete();
+        MaterialBox::query()
+            ->whereIn('id',[$this->data['task']['materialBox']['id']??''])
+            ->delete();
+        StationTaskMaterialBox::query()
+            ->whereIn('id',[$this->data['task']['stationTaskMaterialBox']['id']??''])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 57 - 0
tests/Services/StationRuleBatchService/GetBatches_shouldProcessTest.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace Tests\Services\StationRuleBatchService;
+
+use App\Batch;
+use App\Owner;
+use App\Services\BatchService;
+use App\Services\StationRuleBatchService;
+use App\StationRuleBatch;
+use Tests\TestCase;
+
+class GetBatches_shouldProcessTest extends TestCase
+{
+    /** @var StationRuleBatchService $service */
+    private $service;
+    /** @var BatchService $batchService */
+    private $batchService;
+    private $data = [];
+    private $amountOfInRule = 3;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationRuleBatchService');
+        $this->batchService = app('BatchService');
+        $this->data['owner_target'] = factory(Owner::class)->create();
+        $this->data['owner_none_target'] = factory(Owner::class)->create();
+        $this->data['stationRuleBatch'] = factory(StationRuleBatch::class)
+            ->create([
+                'owner_id' => $this->data['owner_target']['id'],
+            ]);
+        $this->data['batches'] = factory(Batch::class, $this->amountOfInRule)->create([
+            'owner_id' => $this->data['owner_target']['id'],
+        ]);
+        $this->data['batches'][]=factory(Batch::class)->create([
+            'owner_id' => $this->data['owner_none_target']['id'],
+        ]);
+    }
+
+    public function testFilteredOut()
+    {
+        $batches=$this->service->getBatches_shouldProcess($this->data['batches']);
+        $this->assertEquals($this->amountOfInRule,$batches->count());
+    }
+
+    public function tearDown(): void
+    {
+        cache()->flush();
+        Owner::query()->whereIn('id',[
+            $this->data['owner_target']['id'],
+            $this->data['owner_none_target']['id'],
+        ])->delete();
+        StationRuleBatch::query()->where('id',$this->data['stationRuleBatch']['id'])->delete();
+        Batch::query()->whereIn('id',data_get($this->data['batches'],'*.id'))->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+}

+ 81 - 0
tests/Services/StationTaskBatchService/CreateByBatchesTest.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace Tests\Services\StationTaskBatchService;
+
+use App\Batch;
+use App\Owner;
+use App\Services\StationTaskBatchService;
+use App\Services\StationTaskService;
+use App\StationRuleBatch;
+use App\StationTask;
+use App\StationTaskBatch;
+use App\StationTaskChild;
+use App\StationType;
+use Tests\TestCase;
+
+class CreateByBatchesTest extends TestCase
+{
+    /** @var StationTaskBatchService $service */
+    private $service;
+    /** @var StationTaskService $service */
+    private $stationTaskService;
+    private $data = [];
+    const AmountOfBatch=3;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskBatchService');
+        $this->stationTaskService = app('StationTaskService');
+        $this->data['owner'] =
+            factory(Owner::class)
+                ->create();
+        $this->data['batches'] =
+            factory(Batch::class,
+                self::AmountOfBatch)
+                ->create([
+                    'status'=>'未处理',
+                    'owner_id'=>$this->data['owner']['id']
+                ]);
+        $this->data['stationRuleBatch'] =
+            factory(StationRuleBatch::class)
+                -> create([
+                    'owner_id'=>$this->data['owner']['id'],
+                ]);
+        $this->data['stationTask'] =
+            $this->stationTaskService->create(self::AmountOfBatch);
+    }
+
+    public function testReturned()
+    {
+        ($isReturningRightAmount
+            =function (){
+            $this->data['stationTaskBatches']
+                =$this->service->createByBatches($this->data['batches'], $this->data['stationTask']);
+            $this->assertEquals(self::AmountOfBatch, $this->data['stationTaskBatches']->count());
+        })();
+
+        ($isBindingRightRootTasks
+            =function (){
+            $this->assertEquals(
+                data_get($this->data['stationTask'],'*.id'),
+                $this->data['stationTaskBatches']->map(function($taskBatch){
+                    $taskBatch->loadMissing('stationTask');
+                    return $taskBatch['stationTask']['station_task_id'];
+                })->toArray()
+            );
+        })();
+    }
+
+
+    public function tearDown(): void
+    {
+        Batch::query()->whereIn('id',data_get($this->data['batches'],'*.id')??[])->delete();
+        StationTask::query()->whereIn('id',data_get($this->data['stationTask'],'*.id')??[])->delete();
+        StationTaskBatch::query()->whereIn('id',data_get($this->data['stationTaskBatches'],'*.id')??[])->delete();
+        StationTaskChild::query()->whereIn('station_task_id',data_get($this->data['stationTask'],'*.id')??[])->delete();
+        Owner::query()->where('id',$this->data['owner']['id']??'')->delete();
+        parent::tearDown();
+    }
+
+}

+ 130 - 0
tests/Services/StationTaskBatchService/RunManyTest.php

@@ -0,0 +1,130 @@
+<?php
+
+namespace Tests\Services\StationTaskBatchService;
+use App\Batch;
+use App\MaterialBox;
+use App\Order;
+use App\OrderCommodity;
+use App\Owner;
+use App\Services\ForeignHaiRoboticsService;
+use App\Services\MaterialBoxService;
+use App\Services\StationTaskBatchService;
+use App\Services\StationTaskCommodityService;
+use App\Services\StationTaskMaterialBoxService;
+use App\Services\StationTaskService;
+use App\StationRuleBatch;
+use App\StationTask;
+use App\StationTaskCommodity;
+use App\StationTaskMaterialBox;
+use Tests\TestCase;
+use App\StationTaskBatch;
+use App\Traits\TestMockSubServices;
+
+class RunManyTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var StationTaskBatchService $stationTaskBatchService */
+    public $stationTaskBatchService;
+    /** @var StationTaskService $stationTaskService */
+    public $stationTaskService;
+    /** @var StationTaskCommodityService $stationTaskCommodityService */
+    public $stationTaskCommodityService;
+    /** @var StationTaskMaterialBoxService $stationTaskMaterialBoxService */
+    public $stationTaskMaterialBoxService;
+    private $data;
+
+    private $bathAmount=3;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->stationTaskService = app('StationTaskService');
+        $this->stationTaskCommodityService = app('StationTaskCommodityService');
+        $this->stationTaskMaterialBoxService = app('StationTaskMaterialBoxService');
+        $this->stationTaskBatchService=$this->subMock([
+            'class'=>StationTaskBatchService::class,
+//            'subServices'=>[
+//                [
+//                    'serviceName'=>'foreignHaiRoboticsService',
+//                    'class'=>ForeignHaiRoboticsService::class,
+//                    'methods'=>[
+//                        'fetchGroup'=>true,
+//                    ],
+//                ],
+//            ]
+        ]);
+
+        $this->data['owner'] =
+            factory(Owner::class)
+                ->create();
+        $this->data['batches'] =
+            factory(Batch::class,
+                $this->bathAmount)
+                ->create([
+                    'status'=>'未处理',
+                    'owner_id'=>$this->data['owner']['id']
+                ]);
+        $this->data['stationRuleBatch'] =
+            factory(StationRuleBatch::class)
+                -> create([
+                    'owner_id'=>$this->data['owner']['id'],
+                ]);
+        $this->data['stationTask'] =
+            $this->stationTaskService->create($this->bathAmount);
+        $this->data['stationTaskCommodities']=$this->stationTaskCommodityService->createByBatches($this->data['batches'],$this->data['stationTask']); //注册商品任务
+        $this->data['stationTaskMaterialBoxes']=$this->stationTaskMaterialBoxService->createByBatches($this->data['batches'],$this->data['stationTask']); //注册料箱任务
+        $this->data['stationTaskBathes']=$this->stationTaskBatchService->createByBatches($this->data['batches'],$this->data['stationTask']); //注册波次任务
+
+
+    }
+
+    public function testReturned()
+    {
+
+        $taskBatches_failed=$this->stationTaskBatchService->runMany(
+            $this->data['stationTaskBathes']
+        );
+        $this->assertTrue($taskBatches_failed->isEmpty());
+        $this->assertTrue((
+            $全部是处理中状态
+                =function(){
+            $arr=array_unique(
+                data_get($this->data['stationTaskBathes'],'*.status')
+            );
+            return
+                count($arr)==1
+                && $arr[0]=='处理中';
+        })());
+    }
+
+    function tearDown(): void
+    {
+        StationTaskBatch::query()
+            ->whereIn('id',data_get($this->data['stationTaskBathes'],'*.id')??[])
+            ->delete();
+
+        StationRuleBatch::query()
+            ->whereIn('id',$this->data['stationRuleBatch']['id'])
+            ->delete();
+
+        StationTaskMaterialBox::query()
+            ->whereIn('id',data_get($this->data['batches'],'*.id')??[])
+            ->delete();
+        Order::query()
+            ->whereIn('id',data_get($this->data['orders'],'*.id')??[])
+            ->delete();
+        MaterialBox::query()
+            ->whereIn('id',data_get($this->data['materialBoxes'],'*.id')??[])
+            ->delete();
+        OrderCommodity::query()
+            ->whereIn('id',data_get($this->data['orderCommodities'],'*.id')??[])
+            ->delete();
+        StationTask::query()
+            ->whereIn('id',data_get($this->data['stationTask'],'*.id')??[])
+            ->delete();
+        StationTaskCommodity::query()
+            ->whereIn('id',data_get($this->data['stationTaskCommodities'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+
+}

+ 104 - 0
tests/Services/StationTaskCommodityService/CreateByBatchTest.php

@@ -0,0 +1,104 @@
+<?php
+
+namespace Tests\Services\StationTaskCommodityService;
+use App\Batch;
+use App\MaterialBox;
+use App\Order;
+use App\OrderBin;
+use App\OrderCommodity;
+use App\Services\MaterialBoxService;
+use App\Services\StationRuleBatchService;
+use App\Services\StationTaskCommodityService;
+use App\Services\StationTypeService;
+use Tests\TestCase;
+use App\StationTaskCommodity;
+use App\Traits\TestMockSubServices;
+
+class CreateByBatchTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var StationTaskCommodityService $service */
+    public $service;
+    private $data;
+    private $batchAmount=1;
+    private $orderAmount=4;
+    private $orderCommodityAmount=8;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskCommodityService');
+        $this->data['batches'] =
+            factory(Batch::class,
+                $this->batchAmount)
+                ->create([
+                    'status'=>'未处理',
+                ]);
+        $this->data['orders'] =
+            factory(Order::class)
+                ->createMany($this->makeArray($this->orderAmount,[
+                    'status'=>'未处理',
+                    'batch_id' => function(){return $this->getTargetIdCirculately($this->data['batches']);}
+                ]));
+        $this->data['orderBins'] =
+            factory(OrderBin::class)
+                ->createMany($this->makeArray($this->orderAmount,[
+                    'order_id' => function(){return $this->getTargetIdCirculately($this->data['orders']);},
+                    'number'=>$this->getIntegerIncreasely('orderBins_number'),
+                ]));
+        $this->data['orderCommodities'] =
+            factory(OrderCommodity::class)
+                ->createMany($this->makeArray($this->orderCommodityAmount,[
+                    'order_id' => function(){return $this->getTargetIdCirculately($this->data['orders']);},
+                ]));
+    }
+
+    public function testReturned()
+    {
+        $this->service=$this->subMock([
+            'class'=>StationTaskCommodityService::class,
+            'subServices'=>[
+                [
+                    'serviceName'=>'materialBoxService',
+                    'class'=>MaterialBoxService::class,
+                    'methods'=>[
+                        'firstOrCreate'=>new MaterialBox(['id'=>1]),
+                    ],
+                ],
+            ]
+        ]);
+
+        $this->data['stationTaskCommodities']
+            =(function(){
+            if(!isset($this->data['stationTaskCommodities']))
+                $this->data['stationTaskCommodities'] = collect();
+            foreach($this->data['batches'] as $batch){
+                $this->data['stationTaskCommodities']
+                    =$this->data['stationTaskCommodities']->merge(
+                    $this->service->createByBatch($batch)
+                );
+            }
+            return $this->data['stationTaskCommodities'];
+        })();
+        $this->assertEquals($this->orderCommodityAmount, $this->data['stationTaskCommodities']->count());
+    }
+
+    function tearDown(): void
+    {
+        StationTaskCommodity::query()
+            ->whereIn('id',data_get($this->data['stationTaskCommodities'],'*.id')??[])
+            ->delete();
+        Batch::query()
+            ->whereIn('id',data_get($this->data['batches'],'*.id')??[])
+            ->delete();
+        Order::query()
+            ->whereIn('id',data_get($this->data['orders'],'*.id')??[])
+            ->delete();
+        OrderBin::query()
+            ->whereIn('id',data_get($this->data['orderBins'],'*.id')??[])
+            ->delete();
+        OrderCommodity::query()
+            ->whereIn('id',data_get($this->data['orderCommodities'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 83 - 0
tests/Services/StationTaskCommodityService/CreateByBatchesTest.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace Tests\Services\StationTaskCommodityService;
+use App\Batch;
+use App\Order;
+use App\OrderCommodity;
+use App\Services\StationTaskCommodityService;
+use App\Services\StationTaskService;
+use App\StationTask;
+use App\Traits\TestMockSubServices;
+use Tests\TestCase;
+use App\StationTaskCommodity;
+
+class CreateByBatchesTest extends TestCase
+{
+
+    use TestMockSubServices;
+    /** @var StationTaskCommodityService $service */
+    public $service;
+    /** @var StationTaskService $service */
+    private $stationTaskService;
+    private $data;
+    private $batchAmount=2;
+    private $orderAmount=4;
+    private $orderCommodityAmount=8;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskCommodityService');
+        $this->stationTaskService = app('StationTaskService');
+        $this->data['stationTask'] =
+            $this->stationTaskService->create($this->batchAmount);
+        $this->data['batches'] =
+            factory(Batch::class,
+                $this->batchAmount)
+                ->create([
+                    'status'=>'未处理',
+                ]);
+        $this->data['orders'] =
+            factory(Order::class)
+                ->createMany($this->makeArray($this->orderAmount,[
+                    'status'=>'未处理',
+                    'batch_id' => function(){return $this->getTargetIdCirculately($this->data['batches']);}
+                ]));
+        $this->data['orderCommodities'] =
+            factory(OrderCommodity::class)
+                ->createMany($this->makeArray($this->orderCommodityAmount,[
+                    'order_id' => function(){return $this->getTargetIdCirculately($this->data['orders']);}
+                ]));
+    }
+
+    public function testReturned()
+    {
+        $this->data['stationTaskCommodities']=
+            $this->service->createByBatches(
+                $this->data['batches'],
+                $this->data['stationTask']);
+        $this->assertEquals($this->orderCommodityAmount, $this->data['stationTaskCommodities']->count());
+        $this->assertNotFalse(array_search($this->data['stationTaskCommodities'][0]['id'],
+            data_get($this->data['stationTaskCommodities'][0]['stationTask']['stationTaskCommodities'],'*.id')));
+
+    }
+
+    function tearDown(): void
+    {
+        StationTaskCommodity::query()
+            ->whereIn('id',data_get($this->data['stationTaskCommodities'],'*.id')??[])
+            ->delete();
+        StationTask::query()
+            ->whereIn('id',data_get($this->data['stationTask'],'*.id')??[])
+            ->delete();
+        Batch::query()
+            ->whereIn('id',data_get($this->data['batches'],'*.id')??[])
+            ->delete();
+        Order::query()
+            ->whereIn('id',data_get($this->data['orders'],'*.id')??[])
+            ->delete();
+        OrderCommodity::query()
+            ->whereIn('id',data_get($this->data['orderCommodities'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 84 - 0
tests/Services/StationTaskMaterialBoxService/CreateByBatchesTest.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace Tests\Services\StationTaskMaterialBoxService;
+use App\Batch;
+use App\MaterialBox;
+use App\Order;
+use App\OrderCommodity;
+use App\Services\StationTaskMaterialBoxService;
+use App\StationTask;
+use Tests\TestCase;
+use App\StationTaskMaterialBox;
+use App\Traits\TestMockSubServices;
+
+class CreateByBatchesTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var StationTaskMaterialBoxService $service */
+    public $service;
+    private $data;
+    private $batchAmount=2;
+    private $orderAmount=4;
+    private $materialBoxAmount=8;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskMaterialBoxService');
+        $this->data['batches']
+            = factory(Batch::class, $this->batchAmount)
+            ->create();
+        $this->data['orders']
+            = factory(Order::class)
+            ->createMany($this->makeArray($this->orderAmount,[
+                'batch_id' => function(){return $this->getTargetIdCirculately($this->data['batches']);}
+            ]));
+        $this->data['materialBoxes']
+            = factory(MaterialBox::class, $this->materialBoxAmount)
+            ->create();
+        $this->data['orderCommodities']
+            = factory(OrderCommodity::class)
+            ->createMany($this->makeArray($this->materialBoxAmount,[
+                'order_id' => function(){return $this->getTargetIdCirculately($this->data['orders']);},
+                'location' => function(){return $this->getTargetIdCirculately($this->data['materialBoxes'],'','code');},
+            ]));
+        $this->data['stationTask']
+            = factory(StationTask::class, $this->batchAmount)
+            ->create();
+    }
+
+    public function testReturned()
+    {
+        $this->data['stationTaskMaterialBoxes']=$this->service->createByBatches($this->data['batches'],$this->data['stationTask'] );
+        $this->assertTrue($this->data['stationTaskMaterialBoxes']->isNotEmpty());
+        $this->assertEquals(StationTaskMaterialBox::class, get_class($this->data['stationTaskMaterialBoxes']->first()));
+        $this->assertEquals($this->materialBoxAmount, $this->data['stationTaskMaterialBoxes']->count());
+        $this->assertEquals($this->materialBoxAmount, (function(){
+            $taskBoxes=collect();
+            foreach ($this->data['stationTask'] as $stationTask){
+                $stationTask->loadMissing('stationTaskMaterialBoxes');
+                $taskBoxes=$taskBoxes->merge($stationTask['stationTaskMaterialBoxes']);
+            }
+            return $taskBoxes->count();
+        })());
+    }
+
+    function tearDown(): void
+    {
+        StationTaskMaterialBox::query()
+            ->whereIn('id',data_get($this->data['batches'],'*.id')??[])
+            ->delete();
+        Order::query()
+            ->whereIn('id',data_get($this->data['orders'],'*.id')??[])
+            ->delete();
+        MaterialBox::query()
+            ->whereIn('id',data_get($this->data['materialBoxes'],'*.id')??[])
+            ->delete();
+        OrderCommodity::query()
+            ->whereIn('id',data_get($this->data['orderCommodities'],'*.id')??[])
+            ->delete();
+        StationTask::query()
+            ->whereIn('id',data_get($this->data['stationTask'],'*.id')??[])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 37 - 0
tests/Services/StationTaskService/CreateTest.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace Tests\Services\StationTaskService;
+
+use App\Services\StationTaskService;
+use App\StationTask;
+use Illuminate\Support\Collection;
+use Tests\TestCase;
+
+class CreateTest extends TestCase
+{
+    /** @var StationTaskService $service */
+    private $service;
+    private $data = [];
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskService');
+    }
+
+    public function testCreateSuccess()
+    {
+        $amountToCreate=3;
+        $this->data['stationTask']=$this->service->create($amountToCreate);
+        $this->assertEquals(Collection::class,get_class($this->data['stationTask']));
+        $this->assertEquals($amountToCreate,$this->data['stationTask']->count());
+        $this->assertEquals(StationTask::class,get_class($this->data['stationTask'][0]));
+    }
+
+
+    public function tearDown(): void
+    {
+        StationTask::query()->whereIn('id',data_get($this->data['stationTask'],'*.id')??[])->delete();
+        parent::tearDown();
+    }
+}

+ 27 - 0
tests/Services/StationTaskService/TestRegisterSubTasks.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace Tests\Services\StationTaskService;
+use App\Services\StationTaskService;
+use Tests\TestCase;
+
+class TestRegisterSubTasks extends TestCase
+{
+
+    /** @var StationTaskService $service */
+    public $service;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('StationTaskService');
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        parent::tearDown();
+    }
+}

+ 2 - 2
tests/Unit/EchoTest.php

@@ -9,8 +9,8 @@ class EchoTest extends TestCase
 
 
     public function testEcho(){
-        echo "\nabc3213123\n";
-        $this->assertEquals(3,2);
+//        echo "\nabc3213123\n";
+        $this->assertEquals(3,3);
     }
 
 }