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

Merge branch 'zengjun' of ssh://was.baoshi56.com:10022/var/git/bswas

 Conflicts:
	app/Services/PackageStatisticsService.php
LD 5 лет назад
Родитель
Сommit
1aff4aa221

+ 11 - 2
app/Http/Controllers/CacheShelfController.php

@@ -51,9 +51,18 @@ class CacheShelfController extends Controller
     public function lightOnApi(Request $request,CacheShelfService $service)
     {
         if($request['stationCode'] && $request['materialBoxCode'])
-        return $service->createStationTask($request['stationCode'],$request['materialBoxCode']);
-
+           return $service->createStationTask($request['stationCode'],$request['materialBoxCode']);
         return ['success' => false,'message' => '参数错误'];
     }
 
+    /**
+     * @param Request $request
+     * @return array|bool[]
+     */
+    public function clearTaskApi(Request $request): array
+    {
+        $code = $request['station'];
+        return app(CacheShelfService::class)->clearTask($code);
+    }
+
 }

+ 57 - 9
app/Http/Controllers/StationRuleBatchController.php

@@ -2,25 +2,73 @@
 
 namespace App\Http\Controllers;
 
+use App\Components\AsyncResponse;
+use App\Http\Requests\Station\StationRuleBatchRequest;
+use App\Services\OwnerService;
 use App\StationRuleBatch;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\View\Factory;
 use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\View\View;
+
 
 class StationRuleBatchController extends Controller
 {
+    use AsyncResponse;
+
     /**
      * Display a listing of the resource.
      *
-     * @return \Illuminate\Http\Response
+     * @param Request $request
+     * @param OwnerService $ownerService
+     * @return Application|Factory|View
      */
-    public function index()
+    public function index(Request $request,OwnerService $ownerService)
     {
-        //
+        if(!Gate::allows('站管理-站规则')){ return redirect(url('/'));  }
+        $stationRuleBatches = StationRuleBatch::query()->with('stationType','owner')->orderByDesc('id')->paginate($request['paginate'] ?? 50);
+        $owners = $ownerService->getAuthorizedOwners();
+        return view('station.rule.index',compact('stationRuleBatches','owners'));
+    }
+
+    /**
+     * store API
+     * @param StationRuleBatchRequest $request
+     */
+    public function storeApi(StationRuleBatchRequest $request)
+    {
+        $this->gate('站管理-站规则-编辑');
+        $stationRuleBatch = StationRuleBatch::query()->create($request->only(['name','owner_id']));
+        $stationRuleBatch->load('stationType','owner');
+        $this->success($stationRuleBatch);
+    }
+
+    /**
+     * update API
+     * @param StationRuleBatchRequest $request
+     */
+    public function updateApi(StationRuleBatchRequest $request)
+    {
+        $this->gate('站管理-站规则-编辑');
+        $stationRuleBatch = StationRuleBatch::query()->whereKey($request['id'])->first();
+        $stationRuleBatch->update($request->all());
+        $stationRuleBatch->load('stationType','owner');
+        $this->success($stationRuleBatch);
+    }
+
+    public function destroyApi(Request $request)
+    {
+        $this->gate('站管理-站规则-删除');
+        StationRuleBatch::query()->whereKey($request['id'])->delete();
+        $this->success();
     }
 
     /**
      * Show the form for creating a new resource.
      *
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function create()
     {
@@ -31,7 +79,7 @@ class StationRuleBatchController extends Controller
      * Store a newly created resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function store(Request $request)
     {
@@ -42,7 +90,7 @@ class StationRuleBatchController extends Controller
      * Display the specified resource.
      *
      * @param  \App\StationRuleBatch  $stationRuleBatch
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function show(StationRuleBatch $stationRuleBatch)
     {
@@ -53,7 +101,7 @@ class StationRuleBatchController extends Controller
      * Show the form for editing the specified resource.
      *
      * @param  \App\StationRuleBatch  $stationRuleBatch
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function edit(StationRuleBatch $stationRuleBatch)
     {
@@ -65,7 +113,7 @@ class StationRuleBatchController extends Controller
      *
      * @param  \Illuminate\Http\Request  $request
      * @param  \App\StationRuleBatch  $stationRuleBatch
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function update(Request $request, StationRuleBatch $stationRuleBatch)
     {
@@ -76,7 +124,7 @@ class StationRuleBatchController extends Controller
      * Remove the specified resource from storage.
      *
      * @param  \App\StationRuleBatch  $stationRuleBatch
-     * @return \Illuminate\Http\Response
+     * @return Response
      */
     public function destroy(StationRuleBatch $stationRuleBatch)
     {

+ 1 - 1
app/Http/Controllers/api/thirdPart/haiq/LightController.php

@@ -33,7 +33,7 @@ class LightController
      */
     public function update(Request $request){// 拍灯以后的消息发至此处
         $station = Station::query()->with('stationType')->where('code',$request['locCode'])->first();
-        if( $station->stationType && $station->stationType->name == '缓存架' ){  // 拍灯 推送任务
+        if( ($station ?? false) && ($station->stationType->name ?? false) && $station->stationType->name == '缓存架' ){  // 拍灯 推送任务
             if($request['PTLAction'] !== 0) return ['location' => 200,'errMsg' => 'is cacheShelf','data' => $request->all()];
             /** @var CacheShelfService $cacheShelfService */
             $cacheShelfService = app(CacheShelfService::class);

+ 70 - 0
app/Http/Requests/Station/StationRuleBatchRequest.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Http\Requests\Station;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Route;
+
+class StationRuleBatchRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+
+    protected $storeApiRules = [
+        'name' => 'required',
+        'owner_id' => 'required'
+    ];
+    protected $updateApiRules = [
+        'name' => 'required',
+        'owner_id' => 'required'
+    ];
+    protected $storeApiMessage = [
+        'name.required' => '规则名称为必填项',
+        'owner_id.required' => '货主为必填项',
+    ];
+    protected $updateApiMessage = [
+        'name.required' => '规则名称为必填项',
+        'owner_id.required' => '货主为必填项',
+    ];
+
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'station.rule.storeApi':
+                return $this->storeApiRules;
+            case 'station.rule.updateApi':
+                return $this->updateApiRules;
+            default:
+                return [];
+        }
+    }
+
+    public function messages(): array
+    {
+        $routeName = Route::currentRouteName();
+        switch ($routeName) {
+            case 'station.rule.storeApi':
+                return $this->storeApiMessage;
+            case 'station.rule.updateApi':
+                return $this->updateApiMessage;
+            default:
+                return [];
+        }
+    }
+}

+ 2 - 2
app/OracleDOCWaveDetails.php

@@ -13,14 +13,14 @@ class OracleDOCWaveDetails extends Model
     protected $connection='oracle';
     protected $table='DOC_WAVE_DETAILS';
     public $timestamps=false;
-    protected $primaryKey = 'OrdderNo';
+    protected $primaryKey = 'OrderNo';
     function getIncrementing()
     {
         return false;
     }
 
     static public function unpackedOrders($batchNumber){
-        return OracleDOCWaveDetails::where('doc_wave_details.waveno', $batchNumber)->leftJoin('doc_order_header','doc_order_header.orderno','doc_wave_details.orderno')->where(function ($query){
+        return OracleDOCWaveDetails::query()->where('doc_wave_details.waveno', $batchNumber)->leftJoin('doc_order_header','doc_order_header.orderno','doc_wave_details.orderno')->where(function ($query){
             $query->where('doc_order_header.SOSTATUS','<>','99')->where('doc_order_header.SOSTATUS','<>','63');
         })->get();
     }

+ 97 - 40
app/Services/CacheShelfService.php

@@ -7,9 +7,11 @@ use App\Exceptions\ErrorException;
 use App\MaterialBox;
 use App\Station;
 use App\StationTask;
+use App\StationTaskChildren;
 use App\StationTaskMaterialBox;
 use App\StationType;
 use App\Traits\ServiceAppAop;
+use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
@@ -50,7 +52,7 @@ class   CacheShelfService
      */
     public function lightOffTask($locCode, $PTLAction): array
     {
-        $station = Station::query()->where('code', $locCode)->first();
+        $station = Station::query()->with('pendingStationTask.stationTaskMaterialBoxes.materialBox')->where('code', $locCode)->first();
         try {
             $bool = $this->putBinToStore($station);                         // 推送任务
             if($bool){
@@ -81,36 +83,47 @@ class   CacheShelfService
 
         /** @var StationTaskMaterialBox $takeStationTaskMaterialBox */
         $takeStationTaskMaterialBox = $station['pendingStationTask']['stationTaskMaterialBoxes']->first();
-
         $formStation = $this->stationService->getStation_byType('立库');
 
-        // 创建入立库任务
-        $stationTask = $this->stationTaskService->create(1);               // 生成站任务
-        $this->stationTaskService->registerStations($stationTask,[$formStation['id']]);   // 注册站任务站
-        /** @var StationTaskMaterialBox $putStationTaskMaterialBox */
-        $putStationTaskMaterialBox = $this->stationTaskMaterialBoxService->create([
+        // 查询是否有待处理的入库任务
+        $putStationTaskMaterialBox = StationTaskMaterialBox::query()->where([
             'station_id' => $formStation['id'],
             'material_box_id' => $takeStationTaskMaterialBox['material_box_id'],
             'status' => '待处理',
-        ]);
-        $putStationTaskMaterialBox['station_task_id'] = $stationTask->first()['id'];
-        $putStationTaskMaterialBox['type'] = '放';
-        $putStationTaskMaterialBox->update();
+        ])->first();
 
-        $params = [[
-            'station_task_id'=>$stationTask->first()['id'],
-            'station_taskable_type'=>StationTaskMaterialBox::class,
-            'station_taskable_id'=>$putStationTaskMaterialBox['id']
-        ]];
-
-        $this->stationTaskChildService->insert($params);    // 任务任务注册
-        // 标记站任务为处理中
-        $this->stationTaskMaterialBoxService->set($takeStationTaskMaterialBox,[
-            'status' => '处理中'
-        ]);
+        // 创建入立库任务
+        if(!$putStationTaskMaterialBox){
+            $stationTask = $this->stationTaskService->create(1);               // 生成站任务
+            $this->stationTaskService->registerStations($stationTask,[$formStation['id']]);   // 注册站任务站
+            /** @var StationTaskMaterialBox $putStationTaskMaterialBox */
+            $putStationTaskMaterialBox = $this->stationTaskMaterialBoxService->create([
+                'station_id' => $formStation['id'],
+                'material_box_id' => $takeStationTaskMaterialBox['material_box_id'],
+                'status' => '待处理',
+            ]);
+            $putStationTaskMaterialBox['station_task_id'] = $stationTask->first()['id'];
+            $putStationTaskMaterialBox['type'] = '放';
+            $putStationTaskMaterialBox->update();
+
+            $params = [[
+                'station_task_id'=>$stationTask->first()['id'],
+                'station_taskable_type'=>StationTaskMaterialBox::class,
+                'station_taskable_id'=>$putStationTaskMaterialBox['id']
+            ]];
+
+            $this->stationTaskChildService->insert($params);    // 任务任务注册
+        }
 
         // 推立库任务
-        return $this->foreignHaiRoboticsService->putBinToStore_fromCacheShelf($putStationTaskMaterialBox,$station['code']);
+        $isSuccess =  $this->foreignHaiRoboticsService->putBinToStore_fromCacheShelf($putStationTaskMaterialBox,$station['code']);
+        if($isSuccess) $this->stationTaskMaterialBoxService->set($takeStationTaskMaterialBox,['status' => '处理中']);  // 任务推送成功 标记站任务为处理中
+        else {
+            $materialBoxCode = $station['pendingStationTask']['stationTaskMaterialBoxes']->first()->code ?? '';
+            $this->_stationCacheBroadCast($station->code,0,'error');
+            $this->_stationCacheLightOn($station->code,$materialBoxCode,'拍灯重试任务');
+        }
+        return $isSuccess;
     }
 
     /**
@@ -137,12 +150,19 @@ class   CacheShelfService
 
         $materialBox = MaterialBox::query()->firstOrCreate(['code' => $materialBoxCode]);
 
-        if($station['pendingStationTask'] ?? false){
-            return ['success' => false,'message' => '当前已有未完成的站任务'];
+        $station->load('pendingStationTask.stationTaskMaterialBoxes.materialBox');
+        if($station->pendingStationTask){
+            if($station['pendingStationTask']['stationTaskMaterialBoxes']->first()->materialBox->code == $materialBoxCode){
+                $response = $this->_stationCacheLightOn($stationCode,$materialBoxCode,'任务重试');
+                if($response->code) return ['success'=>true,'message' =>  '任务重试'];
+                return ['success'=>true,'message' =>  '任务重试失败'];
+            }
+            return ['success' => false,'message' => '当前已有进行重的任务'];
         }
-        $stationTask = $this->stationTaskService->create(1);                                                    // 生成站任务
+
+        $stationTask = $this->stationTaskService->create(1);                                                       // 生成站任务
         $stationTaskMaterialBox = $this->stationTaskMaterialBoxService->createByStationAndMaterialBox($station,$materialBox);     // 创建料箱任务
-        $this->stationTaskService->registerStations($stationTask,[$station['id']]);                                            // 注册站任务站
+        $this->stationTaskService->registerStations($stationTask,[$station['id']]);                                               // 注册站任务站
         $stationTaskMaterialBox['station_task_id'] = $stationTask->first()['id'];
         $stationTaskMaterialBox->update();
         $params = [[
@@ -153,7 +173,6 @@ class   CacheShelfService
         $this->stationTaskChildService->insert($params);                                                                        // 任务任务注册
 
         $body = $this->_stationCacheLightOn($stationCode,$materialBoxCode);
-
         if($body->code == 200)return ['success'=>true];
         return ['success' => false,'message' => '机器人亮灯异常'];
     }
@@ -161,20 +180,18 @@ class   CacheShelfService
     /**
      * 控制格口亮灯
      * @param $locCode
-     * @param string $title
      * @param null $materialCode
+     * @param string $title
+     * @param string $color
      * @return mixed
      */
-    public function _stationCacheLightOn($locCode,$materialCode = null,$title = 'title')
+    public function _stationCacheLightOn($locCode,$materialCode = null,$title = 'title' ,string $color = '1')
     {
         $params = [
             "areaCode" => "1004",
             'locCode' => $locCode,
             'PTLAction' => 1,
-            'PTLSettings' => [
-                'color'=> 1,
-                'frequency'  =>1
-                ],
+            'PTLSettings' => ['color'=> $color, 'frequency'  =>1],
             "displayInfo" => [
                 "detail01" => $materialCode,
                 "detail02" => "detail02",
@@ -188,8 +205,9 @@ class   CacheShelfService
                 "uomDesc02" => "uo"
             ],
         ];
-        $response = Http::post(config('api.haiq.storage.light'), $params);
-        return json_decode($response->body());
+        return new MaterialBox(['code' => 200]);
+//        $response = Http::post(config('api.haiq.storage.light'), $params);
+//        return json_decode($response->body());
     }
 
     /**
@@ -209,11 +227,12 @@ class   CacheShelfService
     }
 
     /**
-     * 广播 通知货物被取走
+     * 广播 type success成功 error 异常
      * @param $locCode
      * @param $PTLAction
+     * @param string $type
      */
-    public function _stationCacheBroadCast($locCode,$PTLAction)
+    public function _stationCacheBroadCast($locCode, $PTLAction,string $type = 'success')
     {
         if($PTLAction == 0){
             $station = Station::query()->with('parent')->where('code',$locCode)->first();
@@ -223,6 +242,7 @@ class   CacheShelfService
                 'code'  => $station['parent']['code'],
                 'gird_id' => $station['id'],
                 'grid_code' => $station['code'],
+                'type' => $type
             ]);
             broadcast(new BroadcastToStation($station['parent_id'],$json));
         }
@@ -252,7 +272,44 @@ class   CacheShelfService
         // 入立架任务
         if($putStationTaskMaterial->stationTask)$putStationTaskMaterial->stationTask->update(['status' => '完成']);
 
-        $this->_stationCacheLightOff($takeStationTaskMaterialBox->station->code ?? null);
-        $this->_stationCacheBroadCast($takeStationTaskMaterialBox->station->code,0);
+        $this->_stationCacheLightOff($takeStationTaskMaterialBox->station->code ?? null);  //海柔格口灭灯
+        $this->_stationCacheBroadCast($takeStationTaskMaterialBox->station->code, 0);    //通知缓存架任务完成
+    }
+
+    /**
+     * 取消任务
+     * @param $stationCode
+     * @return array
+     */
+    public function clearTask($stationCode): array
+    {
+        $station = Station::query()->with(['currentStationTask.stationTaskMaterialBoxes.materialBox',
+            'pendingStationTask.stationTaskMaterialBoxes.materialBox'])
+            ->where('code',$stationCode)->first();
+
+        if($station->currentStationTask)return ['success' => false,'message' => '当前任务正在执行','data'=>$stationCode];
+        if($station->pendingStationTask->stationTaskMaterialBoxes->count() == 0){
+            $station->pendingStationTask->delete();
+            return ['success' => true];
+        }
+
+        $taskStationTaskMaterialBox = $station->pendingStationTask->stationTaskMaterialBoxes->first() ?? null;
+        $stationTaskMaterialBoxes = StationTaskMaterialBox::query()->with('stationTask')
+            ->where('material_box_id',$taskStationTaskMaterialBox['material_box_id'])
+            ->where('station_id','!=',$station->pendingStationTask['id'])
+            ->get();
+
+        foreach ($stationTaskMaterialBoxes as $stationTaskMaterialBox) {
+            if($stationTaskMaterialBox->stationTask){
+                StationTaskChildren::query()->where([
+                    'station_task_id' => $stationTaskMaterialBox->stationTask['id'],
+                    'station_taskable_type'=>StationTaskMaterialBox::class,
+                    'station_taskable_id'=>$stationTaskMaterialBox['id']])->delete();
+
+                $stationTaskMaterialBox->stationTask->delete();
+            }
+            $stationTaskMaterialBox->delete();
+        }
+        return ['success' => true];
     }
 }

+ 10 - 10
app/Services/OracleDocWaveDetailService.php

@@ -25,9 +25,9 @@ class OracleDocWaveDetailService
             $waveNos = array_values(array_diff(data_get($items, '*.waveno'),['*']));
             try {
                 OracleDOCWaveDetails::query()->whereIn('OrderNo', $clearOrderNos)->whereIn('WaveNo', $waveNos)->delete();
-                app('LogService')->log(__CLASS__, __METHOD__, 'Delete OracleDOCWaveDetails' . '  ' . json_encode($clearOrderNos).json_encode($waveNos));
+                app('LogService')->log(__CLASS__, __FUNCTION__, 'Delete OracleDOCWaveDetails' . '  ' . json_encode($clearOrderNos).json_encode($waveNos));
             } catch (Exception $e) {
-                app('LogService')->log(__CLASS__, __METHOD__,'Error clearCancelledOrder'.json_encode($clearOrderNos).json_encode($waveNos));
+                app('LogService')->log(__CLASS__, __FUNCTION__,'Error clearCancelledOrder'.json_encode($clearOrderNos).json_encode($waveNos));
             }
         });
     }
@@ -99,11 +99,11 @@ class OracleDocWaveDetailService
             return;
 
         $orderHeaders = OracleDOCOrderHeader::query()
-            ->selectRaw('orderno,waveno,editTime')
-            ->where('EDITTIME', '>', Carbon::parse($sync_at))
-            ->where('ERPCANCELFLAG', 'Y')
-            ->orderByDesc('editTime')->get();
-
+            ->selectRaw('orderno,waveno,edittime,erpcancelflag')
+            ->where('EditTime', '>', Carbon::parse($sync_at))
+            ->where('WaveNo','!=','*')
+            ->where('ERPCancelFLAG', 'Y')
+            ->orderByDesc('EditTime')->get();
         $orderHeaderList = $orderHeaders->chunk(50);
         $update_at = Carbon::now();
         if(count($orderHeaders)>0){
@@ -111,19 +111,19 @@ class OracleDocWaveDetailService
                 $this->clearCancelledOrder($items);
                 if ($items->count() > 0) {
                     OracleDOCOrderHeader::query()
-                        ->whereIn('orderNo', data_get($items, '*.orderno'))
+                        ->whereIn('orderno', data_get($items, '*.orderno'))
                         ->whereIn('waveno', data_get($items, '*.waveno'))
                         ->update(['waveno' => '*','editTime' =>$update_at]);
                     $json = json_encode($items->map(function ($orderHeader) {
                         return ['orderno' => $orderHeader->orderno, 'waveno' => $orderHeader->waveno];
                     }));
-                    app('LogService')->log(__CLASS__, __METHOD__, 'update OrderHeader' . '  ' . $json);
+                    app('LogService')->log(__CLASS__, __FUNCTION__, 'update OrderHeader' . '  ' . $json);
                     $this->disposeOrderBatchId(data_get($items, '*.orderno'));
                 }
             }
         }
         $end_time = (string)Carbon::now();
-        $sync_at = $orderHeaders->first()->editTime ?? $sync_at;
+        $sync_at = $orderHeaders->first()->edittime ?? $sync_at;
         $this->setSyncAt($sync_at);
         $this->setSyncStartAt((string)$start_time);
         $this->setSyncEndAt($end_time);

+ 2 - 2
app/Services/PackageStatisticsService.php

@@ -26,8 +26,8 @@ class PackageStatisticsService
                 ->selectRaw('orders.owner_id,logistic_id');
 
         $columnQueryRules=[
-            'created_at_start' => ['alias' => 'created_at','startDate' => ":00"],
-            'created_at_end' => ['alias' => 'created_at','endDate' => ":59"],
+            'created_at_start' => ['alias' => 'weighed_at','startDate' => ":00"],
+            'created_at_end' => ['alias' => 'weighed_at','endDate' => ":59"],
             'logistic_id' => ['multi' => ','],
             'owner_id' => ['multi' => ','],
         ];

+ 5 - 0
app/StationRuleBatch.php

@@ -18,4 +18,9 @@ class StationRuleBatch extends Model
     {
         return $this->belongsTo(StationType::class);
     }
+
+    public function owner() :BelongsTo
+    {
+        return $this->belongsTo(Owner::class);
+    }
 }

+ 38 - 0
database/migrations/2021_05_19_171047_add_station_rule_batch_author.php

@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddStationRuleBatchAuthor extends Migration
+{
+    public $names = [
+        '站管理-站规则',
+        '站管理-站规则-编辑',
+        '站管理-站规则-创建',
+        '站管理-站规则-删除',
+    ];
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        foreach ($this->names as $item) {
+            \App\Authority::query()->firstOrCreate(['name' => $item],['alias_name' => $item]);
+        }
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        foreach ($this->names as $item) {
+            \App\Authority::query()->where('name' , $item)->delete();
+        }
+    }
+}

+ 1 - 0
database/seeds/StationRuleBatchSeeder.php

@@ -12,5 +12,6 @@ class StationRuleBatchSeeder extends Seeder
     public function run()
     {
         //
+        factory(\App\StationRuleBatch::class)->times(3)->create();
     }
 }

+ 4 - 1
resources/views/station/cachingShelf/list/_fillBox.blade.php

@@ -14,6 +14,9 @@
                         <input type="text" id="material-box" class="form-control col" @keydown.enter="pushMaterialBox()" v-model="materialBoxCode">
                     </div>
                 </div>
+                <div class="container" id="alert-box">
+                    <div class="alert-info" >加载中......</div>
+                </div>
                 <hr>
                 <div class="container">
                     <div class="row">
@@ -26,7 +29,7 @@
                 </div>
                 <div class="modal-footer">
                     <button class="btn btn-primary" data-dismiss="modal">关闭</button>
-                    <button class="btn btn-primary" @click="clearCurrentStation">清空</button>
+{{--                    <button class="btn btn-primary" @click="clearCurrentStation">清空</button>--}}
                 </div>
             </div>
         </div>

+ 41 - 15
resources/views/station/cachingShelf/list/index.blade.php

@@ -57,7 +57,8 @@
                             stationCode:stationCode,
                             materialBoxCode:null,
                             row:row,
-                            col:col
+                            col:col,
+                            type:null
                         }
                     }
                 },
@@ -91,19 +92,20 @@
                     $('#box').modal('show');
                 },
                 /** 清空格口号 */
-                clearCurrentStation() {
-                    this.currentStation.data.forEach(function (item, index, items) {
-                        items[index].forEach(function (item, index, self) {
-                            self[index]['code'] = null;
-                        })
-                    });
-                    this.$forceUpdate();
-                },
+                // clearCurrentStation() {
+                //     this.currentStation.data.forEach(function (item, index, items) {
+                //         items[index].forEach(function (item, index, self) {
+                //             self[index]['code'] = null;
+                //         })
+                //     });
+                //     this.$forceUpdate();
+                // },
                 /** 初始化格口 */
                 initCacheGrid() {
                     let url = '{{url('apiLocal/station/cacheShelf/getTasks')}}'+'/'+this.currentStation.id;
                     window.tempTip.setIndex(1099);
                     window.tempTip.setDuration(3000);
+                    $('#alert-box').show();
                     window.axios.get(url).then(res => {
                         if (res.data.data) {
                             for (let index = 0; index < res.data.data.length; index++) {
@@ -115,21 +117,26 @@
                                 let materialBoxCode = res.data.data[index]['pending_station_task']['station_task_material_boxes'][0]['material_box']['code'] ?? null;
                                 this.$set(this.currentStation.grids[stationCode],'materialBoxCode',materialBoxCode);
                             }
+                            $('#alert-box').hide();
                             this.$forceUpdate();
                             return;
                         }
                         window.tempTip.show('获取缓存货架信息失败');
+                        $('#alert-box').hide();
                     }).catch(err => {
                         window.tempTip.show('获取缓存货架信息异常:' + err);
+                        $('#alert-box').hide();
                     });
                 },
                 /** 扫码 1、料箱扫码 */
                 pushMaterialBox(grid = null,$e = null) {
                     // 从格口输入
-                    if(grid) {
+                    if($e) {
                         let materialBoxCode = $($e.target).val();
                         let stationCode = grid['stationCode'];
-                        this.lightOn(stationCode,materialBoxCode);
+
+                        if(materialBoxCode.trim()!=='')this.lightOn(stationCode,materialBoxCode);
+                        else this.clearTask(stationCode);
                         return;
                     }
                     for (const key in this.currentStation.grids) {
@@ -148,7 +155,7 @@
                     window.tempTip.setDuration(2000);
                     window.tempTip.setIndex(1999);
 
-                    if(this.checkMaterialBoxCodeExist(materialBoxCode)){
+                    if(this.checkMaterialBoxCodeExist(materialBoxCode,stationCode)){
                         window.tempTip.show('料箱已被占用');
                         return ;
                     }
@@ -166,10 +173,28 @@
                         window.tempTip.show(err);
                     });
                 },
+                clearTask(stationCode){
+                    let url = '{{url('apiLocal/station/cacheShelf/clearTask')}}';
+                    let data = {station:stationCode};
+                    window.tempTip.setDuration(2000);
+                    window.tempTip.setIndex(1999);
+                    window.axios.post(url,data).then(res=>{
+                        if(res.data.success){
+                            window.tempTip.showSuccess(res.data.message ? res.data.message : '取消任务成功');
+                            this.$set(this.currentStation.grids[stationCode],'materialBoxCode',null);
+                            this.$forceUpdate();
+                            $('#material-box').focus();
+                            return ;
+                        }
+                        window.tempTip.show('取消任务异常:'+res.data.message);
+                    }).catch(err=>{
+                        window.tempTip.show(err);
+                    });
+                },
                 /** 校验是否存在 */
-                checkMaterialBoxCodeExist(materialBoxCode) {
+                checkMaterialBoxCodeExist(materialBoxCode,stationCode) {
                     for (const key in this.currentStation.grids) {
-                        if(this.currentStation.grids[key]['materialBoxCode'] === materialBoxCode)return true;
+                        if(this.currentStation.grids[key]['materialBoxCode'] === materialBoxCode && key !== stationCode )return true;
                     }
                     return false;
                 },
@@ -181,7 +206,8 @@
                         if (!json || json.length === 0) return;
                         if(json['code'] !== this.currentStation.code)return ;
                         if(json['grid_code']){
-                            this.$set(this.currentStation.grids[json['grid_code']],'materialBoxCode',null);
+                            if(json['type'] === 'success') this.$set(this.currentStation.grids[json['grid_code']],'materialBoxCode',null);
+                            if(json['type'] === 'error') this.$set(this.currentStation.grids[json['grid_code']],'type','error');
                             this.$forceUpdate();
                         }
                     });

+ 5 - 0
resources/views/station/menu.blade.php

@@ -10,6 +10,11 @@
                 <li class="nav-item">
                     <a target="station/cachingShelf/index" class="nav-link" href="{{url('station/cachingShelf/index')}}" :class="{active:isActive('cachingShelf',2)}">缓存架</a>
                 </li> @endcan
+            @can('站管理-站规则')
+                <li class="nav-item">
+                    <a target="station/rule/index" class="nav-link" href="{{url('station/rule/index')}}" :class="{active:isActive('rule','2')}">站规则</a>
+                </li>
+            @endcan
         </ul>
     </div>
 </div>

+ 51 - 0
resources/views/station/rule/_edit.blade.php

@@ -0,0 +1,51 @@
+<div class="modal face" id="box">
+    <div class="modal-dialog modal-lg boxClass" >
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="modal-title">
+                    <span v-show="tag==='update'">修改规则</span>
+                    <span v-show="tag==='create'">创建规则</span>
+                </div>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <div class="form-group row">
+                        <label for="owner-id" class="col-sm-3 col-form-label text-right">货主</label>
+                        <div class="col-sm-9 form-inline">
+                            <select id="owner-id" class="form-control col-sm-6"
+                                    :class="errors.owner_id?'is-invalid':''"
+                                    v-model="stationRuleBatch.owner_id" @input="setStationRuleBatchName($event)"
+                                    @change="errors.owner_id = null">
+                                <option value=""></option>
+                                <option :value="owner.id" v-for="owner in ownerFilters">@{{ owner.name }}</option>
+                            </select>
+                            <input type="text" name="material-code" id="owner-id" class="form-control col-sm-3" placeholder="货主" @input="filterOwner($event)" v-model="filterName">
+                            <div class="invalid-feedback" v-if="errors.owner_id">
+                                @{{ errors.owner_id ? errors.owner_id[0] : ''  }}
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="rule-name" class="col-sm-3 col-form-label text-right">名称</label>
+                        <div class="col-sm-9 form-inline">
+                            <input type="text" name="phone" id="rule-name" class="form-control col-9"
+                                   :class="errors.name &&  !stationRuleBatch.name ?'is-invalid':''"
+                                   v-model="stationRuleBatch.name" @change="errors.name = null">
+                            <div class="invalid-feedback" v-if="errors.name">
+                                @{{ errors.name ? errors.name[0] : ''  }}
+                            </div>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button class="btn btn-primary" @click="_edit" v-show="tag==='update'">修改</button>
+                <button class="btn btn-primary" @click="_create" v-show="tag==='create'">创建</button>
+            </div>
+        </div>
+    </div>
+</div>
+

+ 47 - 0
resources/views/station/rule/_table.blade.php

@@ -0,0 +1,47 @@
+<table class="table table-striped table-md table-hover" id="table">
+    <thead>
+    <tr>
+        <th>
+            序号
+        </th>
+        <th>
+            货主
+        </th>
+        <th>
+            规则名称
+        </th>
+        <th>
+            设备类型
+        </th>
+        <th>
+            波次类型
+        </th>
+        <th>
+            操作
+        </th>
+    </tr>
+    <template v-if="stationRuleBatches.length > 0">
+        <tr v-for="(stationRuleBatch,i) in stationRuleBatches" @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
+            <td>
+                @{{ i+1 }}
+            </td>
+            <td>
+                @{{ stationRuleBatch.owner ? stationRuleBatch.owner.name : '' }}
+            </td>
+            <td>
+                @{{ stationRuleBatch.name }}
+            </td>
+            <td>
+                @{{ stationRuleBatch.station_type ? stationRuleBatch.station_type.name  : ''}}
+            </td>
+            <td>
+                @{{ stationRuleBatch.batch_type ? stationRuleBatch.batch_type :'无'}}
+            </td>
+            <td>
+                @can('站管理-站规则-编辑')<button class="btn btn-sm btn-outline-primary" @click="editStationRuleBatch(stationRuleBatch,i)">编辑</button>@endcan
+                @can('站管理-站规则-删除')<button class="btn btn-sm btn-outline-danger" @click="deleteStationRuleBatch(stationRuleBatch,i)">删除</button>@endcan
+            </td>
+        </tr>
+    </template>
+    </thead>
+</table>

+ 140 - 0
resources/views/station/rule/index.blade.php

@@ -0,0 +1,140 @@
+@extends('layouts.app')
+
+@section('title','站规则')
+
+@section('content')
+    <span id="nav2">
+        @component('station.menu')@endcomponent
+        @component('station.rule.menu')@endcomponent
+    </span>
+    <div class="container-fluid d-none" id="list">
+        @can('站管理-站规则-创建')
+            <button class="btn btn-md btn-outline-primary ml-1" @click="createStationRuleBatch">创建</button>
+        @endcan
+        @include('station.rule._table')
+        @include('station.rule._edit')
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        let vue = new Vue({
+            el: '#list',
+            data: {
+                selectTr: null,
+                stationRuleBatches: {!! $stationRuleBatches->toJson() !!}['data'],
+                owners:{!! $owners !!},
+                ownerFilters: [],
+                filterName: null,
+                tag: null,
+                tagIndex: null,
+                stationRuleBatch: {},
+                errors: {}
+            },
+            mounted() {
+                $('#list').removeClass('d-none');
+                this.filterOwner();
+            },
+            methods: {
+                createStationRuleBatch() {
+                    this.tag = 'create';
+                    this.filterOwner();
+                    this.stationRuleBatch = {};
+                    this.errors = {};
+                    $('#box').modal('show');
+                },
+                editStationRuleBatch(item, index) {
+                    this.stationRuleBatch = JSON.parse(JSON.stringify(item));
+                    this.tag = 'update';
+                    this.tagIndex = index;
+                    this.filterOwner();
+                    this.errors = {};
+                    $('#box').modal('show');
+                },
+                deleteStationRuleBatch(item, index) {
+                    if (!confirm("确定要删除对应的栈规则")) {
+                        return;
+                    }
+                    let url = '{{url('apiLocal/station/rule/destroy')}}' + '/?id=' + item['id'];
+                    window.axios.delete(url).then(res => {
+                        if (res.data.success) {
+                            window.tempTip.showSuccess('删除成功');
+                            this.$delete(this.stationRuleBatches, index);
+                            return;
+                        }
+                        window.tempTip.show('删除异常,刷新页面重试');
+                    }).catch(err => {
+                        window.tempTip.show('网络异常,' + err);
+                    });
+                },
+                _create() {
+                    let url = '{{url('apiLocal/station/rule/store')}}';
+                    console.log(this.stationRuleBatch);
+                    window.axios.post(url, this.stationRuleBatch).then(res => {
+                        if (res.data.success) {
+                            this.stationRuleBatches.unshift(res.data.data);
+                            window.tempTip.showSuccess('创建成功');
+                            $('#box').modal('hide');
+                            this.$forceUpdate();
+                            this.tag = null;
+                            this.tagIndex = null;
+                            this.stationRuleBatch = {};
+                            return;
+                        }else if(res.data.errors){
+                            this.errors = res.data.errors;
+                            this.$forceUpdate();
+                            return;
+                        }
+                        window.tempTip.show('创建异常');
+                    }).catch(err => {
+                        window.tempTip.show('网络异常,' + err);
+                    });
+                },
+                _edit() {
+                    let url = '{{url('apiLocal/station/rule/update')}}';
+                    window.axios.put(url, this.stationRuleBatch).then(res => {
+                        if (res.data.success) {
+                            this.$set(this.stationRuleBatches, this.tagIndex, res.data.data);
+                            window.tempTip.showSuccess('修改成功!');
+                            $('#box').modal('hide');
+                            this.tag = null;
+                            this.tagIndex = null;
+                            this.stationRuleBatch = {};
+                            this.$forceUpdate();
+                            return;
+                        }else if(res.data.errors){
+                            this.errors =res.data.errors;
+                            this.$forceUpdate();
+                            return;
+                        }
+                        window.tempTip.show('编辑异常,刷新页面重试');
+                    }).catch(err => {
+                        window.tempTip.show('网络异常,' + err);
+                    });
+                },
+                setStationRuleBatchName($e){
+                    let selectValue = $($e.target).find('option:selected').text();
+                    if(selectValue && !this.stationRuleBatch.name )
+                        this.$set(this.stationRuleBatch,'name',selectValue)
+                },
+                filterOwner($e = null) {
+                    let copyOwner = JSON.parse(JSON.stringify(this.owners));
+                    this.ownerFilters = copyOwner;
+                    if ($e !== null) {
+                        let value = $($e.target).val();
+                        this.ownerFilters = copyOwner.filter(function (owner) {
+                            return owner.name.indexOf(value) !== -1;
+                        });
+                        if (this.ownerFilters.length !== this.owners.length && this.ownerFilters.length > 0) {
+                            this.$set(this.stationRuleBatch,'owner_id',this.ownerFilters[0]['id']);
+                            this.$set(this.stationRuleBatch,'name',this.ownerFilters[0]['name']);
+                        } else {
+                            this.$set(this.stationRuleBatch,'owner_id',null);
+                        }
+                    }
+                    this.$forceUpdate();
+                }
+            }
+        })
+    </script>
+@endsection

+ 9 - 0
resources/views/station/rule/menu.blade.php

@@ -0,0 +1,9 @@
+<div class="container-fluid nav3">
+    <div class="card">
+        <ul class="nav nav-pills">
+            <li class="nav-item">
+                <a target="station/rule/index" class="nav-link" href="{{url('station/rule/index')}}" :class="{active:isActive('rule','2')}">查询</a>
+            </li>
+        </ul>
+    </div>
+</div>

+ 10 - 1
routes/apiLocal.php

@@ -183,13 +183,22 @@ Route::group(['prefix'=>'demand'],function(){
 
 Route::get('/authority/get','AuthorityController@getAuthoritiesApi')->name('authority.getAuthoritiesApi');
 
-/** 缓存架 */
+/** 栈管理 */
 Route::group(['prefix' => 'station'],function(){
+    /** 缓存架 */
     Route::group(['prefix'=>'cacheShelf'],function(){
         Route::post('pushTask','CacheShelfController@pushTaskApi')->name('station.cacheShelf.pushTaskApi');
+        Route::post('clearTask','CacheShelfController@clearTaskApi')->name('station.cacheShelf.clearTaskApi');
         Route::post('lightOn','CacheShelfController@lightOnApi')->name('station.cacheShelf.lightOnApi');
         Route::get('getTasks/{id}','CacheShelfController@getTasksApi')->name('station.cacheShelf.getTasksApi');
     });
+
+    /** 栈规则 */
+    Route::group(['prefix'=>'rule'],function(){
+        Route::post('store','StationRuleBatchController@storeApi')->name('station.rule.storeApi');
+        Route::put('update','StationRuleBatchController@updateApi')->name('station.rule.updateApi');
+        Route::delete('destroy','StationRuleBatchController@destroyApi')->name('station.rule.destroyApi');
+    });
 });
 
 

+ 6 - 0
routes/web.php

@@ -800,14 +800,20 @@ Route::group(['prefix'=>'customer'],function(){
 /** 站管理 */
 Route::group(['prefix'=>'station'],function(){
     Route::get('index','StationController@monitorIndex');
+    /** 监视器 */
     Route::group(['prefix'=>'monitor'],function(){
         Route::get('/','StationController@monitorIndex');
         Route::get('/index','StationController@monitorIndex');
         Route::get('/{station}','StationController@monitorShow');
     });
+    /** 缓存架 */
     Route::group(['prefix'=>'cachingShelf'],function(){
         Route::get('/index','CacheShelfController@index');
     });
+    /** 栈规则 */
+    Route::group(['prefix'=>'rule'],function(){
+        Route::get('/index','StationRuleBatchController@index');
+    });
 });
 /** 控制台 */
 Route::group(['prefix'=>'control'],function () {

+ 114 - 0
tests/Services/CacheShelfService/ClearTaskTest.php

@@ -0,0 +1,114 @@
+<?php
+
+
+namespace Tests\Services\CacheShelfService;
+
+
+use App\Material;
+use App\MaterialBox;
+use App\Services\CacheShelfService;
+use App\Services\StationTaskChildService;
+use App\Services\StationTaskMaterialBoxService;
+use App\Services\StationTaskService;
+use App\Station;
+use App\StationTask;
+use App\StationTaskChildren;
+use App\StationTaskMaterialBox;
+use App\StationType;
+use Tests\TestCase;
+
+class ClearTaskTest extends TestCase
+{
+
+    /** @var CacheShelfService $service */
+    /** @var StationTaskService $stationTaskService  */
+    /** @var StationTaskMaterialBoxService $stationTaskMaterialBoxService  */
+    /** @var StationTaskChildService $stationTaskChildService  */
+    public $service;
+    public $stationTaskService;
+    public $stationTaskMaterialBoxService;
+    public $stationTaskChildService;
+    public $data =[];
+
+    protected function setUp(): void
+    {
+        parent::setUp(); // TODO: Change the autogenerated stub
+        $this->service = app(CacheShelfService::class);
+        $this->stationTaskService = app(StationTaskService::class);
+        $this->stationTaskMaterialBoxService = app(StationTaskMaterialBoxService::class);
+        $this->stationTaskChildService = app(StationTaskChildService::class);
+
+        $stationType = StationType::query()->firstOrCreate(['name'=>'立库']);
+
+        $this->data['LiKuStation'] = factory(Station::class)->create(['station_type_id'=>$stationType['id']]);
+        $this->data['station'] = factory(Station::class)->create();
+
+        $this->data['stationTask'] = [];
+        $this->data['stationTaskMaterialBoxes'] = [];
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+
+        $this->data['stationTask'] = $this->stationTaskService->create(1);                                                    // 生成站任务
+        $this->data['stationTaskMaterialBoxes'][] = $this->stationTaskMaterialBoxService->createByStationAndMaterialBox($this->data['station'],$this->data['materialBox']);     // 创建料箱任务
+        $this->stationTaskService->registerStations($this->data['stationTask'],[$this->data['station']['id']]);                                            // 注册站任务站
+        $this->data['stationTaskMaterialBoxes'][0]['station_task_id'] = $this->data['stationTask'][0]['id'];
+        $this->data['stationTaskMaterialBoxes'][0]->update();
+        $params = [[
+            'station_task_id'=>$this->data['stationTask'][0]->first()['id'],
+            'station_taskable_type'=>StationTaskMaterialBox::class,
+            'station_taskable_id'=>$this->data['stationTaskMaterialBoxes'][0]['id']
+        ]];
+
+        $this->stationTaskChildService->insert($params);                                                                        // 任务任务注册
+    }
+
+    public function testClearTask()
+    {
+        $result = $this->service->clearTask($this->data['station']->code);
+        $stationTask = StationTask::query()->where('station_id',$this->data['station']['id'])->first();
+        $this->assertEmpty($stationTask);
+        $stationTaskMaterialBox = StationTaskMaterialBox::query()->where('material_box_id',$this->data['materialBox']['id'])->get();
+        $this->assertEmpty($stationTaskMaterialBox);
+    }
+
+    public function testClearTask_taskIsRunning()
+    {
+        StationTask::query()->where('station_id',$this->data['station']['id'])->update(['status' => '处理中']);
+        $result = $this->service->clearTask($this->data['station']->code);
+
+        $stationTask = StationTask::query()->where('station_id',$this->data['station']['id'])->first();
+
+        $this->assertEquals('处理中',$stationTask->status);
+        $this->assertFalse($result['success']);
+    }
+
+
+    protected function tearDown(): void
+    {
+        if($this->data['station']){
+            $stationTasks = StationTask::query()->where('station_id',$this->data['station']['id'])->get();
+            foreach ($stationTasks as $stationTask) {
+                $stationTaskMaterialBoxes = $stationTask->stationTaskMaterialBoxes;
+                foreach ($stationTaskMaterialBoxes as $stationTaskMaterialBox) {
+                    StationTaskChildren::query()->where(['station_task_id' => $stationTask['id'],'station_taskable_type'=> StationTaskMaterialBox::class,'station_taskable_id'=>$stationTaskMaterialBox['id']])->delete();
+                    $stationTaskMaterialBox->delete();
+                }
+            }
+            Station::query()->where('id',$this->data['station']['id'])->delete();
+        }
+
+        if($this->data['LiKuStation']){
+            $stationTasks = StationTask::query()->where('station_id',$this->data['LiKuStation']['id'])->get();
+            foreach ($stationTasks as $stationTask) {
+                $stationTaskMaterialBoxes = $stationTask->stationTaskMaterialBoxes;
+                foreach ($stationTaskMaterialBoxes as $stationTaskMaterialBox) {
+                    StationTaskChildren::query()->where(['station_task_id' => $stationTask['id'],'station_taskable_type'=> StationTaskMaterialBox::class,'station_taskable_id'=>$stationTaskMaterialBox['id']])->delete();
+                    $stationTaskMaterialBox->delete();
+                }
+            }
+            Station::query()->where('id',$this->data['LiKuStation']['id'])->delete();
+        }
+        if($this->data['materialBox'])MaterialBox::query()->where('id',$this->data['materialBox'])->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+
+}