Kaynağa Gözat

半箱入库

Zhouzhendong 4 yıl önce
ebeveyn
işleme
6fafe9d3cc

+ 19 - 0
app/CommodityMaterialBoxModel.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class CommodityMaterialBoxModel extends Model
+{
+    use ModelLogChanging;
+
+    protected $table = "commodity_material_box_model";
+    public $timestamps = false;
+
+    protected $fillable=[
+        "commodity_id","material_box_model_id","maximum"
+    ];
+}

+ 2 - 1
app/Http/Controllers/DeliveryAppointmentController.php

@@ -35,7 +35,8 @@ class DeliveryAppointmentController extends Controller
 
         $warehouses = Warehouse::query()->select("id","name")->get();
         $owners = app("OwnerService")->getIntersectPermitting();
-        return view("store.deliveryAppointment.list",compact("list","warehouses","owners"));
+        $params = request()->input();
+        return view("store.deliveryAppointment.list",compact("list","warehouses","owners","params"));
     }
 
     public function appointment()

+ 112 - 1
app/Http/Controllers/StorageController.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers;
 
+use App\CommodityMaterialBoxModel;
 use App\Components\AsyncResponse;
 use App\MaterialBox;
 use App\Station;
@@ -9,8 +10,10 @@ use App\StationTask;
 use App\StationTaskMaterialBox;
 use App\Storage;
 use App\StoreItem;
+use App\TaskTransaction;
 use App\ValueStore;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 
@@ -71,12 +74,49 @@ sql;
             });
         })->first();
         //库存记录
-        app("StorageService")->enterWarehouse($station->id, $box->id, $item->commodity_id ?? null, $amount);
+        app("StorageService")->enterWarehouse($station->id, $box->id, $item->commodity_id ?? null, $amount, $box->material_box_model_id);
         //建立入库任务
         if (!app("ForeignHaiRoboticsService")->putWareHousing($fromLocation,$box->id))$this->error("错误库位或库位已被下达任务");
+
+        $maximum = app("CommodityMaterialBoxModelService")->getMaximum($box->material_box_model_id,$item->commodity_id ?? null);
+        if ($maximum && $maximum<$amount)app("CommodityMaterialBoxModelService")->setMaximum($box->material_box_model_id,$item->commodity_id ?? null,$amount);
+        $this->success(["model" => $box->material_box_model_id,"commodity" => $item->commodity_id ?? null, "maximum" => $maximum]);
+    }
+
+    public function setMaximum()
+    {
+        app("CommodityMaterialBoxModelService")->setMaximum(request("model"),request("commodity"),request("maximum"));
         $this->success();
     }
 
+    /**
+     * 检查最大限值并返回
+     *
+     */
+    public function checkMaximum()
+    {
+        $item = StoreItem::query()->whereHas("store",function (Builder $query){
+            $query->where("asn_code",request("asn"));
+        })->whereHas("commodity",function (Builder $query){
+            $query->whereHas("barcodes",function (Builder $query){
+                $query->where("code",request("barCode"));
+            });
+        })->first();
+        if (!$item)$this->error("WAS无此单据记录");
+        $models = CommodityMaterialBoxModel::query()->where("commodity_id",$item->commodity_id)->get();
+        if ($models->count()==0)$this->error("商品首入,请使用缓存架空箱入库");
+        foreach ($models as $model){
+            $box = Storage::query()->select(DB::raw("MAX({$model->maximum}-amount) need"),"material_box_id")
+                ->whereHas("materialBox",function (Builder $query)use($model){
+                $query->where("material_box_model_id",$model->material_box_model_id);
+            })->where("commodity_id",$model->commodity_id)->where("amount","<",$model->maximum)
+                ->where("status",0)->first();
+            $box->commodity_id = $item->commodity_id;
+            if ($box)$this->success($box);
+        }
+        $this->success(["need"=>$models[0]->maximum,"material_box_model_id"=>$models[0]->material_box_model_id,"commodity_id"=>$item->commodity_id]);
+    }
+
     public function fluxPA($asn,$ide,$amount)
     {
         if (!$asn->taskid)$this->error("ASN单无此入库信息,禁止上架");
@@ -230,4 +270,75 @@ sql;
         app("ForeignHaiRoboticsService")->paddingCacheShelf($station->get());
         $this->success(["data"=>$data,"boxes"=>$boxes]);
     }
+
+    /**
+     * 取得料箱
+     */
+    public function acquireBox()
+    {
+        $boxId = request("material_box_id");
+        $modelId = request("material_box_model_id");
+        //获取目标库位
+        $station = app("StationService")->getMirrorMappingLocation(request("station"));
+        if (!$station)$this->error("未知库位");
+        //获取料箱
+        if ($boxId && !app("MaterialBoxService")->checkUsableBox($boxId)){
+            $boxId = null;
+            //料箱存在且不可用
+            $models = CommodityMaterialBoxModel::query()->where("commodity_id",request("commodity_id"))->get();
+            foreach ($models as $model){
+                Storage::query()->select("material_box_id")
+                    ->whereHas("materialBox",function (Builder $query)use($model){
+                        $query->where("material_box_model_id",$model->material_box_model_id);
+                    })->where("commodity_id",$model->commodity_id)->where("amount","<",$model->maximum)
+                    ->where("status",0)->where(DB::raw("{$model->maximum}-amount"),">=",request("amount"))->get()->each(function ($box)use(&$boxId){
+                        if (app("MaterialBoxService")->checkUsableBox($box->id)){
+                            $boxId = $box->id;
+                            return true;
+                        }
+                        return false;
+                    });
+                if ($boxId)break;
+            }
+        }
+        if (!$boxId){
+            if (!$modelId){
+                $box = null;
+                $models = CommodityMaterialBoxModel::query()->where("commodity_id",request("commodity_id"))->get();
+                foreach ($models as $model){
+                    $box = app("MaterialBoxService")->getAnEmptyBox([],$model->material_box_model_id);
+                    if($box)break;
+                }
+            }else $box = app("MaterialBoxService")->getAnEmptyBox([],$modelId);
+            if (!$box)$this->error("无可用料箱");
+            $boxId = $box->id;
+        }
+        //发起取箱任务
+        $collection = new Collection();
+        $task = StationTask::query()->create([
+            'status' => "待处理",
+            'station_id' => $station->id,
+        ]);
+        $collection->add(StationTaskMaterialBox::query()->create([
+            'station_id' => $station->id,
+            'material_box_id'=>$boxId,
+            'status'=>"待处理",
+            'type' => '取',
+            'station_task_id' => $task->id,
+        ]));
+        if (!app("ForeignHaiRoboticsService")->fetchGroup($station->code,$collection,'','立架出至缓存架'))$this->error("呼叫机器人失败");
+        //生成临时任务事务
+        TaskTransaction::query()->create([
+            "fm_station_id" => $station->id,
+            "material_box_id" => $boxId,
+            "commodity_id" => request("commodity_id"),
+            "amount" => request("amount"),
+            "type" => "入库",
+            "user_id" => Auth::id(),
+            "mark" => 1
+        ]);
+        //亮灯
+        app("CacheShelfService")->stationLightUp($station->code,null,'2');
+        $this->success();
+    }
 }

+ 8 - 0
app/Http/Controllers/StoreController.php

@@ -446,4 +446,12 @@ class StoreController extends Controller
         })->get();
         return \view("store.inStorage.cacheRackStorage",compact("storages"));
     }
+
+    /**
+     * 缓存架半箱入库
+     */
+    public function halfChestStorage()
+    {
+        return \view("store.inStorage.halfChestStorage");
+    }
 }

+ 1 - 13
app/Http/Controllers/TestController.php

@@ -123,19 +123,7 @@ class TestController extends Controller
     }
     public function test()
     {
-        StationTask::destroy([1278,1279,1280,1282,1283]);
-        StationTaskMaterialBox::destroy([18405,18406,18407,18409,18410]);
-        dd("OK");
-        $s = Station::query()->select("id")->where("parent_id",6)->whereNotIn("code",[
-            "HAIB1-01-01","HAIB1-03-01","HAIB1-03-03"
-        ]);
-        dd($s->get());
-        $t = StationTask::query()->select("id")->where("status",'待处理')
-            ->whereIn("station_id",$s);
-        StationTask::query()->where("status",'待处理')
-            ->whereIn("station_id",$s)->update(["status"=>"完成"]);
-        StationTaskMaterialBox::query()->whereIn("station_task_id",$t)->update(["status"=>"完成"]);
-        dd("OK");
+
     }
     public function orderCreateBill()
     {

+ 5 - 1
app/MaterialBox.php

@@ -10,7 +10,7 @@ class MaterialBox extends Model
 {
     use ModelLogChanging;
 
-    protected $fillable=['code','status'];
+    protected $fillable=['code','status',"material_box_model_id"];
 
     static public $enums=[
         'status'=>[
@@ -48,4 +48,8 @@ class MaterialBox extends Model
     {   //料箱任务
         return $this->hasMany(StationTaskMaterialBox::class,"material_box_id","id");
     }
+    public function materialBoxModel()
+    {   //料箱型号
+        return $this->belongsTo(MaterialBoxModel::class);
+    }
 }

+ 16 - 0
app/MaterialBoxModel.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class MaterialBoxModel extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable=[
+        "code"
+    ];
+}

+ 2 - 0
app/Providers/AppServiceProvider.php

@@ -119,6 +119,7 @@ use App\Services\OrderPackageExceptionTypeCountingRecordService;
 use App\Services\LogisticYDService;
 use App\Services\ForeignZhenCangService;
 use App\Services\StorageService;
+use App\Services\CommodityMaterialBoxModelService;
 
 class AppServiceProvider extends ServiceProvider
 {
@@ -170,6 +171,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('CacheShelfService',CacheShelfService::class);
         app()->singleton('CheckActiveMenuService',CheckActiveMenuService::class);
         app()->singleton('CommodityBarcodeService',CommodityBarcodeService::class);
+        app()->singleton('CommodityMaterialBoxModelService',CommodityMaterialBoxModelService::class);
         app()->singleton('CommodityService', CommodityService::class);
         app()->singleton('ConfigurationService',ConfigurationService::class);
         app()->singleton('CustomerLogService',CustomerLogService::class);

+ 34 - 0
app/Services/CacheShelfService.php

@@ -209,6 +209,40 @@ class   CacheShelfService
         return json_decode($response->body());
     }
 
+    /**
+     * 站亮灯
+     *
+     * @param string $stationCode
+     * @param string|null $materialCode
+     * @param string $color             explain: 0-red 1-green 2-blue 3-yellow
+     * @param string $frequency         explain: 0-常亮 1-一次 2-两次 3-三次 4-四次 5-五次 (均为/秒)
+     * @param string $title
+     * @return mixed
+     */
+    public function stationLightUp(string $stationCode,?string $materialCode = null, string $color = '1', string $frequency = '0', $title = '')
+    {
+        $params = [
+            "areaCode" => "1004",
+            'locCode' => $stationCode,
+            'PTLAction' => 1,
+            'PTLSettings' => ['color' => $color, 'frequency'  => $frequency],
+            "displayInfo" => [
+                "detail01" => $materialCode,
+                "detail02" => "detail02",
+                "detail03" => "detail03",
+                "qrCode" => "qrCode",
+                "qty00" => "11",
+                "qty01" => 1,
+                "qty02" => 2,
+                "title" => $title,
+                "uomDesc01" => "uo",
+                "uomDesc02" => "uo"
+            ],
+        ];
+        $response = Http::post(config('api.haiq.storage.light'), $params);
+        return json_decode($response->body());
+    }
+
     /**
      * 控制格口灭灯
      * @param $locCode

+ 51 - 0
app/Services/CommodityMaterialBoxModelService.php

@@ -0,0 +1,51 @@
+<?php 
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\CommodityMaterialBoxModel;
+
+class CommodityMaterialBoxModelService
+{
+    use ServiceAppAop;
+    protected $modelClass=CommodityMaterialBoxModel::class;
+
+
+    /**
+     * 获取最大限值
+     *
+     * @param integer|null $modelId
+     * @param integer|null $commodityId
+     *
+     * @return int|null
+     */
+    public function getMaximum($modelId, $commodityId):?int
+    {
+        if (!$modelId || !$commodityId)return null;
+        $model = CommodityMaterialBoxModel::query()->select("maximum")->where("commodity_id",$commodityId)
+            ->where("material_box_model_id",$modelId)->first();
+        return (int)$model->maximum ?? null;
+    }
+
+    /**
+     * 设置最大限值
+     *
+     * @param integer|null $modelId
+     * @param integer|null $commodityId
+     * @param integer $maximum
+     *
+     * @return bool
+     */
+    public function setMaximum($modelId, $commodityId, $maximum):bool
+    {
+        if (!$modelId || !$commodityId)return false;
+        $model = CommodityMaterialBoxModel::query()->select("maximum")->where("commodity_id",$commodityId)
+            ->where("material_box_model_id",$modelId)->first();
+        if (!$model)CommodityMaterialBoxModel::query()->create([
+            "maximum" => $maximum,
+            "commodity_id" => $commodityId,
+            "material_box_model_id" => $modelId,
+        ]);else $model->update(["maximum" => $maximum]);
+        return true;
+    }
+}

+ 21 - 3
app/Services/MaterialBoxService.php

@@ -24,10 +24,11 @@ class MaterialBoxService
      * 获取一个空料箱
      *
      * @param array $blacklist
+     * @param integer|null $modelId
      *
      * @return MaterialBox|null
      */
-    public function getAnEmptyBox(array $blacklist = [])
+    public function getAnEmptyBox(array $blacklist = [], $modelId = null)
     {
         $id = 0;
         while (true){
@@ -36,8 +37,9 @@ class MaterialBoxService
                 ->where("id",">",$id)->where("code","like","IDE%")
                 ->where("status",4)->limit(10)->orderBy("id")
                 ->whereNotIn("id",StationTaskMaterialBox::query()->select("material_box_id")
-                    ->where("status","!=","已完成")->groupBy("material_box_id"))
-                ->get();
+                    ->where("status","!=","已完成")->groupBy("material_box_id"));
+            if ($modelId)$boxes->where("material_box_model_id",$modelId);
+            $boxes = $boxes->get();
             if ($boxes->count()==0)break;
             $haiBoxes = DB::connection("mysql_haiRobotics")->table("ks_bin")
                 ->where("status",1)->whereIn("ks_bin_code",array_column($boxes->toArray(),"code"))->get();
@@ -79,4 +81,20 @@ sql;
             ->where("ks_bin_code",$ide)->where("status",1)->first();
         return $bin->ks_bin_space_code ?? null;
     }
+
+    /**
+     * 检查可用料箱
+     *
+     * @param integer $boxId
+     *
+     * @return bool
+     */
+    public function checkUsableBox($boxId):bool
+    {
+        /** @var MaterialBox|\stdClass $box */
+        $box = MaterialBox::query()->find($boxId);
+        if (!$this->getBoxLocation($box->code))return false;
+        if (StationTaskMaterialBox::query()->select(DB::raw(1))->where("status","!=",'完成')->where("material_box_id",$boxId)->first())return false;
+        return true;
+    }
 }

+ 16 - 0
app/Services/StationService.php

@@ -9,6 +9,7 @@ use App\Station;
 use App\StationTask;
 use App\StationType;
 use Exception;
+use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
 
@@ -84,4 +85,19 @@ class StationService
         $this->broadcast($station_id, $stationTask);
     }
 
+    /**
+     * 获取镜像映射库位
+     *
+     * @param string $mirrorLocation
+     *
+     * @return Model|null
+     */
+    public function getMirrorMappingLocation($mirrorLocation)
+    {
+        $station = Station::query()->select("parent_id")->where("code",$mirrorLocation)->first();
+        if (!$station)return null;
+        return Station::query()->where("station_type_id",5)
+            ->where("id",$station->parent_id)->first();
+    }
+
 }

+ 2 - 0
app/Services/StationTaskMaterialBoxService.php

@@ -179,7 +179,9 @@ class StationTaskMaterialBoxService
                     $this->cacheShelfService->putStationTaskMaterialBoxProcess($stationTaskMaterialBox);
                     $stationTaskMaterialBox->materialBox['status']='在立库';
                     $stationTaskMaterialBox->materialBox->update();
+                    $stationTaskMaterialBox->loadMissing("station");    //提前加载站,后续都需要站信息来处理
                     $this->storageService->releaseOccupation($stationTaskMaterialBox); //释放库位占用
+                    $this->storageService->checkMark($stationTaskMaterialBox); //检查标记并做一些特殊处理
                     break;
                 case '入缓存架':
                     $stationTaskMaterialBox->materialBox['status']='在缓存架';

+ 44 - 15
app/Services/StorageService.php

@@ -2,11 +2,12 @@
 
 namespace App\Services;
 
+use App\CommodityMaterialBoxModel;
 use App\StationTask;
 use App\StationTaskMaterialBox;
+use App\TaskTransaction;
 use App\Traits\ServiceAppAop;
 use App\Storage;
-use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\DB;
 
@@ -53,7 +54,6 @@ class StorageService
      */
     public function releaseOccupation($stationTaskMaterialBox)
     {
-        $stationTaskMaterialBox->loadMissing("station");
         if ($stationTaskMaterialBox->station->station_type_id != 5)return;
         $storage = Storage::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id)->first();
         if (!$storage)return;
@@ -63,6 +63,20 @@ class StorageService
         if ($update)$storage->update($update);
     }
 
+    /**
+     * 检查临时事务标记处理一些特殊情况
+     *
+     * @param StationTaskMaterialBox|\stdClass $stationTaskMaterialBox
+     */
+    public function checkMark($stationTaskMaterialBox)
+    {
+        $task = TaskTransaction::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id)
+            ->where("status",0)->first();
+        if (!$task)return;
+        //蓝灯闪烁
+        if ($task->type == '入库' && $task->mark == 1)app("CacheShelfService")->stationLightUp($stationTaskMaterialBox->station->code,null,'2','2');
+    }
+
     /**
      * 入库
      *
@@ -70,20 +84,35 @@ class StorageService
      * @param integer $boxId
      * @param integer $commodityId
      * @param integer $amount
+     * @param integer $modelId
      */
-    public function enterWarehouse($stationId, $boxId, $commodityId, $amount)
+    public function enterWarehouse($stationId, $boxId, $commodityId, $amount, $modelId)
     {
-        $storage = Storage::query()->where("material_box_id",$boxId)->first();
-        $obj = [
-            "station_id" => $stationId,
-            "material_box_id" => $boxId,
-            "commodity_id" => $commodityId,
-            "amount" => $amount,
-            "status" => 1,
-        ];
-        if ($storage){
-            $obj["amount"] = DB::raw("amount+{$amount}");
-            $storage->update($obj);
-        } else Storage::query()->create($obj);
+        DB::beginTransaction();
+        try{
+            $storage = Storage::query()->where("material_box_id",$boxId)->lockForUpdate()->first();
+            $obj = [
+                "station_id" => $stationId,
+                "material_box_id" => $boxId,
+                "commodity_id" => $commodityId,
+                "amount" => $amount,
+                "status" => 1,
+            ];
+            if ($storage){
+                $obj["amount"] = DB::raw("amount+{$amount}");
+                $storage->update($obj);
+                $amount = (int)$storage->amount + (int)$amount;
+            } else Storage::query()->create($obj);
+            if ($commodityId){
+                //维护料箱最大上限 用于半箱补货
+                $model = CommodityMaterialBoxModel::query()->select("maximum")->where("commodity_id",$commodityId)
+                    ->where("material_box_model_id",$modelId)->first();
+                if (!$model)CommodityMaterialBoxModel::query()->create(["commodity_id"=>$commodityId,"material_box_model_id"=>$modelId,"maximum"=>$amount]);
+                if ($model && $model->maximum < $amount)$model->update(["maximum"=>$amount]);
+            }
+            DB::commit();
+        }catch(\Exception $e){
+            DB::rollBack();
+        }
     }
 }

+ 35 - 0
app/TaskTransaction.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class TaskTransaction extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable = [
+        "fm_station_id",
+        "to_station_id",
+        "material_box_id",
+        "task_id",
+        "commodity_id",
+        "amount",
+        "type",
+        "status",
+        "user_id",
+        "mark"
+    ];
+
+    const STATUS = [
+        0 => "待做",
+        1 => "完成",
+        2 => "失败"
+    ];
+    const MARK = [
+        0 => "无",
+        1 => "缓存架半箱入库"
+    ];
+}

+ 4 - 4
composer.lock

@@ -3323,12 +3323,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/oursdreams/export.git",
-                "reference": "507ed53371d4ecc4f4350a9066422621ac2fae1c"
+                "reference": "ef7694ac342ff18742c17ddbce3a85076cac17e3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/oursdreams/export/zipball/507ed53371d4ecc4f4350a9066422621ac2fae1c",
-                "reference": "507ed53371d4ecc4f4350a9066422621ac2fae1c",
+                "url": "https://api.github.com/repos/oursdreams/export/zipball/ef7694ac342ff18742c17ddbce3a85076cac17e3",
+                "reference": "ef7694ac342ff18742c17ddbce3a85076cac17e3",
                 "shasum": ""
             },
             "type": "library",
@@ -3359,7 +3359,7 @@
                 "issues": "https://github.com/oursdreams/export/issues",
                 "source": "https://github.com/oursdreams/export/tree/0.0.7"
             },
-            "time": "2021-05-28T02:57:41+00:00"
+            "time": "2021-06-01T03:01:13+00:00"
         },
         {
             "name": "overtrue/laravel-pinyin",

+ 46 - 0
database/migrations/2021_06_03_171554_create_material_box_models_table.php

@@ -0,0 +1,46 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMaterialBoxModelsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('material_box_models', function (Blueprint $table) {
+            $table->id();
+            $table->string("code")->comment("型号");
+            $table->timestamps();
+        });
+        Schema::table('material_boxes', function (Blueprint $table) {
+            $table->bigInteger("material_box_model_id")->nullable()->index()->comment("型号");
+        });
+        Schema::create('commodity_material_box_model', function (Blueprint $table) {
+            $table->bigInteger("commodity_id")->comment("商品ID");
+            $table->bigInteger("material_box_model_id")->comment("料箱模型ID");
+            $table->integer("maximum")->default(0)->comment("存储最大限值");
+        });
+        \App\StationType::query()->create(["name"=>"镜像架"]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('material_box_models');
+        Schema::table('material_boxes', function (Blueprint $table) {
+            $table->dropColumn("material_box_model_id");
+        });
+        Schema::dropIfExists('commodity_material_box_model');
+        \App\StationType::query()->where("name","镜像架")->delete();
+    }
+}

+ 41 - 0
database/migrations/2021_06_07_100646_create_task_transactions_table.php

@@ -0,0 +1,41 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateTaskTransactionsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('task_transactions', function (Blueprint $table) {
+            $table->id();
+            $table->string("fm_station_id")->nullable()->comment("来源库位");
+            $table->string("to_station_id")->nullable()->comment("目标库位");
+            $table->string("material_box_id")->nullable()->comment("料箱ID");
+            $table->bigInteger("task_id")->nullable()->index()->comment("任务ID");
+            $table->bigInteger("commodity_id")->nullable()->comment("商品ID");
+            $table->integer("amount")->default(0)->comment("数量");
+            $table->enum("type",["出库","入库","移库"])->comment("操作类型");
+            $table->tinyInteger("status")->default(0)->comment("事务状态");
+            $table->bigInteger("user_id")->nullable()->comment("操作人");
+            $table->tinyInteger("mark")->default(0)->comment("标记类型");
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('task_transactions');
+    }
+}

+ 3 - 2
resources/views/store/deliveryAppointment/list.blade.php

@@ -116,7 +116,7 @@
                             <div class="col-2 text-secondary">@{{ info.cars[0].driver_phone }}</div>
                             <div class="col-3">
                                 @can("入库管理-入库预约-预约管理-卸货完成")<button class="btn btn-sm btn-outline-success" @click="unloading(i,0)" v-if="info.cars[0].status==1">卸货完成</button>@endcan
-                                @can("入库管理-入库预约-预约管理-签到")<button class="btn btn-sm btn-outline-success" @click="signIn(i,0)" v-if="info.cars[0].status==0">签到</button>@endcan
+                                @can("入库管理-入库预约-预约管理-签到")<button class="btn btn-sm btn-outline-success" @click="signIn(i,0)" v-if="info.status==0 && info.cars[0].status==0">签到</button>@endcan
                                 <div v-if="info.cars[0].status==2">@{{ info.cars[0].delivery_time }}</div>
                             </div>
                         </div>
@@ -129,7 +129,7 @@
                                 <div class="col-2 text-secondary">@{{ car.driver_phone }}</div>
                                 <div class="col-3">
                                     @can("入库管理-入库预约-预约管理-卸货完成")<button class="btn btn-sm btn-outline-success" @click="unloading(i,j)" v-if="car.status==1">卸货完成</button>@endcan
-                                    @can("入库管理-入库预约-预约管理-签到")<button class="btn btn-sm btn-outline-success" @click="signIn(i,j)" v-if="car.status==0">签到</button>@endcan
+                                    @can("入库管理-入库预约-预约管理-签到")<button class="btn btn-sm btn-outline-success" @click="signIn(i,j)" v-if="info.status==0 && car.status==0">签到</button>@endcan
                                     <div v-if="car.status==2">@{{ car.delivery_time }}</div>
                                 </div>
                             </div>
@@ -173,6 +173,7 @@
                 <td>@{{ info.created_at }}</td>
             </tr>
         </table>
+        {{$list->appends($params)->links()}}
         @include("store.deliveryAppointment._selectDate")
         @include("store.deliveryAppointment._printBody")
         @include("store.deliveryAppointment._printInfo")

+ 8 - 2
resources/views/store/inStorage/cacheRackStorage.blade.php

@@ -120,7 +120,7 @@
                     if (JSON.stringify(this.selectedBox)==='{}'){window.tempTip.show("未选中格口");return;}
                     window.tempTip.confirm("确定选中格口已无料箱存在?",()=>{
                         let boxes = [];
-                        for (let key in this.selectedBox)boxes.push(key);
+                        for (let key in this.selectedBox)if (this.selectedBox[key]) boxes.push(key);
                         window.tempTip.postBasicRequest("{{url('store/inStorage/resetCacheShelf')}}",{boxes:boxes},res=>{
                             for (let i=0;i<res.boxes.length;i++){
                                 this.$set(this.shelfOccupy,res.boxes[i],false);
@@ -167,7 +167,13 @@
                     this._exeTask();
                 },
                 _exeTask(){
-                    window.tempTip.postBasicRequest("{{url('store/inStorage/putShelf')}}",this.info,()=>{
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/putShelf')}}",this.info,res=>{
+                        if (!res.maximum){
+                            window.tempTip.inputVal('商品首入,请输入预估最大可放入数:',(maximum)=>{
+                                res.maximum = maximum;
+                                window.tempTip.postBasicRequest("{{url('store/inStorage/setMaximum')}}",res,()=>{});
+                            });
+                        }
                         this.info = {};
                         this.errors = {};
                         return "缓存架上架成功!";

+ 134 - 0
resources/views/store/inStorage/halfChestStorage.blade.php

@@ -0,0 +1,134 @@
+@extends('layouts.app')
+@section('title')缓存架入库-入库管理@endsection
+
+@section('content')
+    <span id="nav2">
+        @component('store.menu')@endcomponent
+        @component('store.inStorage.menu')@endcomponent
+    </span>
+    <div class="container-fluid" id="container">
+        <div class="row">
+            <div class="card offset-md-3 col-md-6 col-sm-12">
+                <div class="card-body">
+                    <div class="form-group text-center font-weight-bold h4">
+                        入库信息
+                    </div>
+                    <div class="form-group row">
+                        <label for="asn" class="col-sm-2 col-3 text-right">ASN号:</label>
+                        <input type="text" class="form-control col-8" :class="errors.asn ? 'is-invalid' : ''" id="asn" v-model="info.asn" @blur="checkAsn()" placeholder="只需填写后几位,自动补充">
+                        <span class="invalid-feedback offset-2" role="alert" v-if="errors.asn">
+                            <strong>@{{ errors.asn[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" :class="errors.station ? 'is-invalid' : ''" id="station" v-model="info.station"
+                               placeholder="扫描货架条码">
+                        <span class="invalid-feedback offset-2" 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" :class="errors.barCode ? 'is-invalid' : ''" id="barCode" v-model="info.barCode" placeholder="扫描商品条码">
+                        <span class="invalid-feedback offset-2" 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" :class="errors.amount ? 'is-invalid' : ''" id="amount" v-model="info.amount"
+                               :placeholder="info.maximum!==undefined ? '最大可上:'+info.maximum : ''" :max="info.maximum" step="1">
+                        <span class="invalid-feedback offset-2" role="alert" v-if="errors.amount">
+                            <strong>@{{ errors.amount[0] }}</strong>
+                        </span>
+                    </div>
+                    <div class="input-group row mt-5">
+                        <button type="submit" class="btn btn-success offset-2 col-9" @click="checkInfo()">提交</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+@stop
+
+@section('lastScript')
+    <script type="text/javascript">
+        new Vue({
+            el:"#container",
+            data:{
+                permissionList:[ //允许聚焦许可列表
+                    "asn","station","amount"
+                ],
+                info:{},
+                mount:false,
+                before:{
+                    asn:"",
+                },
+                errors:{},
+            },
+            mounted(){
+                this.codeFocus();
+                this.globalClick();
+                this.createBefore();
+            },
+            methods:{
+                //聚焦 白名单
+                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.asn)error.asn = ["ASN号必填"];
+                    if (this.info.asn && this.info.asn.length!==13)error.asn = ["非法ASN号"];
+                    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,()=>{
+                        this.info = {};
+                        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';
+                },
+                checkAsn(){
+                    if(!this.info.asn)return;
+                    let len = this.info.asn.length;
+                    if (len<13)this.info.asn = this.before.asn.substr(0,13-len)+this.info.asn;
+                    if (!this.info.ide)document.getElementById("station").focus();
+                    this.checkMaximum();
+                },
+                checkMaximum(){
+                    if (!this.info.asn || !this.info.barCode)return;
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/checkMaximum')}}",this.info,res=>{
+                        this.info.maximum = res.need;
+                        this.info.material_box_id = res.material_box_id;
+                        this.info.material_box_model_id = res.material_box_model_id;
+                        this.info.commodity_id = res.commodity_id;
+                    });
+                },
+            },
+        });
+    </script>
+@stop

+ 5 - 2
resources/views/store/inStorage/menu.blade.php

@@ -8,8 +8,11 @@
                     </li> @endcan
                 @can('入库管理-入库-缓存架入库')
                 <li class="nav-item">
-                    <a target="store/inStorage/index" class="nav-link" href="{{url('store/inStorage/cacheRackStorage')}}" :class="{active:isActive('cacheRackStorage',3)}">缓存架入库</a>
-                </li> @endcan
+                    <a target="store/inStorage/cacheRackStorage" class="nav-link" href="{{url('store/inStorage/cacheRackStorage')}}" :class="{active:isActive('cacheRackStorage',3)}">缓存架入库</a>
+                </li>
+                <li class="nav-item">
+                    <a target="store/inStorage/halfChestStorage" class="nav-link" href="{{url('store/inStorage/halfChestStorage')}}" :class="{active:isActive('halfChestStorage',3)}">半箱补货入库</a>
+                </li>@endcan
             </ul>
         </div>
     </div>

+ 3 - 0
routes/web.php

@@ -415,8 +415,11 @@ Route::group(['prefix'=>'store'],function(){
     Route::group(['prefix'=>'inStorage'],function() {
         Route::get('index','StoreController@storage');
         Route::get('cacheRackStorage','StoreController@cacheRackStorage');
+        Route::get('halfChestStorage','StoreController@halfChestStorage');
         Route::post('putShelf','StorageController@putShelf');
         Route::post('resetCacheShelf','StorageController@resetCacheShelf');
+        Route::post('setMaximum','StorageController@setMaximum');
+        Route::post('checkMaximum','StorageController@checkMaximum');
     });
     Route::group(['prefix'=>'fast'],function() {
         Route::resource('storeItem','StoreItemController');