Просмотр исходного кода

半箱入库批量调取,逐级分发
同出库逻辑一样,使用缓存架排队序列等候海柔通知

Zhouzhendong 4 лет назад
Родитель
Сommit
06ae5096f2

+ 174 - 14
app/Http/Controllers/StorageController.php

@@ -9,6 +9,7 @@ use App\MaterialBox;
 use App\MaterialBoxCommodity;
 use App\MaterialBoxModel;
 use App\Owner;
+use App\Services\ForeignHaiRoboticsService;
 use App\Services\LogService;
 use App\Station;
 use App\StationTask;
@@ -113,7 +114,7 @@ SQL;
         foreach ($models as $model){
             if (!isset($map[$model->id]))continue;
             $model->maximum = $map[$model->id]->maximum;
-            $boxCodes = app("MaterialBoxService")->getModelAvailableBox($model->id,true);
+            list($boxCodes) = app("MaterialBoxService")->getModelAvailableBox($model->id,true);
             if (!$boxCodes)continue;
             if (!$m)$m = $model;
             $sql = <<<SQL
@@ -189,6 +190,154 @@ sql;
      * 取得料箱
      */
     public function acquireBox()
+    {
+        $this->gate("入库管理-入库-半箱补货入库");
+
+        list($track, $barCode, $lotNum, $amount) = request()->only(["track","barCode","lotNum","amount"]);
+        if (!$track || !$barCode || !$lotNum || !$amount)$this->error("提交信息不完整");
+
+        $sql = <<<SQL
+SELECT SUM(FMQTY) qty,TSK_TASKLISTS.SKU,TSK_TASKLISTS.CUSTOMERID
+FROM TSK_TASKLISTS
+LEFT JOIN BAS_SKU ON TSK_TASKLISTS.CUSTOMERID = BAS_SKU.CUSTOMERID
+AND TSK_TASKLISTS.SKU = BAS_SKU.SKU
+WHERE FMID = ? AND FMLOTNUM = ? AND
+      (ALTERNATE_SKU1 = ? OR ALTERNATE_SKU2 = ? OR ALTERNATE_SKU3 = ?)
+  AND TASKPROCESS = '00' AND TASKTYPE = 'PA'
+GROUP BY FMID,FMLOTNUM,TSK_TASKLISTS.SKU,TSK_TASKLISTS.CUSTOMERID
+SQL;
+        $task = DB::connection("oracle")->selectOne(DB::raw($sql));
+        if (!$task || $task->qty<$amount)$this->error("待上架数量不足");
+        $commodity = Commodity::query()->whereHas("owner",function ($query)use($task){
+            $query->where("code",$task->customerid);
+        })->where("sku",$task->sku)->first();
+        if (!$commodity)$this->error("商品在WAS丢失,联系管理员处理");
+
+        /** @var \Illuminate\Database\Eloquent\Collection $models */
+        $models = app("MaterialBoxModelService")->getModelSortedByOwner($commodity->owner_id);
+        $models->load(["commodity"=>function($query)use($commodity){
+            $query->where("commodity_id",$commodity->id);
+        }]);
+        $models = $models->whereNotNull("commodity");
+        if ($models->count()==0)$this->success(["status"=>false]);
+
+        //设定一个默认缓存架 仅用于任务占位 没有实际作用
+        $defaultStation = Station::query()->where("station_type_id",5)
+            ->whereNull("parent_id")->first();
+        if (!$defaultStation)$this->error("默认缓存架丢失");
+        DB::beginTransaction();
+        try {
+            //建立任务
+            $exe = function ($station, $boxId, $amount)use($defaultStation, $commodity, $lotNum, $track){
+                $stationId = $station ? $station->id : $defaultStation->id;
+                $task = StationTask::query()->create([
+                    'status' => "待处理",
+                    'station_id' => $stationId,
+                ]);
+                $task = StationTaskMaterialBox::query()->create([
+                    'station_id' => $stationId,
+                    'material_box_id'=>$boxId,
+                    'status'=>"待处理",
+                    'type' => '取',
+                    'station_task_id' => $task->id,
+                ]);
+                //生成临时任务事务
+                TaskTransaction::query()->create([
+                    "bar_code" => request("barCode"),
+                    "fm_station_id" => $stationId,
+                    "material_box_id" => $boxId,
+                    "commodity_id" => $commodity->id,
+                    "amount" => $amount,
+                    "type" => "入库",
+                    "user_id" => Auth::id(),
+                    "mark" => 1,
+                    "lot_num" => $lotNum,
+                    "track_num" => $track,
+                    "status" => $station ? 0 : 3,
+                    "task_id" => $task->id
+                ]);
+                return $task;
+            };
+
+            $stations = app("StationService")->getCacheShelf(true);
+            $collection = collect();
+            $location = collect();
+            $ids = [];
+            //寻找半箱
+            foreach ($models as $model){
+                list($invs,$map) = app("StorageService")->getMaxAvailableHalfBoxLocation($model->commodity, request("lotNum"));
+                if (!$invs)continue;
+                foreach ($invs as $inv){
+                    $station = $stations->last();
+                    $boxId = $map[$inv->locationid];
+                    $number = $amount >= $inv->qty ? $amount-$inv->qty : $amount;
+                    $task = $exe($station, $boxId, $number);
+                    if ($station){
+                        $stations->offsetUnset($stations->count()-1);
+                        $collection->push($task);
+                        $location->push($station->code);
+                        $ids[] = ["code"=>$station->code,"id"=>$station->id,"amount"=>$number];
+                    }
+                    $amount -= $number;
+                    if ($amount==0)break;
+                }
+                if ($amount==0)break;
+            }
+            if ($amount){
+                //寻找空箱
+                $blacklist = [];//空箱逐一寻找需要列队黑名单
+                foreach ($models as $model){
+                    while ($amount!=0){
+                        $station = $stations->last();
+                        $box = app("MaterialBoxService")->getAnEmptyBox($model,$blacklist);
+                        if (!$box)break; //此型号下无空箱可用
+                        $blacklist[] = $box->id; //当前空箱黑名单
+                        $number = $amount >= $model->commodity->maximum ? $amount-$model->commodity->maximum : $amount;
+                        $task = $exe($station, $box->id, $number);
+                        if ($station){
+                            $stations->offsetUnset($stations->count()-1);
+                            $collection->push($task);
+                            $location->push($station->code);
+                            $ids[] = ["code"=>$station->code,"id"=>$station->id,"amount"=>$number];
+                        }
+                        $amount -= $number;
+                    }
+                    if ($amount==0)break;
+                }
+            }
+            if ($location->count()){
+                /** @var ForeignHaiRoboticsService $service */
+                $service = app("ForeignHaiRoboticsService");
+                $result = $service->fetchGroup_multiLocation($location,$collection,'','立架出至缓存架');
+                if (!$result){
+                    DB::rollBack();
+                    $this->error("机器人呼叫失败,海柔任务错误");
+                }
+                foreach ($ids as $obj){
+                    $options = [
+                        "detail01" => $obj["code"],
+                        "detail02" => $barCode,
+                        "qty02" => $obj["amount"],
+                        "title" => '入库任务',
+                        "uomDesc02" => "件"
+                    ];
+                    app("CacheShelfService")->lightUp($obj["code"],'3','0',$options);
+                    Cache::forever("CACHE_SHELF_OCCUPANCY_{$obj["id"]}",true);
+                }
+                app("StationService")->locationOccupyMulti($location->toArray());
+            }
+            DB::commit();
+            $this->success(["status"=>true,"amount"=>$amount]);
+        }catch (\Exception $e){
+            DB::rollBack();
+            $this->error("处理失败:".$e->getMessage());
+        }
+    }
+
+    /**
+     * 取得料箱 废弃
+     */
+    public function acquireBoxTemp()
     {
         $this->gate("入库管理-入库-半箱补货入库");
         $boxId = request("material_box_id");
@@ -293,12 +442,13 @@ sql;
     public function overflowRevision()
     {
         $this->gate("入库管理-入库-半箱补货入库");
-        $station = request("station");
+        $ide = request("ide");
         $amount = request("amount");
-        //获取目标库位
-        $station = app("StationService")->getMirrorMappingLocation($station);
-        if (!$station)$this->error("未知库位");
-        $task = TaskTransaction::query()->with("materialBox")->where("fm_station_id",$station->id)->where("amount",">",$amount)
+        //获取目标料箱
+        $box = MaterialBox::query()->where("code",$ide)->first();
+        if (!$box)$this->error("未知料箱");
+
+        $task = TaskTransaction::query()->where("material_box_id",$box->id)->where("amount",">",$amount)
             ->where("type","入库")->where("mark",1)->where("status",0)->first();
         if (!$task)$this->error("无任务存在");
         $task->update(["amount" => DB::raw("amount - {$amount}")]);
@@ -550,23 +700,33 @@ SQL;
         $track = request("track");
         $barCode = request("barCode");
         $sql = <<<SQL
-SELECT TSK_TASKLISTS.FMLOTNUM FROM TSK_TASKLISTS LEFT JOIN BAS_SKU ON TSK_TASKLISTS.CUSTOMERID = BAS_SKU.CUSTOMERID
+SELECT TSK_TASKLISTS.FMLOTNUM,SUM(FMQTY) qty FROM TSK_TASKLISTS LEFT JOIN BAS_SKU ON TSK_TASKLISTS.CUSTOMERID = BAS_SKU.CUSTOMERID
 AND TSK_TASKLISTS.SKU = BAS_SKU.SKU
 WHERE FMID = ? AND (ALTERNATE_SKU1 = ? OR ALTERNATE_SKU2 = ? OR ALTERNATE_SKU3 = ?)
 AND TASKPROCESS = '00' AND TASKTYPE = 'PA' GROUP BY FMID,FMLOTNUM
 SQL;
         $tasks = DB::connection("oracle")->select(DB::raw($sql),[$track,$barCode,$barCode,$barCode]);
         $result = ["count"=>count($tasks)];
-        if (count($tasks)>1){
-            $lotNums = "";
-            foreach ($tasks as $task)$lotNums .= "'".$task->fmlotnum."',";
-            $lotNums = rtrim($lotNums,",");
-            $sql = <<<SQL
+        switch ($result["count"]){
+            case 0:
+                break;
+            case 1:
+                $result["lots"] = $tasks[0]->fmlotnum;
+                $result["lotMap"] = [$result["lots"] => $tasks[0]->qty];
+                break;
+            default:
+                $lotNums = "";
+                $result["lotMap"] = [];
+                foreach ($tasks as $task){
+                    $lotNums .= "'".$task->fmlotnum."',";
+                    $result["lotMap"][$task->fmlotnum] = $task->qty;
+                }
+                $lotNums = rtrim($lotNums,",");
+                $sql = <<<SQL
 SELECT * FROM INV_LOT_ATT WHERE LOTNUM IN ({$lotNums});
 SQL;
-            $result["lots"] = DB::connection("oracle")->select(DB::raw($sql));
+                $result["lots"] = DB::connection("oracle")->select(DB::raw($sql));
         }
-        if (count($tasks)==1)$result["lots"] = $tasks[0]->fmlotnum;
         $this->success($result);
     }
 

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

@@ -18,6 +18,8 @@ use App\StationTask;
 use App\StationTaskMaterialBox;
 use App\TaskTransaction;
 use App\Unit;
+use App\Waybill;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cache;
@@ -57,13 +59,11 @@ class TestController extends Controller
     private $key = "CACHE_SHELF_AVAILABLE";
     public function test()
     {
-        $modelId = 1;
-        $blacklist = [];
-        $query = MaterialBox::query()->where("material_box_model_id",$modelId)
-            ->where("status",4);
-        $boxes = $query->whereNotIn("id",$query->select("id")->whereHas("performTask"));
-        if ($blacklist)$boxes = $boxes->whereNotIn("id",$blacklist);
-        dd($boxes->get());
+        $a = new Collection(["a","b"]);
+        dd($a->filter(function ($b){
+            if ($b=="a")return true;
+            else return false;
+        }));
     }
 
 }

+ 107 - 51
app/Jobs/CacheShelfTaskJob.php

@@ -9,6 +9,7 @@ use App\StationTaskMaterialBox;
 use App\TaskTransaction;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Support\Collection;
@@ -43,57 +44,13 @@ class CacheShelfTaskJob implements ShouldQueue
         /** @var ForeignHaiRoboticsService $service */
         $service = app("ForeignHaiRoboticsService");
         switch ($this->key){
-            case "CACHE_SHELF_AVAILABLE"://出库呼叫
-                DB::beginTransaction();
-                try {
-                    $available = Cache::get($this->key,function (){return [];});
-                    if ($this->count!==count($available))return;
-                    $tasks = TaskTransaction::query()->selectRaw("task_id,GROUP_CONCAT(id) AS ids,id")->with("task")
-                        ->where("type","出库")->whereHas("task",function ($query){
-                            $query->where("status","待处理");
-                        })->where("status",3)->lockForUpdate()
-                        ->where("mark",2)->groupBy("task_id")->get(); //检索等待的队列事务来获取对应任务
-                    if (!$tasks->count())return;
-                    $tasks = $tasks->where("task.station_task_batch_id",$tasks[0]->task->station_task_batch_id);//仅处理同波次
-                    if ($tasks->count()>count($available))$tasks = $tasks->slice(0,count($available));//事务过多切割部分处理
-                    $toLocation = collect();
-                    $task = collect();
-                    $availableTemp = array_keys($available);
-                    $map = app("StationService")->getStationMapping($availableTemp);//获取库位映射信息
-                    $updateTask = [["id","station_id","updated_at"]];
-                    $updateTransaction = [["id","to_station_id","status","updated_at"]];
-                    $time = date("Y-m-d H:i:s");
-                    foreach ($tasks as $index=>$obj){
-                        $loc = $availableTemp[$index];
-                        $toLocation->push($loc);
-                        $obj->task->station_id = $map[$loc];
-                        $task->push($obj->task);
-                        unset($available[$loc]);
-                        $updateTask[] = ["id"=>$obj->task->id,"station_id"=>$map[$loc],"updated_at"=>$time];
-                        if ($obj->ids!=$obj->id){
-                            $ids = explode(",",$obj->ids);
-                            foreach ($ids as $id)$updateTransaction[] = ["id"=>$id,"to_station_id"=>$map[$loc],"status"=>0,"updated_at"=>$time];
-                        }else $updateTransaction[] = ["id"=>$obj->id,"to_station_id"=>$map[$loc],"status"=>0,"updated_at"=>$time];
-                    }
-                    app("BatchUpdateService")->batchUpdate("station_task_material_boxes",$updateTask);
-                    app("BatchUpdateService")->batchUpdate("task_transactions",$updateTransaction);
-                    $result = $service->fetchGroup_multiLocation($toLocation,$task,$tasks[0]->station_task_batch_id,'立架出至缓存架',20);
-                    if ($result){
-                        Cache::forever($this->key,$available);
-                        foreach ($toLocation as $value){
-                            app("CacheShelfService")->lightUp($value,'3','0');
-                            Cache::forever("CACHE_SHELF_OCCUPANCY_{$map[$value]}",true);
-                        }
-                        app("StationService")->locationOccupyMulti($toLocation->toArray());
-                        DB::commit();
-                    }else{
-                        DB::rollBack();
-                        $this->push(__METHOD__."->".__LINE__,"出库队列执行失败","库位信息:".json_encode($toLocation)."  任务信息:".json_encode($task));
-                    }
-                }catch (\Exception $e){
-                    DB::rollBack();
-                    $this->push(__METHOD__."->".__LINE__,"出库队列执行错误",$e->getMessage()." | 当前任务数:".$this->count." | 缓存信息:".(isset($available) ? json_encode($available) : ''));
-                }
+            case "CACHE_SHELF_AVAILABLE"://缓存架释放呼叫
+                //等待一定时间来合并同类请求至此
+                $available = Cache::get($this->key,function (){return [];});
+                if ($this->count!==count($available))return;
+                //检查事务 尝试分发任务 改变下方序列来控制分发顺序 逐级分发 一次成功就终止
+                if ($this->dispatchOutTask($available,$service))break; //首先尝试向出库事务分发 分发成功跳出
+                if ($this->dispatchInTask($available,$service))break;  //尝试向入库事务分发
                 break;
             default://入库呼叫
                 if (!Cache::has($this->key))return;
@@ -127,4 +84,103 @@ class CacheShelfTaskJob implements ShouldQueue
         foreach ($task as $key=>$obj)$map[$obj->material_box_id] = $location[$key];
         Cache::forever("CACHE_SHELF_MAPPING",$map);
     }
+
+    /**
+     * 分发出库任务
+     *
+     * @param array $available
+     * @param $service
+     * @return bool
+     */
+    private function dispatchOutTask(array $available, $service):bool
+    {
+        DB::beginTransaction();
+        try {
+            $tasks = TaskTransaction::query()->selectRaw("task_id,GROUP_CONCAT(id) AS ids,id")->with("task")
+                ->where("type","出库")->whereHas("task",function ($query){
+                    $query->where("status","待处理");
+                })->where("status",3)->lockForUpdate()
+                ->where("mark",2)->groupBy("task_id")->get(); //检索等待的队列事务来获取对应任务
+            if ($this->dispatchTask($tasks,$available,$service,function ($obj,$stationId,$time,&$updateTransaction){
+                if ($obj->ids!=$obj->id){
+                    $ids = explode(",",$obj->ids);
+                    foreach ($ids as $id)$updateTransaction[] = ["id"=>$id,"to_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
+                }else $updateTransaction[] = ["id"=>$obj->id,"to_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
+            },function ($service,$toLocation,$task,$prefix){
+                return $service->fetchGroup_multiLocation($toLocation,$task,$prefix,'立架出至缓存架',20);
+            })){DB::commit();return true;}
+            DB::rollBack();
+        }catch (\Exception $e){
+            DB::rollBack();
+            $this->push(__METHOD__."->".__LINE__,"出库队列执行错误",$e->getMessage()." | 当前任务数:".$this->count." | 缓存信息:".(isset($available) ? json_encode($available) : ''));
+        }
+        return false;
+    }
+
+    /**
+     * 分发入库任务
+     *
+     * @param array $available
+     * @param $service
+     * @return bool
+     */
+    private function dispatchInTask(array $available, $service):bool
+    {
+        DB::beginTransaction();
+        try {
+            $tasks = TaskTransaction::query()->with("task")
+                ->where("type","入库")->whereHas("task",function ($query){
+                    $query->where("status","待处理");
+                })->where("status",3)->lockForUpdate()
+                ->where("mark",1)->get(); //检索等待的队列事务来获取对应任务
+            if ($this->dispatchTask($tasks,$available,$service,function ($obj,$stationId,$time,&$updateTransaction){
+                $updateTransaction[] = ["id"=>$obj->id,"fm_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
+            },function ($service,$toLocation,$task,$prefix){
+                return $service->fetchGroup_multiLocation($toLocation,$task,'','立架出至缓存架');
+            })){DB::commit();return true;}
+            DB::rollBack();
+        }catch (\Exception $e){
+            DB::rollBack();
+            $this->push(__METHOD__."->".__LINE__,"入库队列执行错误",$e->getMessage()." | 当前任务数:".$this->count." | 缓存信息:".(isset($available) ? json_encode($available) : ''));
+        }
+        return false;
+    }
+
+    private function dispatchTask(\Illuminate\Database\Eloquent\Collection $tasks, array $available, $service,
+                                  \Closure $update, \Closure $execute):bool
+    {
+        if (!$tasks->count())return false;
+        if ($tasks->count()>count($available))$tasks = $tasks->slice(0,count($available));//事务过多切割部分处理
+        $toLocation = collect();
+        $task = collect();
+        $availableTemp = array_keys($available);
+        $map = app("StationService")->getStationMapping($availableTemp);//获取库位映射信息
+        $updateTask = [["id","station_id","updated_at"]];
+        $updateTransaction = [["id","to_station_id","status","updated_at"]];
+        $time = date("Y-m-d H:i:s");
+        foreach ($tasks as $index=>$obj){
+            $loc = $availableTemp[$index];
+            $toLocation->push($loc);
+            $obj->task->station_id = $map[$loc];
+            $task->push($obj->task);
+            unset($available[$loc]);
+            $updateTask[] = ["id"=>$obj->task->id,"station_id"=>$map[$loc],"updated_at"=>$time];
+            $update($obj,$map[$loc],$time,$updateTransaction);
+        }
+        app("BatchUpdateService")->batchUpdate("station_task_material_boxes",$updateTask);
+        app("BatchUpdateService")->batchUpdate("task_transactions",$updateTransaction);
+        if ($execute($service,$toLocation,$task,$tasks[0]->station_task_batch_id)){
+            Cache::forever($this->key,$available);
+            foreach ($toLocation as $value){
+                app("CacheShelfService")->lightUp($value,'3','0');
+                Cache::forever("CACHE_SHELF_OCCUPANCY_{$map[$value]}",true);
+            }
+            app("StationService")->locationOccupyMulti($toLocation->toArray());
+            DB::commit();
+            return true;
+        }
+        DB::rollBack();
+        $this->push(__METHOD__."->".__LINE__,"缓存队列执行错误","库位信息:".json_encode($toLocation)."  任务信息:".json_encode($task));
+        return false;
+    }
 }

+ 34 - 14
app/Services/MaterialBoxService.php

@@ -42,17 +42,9 @@ class MaterialBoxService
             if ($boxes->count()==0)break;
             $id = $boxes[count($boxes)-1]->id;
             $boxCodes = array_column($boxes->toArray(),"code");
-            //检测海柔的有效料箱
-            $haiBoxes = DB::connection("mysql_haiRobotics")->table("ks_bin")
-                ->where("status",1)->whereIn("ks_bin_code",$boxCodes)->get();
-            if ($haiBoxes->count()==0)continue;
-            $haiBoxes->each(function ($haiBox)use(&$codes){$codes[$haiBox->ks_bin_code] = true;});
-            //剔除有任务待处理的料箱
-            $haiBoxes = DB::connection("mysql_haiRobotics_ess")->table("ks_ess_task_detail")
-                ->whereIn("bin_code",$boxCodes)
-                ->whereNotIn("status",[0,4])->get();
-            $haiBoxes->each(function ($haiBox)use(&$notCodes){$notCodes[$haiBox->bin_code] = true;});
-
+            //检测海柔的有效料箱并剔除有任务待处理的料箱
+            list($codes,$notCodes) = $this->checkHaiQ($boxCodes);
+            if (!$codes)continue;
             //剔除FLUX已有库存并且库位内种类超出的料箱
             $ides = [];
             $str = "(";
@@ -73,6 +65,21 @@ sql;
         return null;
     }
 
+    private function checkHaiQ(array $boxCodes)
+    {
+        $haiBoxes = DB::connection("mysql_haiRobotics")->table("ks_bin")
+            ->where("status",1)->whereIn("ks_bin_code",$boxCodes)->get();
+        if ($haiBoxes->count()==0)return array(null,null);
+        $codes = [];
+        $haiBoxes->each(function ($haiBox)use(&$codes){$codes[$haiBox->ks_bin_code] = true;});
+        $haiBoxes = DB::connection("mysql_haiRobotics_ess")->table("ks_ess_task_detail")
+            ->whereIn("bin_code",$boxCodes)
+            ->whereNotIn("status",[0,4])->get();
+        $notCodes = [];
+        $haiBoxes->each(function ($haiBox)use(&$notCodes){$notCodes[$haiBox->bin_code] = true;});
+        return array($codes,$notCodes);
+    }
+
     /**
      * 获取所有者排序的空盒子
      *
@@ -109,8 +116,10 @@ sql;
      * 获取某个型号下的可用料箱
      *
      * @param integer $modelId
+     * @param bool $sqlQuery
+     * @param array $blacklist
      *
-     * @return Collection|string|null
+     * @return Collection|string|null|array
      */
     public function getModelAvailableBox(int $modelId, bool $sqlQuery = false, array $blacklist = [])
     {
@@ -118,12 +127,23 @@ sql;
         $boxes = $query->whereNotIn("id",$query->select("id")->whereHas("performTask"));
         if ($blacklist)$boxes = $boxes->whereNotIn("id",$blacklist);
         $boxes = $boxes->get();
+
+        //筛选下海柔可用箱
+        list($codes,$notCodes) = $this->checkHaiQ(array_column($boxes->toArray(),"code"));
+        if (!$codes)$boxes = new \Illuminate\Database\Eloquent\Collection();
+        $boxes = $boxes->filter(function ($box)use($codes,$notCodes){
+            if (!isset($codes[$box->code]) || isset($notCodes[$box->code]))return false;
+            return true;
+        });
+
         if (!$sqlQuery)return $boxes;
-        if ($boxes->count()==0)return null;
+        if ($boxes->count()==0)return array(null,null);
         $boxCodes = "";
+        $map = [];
         foreach ($boxes as $box){
             $boxCodes .= "'".$box->code."',";
+            $map[$box->code] = $box->id;
         }
-        return rtrim($boxCodes,",");
+        return array(rtrim($boxCodes,","),$map);
     }
 }

+ 5 - 2
app/Services/StationService.php

@@ -10,6 +10,7 @@ use App\StationTask;
 use App\StationTaskMaterialBox;
 use App\StationType;
 use Exception;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
@@ -133,9 +134,11 @@ class StationService
     /**
      * 获取缓存架
      *
-     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
+     * @param bool $onlyAvailable
+     *
+     * @return Collection
      */
-    public function getCacheShelf($onlyAvailable = false)
+    public function getCacheShelf(bool $onlyAvailable = false):Collection
     {
         $stations = Station::query()->where("station_type_id",5)
             ->whereNotNull("parent_id");

+ 4 - 0
app/Services/StationTaskBatchService.php

@@ -13,6 +13,7 @@ use Exception;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\DB;
 
 
 class StationTaskBatchService
@@ -183,6 +184,7 @@ class StationTaskBatchService
                 LogService::log(__METHOD__,'runMany','波次任务分配6.r4:'.json_encode($stationTaskBatch));
                 throw new Exception('找不到料箱:' . json_encode($stationTaskBatch));
             })();//存在任务返回任务 否则抛出无料箱异常
+        DB::beginTransaction();
         try{
             //获取放线入口
             switch ($locationType){
@@ -206,8 +208,10 @@ class StationTaskBatchService
                 default:
                     $isFetchedFromRobotics = false;
             }
+            DB::commit();
             LogService::log(__METHOD__,'runMany','波次任务分配6.r6:'.json_encode($stationTaskBatch));
         }catch(Exception $e){
+            DB::rollBack();
             throw new ErrorException('$stationTaskBatch运行波次机器人任务失败,获取组失败: '.$stationTaskBatch->toJson() . $e->getMessage());
         }
         (function()use($isFetchedFromRobotics,$stationTaskBatch){

+ 9 - 8
app/Services/StorageService.php

@@ -61,7 +61,7 @@ class StorageService
                         case 1:
                             $task = $tasks[0];
                             $options["detail01"] = $task->materialBox->code ?? '';
-                            $options["detail02"] = $task->doc_code ?: $task->track_num;
+                            $options["detail02"] = $task->doc_code ?: '跟踪:‘'.$task->track_num."’ 批次:‘".$task->lot_num."’";
                             $options["detail03"] = $task->bar_code;
                             $options["qty01"] = $task->amount;
                             $options["uomDesc01"] = '件';
@@ -604,19 +604,20 @@ SQL;
      *
      * @param CommodityMaterialBoxModel $model
      * @param string $lotNum
-     * @return string|null
+     * @param bool $multi
+     * @param array $blacklist
+     * @return mixed
      */
-    public function getMaxAvailableHalfBoxLocation(CommodityMaterialBoxModel $model, string $lotNum, array $blacklist = []):?string
+    public function getMaxAvailableHalfBoxLocation(CommodityMaterialBoxModel $model, string $lotNum, bool $multi = true, array $blacklist = [])
     {
-        $boxCodes = app("MaterialBoxService")->getModelAvailableBox($model->material_box_model_id,true,$blacklist);
+        list($boxCodes,$map) = app("MaterialBoxService")->getModelAvailableBox($model->material_box_model_id,true,$blacklist);
         if (!$boxCodes)return null;
         $sql = <<<SQL
 SELECT LOCATIONID,({$model->maximum}-QTY) AS QTY FROM INV_LOT_LOC_ID WHERE LOTNUM = '{$lotNum}'
-AND LOCATIONID IN ({$boxCodes}) AND TRACEID = '*' AND {$model->maximum}-QTY > 0 ORDER BY (CASE QTY WHEN 0 THEN 1 ELSE 0 END),{$model->maximum}-QTY
+AND LOCATIONID IN ({$boxCodes}) AND TRACEID = '*' AND {$model->maximum}-QTY > 0 AND QTY > 0 ORDER BY {$model->maximum}-QTY
 SQL;
-        $res = DB::connection("oracle")->selectOne(DB::raw($sql));
-        if ($res)return $res;
-        return null;
+        if ($multi)return array(DB::connection("oracle")->select(DB::raw($sql)),$map);
+        return DB::connection("oracle")->selectOne(DB::raw($sql));
     }
 
     /**

+ 14 - 64
resources/views/store/inStorage/halfChestStorage.blade.php

@@ -17,14 +17,6 @@
                             <strong>@{{ errors.track[0] }}</strong>
                         </span>
                     </div>
-                    <div class="form-group row">
-                        <label for="station" class="col-sm-2 col-3 text-right">库位:</label>
-                        <input type="text" class="form-control col-8" id="station" placeholder="扫描货架条码"
-                               :class="errors.station ? 'is-invalid' : ''" v-model="info.station" @blur="check()" @keydown.enter="enterVal($event)">
-                        <span class="invalid-feedback offset-3" role="alert" v-if="errors.station">
-                            <strong>@{{ errors.station[0] }}</strong>
-                        </span>
-                    </div>
                     <div class="form-group row">
                         <label for="barCode" class="col-sm-2 col-3 text-right">条码:</label>
                         <input type="text" class="form-control col-8" id="barCode" placeholder="扫描商品条码"
@@ -71,8 +63,8 @@
                         </div>
                         <div class="modal-body">
                             <div class="form-group">
-                                <label for="location">库位码</label>
-                                <input id="location" type="text" v-model="ov.station" class="form-control" placeholder="库位码">
+                                <label for="location">料箱码</label>
+                                <input id="location" type="text" v-model="ov.ide" class="form-control" placeholder="料箱码">
                             </div>
                             <div class="form-group">
                                 <label for="ov_amount">溢出数量</label>
@@ -97,7 +89,7 @@
             el:"#container",
             data:{
                 permissionList:[ //允许聚焦许可列表
-                    "track","station","amount","location","ov_amount"
+                    "track","amount","location","ov_amount"
                 ],
                 info:{},
                 mount:false,
@@ -106,7 +98,7 @@
                 errors:{},
                 ov:{},//溢出减量数值
                 element:[
-                    "track","station","barCode","amount","submit"
+                    "track","barCode","amount","submit"
                 ],
                 isAndroid:false,
                 shelfOccupy:{},
@@ -126,13 +118,11 @@
                 models:null,
                 oldInfo:{},
                 lots:[],
+                lotMap:{},
             },
             mounted(){
                 if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
                 @foreach($stations as $station)this.$set(this.shelfOccupy,"{{$station->code}}",!!{{$station->material_box_id}});@endforeach
-                //this.codeFocus();
-                //this.globalClick();
-                //this.createBefore();
                 this.pageInit();
                 $("#container").removeClass("d-none");
             },
@@ -169,64 +159,24 @@
                         document.getElementById("location").focus();
                     },500);
                 },
-                /*//聚焦 白名单
-                codeFocus(){
-                    if (!this.permissionList.includes(document.activeElement.id)) document.getElementById("barCode").focus();
-                },
-                //全局点击聚焦
-                globalClick(turn = true){
-                    if (turn===this.mount)return;
-                    this.mount = turn;//防止重复挂载事件
-                    if (turn) window.addEventListener("click",this.codeFocus);
-                    else window.removeEventListener("click",this.codeFocus);
-                },*/
-
                 checkInfo(){
                     let error = {};
                     if (!this.info.track)error.track = ["跟踪号必填"];
                     if (!this.info.barCode)error.barCode = ["商品条码必填"];
-                    if (!this.info.station)error.station = ["库位必填"];
                     if (!this.info.amount && !this.info.maximum)error.amount = ["数量必填"];
                     if (JSON.stringify(error)!=='{}'){this.errors = error;return;}
                     if (!this.info.amount && this.info.maximum)this.info.amount = this.info.maximum;
                     this._exeTask();
                 },
                 _exeTask(){
-                    window.tempTip.postBasicRequest("{{url('store/inStorage/acquireBox')}}",this.info,()=>{
-                        if (!this.status){
-                            window.tempTip.show("调取失败,内部错误");
-                            return;
-                        }
-                        if (this.amount>0){
-                            this.info.station = "";
-                            this.info.amount = "";
-                        }else this.info = {track:this.info.track};
-                        this.errors = {};
-                        return "上架成功!";
-                    });
-                },
-  /*              createBefore(){
-                    let now = new Date();
-                    let yy = now.getFullYear().toString().substr(2, 2);
-                    let mm = now.getMonth() + 1;
-                    mm = mm <10 ? '0'+mm : mm.toString();
-                    let dd = now.getDate();
-                    dd = dd <10 ? '0'+dd : dd.toString();
-                    this.before.asn = 'ASN'+yy+mm+dd+'000';
-                },*/
-                checkMaximum(){
-                    window.tempTip.postBasicRequest("{{url('store/inStorage/checkMaximum')}}",this.info,res=>{
-                        if (!res.material_box_model_id){
-                            this.info.commodity_id = res.commodity_id;
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/acquireBox')}}",this.info,res=>{
+                        if (!res.status){
                             this.showMaximumModal();
                             return;
                         }
-                        this.info.maximum = res.need;
-                        this.info.location = res.location;
-                        this.info.material_box_model_id = res.material_box_model_id;
-                        this.info.commodity_id = res.commodity_id;
-                        if(!this.info.amount)this.info.amount = res.need;
-                        return "该库位最大可上数为"+res.need;
+                        this.info = {track:this.info.track};
+                        this.errors = {};
+                        return res.amount==0 ? "调取料箱成功!" : "空箱不足,剩余”"+res.amount+"“未上架";
                     });
                 },
                 check(){
@@ -234,13 +184,14 @@
                     if (!this.info.lotNum || this.info.track !== this.oldInfo.track || this.info.barCode !== this.oldInfo.barCode){
                         window.tempTip.postBasicRequest("{{url('store/inStorage/checkTask')}}",this.info,res=>{
                             this.oldInfo = {track:this.info.track,barCode:this.info.barCode};
+                            this.lotMap = res.lotMap;
                             switch (res.count){
                                 case 0:
                                     window.tempTip.show("无此上架信息");
                                     break;
                                 case 1:
                                     this.info.lotNum = res.lots;
-                                    this.checkMaximum();
+                                    this.info.maximum = res.lotMap[res.lots];
                                     break;
                                 default:
                                     this.lots = res.lots;
@@ -320,13 +271,12 @@
                         return;
                     }
                     window.tempTip.postBasicRequest("{{url('store/inStorage/setMaximum')}}",
-                        {models:models,commodityId:this.info.commodity_id},res=>{
-                        this.checkMaximum();
+                        {models:models,commodityId:this.info.commodity_id},()=>{
                     },true);
                 },
                 selectedLot(index){
                     this.info.lotNum = this.lots[index].lotnum;
-                    this.checkMaximum();
+                    this.info.maximum = this.lotMap[this.lots[index].lotnum];
                     $("#lotModal").modal("hide");
                 },
             },

+ 335 - 0
resources/views/store/inStorage/halfChestStorage.blade.temp

@@ -0,0 +1,335 @@
+@extends('layouts.app')
+@section('title')缓存架入库-半箱入库@endsection
+
+@section('content')
+    <div class="container-fluid d-none" id="container">
+        <div class="row">
+            <div class="card offset-md-1 col-md-5 col-sm-12">
+                <div class="card-body">
+                    <div class="form-group text-center mt-2" id="header_title">
+                        <span class="font-weight-bold h4">入库信息</span>
+                        <a class="small" href="#" @click="openModal()">溢出减量</a>
+                    </div>
+                    <div class="form-group row">
+                        <label for="track" class="col-sm-2 col-3 text-right">跟踪号:</label>
+                        <input type="text" class="form-control col-8" id="track" :class="errors.track ? 'is-invalid' : ''" @keydown.enter="enterVal($event)" v-model="info.track" @blur="check()">
+                        <span class="invalid-feedback offset-3" role="alert" v-if="errors.track">
+                            <strong>@{{ errors.track[0] }}</strong>
+                        </span>
+                    </div>
+                    <div class="form-group row">
+                        <label for="station" class="col-sm-2 col-3 text-right">库位:</label>
+                        <input type="text" class="form-control col-8" id="station" placeholder="扫描货架条码"
+                               :class="errors.station ? 'is-invalid' : ''" v-model="info.station" @blur="check()" @keydown.enter="enterVal($event)">
+                        <span class="invalid-feedback offset-3" role="alert" v-if="errors.station">
+                            <strong>@{{ errors.station[0] }}</strong>
+                        </span>
+                    </div>
+                    <div class="form-group row">
+                        <label for="barCode" class="col-sm-2 col-3 text-right">条码:</label>
+                        <input type="text" class="form-control col-8" id="barCode" placeholder="扫描商品条码"
+                               :class="errors.barCode ? 'is-invalid' : ''" v-model="info.barCode" @blur="check()" @keydown.enter="enterVal($event)">
+                        <span class="invalid-feedback offset-3" role="alert" v-if="errors.barCode">
+                            <strong>@{{ errors.barCode[0] }}</strong>
+                        </span>
+                    </div>
+                    <div class="form-group row">
+                        <label for="amount" class="col-sm-2 col-3 text-right">数量:</label>
+                        <input type="number" class="form-control col-8" id="amount"
+                               @keydown.enter="enterVal($event)" :class="errors.amount ? 'is-invalid' : ''" @blur="check()" v-model="info.amount" :placeholder="info.maximum!==undefined ? '最大可上:'+info.maximum : ''" :max="info.maximum" step="1">
+                        <span class="invalid-feedback offset-3" role="alert" v-if="errors.amount">
+                            <strong>@{{ errors.amount[0] }}</strong>
+                        </span>
+                    </div>
+                    <div class="input-group row mt-5">
+                        <button type="submit" id="submit" class="btn btn-success offset-2 col-8" @click="checkInfo()">提交</button>
+                    </div>
+                </div>
+            </div>
+            <div class="card col-md-5 col-sm-12">
+                <div class="card-body">
+                    <div class="mt-1 text-center">
+                        <button class="btn btn-primary" @click="submitBox()">为选中格口手动补充料箱</button>
+                        <button class="btn btn-sm btn-info text-white" @click="reverse()">全选/反选</button>
+                    </div>
+                    <div class="mt-2 h-75">
+                        <div class="w-100 text-center mt-2" style="cursor: pointer" :style="{height:(100/ides.length)+'%'}" v-for="arr in ides">
+                            <div class="row" style="height: 33.3%" v-for="a in arr">
+                                <div class="col-4 border border-dark" v-for="ide in a" :class="[shelfOccupy[ide] ? 'bg-danger' : 'bg-success',selectedBox[ide] ? 'box-shadow-dark' : '']"
+                                     @click="fillingBox(ide)">@{{ ide }}</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal fade" tabindex="-1" role="dialog" id="modal">
+                <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
+                    <div class="modal-content">
+                        <div class="modal-header">
+                            <div class="font-weight-bold h4">溢出减量</div>
+                            <button type="button" class="close" data-dismiss="modal">&times;</button>
+                        </div>
+                        <div class="modal-body">
+                            <div class="form-group">
+                                <label for="location">库位码</label>
+                                <input id="location" type="text" v-model="ov.station" class="form-control" placeholder="库位码">
+                            </div>
+                            <div class="form-group">
+                                <label for="ov_amount">溢出数量</label>
+                                <input id="ov_amount" type="number" v-model="ov.amount" min="1" step="1" class="form-control" placeholder="溢出数量">
+                            </div>
+                        </div>
+                        <div class="modal-footer">
+                            <button type="button" class="btn btn-success" @click="overflowRevision()">提交</button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            @include("store.inStorage._setMaximum")
+            @include("store.inStorage._lotModal")
+        </div>
+    </div>
+@stop
+
+@section('lastScript')
+    <script type="text/javascript">
+        new Vue({
+            el:"#container",
+            data:{
+                permissionList:[ //允许聚焦许可列表
+                    "track","station","amount","location","ov_amount"
+                ],
+                info:{},
+                mount:false,
+                /*before:{},*/
+                focus:"",
+                errors:{},
+                ov:{},//溢出减量数值
+                element:[
+                    "track","station","barCode","amount","submit"
+                ],
+                isAndroid:false,
+                shelfOccupy:{},
+                selectedBox:{},
+                ides:[
+                    [
+                        ["HAIB2-03-03","HAIB2-02-03","HAIB2-01-03"],
+                        ["HAIB2-03-02","HAIB2-02-02","HAIB2-01-02"],
+                        ["HAIB2-03-01","HAIB2-02-01","HAIB2-01-01"],
+                    ],
+                    [
+                        ["HAIB1-03-03","HAIB1-02-03","HAIB1-01-03"],
+                        ["HAIB1-03-02","HAIB1-02-02","HAIB1-01-02"],
+                        ["HAIB1-03-01","HAIB1-02-01","HAIB1-01-01"],
+                    ],
+                ],
+                models:null,
+                oldInfo:{},
+                lots:[],
+            },
+            mounted(){
+                if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
+                @foreach($stations as $station)this.$set(this.shelfOccupy,"{{$station->code}}",!!{{$station->material_box_id}});@endforeach
+                //this.codeFocus();
+                //this.globalClick();
+                //this.createBefore();
+                this.pageInit();
+                $("#container").removeClass("d-none");
+            },
+            methods:{
+                //页面初始化
+                pageInit(){
+                    if (!this.isAndroid)return;
+                    let element = document.getElementById("navbarSupportedContent").parentElement;
+                    element.className = "row";
+                    element.children[0].className += " col-5";
+                    element.children[0].href = "#";
+                    element.innerHTML = element.children[0].outerHTML;
+                    let e1 = document.getElementById("menu");
+                    let e2 = document.getElementById("demand-div");
+                    if (e1)e1.remove();
+                    if (e2)e2.remove();
+                },
+                //提交溢出减量
+                overflowRevision(){
+                    if (!this.ov.station || !this.ov.amount){
+                        window.tempTip.show("信息不完整");
+                        return;
+                    }
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/overflowRevision')}}",this.ov,()=>{
+                        $("#modal").modal('hide');
+                        this.ov = {};
+                        return "溢出减量成功!";
+                    });
+                },
+                //打开溢出减量模态框
+                openModal(){
+                    $("#modal").modal("show");
+                    setTimeout(function () {
+                        document.getElementById("location").focus();
+                    },500);
+                },
+                /*//聚焦 白名单
+                codeFocus(){
+                    if (!this.permissionList.includes(document.activeElement.id)) document.getElementById("barCode").focus();
+                },
+                //全局点击聚焦
+                globalClick(turn = true){
+                    if (turn===this.mount)return;
+                    this.mount = turn;//防止重复挂载事件
+                    if (turn) window.addEventListener("click",this.codeFocus);
+                    else window.removeEventListener("click",this.codeFocus);
+                },*/
+
+                checkInfo(){
+                    let error = {};
+                    if (!this.info.track)error.track = ["跟踪号必填"];
+                    if (!this.info.barCode)error.barCode = ["商品条码必填"];
+                    if (!this.info.station)error.station = ["库位必填"];
+                    if (!this.info.amount && !this.info.maximum)error.amount = ["数量必填"];
+                    if (JSON.stringify(error)!=='{}'){this.errors = error;return;}
+                    if (!this.info.amount && this.info.maximum)this.info.amount = this.info.maximum;
+                    this._exeTask();
+                },
+                _exeTask(){
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/acquireBox')}}",this.info,()=>{
+                        if (!this.status){
+                            window.tempTip.show("调取失败,内部错误");
+                            return;
+                        }
+                        if (this.amount>0){
+                            this.info.station = "";
+                            this.info.amount = "";
+                        }else this.info = {track:this.info.track};
+                        this.errors = {};
+                        return "上架成功!";
+                    });
+                },
+  /*              createBefore(){
+                    let now = new Date();
+                    let yy = now.getFullYear().toString().substr(2, 2);
+                    let mm = now.getMonth() + 1;
+                    mm = mm <10 ? '0'+mm : mm.toString();
+                    let dd = now.getDate();
+                    dd = dd <10 ? '0'+dd : dd.toString();
+                    this.before.asn = 'ASN'+yy+mm+dd+'000';
+                },*/
+                checkMaximum(){
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/checkMaximum')}}",this.info,res=>{
+                        if (!res.material_box_model_id){
+                            this.info.commodity_id = res.commodity_id;
+                            this.showMaximumModal();
+                            return;
+                        }
+                        this.info.maximum = res.need;
+                        this.info.location = res.location;
+                        this.info.material_box_model_id = res.material_box_model_id;
+                        this.info.commodity_id = res.commodity_id;
+                        if(!this.info.amount)this.info.amount = res.need;
+                        return "该库位最大可上数为"+res.need;
+                    });
+                },
+                check(){
+                    if (!this.info.track || !this.info.barCode)return;
+                    if (!this.info.lotNum || this.info.track !== this.oldInfo.track || this.info.barCode !== this.oldInfo.barCode){
+                        window.tempTip.postBasicRequest("{{url('store/inStorage/checkTask')}}",this.info,res=>{
+                            this.oldInfo = {track:this.info.track,barCode:this.info.barCode};
+                            switch (res.count){
+                                case 0:
+                                    window.tempTip.show("无此上架信息");
+                                    break;
+                                case 1:
+                                    this.info.lotNum = res.lots;
+                                    this.checkMaximum();
+                                    break;
+                                default:
+                                    this.lots = res.lots;
+                                    $("#lotModal").modal("show");
+                            }
+                        });
+                    }
+                },
+                //回车向下TAB
+                enterVal(e){
+                    let index = this.element.indexOf(e.target.id)+1;
+                    let element = document.getElementById(this.element[index]);
+                    if (element)element.focus();
+                    e.preventDefault();
+                    return false;
+                },
+                //提交填充料箱
+                submitBox(){
+                    window.tempTip.setDuration(3000);
+                    if (JSON.stringify(this.selectedBox)==='{}'){window.tempTip.show("未选中格口");return;}
+                    window.tempTip.confirm("确定选中格口已无料箱存在?",()=>{
+                        window.tempTip.setDuration(99999);
+                        window.tempTip.waitingTip("调取料箱中,请稍等");
+                        let boxes = [];
+                        for (let key in this.selectedBox)if (this.selectedBox[key]) boxes.push(key);
+                        window.tempTip.postBasicRequest("{{url('store/inStorage/resetCacheShelf')}}",{boxes:boxes},res=>{
+                            window.tempTip.cancelWaitingTip();
+                            window.tempTip.setDuration(3000);
+                            for (let i=0;i<res.boxes.length;i++){
+                                this.$set(this.shelfOccupy,res.boxes[i],true);
+                                this.$set(this.selectedBox,res.boxes[i],true);
+                            }
+                            if (res.data){
+                                window.tempTip.show(res.data);
+                                return;
+                            }
+                            return "手动补充成功";
+                        },true);
+                    })
+                },
+                reverse(){
+                    let ides = [];
+                    this.ides.forEach(arr=>{
+                        arr.forEach(a=>{
+                            a.forEach(ide=>{
+                                ides.push(ide);
+                            })
+                        })
+                    });
+                    ides.forEach((ideCode)=>{
+                        this.$set(this.selectedBox,ideCode,this.selectedBox[ideCode] ? !this.selectedBox[ideCode] : true);
+                    });
+                },
+                //选中填充料箱
+                fillingBox(ideCode){
+                    this.$set(this.selectedBox,ideCode,this.selectedBox[ideCode] ? !this.selectedBox[ideCode] : true);
+                },
+                showMaximumModal(){
+                    if (this.models){
+                        $("#maximumModal").modal("show");
+                        return;
+                    }
+                    window.tempTip.postBasicRequest("{{url("store/inStorage/getModels")}}",{},res=>{
+                        this.models = res;
+                        $("#maximumModal").modal("show");
+                    })
+                },
+                settingModelMaximum(){
+                    let models = [];
+                    this.models.forEach(model=>{
+                       if (model.maximum)models.push(model);
+                    });
+                    if (models.length<1){
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.setIndex(1099);
+                        window.tempTip.show("请至少设定一个上限型号");
+                        return;
+                    }
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/setMaximum')}}",
+                        {models:models,commodityId:this.info.commodity_id},res=>{
+                        this.checkMaximum();
+                    },true);
+                },
+                selectedLot(index){
+                    this.info.lotNum = this.lots[index].lotnum;
+                    this.checkMaximum();
+                    $("#lotModal").modal("hide");
+                },
+            },
+        });
+    </script>
+@stop