diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index b88bac9df..4ccd4c760 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -282,7 +282,8 @@ class AssetsController extends Controller 'assets.name', 'assets.asset_tag', 'assets.model_id', - ]))->with('model')->RTD(); + 'assets.status_id' + ])->with('model', 'assetstatus')->NotArchived()); if ($request->has('search')) { @@ -300,6 +301,10 @@ class AssetsController extends Controller // they may not have a ->name value but we want to display something anyway foreach ($assets as $asset) { $asset->use_text = $asset->present()->fullName; + if ($asset->assetstatus->getStatuslabelType()=='pending') { + $asset->use_text = $asset->present()->fullName.' ('.$asset->assetstatus->getStatuslabelType().')'; + } + $asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null; } diff --git a/app/Http/Controllers/Api/LicensesController.php b/app/Http/Controllers/Api/LicensesController.php index ff58362f6..83915905b 100644 --- a/app/Http/Controllers/Api/LicensesController.php +++ b/app/Http/Controllers/Api/LicensesController.php @@ -21,7 +21,7 @@ class LicensesController extends Controller public function index(Request $request) { $this->authorize('view', License::class); - $licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer', 'supplier')); + $licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier')->withCount('freeSeats')); if ($request->has('search')) { $licenses = $licenses->TextSearch($request->input('search')); @@ -77,17 +77,17 @@ class LicensesController extends Controller switch ($request->input('sort')) { - case 'manufacturer': - $licenses = $licenses->OrderManufacturer($order); + case 'manufacturer': + $licenses = $licenses->leftJoin('manufacturers', 'licenses.manufacturer_id', '=', 'manufacturers.id')->orderBy('manufacturers.name', $order); break; case 'supplier': - $licenses = $licenses->OrderSupplier($order); + $licenses = $licenses->leftJoin('suppliers', 'licenses.supplier_id', '=', 'suppliers.id')->orderBy('suppliers.name', $order); break; case 'company': - $licenses = $licenses->OrderCompany($order); + $licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order); break; default: - $allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email']; + $allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email','free_seats_count','seats']; $sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at'; $licenses = $licenses->orderBy($sort, $order); break; @@ -95,6 +95,7 @@ class LicensesController extends Controller $total = $licenses->count(); + $licenses = $licenses->skip($offset)->take($limit)->get(); return (new LicensesTransformer)->transformLicenses($licenses, $total); diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index d0478a159..541707577 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -225,6 +225,10 @@ class UsersController extends Controller $user = User::findOrFail($id); $user->fill($request->all()); + if ($user->id == $request->input('manager_id')) { + return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager')); + } + if ($request->has('password')) { $user->password = bcrypt($request->input('password')); } diff --git a/app/Http/Controllers/LicensesController.php b/app/Http/Controllers/LicensesController.php index 3d4366adb..94aa4add5 100755 --- a/app/Http/Controllers/LicensesController.php +++ b/app/Http/Controllers/LicensesController.php @@ -239,16 +239,19 @@ class LicensesController extends Controller * @param int $seatId * @return \Illuminate\Contracts\View\View */ - public function getCheckout($seatId) + public function getCheckout($licenceId) { - // Check if the license seat exists - if (is_null($licenseSeat = LicenseSeat::find($seatId))) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + // Check that the license is valid + if ($license = License::where('id',$licenceId)->first()) { + + // If the license is valid, check that there is an available seat + if ($license->getAvailSeatsCountAttribute() < 1) { + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } } - $this->authorize('checkout', $licenseSeat); - return view('licenses/checkout', compact('licenseSeat')); + $this->authorize('checkout', $license); + return view('licenses/checkout', compact('license')); } @@ -262,78 +265,95 @@ class LicensesController extends Controller * @param int $seatId * @return \Illuminate\Http\RedirectResponse */ - public function postCheckout(Request $request, $seatId) + public function postCheckout(Request $request, $licenseId) { - $licenseSeat = LicenseSeat::find($seatId); - $assigned_to = e($request->input('assigned_to')); - $asset_id = e($request->input('asset_id')); - $this->authorize('checkout', $licenseSeat); + // Check that the license is valid + if ($license = License::where('id',$licenseId)->first()) { - // Declare the rules for the form validation - $rules = [ - 'note' => 'string|nullable', - 'asset_id' => 'required_without:assigned_to', - ]; + // If the license is valid, check that there is an available seat + if ($license->getAvailSeatsCountAttribute() < 1) { + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } + $next = $license->freeSeat(); - // Create a new validator instance from our validation rules - $validator = Validator::make(Input::all(), $rules); - // If validation fails, we'll exit the operation now. - if ($validator->fails()) { - // Ooops.. something went wrong - return redirect()->back()->withInput()->withErrors($validator); - } - $target = null; - if ($assigned_to!='') { - // Check if the user exists - if (is_null($target = User::find($assigned_to))) { + $licenseSeat = LicenseSeat::where('license_id',$license->id)->find($next)->first(); + $assigned_to = $request->input('assigned_to'); + $asset_id = $request->input('asset_id'); + + $this->authorize('checkout', $licenseSeat); + + // Declare the rules for the form validation + $rules = [ + 'note' => 'string|nullable', + 'asset_id' => 'required_without:assigned_to', + ]; + + // Create a new validator instance from our validation rules + $validator = Validator::make(Input::all(), $rules); + + // If validation fails, we'll exit the operation now. + if ($validator->fails()) { + // Ooops.. something went wrong + return redirect()->back()->withInput()->withErrors($validator); + } + $target = null; + if ($assigned_to!='') { + // Check if the user exists + if (is_null($target = User::find($assigned_to))) { + // Redirect to the asset management page with error + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist')); + } + } + + if ($asset_id!='') { + if (is_null($target = Asset::find($asset_id))) { + // Redirect to the asset management page with error + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist')); + } + + if (($request->has('assigned_to')) && ($request->has('asset_id'))) { + return redirect()->back()->withInput()->with('error', trans('admin/licenses/message.select_asset_or_person')); + } + } + + // Check if the asset exists + if (is_null($licenseSeat)) { // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist')); - } - } - - if ($asset_id!='') { - if (is_null($target = Asset::find($asset_id))) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist')); + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); } - if (($request->has('assigned_to')) && ($request->has('asset_id'))) { - return redirect()->back()->withInput()->with('error', trans('admin/licenses/message.select_asset_or_person')); + if ($request->input('asset_id') == '') { + $licenseSeat->asset_id = null; + } else { + $licenseSeat->asset_id = $request->input('asset_id'); } - } - // Check if the asset exists - if (is_null($licenseSeat)) { - // Redirect to the asset management page with error - return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); - } - - if ($request->input('asset_id') == '') { - $licenseSeat->asset_id = null; - } else { - $licenseSeat->asset_id = $request->input('asset_id'); - } - - // Update the asset data - if ($request->input('assigned_to') == '') { + // Update the asset data + if ($request->input('assigned_to') == '') { $licenseSeat->assigned_to = null; - } else { + } else { $licenseSeat->assigned_to = $request->input('assigned_to'); + } + + // Was the asset updated? + if ($licenseSeat->save()) { + $licenseSeat->logCheckout($request->input('note'), $target); + + $data['license_id'] = $licenseSeat->license_id; + $data['note'] = $request->input('note'); + + // Redirect to the new asset page + return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success')); + } + } + return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found')); + - // Was the asset updated? - if ($licenseSeat->save()) { - $licenseSeat->logCheckout($request->input('note'), $target); - $data['license_id'] = $licenseSeat->license_id; - $data['note'] = $request->input('note'); - // Redirect to the new asset page - return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success')); - } - return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkout.error')); } diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index e592d3b02..d3ebe3431 100755 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -106,7 +106,6 @@ class UsersController extends Controller $user->password = bcrypt($request->input('password')); $data['password'] = $request->input('password'); } - // Update the user $user->first_name = $request->input('first_name'); $user->last_name = $request->input('last_name'); $user->locale = $request->input('locale'); @@ -278,6 +277,10 @@ class UsersController extends Controller try { $user = User::find($id); + + if ($user->id == $request->input('manager_id')) { + return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.'); + } $this->authorize('update', $user); // Figure out of this user was an admin before this edit $orig_permissions_array = $user->decodePermissions(); diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index f3644dd4d..e96a9ed84 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -32,17 +32,15 @@ class LicensesTransformer 'purchase_cost' => e($license->purchase_cost), 'notes' => e($license->notes), 'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'), - 'total_seats' => (int) $license->seats, - 'next_seat' => ($license->freeSeat()) ? (int) $license->freeSeat()->id : null, - 'remaining_qty' => (int) $license->remaincount(), - 'min_qty' => $license->remaincount(), + 'seats' => (int) $license->seats, + 'free_seats_count' => (int) $license->free_seats_count, 'license_name' => e($license->license_name), 'license_email' => e($license->license_email), 'maintained' => ($license->maintained == 1) ? true : false, 'supplier' => ($license->supplier) ? ['id' => (int) $license->supplier->id,'name'=> e($license->supplier->name)] : null, 'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'), - 'user_can_checkout' => (bool) ($license->remaincount() > 0), + 'user_can_checkout' => (bool) ($license->free_seats_count > 0), ]; $permissions_array['available_actions'] = [ diff --git a/app/Models/License.php b/app/Models/License.php index 7258dae6d..11f1326aa 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -266,7 +266,9 @@ class License extends Depreciable public function availCount() { return $this->licenseSeatsRelation() - ->whereNull('asset_id'); + ->whereNull('asset_id') + ->whereNull('assigned_to') + ->whereNull('deleted_at'); } public function getAvailSeatsCountAttribute() @@ -345,6 +347,15 @@ class License extends Depreciable ->first(); } + /* + * Get the next available free seat - used by + * the API to populate next_seat + */ + public function freeSeats() + { + return $this->hasMany('\App\Models\LicenseSeat')->whereNull('assigned_to')->whereNull('deleted_at')->whereNull('asset_id'); + } + public static function getExpiringLicenses($days = 60) { diff --git a/app/Models/User.php b/app/Models/User.php index 537e07f5a..1a4ad5106 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -61,7 +61,6 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo 'email' => 'email|nullable', 'password' => 'required|min:6', 'locale' => 'max:10|nullable', - 'manager_id' => 'nullable|different:id', ]; diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php index fb0da5ccd..f58bbbe2d 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -76,14 +76,14 @@ class LicensePresenter extends Presenter "title" => trans('general.manufacturer'), "formatter" => "manufacturersLinkObjFormatter", ], [ - "field" => "total_seats", + "field" => "seats", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('admin/accessories/general.total'), ], [ - "field" => "remaining_qty", + "field" => "free_seats_count", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('admin/accessories/general.remaining'), ], [ "field" => "purchase_date", diff --git a/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php b/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php index 2ea83bb1a..d6bf0946e 100644 --- a/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php +++ b/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php @@ -31,7 +31,7 @@ class MigrateDenormedAssetLocations extends Migration $assigned_user_assets = Asset::where('assigned_type',User::class)->whereNotNull('assigned_to')->get(); \Log::debug('User-assigned assets:'); foreach ($assigned_user_assets as $assigned_user_asset) { - if ($assigned_user_asset->assignedTo->userLoc) { + if (($assigned_user_asset->assignedTo) && ($assigned_user_asset->assignedTo->userLoc)) { $new_location=$assigned_user_asset->assignedTo->userloc->id; \Log::info(' They are in '.$assigned_user_asset->assignedTo->userloc->name.' which is id: '.$new_location); } else { diff --git a/resources/views/consumables/checkout.blade.php b/resources/views/consumables/checkout.blade.php index dc6ba5450..2c9ce7e07 100644 --- a/resources/views/consumables/checkout.blade.php +++ b/resources/views/consumables/checkout.blade.php @@ -38,7 +38,7 @@ @endif - @include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'assigned_to']) + @include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'assigned_to', 'required'=> 'true']) @if ($consumable->category->require_acceptance=='1')
diff --git a/resources/views/licenses/checkout.blade.php b/resources/views/licenses/checkout.blade.php index 50bbff7b9..47ce4a7c0 100755 --- a/resources/views/licenses/checkout.blade.php +++ b/resources/views/licenses/checkout.blade.php @@ -21,7 +21,7 @@
-

{{ $licenseSeat->license->name }}

+

{{ $license->name }}

@@ -29,7 +29,7 @@
-

{{ $licenseSeat->license->name }}

+

{{ $license->name }}

@@ -37,7 +37,7 @@
-

{{ $licenseSeat->license->serial }}

+

{{ $license->serial }}

@@ -54,7 +54,7 @@
- + {!! $errors->first('note', ' :message') !!}
diff --git a/resources/views/licenses/view.blade.php b/resources/views/licenses/view.blade.php index 11a21ebf6..d21c73b45 100755 --- a/resources/views/licenses/view.blade.php +++ b/resources/views/licenses/view.blade.php @@ -90,14 +90,14 @@ @can('checkout', $licensedto) @if (($licensedto->assigned_to) || ($licensedto->asset_id)) @if ($license->reassignable) - + {{ trans('general.checkin') }} @else Assigned @endif @else - + {{ trans('general.checkout') }} @endif diff --git a/resources/views/partials/forms/edit/department-select.blade.php b/resources/views/partials/forms/edit/department-select.blade.php index 8ade5b018..d68b9d625 100644 --- a/resources/views/partials/forms/edit/department-select.blade.php +++ b/resources/views/partials/forms/edit/department-select.blade.php @@ -2,7 +2,7 @@ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
+
@if ($user_id = Input::old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))