stationService=null; $this->stationTypeService=null; $this->stationTaskService=null; $this->materialBoxService=null; $this->stationTaskBatchService=null; $this->stationTaskCommodityService=null; } function create($kvPairs) { return StationTaskMaterialBox::query()->create($kvPairs); } function createByStationAndMaterialBox($station, $materialBox) { return StationTaskMaterialBox::query()->create([ 'station_id' => $station['id'], 'material_box_id' => $materialBox['id'], 'status' => '待处理' ]); } function getOccupied_byBatches(?Collection $batches): ?Collection { return StationTaskMaterialBox::query() ->where('status','<>','完成') ->where('created_at','>',Carbon::now()->subHours(2)) ->whereHas('materialBox',function ($query)use($batches){ $locations=OrderCommodity::query() ->whereHas('order',function ($queryO)use($batches){ $queryO->whereIn('batch_id',data_get($batches,'*.id')??[]); })->get('location'); $query->whereIn('code',data_get($locations,'*.location')??[]); }) ->get(); } function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection { $this->instant($this->stationTaskService,'StationTaskService'); LogService::log(__METHOD__,'assignTasks','波次任务分配4.c1:'.json_encode($batches)); $stationTaskMaterialBoxes_byBatch = (function () use ($batches) { $stationTaskMaterialBoxes_listByBatch = new Collection(); foreach ($batches as $batch) { $stationTaskMaterialBoxes_listByBatch->push( $this->createByBatch($batch) ); } return $stationTaskMaterialBoxes_listByBatch; })(); LogService::log(__METHOD__,'assignTasks','波次任务分配4.c2:'.json_encode($batches)); $this->stationTaskService ->registerSubTasks( $stationTasks_toAttach, $stationTaskMaterialBoxes_byBatch); return collect(data_get($stationTaskMaterialBoxes_byBatch,'*.*')); } function createByBatch(Batch $batch): ?Collection { $this->instant($this->materialBoxService,'MaterialBoxService'); $this->instant($this->stationTypeService,'StationTypeService'); $this->instant($this->stationService,'StationService'); $this->instant($this->stationTaskBatchService,'StationTaskBatchService'); $this->instant($this->orderCommodityService,'OrderCommodityService'); $stationMaterialBoxes_toCreate=new Collection(); $order_ids=data_get($batch['orders'],'*.id'); $orderCommodities=OrderCommodity::query()->orderByRaw("commodity_id,amount")//同商品多条 数量最小优先 ->with('orderBin')->whereIn('order_id',$order_ids)->get(); //$orderCommodities=$this->orderCommodityService->correctLocation_fromWMS($orderCommodities); if($orderCommodities->isEmpty())return $stationMaterialBoxes_toCreate; $stationType=$this->stationTypeService->getForMaterialBox_onBatchProcess(); $stationTaskBatch=$this->stationTaskBatchService->get(['batch_id'=>$batch['id']])->first(); $materialBoxIds_used=[]; //$orderCommodities=$orderCommodities->sortBy('commodity_id');//按商品排序后,出货可以同商品挨在一起 foreach ($orderCommodities as $orderCommodity){ $station=$this->stationService->getStation_byType($stationType['name']); if (!$this->materialBoxService->checkBoxNorm($orderCommodity['location']))continue; $materialBox=$this->materialBoxService->firstOrCreate(['code' => $orderCommodity['location']]); if(in_array($materialBox['id'],$materialBoxIds_used))continue; $stationMaterialBoxes_toCreate->push([ 'station_id'=>$station['id'], 'material_box_id'=>$materialBox['id'], 'station_task_batch_id'=>$stationTaskBatch['id'], 'status'=>'待处理' ]); $materialBoxIds_used[]=$materialBox['id']; } return $this->insert($stationMaterialBoxes_toCreate->toArray(),true); } function get(array $kvPairs, $with=null){ ksort($kvPairs); return Cache::remember('StationTaskMaterialBox'.md5(json_encode($kvPairs).json_encode([$with])), config('cache.expirations.fastChange'), function ()use($kvPairs,$with) { $query = StationTaskMaterialBox::query(); if($with){ $query->with($with); } foreach ($kvPairs as $column => $value){ if (is_array($value))$query->whereIn($column,$value); else $query->where($column,$value); } return $query->get(); }); } function markHasPut(StationTaskMaterialBox $stationTaskMaterialBox){ $this->instant($this->stationTaskBatchService,'StationTaskBatchService'); $this->instant($this->stationTaskCommodityService,'StationTaskCommodityService'); $this->instant($this->stationTaskService,'StationTaskService'); $this->instant($this->stationService,'StationService'); $this->instant($this->cacheShelfService,'CacheShelfService'); $this->instant($this->storageService,'StorageService'); try{ $taskType=$this->getServingTaskType($stationTaskMaterialBox); LogService::log('海柔请求','markHasTaken2', json_encode($stationTaskMaterialBox)); switch ($taskType){ case '分波次': $this->markProcessing($stationTaskMaterialBox); $this->stationTaskBatchService->markProcessing_byIds($stationTaskMaterialBox['station_task_batch_id']); $this->stationTaskCommodityService->markProcessing($stationTaskMaterialBox['stationTaskCommodities']); $this->stationTaskService->markProcessing_byIds(data_get($stationTaskMaterialBox['stationTaskCommodities'],'*.station_task_id')); /** @var StationTask $stationTask */ $stationTask = $this->stationTaskService->getProcessing(); $this->stationService->broadcastBinMonitor($stationTaskMaterialBox['station_id'], $stationTask); $stationTaskMaterialBox->materialBox['status']='在U型线'; $stationTaskMaterialBox->materialBox->update(); break; case '入立库': $stationTaskMaterialBox->materialBox['status']='在立库'; $stationTaskMaterialBox->materialBox->update(); break; case '入缓存架': $stationTaskMaterialBox->materialBox['status']='在缓存架'; $stationTaskMaterialBox->materialBox->update(); $stationTaskMaterialBox->loadMissing("station"); //提前加载站,后续都需要站信息来处理 $this->storageService->putCacheShelf($stationTaskMaterialBox); break; default:; } $this->taskCompleted($stationTaskMaterialBox); }catch (\Exception $e){ throw new ErrorException('放置料箱出错'); } } private function taskCompleted($stationTaskMaterialBox) { $this->set($stationTaskMaterialBox,[ 'id' => $stationTaskMaterialBox['station_id'], 'status' => '完成', ]); if (!$stationTaskMaterialBox->station_task_id)return; $task = StationTaskMaterialBox::query()->select(DB::raw(1)) ->where("station_task_id",$stationTaskMaterialBox->station_task_id) ->where("status","!=","完成")->first(); if (!$task)StationTask::query()->where("id",$stationTaskMaterialBox->station_task_id) ->update(["status"=>"完成"]); } /** * 取出料箱通知 * * @param StationTaskMaterialBox|\stdClass $stationTaskMaterialBox * @throws \Exception */ function markHasTaken($stationTaskMaterialBox) { $this->instant($this->cacheShelfService,'CacheShelfService'); //$stationTaskMaterialBox->loadMissing("station"); //判断取出料箱是否是在缓存架 $station = Station::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id) ->first(); if ($station && app("StationService")->isHalfBoxLocation($station)) app("CacheShelfService")->boxHasBeenTaken($station); /*//维护缓存架可用度 $map = Cache::get("CACHE_SHELF_MAPPING",function (){return [];}); if (isset($map[$stationTaskMaterialBox->material_box_id])){ $available=Cache::get("CACHE_SHELF_AVAILABLE",function (){return [];}); $available[$map[$stationTaskMaterialBox->material_box_id]] = true; Cache::forever("CACHE_SHELF_AVAILABLE",$available); CacheShelfTaskJob::dispatch("CACHE_SHELF_AVAILABLE",count($available))->delay(now()->addSeconds(config("haiRou.cacheShelf.outBinAwait"))); unset($map[$stationTaskMaterialBox->material_box_id]); Cache::forever("CACHE_SHELF_MAPPING",$map); }*/ } function processNextQueued(?StationTaskMaterialBox $stationTaskMaterialBox_lastProcessed){ $station_id=$stationTaskMaterialBox_lastProcessed['station_id']; $stationTaskMaterialBox_next=StationTaskMaterialBox::query() ->where('station_id',$station_id) ->where('status','处理队列') ->orderBy('updated_at') ->first(); if($stationTaskMaterialBox_next){ $stationTaskMaterialBox_next->update(['status'=>'处理中']); } return $stationTaskMaterialBox_next; } function markProcessed(StationTaskMaterialBox $stationTaskMaterialBox){ $stationTaskMaterialBox['status'] = '完成'; $stationTaskMaterialBox->save(); } function getNotProcessedSiblings($stationTaskMaterialBox){ return StationTaskMaterialBox::query() ->whereNotIn('status',['完成']) ->where('station_task_id',$stationTaskMaterialBox['station_task_id']) ->get(); } /** * 每波次仅将最老的作务标为“处理中”,其他置入队列; * 如某波次已经有“处理中“,则他部置入队列 * @param $stationTaskMaterialBox_orBoxes ?? 单个或多个 */ function markProcessing($stationTaskMaterialBox_orBoxes) { $this->instant($this->stationTaskService,'StationTaskService'); $stationTaskMaterialBoxes = (function()use($stationTaskMaterialBox_orBoxes){ if (get_class($stationTaskMaterialBox_orBoxes)==StationTaskMaterialBox::class){ return collect([$stationTaskMaterialBox_orBoxes]); } return collect($stationTaskMaterialBox_orBoxes); })(); $stationTaskMaterialBoxes_grouped= ($按时间从前往后排出顺序=function ()use(&$stationTaskMaterialBoxes){ return $stationTaskMaterialBoxes ->sortBy('id') ->groupBy('station_task_batch_id'); })(); $stationTaskMaterialBoxes_grouped->each(function(&$groupByBatch){ ($将所有要标记的箱任务先放在队列里=function()use(&$groupByBatch){ $groupByBatch->each(function (&$stationTaskMaterialBox){ $stationTaskMaterialBox['status']='处理队列'; }); })(); ($如果之前没有处理中则标记第一个为处理目标,准备持久化=function()use(&$groupByBatch){ $stationId=$groupByBatch[0]['station_id']; $processing=$this->getProcessing_byStationId($stationId); if(!$processing){ $groupByBatch[0]['status']='处理中'; $groupByBatch[0]->update(); }else{ foreach ($groupByBatch as &$stationTaskMaterialBox){ if($stationTaskMaterialBox['id']==$processing['id']){ $stationTaskMaterialBox['status']='处理中'; } } } })(); }); ($持久化处理队列的记录=function()use(&$stationTaskMaterialBoxes_grouped){ $toArray = $stationTaskMaterialBoxes_grouped->collapse(); $toArray=$toArray->where('status','处理队列'); $ids_toUpdate = data_get($toArray, '*.id'); if(count($ids_toUpdate)) StationTaskMaterialBox::query()->whereIn('id',$ids_toUpdate)->update(['status'=>'处理队列']); })(); // StationTaskMaterialBox::query() // ->whereIn('id', data_get($stationTaskMaterialBoxes, '*.id')) // ->update(['status'=>'处理中']); $this->stationTaskService ->markProcessing_byIds( data_get($stationTaskMaterialBoxes, '*.*.station_id') ); } function getProcessing_byStationId($stationId) { //这里不能用缓存,因为更新会非常快 return StationTaskMaterialBox::query() ->where('station_id',$stationId) ->where('status','处理中') ->where('created_at','>',Carbon::now()->subDay()) ->first(); } function excepted($stationTaskMaterialBoxes_orBox){ if (get_class($stationTaskMaterialBoxes_orBox)==StationTaskMaterialBox::class){ $stationTaskMaterialBoxes_orBox = collect([$stationTaskMaterialBoxes_orBox]); } StationTaskMaterialBox::query()->whereIn('id',data_get($stationTaskMaterialBoxes_orBox,'*.id')) ->update(['status'=>'异常']); switch (get_class($stationTaskMaterialBoxes_orBox)){ case MaterialBox::class: case StationTaskMaterialBox::class: throw new ErrorException('料箱异常'.json_encode($stationTaskMaterialBoxes_orBox->toJson())); } } function getServingTaskType(StationTaskMaterialBox $stationTaskMaterialBox): string { $stationTaskMaterialBox->load('station.stationType'); switch ($stationTaskMaterialBox['station']['stationType']['name']){ case "立库": return '入立库'; case "缓存架": return '入缓存架'; case "料箱监视器": if ($stationTaskMaterialBox['station_task_batch_id'])return "分波次"; default: throw new ErrorException('当前类型找不到'); } } }