Kits checkout. But only with models.

This commit is contained in:
Minaev Dmitriy 2018-11-13 20:33:32 +03:00
parent 79d979f47f
commit 0bbe499414
9 changed files with 346 additions and 38 deletions

View file

@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers\Kits;
use App\Models\PredefinedKit;
use App\Models\AssetModel;
use App\Models\PredefinedModel;
use App\Models\License;
use App\Models\PredefinedLicence;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Accessory;
use App\Models\SnipeItPivot;
use Illuminate\Http\Request;
use App\Http\Controllers\CheckInOutRequest;
use App\Services\PredefinedKitService;
use App\Models\User;
/**
* This controller handles all access kits management:
* list, add/remove/change
*
* @version v2.0
*/
class CheckoutKitController extends Controller
{
public $kitService;
use CheckInOutRequest;
public function __construct(PredefinedKitService $kitService)
{
$this->kitService = $kitService;
}
/**
* Show Bulk Checkout Page
* @return View View to checkout multiple assets
*/
public function showCheckout($kit_id)
{
// METODO: добавить больше проверок, тут ещё и модель и прочее что мне надо бу
$this->authorize('checkout', Asset::class);
$kit = PredefinedKit::findOrFail($kit_id);
return view('kits/checkout')->with('kit', $kit);
}
/**
* Validate and process the new Predefined Kit data.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
public function store(Request $request, $kit_id)
{
$user_id = e($request->get('user_id'));
if ( is_null($user = User::find( $user_id )) ) {
return redirect()->back()->with('error', trans('admin/users/message.user_not_found'));
}
$kit = new PredefinedKit();
$kit->id = $kit_id;
$errors = $this->kitService->checkout($request, $kit, $user);
if( count($errors) > 0 ) {
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'))->with('error_messages', $errors);
}
return redirect()->back()->with('success', trans('admin/hardware/message.checkout.success'));
}
}

View file

@ -39,8 +39,7 @@ class PredefinedKitsController extends Controller
*/
public function create()
{
//$this->authorize('create', PredefinedKit::class);
$this->authorize('create', PredefinedKit::class);
return view('kits/create')->with('item', new PredefinedKit);
}
@ -53,17 +52,15 @@ class PredefinedKitsController extends Controller
*/
public function store(ImageUploadRequest $request)
{
//$this->authorize('create', AssetModel::class);
$this->authorize('create', PredefinedKit::class);
// Create a new Predefined Kit
$kit = new PredefinedKit;
// Save the model data
$kit->name = $request->input('name');
if(!$kit->save()) {
return redirect()->back()->withInput()->withErrors($kit->getErrors());
}
// METODO: удалить
$model_ids = $request->input('models');
if (!is_array($model_ids)) {
$model_ids = [];
@ -226,52 +223,25 @@ class PredefinedKitsController extends Controller
* @return View
*/
public function updateModel(Request $request, $kit_id, $model_id) {
// $r = $request->all();
// $r['__model_id'] = $model_id;
// $r['__kit_id'] = $kit_id;
// dd($r);
$this->authorize('update', PredefinedKit::class);
if (is_null($kit = PredefinedKit::find($kit_id))) {
// Redirect to the kits management page
return redirect()->route('kits.index')->with('error','Kit does not exist'); // TODO: trans
}
//return view('kits/create-model')->with('item', $kit);
// $quantity = $request->input('quantity', 1);
// if( $quantity < 1) {
// $quantity = 1;
// }
// $validator = \Validator::make($request->all(), $kit->modelRules);
$validator = \Validator::make($request->all(), $kit->makeModelRules($model_id));
// $pivot_id = $request->input('pivot_id');
// $kit->models()->wherePivot('id', '!=', $pivot_id)
// ->wherePivot('id', '!=', $pivot_id)
// ->first()->pivot;
// $validator->after(function ($validator) use($kit) {
// // if ($this->somethingElseIsInvalid()) {
// // $validator->errors()->add('field', 'Something is wrong with this field!');
// // }
// });
if ($validator->fails()) {
return redirect()->back()->withInput()->withErrors($validator);
}
// $kit->models()->sync([$request->input('model_id') => ['quantity' => $request->input('quantity')]]);
// $kit->models()->updateExistingPivot($request->input('pivot_id'), ['model_id' => $request->input('model_id'), 'quantity' => $request->input('quantity')]);
// $s = [$request->input('pivot_id') => ['model_id' => $request->input('model_id'), 'quantity' => $request->input('quantity')]];
//dd($s);
// $changes = $kit->models()->syncWithoutDetaching([$request->input('pivot_id') => ['model_id' => $request->input('model_id'), 'quantity' => $request->input('quantity')]]);
// $changes = $kit->models()->syncWithoutDetaching(['1' => ['model_id' => '2', 'quantity' => '35']]);
$pivot = $kit->models()->wherePivot('id', $request->input('pivot_id'))->first()->pivot;
// $pivot = $kit->models()->newPivotStatement()->find('1');
// $ret = $kit->models()->newPivotStatement()->find('1');
$pivot->model_id = $request->input('model_id');
$pivot->quantity = $request->input('quantity');
$pivot->save();
// return $this->edit($kit_id)->with('success', 'Model updated successfully.');
return redirect()->route('kits.edit', $kit_id)->with('success', 'Model updated successfully.'); // TODO: trans
}

View file

@ -30,10 +30,11 @@ class PredefinedKitsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', PredefinedKit::class),
'delete' => Gate::allows('delete', PredefinedKit::class),
'checkout' => Gate::allows('checkout', PredefinedKit::class) ? true : false,
// 'clone' => Gate::allows('create', PredefinedKit::class),
// 'restore' => Gate::allows('create', PredefinedKit::class),
];
$array['user_can_checkout'] = true;
$array += $permissions_array;
return $array;
}

View file

@ -34,6 +34,16 @@ class PredefinedKitPresenter extends Presenter
]
];
$layout[] = [
"field" => "checkincheckout",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('general.checkin').'/'.trans('general.checkout'),
"visible" => true,
"formatter" => "kitsInOutFormatter",
];
$layout[] = [
"field" => "actions",
"searchable" => false,

View file

@ -0,0 +1,99 @@
<?php
namespace App\Services;
use App\Models\PredefinedKit;
use App\Models\User;
use App\Http\Controllers\CheckInOutRequest;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class PredefinedKitService
{
use AuthorizesRequests;
/**
* @return array [string_error1, string_error2...]
*/
public function checkout(Request $request, PredefinedKit $kit, User $user) {
try {
$models = $kit->models()
->with( ['assets' => function($hasMany) { $hasMany->RTD(); }] )
->get();
//$licenses = $kit->licenses()->with(['assets' => function($hasMany) { $hasMany->RTD(); }])->get();
// Check if the user exists
if (is_null($user) ) {
return [trans('admin/users/message.user_not_found')];
}
$assets_to_add = [];
$errors = [];
foreach($models as $model) {
$assets = $model->assets;
$quantity = $model->pivot->quantity;
foreach($assets as $asset) {
if ($asset->availableForCheckout()
&& !$asset->is($user)) {
$this->authorize('checkout', $asset);
$quantity -= 1;
$assets_to_add []= $asset;
if($quantity <= 0) {
break;
}
}
}
if($quantity > 0) {
$errors []= "Don't have available assets for model " . $model->name . '. Need ' . $model->pivot->quantity . ' assets.'; // TODO: trans
}
}
if( count($errors) > 0 ) {
return $errors;
}
$checkout_at = date("Y-m-d H:i:s");
if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = $request->get('checkout_at');
}
$expected_checkin = '';
if ($request->filled('expected_checkin')) {
$expected_checkin = $request->get('expected_checkin');
}
$admin = Auth::user();
$note = e($request->get('note'));
$errors = DB::transaction(function () use ($user, $admin, $checkout_at, $expected_checkin, $errors, $assets_to_add, $note) {
foreach ($assets_to_add as $asset) {
$asset->location_id = $user->location_id;
$error = $asset->checkOut($user, $admin, $checkout_at, $expected_checkin, $note, null);
if ($error) {
array_merge_recursive($errors, $asset->getErrors()->toArray());
}
}
return $errors;
});
return $errors;
} catch (ModelNotFoundException $e) {
return [$e->getMessage()];
} catch (CheckoutNotAllowed $e) {
return [$e->getMessage()];
}
}
}

View file

@ -0,0 +1,97 @@
@extends('layouts/default')
{{-- Page title --}}
@section('title')
Apply predefined kit{{-- TODO: trans --}}
@parent
@stop
{{-- Page content --}}
@section('content')
<style>
.input-group {
padding-left: 0px !important;
}
</style>
<div class="row">
<!-- left column -->
<div class="col-md-7">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title"> Apply predefined kit {{ $kit->name }} to user {{-- TODO: trans --}} </h3>
</div>
<div class="box-body">
<form class="form-horizontal" method="post" action="" autocomplete="off">
{{ csrf_field() }}
@include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'user_id', 'required'=> 'true'])
<!-- Checkout/Checkin Date -->
<div class="form-group {{ $errors->has('checkout_at') ? 'error' : '' }}">
{{ Form::label('name', trans('admin/hardware/form.checkout_date'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-8">
<div class="input-group date col-md-5" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-date-end-date="0d">
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="checkout_at" id="checkout_at" value="{{ Input::old('checkout_at') }}">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
{!! $errors->first('checkout_at', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Expected Checkin Date -->
<div class="form-group {{ $errors->has('expected_checkin') ? 'error' : '' }}">
{{ Form::label('name', trans('admin/hardware/form.expected_checkin'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-8">
<div class="input-group date col-md-5" data-provide="datepicker" data-date-format="yyyy-mm-dd" data-date-start-date="0d">
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="expected_checkin" id="expected_checkin" value="{{ Input::old('expected_checkin') }}">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
{!! $errors->first('expected_checkin', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Note -->
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
{{ Form::label('note', trans('admin/hardware/form.notes'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-8">
<textarea class="col-md-6 form-control" id="note" name="note">{{ Input::old('note') }}</textarea>
{!! $errors->first('note', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
</div> <!--./box-body-->
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}"> {{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i> {{ trans('general.checkout') }}</button>
</div>
</div>
</form>
</div> <!--/.col-md-7-->
<!-- right column -->
<div class="col-md-5" id="current_assets_box" style="display:none;">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('admin/users/general.current_assets') }}</h3>
</div>
<div class="box-body">
<div id="current_assets_content">
</div>
</div>
</div>
</div>
</div>
@stop
@section('moar_scripts')
@include('partials/assets-assigned')
@stop
@section('notifications')
@parent
<!-- included content -->
@stop

View file

@ -45,6 +45,19 @@
</div>
@endif
@if ($messages = Session::get('error_messages'))
@foreach ($messages as $message)
<div class="col-md-12">
<div class="alert alert alert-danger fade in">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<i class="fa fa-exclamation-circle faa-pulse animated"></i>
<strong>Error: </strong>
{{ $message }}
</div>
</div>
@endforeach
@endif
@if ($message = Session::get('warning'))
<div class="col-md-12">
<div class="alert alert-warning fade in">

View file

@ -0,0 +1,27 @@
<div id="kit_id" class="form-group{{ $errors->has($fieldname) ? ' has-error' : '' }}"{!! (isset($style)) ? ' style="'.e($style).'"' : '' !!}>
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ ((isset($required)) && ($required=='true')) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="kits" data-placeholder="Select a kit{{-- TODO: trans --}}" name="{{ $fieldname }}" style="width: 100%" id="kit_id_select">
@if ($kit_id = Input::old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $kit_id }}" selected="selected">
{{ (\App\Models\User::find($kit_id)) ? \App\Models\User::find($kit_id)->present()->fullName : '' }}
</option>
@else
<option value="">Select a kit{{-- TODO: trans --}}</option>
@endif
</select>
</div>
<div class="col-md-1 col-sm-1 text-left">
@can('create', \App\Models\PredefinedKit::class)
@if ((!isset($hide_new)) || ($hide_new!='true'))
{{-- <a href='{{ route('modal.kit') }}' data-toggle="modal" data-target="#createModal" data-select='kit_id_select' class="btn btn-sm btn-default">New</a> --}}
@endif
@endcan
</div>
{!! $errors->first($fieldname, '<div class="col-md-8 col-md-offset-3"><span class="alert-msg"><i class="fa fa-times"></i> :message</span></div>') !!}
</div>

View file

@ -76,4 +76,17 @@ Route::group([ 'prefix' => 'kits/{kit_id}', 'middleware' => ['auth'] ], function
]
);
Route::get('checkout',
[
'as' => 'kits.checkout.show',
'uses' => 'Kits\CheckoutKitController@showCheckout',
]
);
Route::post('checkout',
[
'as' => 'kits.checkout.store',
'uses' => 'Kits\CheckoutKitController@store',
]
);
}); // kits