From 8a0ed496235b6aa0a6b106261fdfa3fed018214b Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 13 Jan 2025 13:35:48 -0800 Subject: [PATCH 01/17] allows checkin of unreassignable license seats --- .../Licenses/LicenseCheckinController.php | 10 ++++------ app/Http/Transformers/LicenseSeatsTransformer.php | 15 +++++++++++++++ app/Listeners/CheckoutableListener.php | 2 +- app/Presenters/LicensePresenter.php | 9 +++++++++ resources/lang/en-US/admin/licenses/message.php | 2 +- .../views/partials/bootstrap-table.blade.php | 9 ++++++--- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 373a167642d0..f70c01bfd318 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -69,12 +69,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $this->authorize('checkout', $license); - if (! $license->reassignable) { - // Not allowed to checkin - Session::flash('error', trans('admin/licenses/message.checkin.not_reassignable') . '.'); - return redirect()->back()->withInput(); - } // Declare the rules for the form validation $rules = [ @@ -100,13 +95,16 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->assigned_to = null; $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); + if (! $license->reassignable) { + $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; + } session()->put(['redirect_option' => $request->get('redirect_option')]); // Was the asset updated? if ($licenseSeat->save()) { - event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $request->input('notes'))); + event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $licenseSeat->notes)); return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.checkin.success')); diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index 7ae68e9e449c..742fc865e14a 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -2,6 +2,7 @@ namespace App\Http\Transformers; +use App\Models\Actionlog; use App\Models\License; use App\Models\LicenseSeat; use Illuminate\Support\Facades\Gate; @@ -48,6 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), + 'disabled' => $this->unReassignable($seat), ]; if ($seat_count != 0) { @@ -66,4 +68,17 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) return $array; } + private function unReassignable($seat) + { + if (!$seat->license->reassignable) { + $exists = Actionlog::where('action_type', '=', 'checkin from') + ->where('item_id', '=', $seat->license->id) + ->where('updated_at', '=', $seat->updated_at) + ->exists(); + if($exists) { + return true; + } + return false; + } + } } diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index b297a4f72071..f5b490fa14dc 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -156,7 +156,7 @@ public function onCheckedIn($event) $ccEmails = array_filter($adminCcEmailsArray); $mailable = $this->getCheckinMailType($event); $notifiable = $this->getNotifiables($event); - if ($event->checkedOutTo->locale){ + if ($event->checkedOutTo?->locale){ $mailable->locale($event->checkedOutTo->locale); } // Send email notifications diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php index 4256c2c68649..faac314e87af 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -284,6 +284,15 @@ public static function dataTableLayoutSeats() 'title' => trans('general.notes'), 'formatter' => 'notesFormatter' ], + [ + 'field' => 'reassignable', + 'searchable' => false, + 'sortable' => false, + 'visible' => true, + 'title' => trans('admin/licenses/form.reassignable'), + 'formatter' => 'trueFalseFormatter', + 'class' => 'text-center', + ], [ 'field' => 'checkincheckout', 'searchable' => false, diff --git a/resources/lang/en-US/admin/licenses/message.php b/resources/lang/en-US/admin/licenses/message.php index 74e1d7af5ac5..3cda5e00e5eb 100644 --- a/resources/lang/en-US/admin/licenses/message.php +++ b/resources/lang/en-US/admin/licenses/message.php @@ -50,7 +50,7 @@ 'checkin' => array( 'error' => 'There was an issue checking in the license. Please try again.', - 'not_reassignable' => 'License not reassignable', + 'not_reassignable' => 'Seat has been used.', 'success' => 'The license was checked in successfully' ), diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 099640f0b670..51e9c7299b48 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -431,13 +431,16 @@ function checkboxEnabledFormatter (value, row) { // Checkouts need the license ID, checkins need the specific seat ID function licenseSeatInOutFormatter(value, row) { + if(row.disabled) { + return '{{ trans('general.checkout') }}'; + } else // The user is allowed to check the license seat out and it's available if ((row.available_actions.checkout === true) && (row.user_can_checkout === true) && ((!row.asset_id) && (!row.assigned_to))) { return '{{ trans('general.checkout') }}'; - } else { - return '{{ trans('general.checkin') }}'; } - + else { + return '{{ trans('general.checkin') }}'; + } } function genericCheckinCheckoutFormatter(destination) { From 5e1562ae4c40c9956528a4cde4c6d6645ed07b59 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 13 Jan 2025 14:31:54 -0800 Subject: [PATCH 02/17] adds count on tabs and reports and index --- app/Helpers/Helper.php | 12 ++++++++++++ .../Controllers/Licenses/LicensesController.php | 13 ++++++++++--- app/Http/Transformers/LicensesTransformer.php | 4 ++-- app/Models/License.php | 3 ++- resources/lang/en-US/admin/licenses/message.php | 2 +- resources/views/licenses/view.blade.php | 2 +- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 95a344dce9e7..723091768412 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -2,6 +2,7 @@ namespace App\Helpers; use App\Models\Accessory; +use App\Models\Actionlog; use App\Models\Asset; use App\Models\AssetModel; use App\Models\Component; @@ -9,6 +10,7 @@ use App\Models\CustomField; use App\Models\CustomFieldset; use App\Models\Depreciation; +use App\Models\LicenseSeat; use App\Models\Setting; use App\Models\Statuslabel; use App\Models\License; @@ -1529,4 +1531,14 @@ static public function getRedirectOption($request, $id, $table, $item_id = null) } return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error')); } + public static function unReassignableCount($license) + { + + if (!$license->reassignable) { + $count = Actionlog::where('action_type', '=', 'checkin from') + ->where('item_id', '=', $license->id) + ->count(); + return $count; + } + } } diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index 6098423ba3e6..8ddac020b579 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -248,16 +248,23 @@ public function show($licenseId = null) } $users_count = User::where('autoassign_licenses', '1')->count(); - $total_seats_count = $license->totalSeatsByLicenseID(); + $total_seats_count = (int) $license->totalSeatsByLicenseID(); $available_seats_count = $license->availCount()->count(); - $checkedout_seats_count = ($total_seats_count - $available_seats_count); + $unreassignable_seats_count = Helper::unReassignableCount($license); + if(!$license->reassignable){ + $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); + } + else { + $checkedout_seats_count = ($total_seats_count - $available_seats_count); + } $this->authorize('view', $license); return view('licenses.view', compact('license')) ->with('users_count', $users_count) ->with('total_seats_count', $total_seats_count) ->with('available_seats_count', $available_seats_count) - ->with('checkedout_seats_count', $checkedout_seats_count); + ->with('checkedout_seats_count', $checkedout_seats_count) + ->with('unreassignable_seats_count', $unreassignable_seats_count); } diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index 673ac06b3dab..6ae57e629273 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -7,7 +7,7 @@ use Illuminate\Support\Facades\Gate; use Illuminate\Database\Eloquent\Collection; -class LicensesTransformer +class LicensesTransformer { public function transformLicenses(Collection $licenses, $total) { @@ -37,7 +37,7 @@ public function transformLicense(License $license) 'notes' => Helper::parseEscapedMarkedownInline($license->notes), 'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'), 'seats' => (int) $license->seats, - 'free_seats_count' => (int) $license->free_seats_count, + 'free_seats_count' => (int) $license->free_seats_count - Helper::unReassignableCount($license), 'min_amt' => ($license->min_amt) ? (int) ($license->min_amt) : null, 'license_name' => ($license->license_name) ? e($license->license_name) : null, 'license_email' => ($license->license_email) ? e($license->license_email) : null, diff --git a/app/Models/License.php b/app/Models/License.php index 0997c1e57b99..5ca621bce73c 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -594,7 +594,8 @@ public function remaincount() { $total = $this->licenseSeatsCount; $taken = $this->assigned_seats_count; - $diff = ($total - $taken); + $unreassignable = Helper::unReassignableCount($this); + $diff = ($total - $taken - $unreassignable); return (int) $diff; } diff --git a/resources/lang/en-US/admin/licenses/message.php b/resources/lang/en-US/admin/licenses/message.php index 3cda5e00e5eb..9a0219d857a6 100644 --- a/resources/lang/en-US/admin/licenses/message.php +++ b/resources/lang/en-US/admin/licenses/message.php @@ -50,7 +50,7 @@ 'checkin' => array( 'error' => 'There was an issue checking in the license. Please try again.', - 'not_reassignable' => 'Seat has been used.', + 'not_reassignable' => 'Seat has been used', 'success' => 'The license was checked in successfully' ), diff --git a/resources/views/licenses/view.blade.php b/resources/views/licenses/view.blade.php index 2de0f9d6e0bc..7af8676156a8 100755 --- a/resources/views/licenses/view.blade.php +++ b/resources/views/licenses/view.blade.php @@ -32,7 +32,7 @@ - {{ number_format($license->availCount()->count()) }} / {{ number_format($license->seats) }} + {{ number_format($license->availCount()->count() - number_format($unreassignable_seats_count) ) }} / {{ number_format($license->seats)}} From 50e0e4a07b594989064758a12f6fa215f2c780af Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 13 Jan 2025 14:37:03 -0800 Subject: [PATCH 03/17] remove unrelated change --- app/Listeners/CheckoutableListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index f5b490fa14dc..b297a4f72071 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -156,7 +156,7 @@ public function onCheckedIn($event) $ccEmails = array_filter($adminCcEmailsArray); $mailable = $this->getCheckinMailType($event); $notifiable = $this->getNotifiables($event); - if ($event->checkedOutTo?->locale){ + if ($event->checkedOutTo->locale){ $mailable->locale($event->checkedOutTo->locale); } // Send email notifications From 9da15a8e5800c36ddcbd941b92180842f54d1e2f Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 13 Jan 2025 14:44:26 -0800 Subject: [PATCH 04/17] get button color correct --- resources/views/partials/bootstrap-table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 51e9c7299b48..136428870dad 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -432,7 +432,7 @@ function checkboxEnabledFormatter (value, row) { function licenseSeatInOutFormatter(value, row) { if(row.disabled) { - return '{{ trans('general.checkout') }}'; + return '{{ trans('general.checkout') }}'; } else // The user is allowed to check the license seat out and it's available if ((row.available_actions.checkout === true) && (row.user_can_checkout === true) && ((!row.asset_id) && (!row.assigned_to))) { From 7a23372489e957af732021bb3ca10e31f8e1c937 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 15 Jan 2025 15:36:12 -0800 Subject: [PATCH 05/17] adds migration for column unavailable, changes logic to utlize value --- app/Helpers/Helper.php | 4 +-- .../Licenses/LicenseCheckinController.php | 1 + .../Transformers/LicenseSeatsTransformer.php | 28 +++++++++--------- app/Models/License.php | 1 + app/Presenters/LicensePresenter.php | 9 ------ ...ds_unavailable_to_license_seats_tables.php | 29 +++++++++++++++++++ 6 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 723091768412..263204853c11 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,8 +1535,8 @@ public static function unReassignableCount($license) { if (!$license->reassignable) { - $count = Actionlog::where('action_type', '=', 'checkin from') - ->where('item_id', '=', $license->id) + $count = LicenseSeat::where('unavailable', '=', true) + ->where('license_id', '=', $license->id) ->count(); return $count; } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index f70c01bfd318..1581fc14197b 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,6 +96,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); if (! $license->reassignable) { + $licenseSeat->unavailable = 1; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; } diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index 742fc865e14a..f04c5933937b 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), - 'disabled' => $this->unReassignable($seat), + 'disabled' => $seat->unavailable, ]; if ($seat_count != 0) { @@ -68,17 +68,17 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) return $array; } - private function unReassignable($seat) - { - if (!$seat->license->reassignable) { - $exists = Actionlog::where('action_type', '=', 'checkin from') - ->where('item_id', '=', $seat->license->id) - ->where('updated_at', '=', $seat->updated_at) - ->exists(); - if($exists) { - return true; - } - return false; - } - } +// private function unReassignable($seat) +// { +// if (!$seat->license->reassignable) { +// $exists = Actionlog::where('action_type', '=', 'checkin from') +// ->where('item_id', '=', $seat->license->id) +// ->where('updated_at', '=', $seat->updated_at) +// ->exists(); +// if($exists) { +// return true; +// } +// return false; +// } +// } } diff --git a/app/Models/License.php b/app/Models/License.php index 5ca621bce73c..a9966c16b0d7 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,6 +653,7 @@ public function freeSeat() { return $this->licenseseats() ->whereNull('deleted_at') + ->where('unavailable', '=', 0) ->where(function ($query) { $query->whereNull('assigned_to') ->whereNull('asset_id'); diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php index faac314e87af..4256c2c68649 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -284,15 +284,6 @@ public static function dataTableLayoutSeats() 'title' => trans('general.notes'), 'formatter' => 'notesFormatter' ], - [ - 'field' => 'reassignable', - 'searchable' => false, - 'sortable' => false, - 'visible' => true, - 'title' => trans('admin/licenses/form.reassignable'), - 'formatter' => 'trueFalseFormatter', - 'class' => 'text-center', - ], [ 'field' => 'checkincheckout', 'searchable' => false, diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php new file mode 100644 index 000000000000..b0ec692ea07c --- /dev/null +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -0,0 +1,29 @@ +addColumn('boolean', 'unavailable')->default(false)->after('assigned_to'); + }); + } + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('license_seats_tables', function (Blueprint $table) { + $table->dropColumn('unavailable'); + }); + } +}; From 344b4e7d6074ea3fee9cce88a250981582b1feb3 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 09:46:03 -0800 Subject: [PATCH 06/17] fixes test to check if checked in licenses is unavailable --- .../Licenses/LicenseCheckinController.php | 3 ++- database/factories/LicenseSeatFactory.php | 1 + tests/Feature/Checkins/Ui/LicenseCheckinTest.php | 12 +++++------- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 1581fc14197b..07b063af5e52 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -95,9 +95,10 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->assigned_to = null; $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); - if (! $license->reassignable) { + if (! $licenseSeat->license->reassignable) { $licenseSeat->unavailable = 1; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; + } session()->put(['redirect_option' => $request->get('redirect_option')]); diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index aaf75bdc2d82..2aa1c55f3731 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,6 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), + 'unavailable' => 0, ]; } diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index 7a6553d8ba61..093455c5e733 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -20,7 +20,7 @@ public function testCheckingInLicenseRequiresCorrectPermission() ->assertForbidden(); } - public function testCannotCheckinNonReassignableLicense() + public function testNonReassignableLicenseSeatIsUnavailable() { $licenseSeat = LicenseSeat::factory() ->notReassignable() @@ -28,13 +28,11 @@ public function testCannotCheckinNonReassignableLicense() ->create(); $this->actingAs(User::factory()->checkoutLicenses()->create()) - ->post(route('licenses.checkin.save', $licenseSeat), [ - 'notes' => 'my note', - 'redirect_option' => 'index', - ]) - ->assertSessionHas('error', trans('admin/licenses/message.checkin.not_reassignable') . '.'); + ->post(route('licenses.checkin.save', $licenseSeat)); + + $licenseSeat->refresh(); - $this->assertNotNull($licenseSeat->fresh()->assigned_to); + $this->assertEquals(1, $licenseSeat->unavailable); } public function testCannotCheckinLicenseThatIsNotAssigned() From f47a2b10c0f02164dbc68e139e0b94a6eece4bb3 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 11:53:15 -0800 Subject: [PATCH 07/17] updated column name, updated Api license checkin and out --- app/Helpers/Helper.php | 2 +- app/Http/Controllers/Api/LicenseSeatsController.php | 8 +++++++- .../Controllers/Licenses/LicenseCheckinController.php | 2 +- app/Http/Transformers/LicenseSeatsTransformer.php | 2 +- database/factories/LicenseSeatFactory.php | 2 +- ...15_190348_adds_unavailable_to_license_seats_tables.php | 6 +++--- tests/Feature/Checkins/Ui/LicenseCheckinTest.php | 2 +- 7 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 263204853c11..a980b0efaccd 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ public static function unReassignableCount($license) { if (!$license->reassignable) { - $count = LicenseSeat::where('unavailable', '=', true) + $count = LicenseSeat::where('dead', '=', true) ->where('license_id', '=', $license->id) ->count(); return $count; diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 2ed709732236..1017797937d8 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,9 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a // nothing to update return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } - + if( $touched && $licenseSeat->dead) { + return response()->json(Helper::formatStandardApiResponse('error', $licenseSeat, trans('admin/licenses/message.checkout.unavailable'))); + } // the logging functions expect only one "target". if both asset and user are present in the request, // we simply let assets take precedence over users... if ($licenseSeat->isDirty('assigned_to')) { @@ -137,6 +139,10 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { $licenseSeat->logCheckin($target, $request->input('note')); + if(!$licenseSeat->license->ressignable){ + $licenseSeat->dead = 1; + $licenseSeat->save(); + } return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 07b063af5e52..9d61b5e2f1e8 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); if (! $licenseSeat->license->reassignable) { - $licenseSeat->unavailable = 1; + $licenseSeat->dead = 1; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; } diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index f04c5933937b..55c95bb54b2b 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), - 'disabled' => $seat->unavailable, + 'disabled' => $seat->dead, ]; if ($seat_count != 0) { diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index 2aa1c55f3731..34caeb303831 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), - 'unavailable' => 0, + 'dead' => 0, ]; } diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php index b0ec692ea07c..be123dc27617 100644 --- a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -14,7 +14,7 @@ public function up(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->addColumn('boolean', 'unavailable')->default(false)->after('assigned_to'); + $table->addColumn('boolean', 'dead')->default(false)->after('assigned_to'); }); } /** @@ -22,8 +22,8 @@ public function up(): void */ public function down(): void { - Schema::table('license_seats_tables', function (Blueprint $table) { - $table->dropColumn('unavailable'); + Schema::table('license_seats', function (Blueprint $table) { + $table->dropColumn('dead'); }); } }; diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index 093455c5e733..1a711306d11f 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ public function testNonReassignableLicenseSeatIsUnavailable() $licenseSeat->refresh(); - $this->assertEquals(1, $licenseSeat->unavailable); + $this->assertEquals(1, $licenseSeat->dead); } public function testCannotCheckinLicenseThatIsNotAssigned() From db11fc35f4dcb216ee1bc96ec6746f1ace257960 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:00:49 -0800 Subject: [PATCH 08/17] fixed typo, fixed variable name --- app/Http/Controllers/Api/LicenseSeatsController.php | 2 +- app/Models/License.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 1017797937d8..d9a34c32be48 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -139,7 +139,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { $licenseSeat->logCheckin($target, $request->input('note')); - if(!$licenseSeat->license->ressignable){ + if(!$licenseSeat->license->reassignable){ $licenseSeat->dead = 1; $licenseSeat->save(); } diff --git a/app/Models/License.php b/app/Models/License.php index a9966c16b0d7..f837fe289586 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ public function freeSeat() { return $this->licenseseats() ->whereNull('deleted_at') - ->where('unavailable', '=', 0) + ->where('dead', '=', 0) ->where(function ($query) { $query->whereNull('assigned_to') ->whereNull('asset_id'); From f050864fb4cb766e2765c6ddc844168c99b821fb Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:12:14 -0800 Subject: [PATCH 09/17] renamed dead to unassigned, replaced 0 and 1 with true and flase --- app/Helpers/Helper.php | 2 +- app/Http/Controllers/Api/LicenseSeatsController.php | 4 ++-- app/Http/Controllers/Licenses/LicenseCheckinController.php | 2 +- app/Http/Transformers/LicenseSeatsTransformer.php | 2 +- app/Models/License.php | 2 +- database/factories/LicenseSeatFactory.php | 2 +- ..._01_15_190348_adds_unavailable_to_license_seats_tables.php | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index a980b0efaccd..0d7665f978f4 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ public static function unReassignableCount($license) { if (!$license->reassignable) { - $count = LicenseSeat::where('dead', '=', true) + $count = LicenseSeat::where('unassignable', '=', true) ->where('license_id', '=', $license->id) ->count(); return $count; diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index d9a34c32be48..de1cc3b53c4f 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a // nothing to update return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } - if( $touched && $licenseSeat->dead) { + if( $touched && $licenseSeat->unassignable) { return response()->json(Helper::formatStandardApiResponse('error', $licenseSeat, trans('admin/licenses/message.checkout.unavailable'))); } // the logging functions expect only one "target". if both asset and user are present in the request, @@ -140,7 +140,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { $licenseSeat->logCheckin($target, $request->input('note')); if(!$licenseSeat->license->reassignable){ - $licenseSeat->dead = 1; + $licenseSeat->unassignable = true; $licenseSeat->save(); } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 9d61b5e2f1e8..94cf55380aae 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); if (! $licenseSeat->license->reassignable) { - $licenseSeat->dead = 1; + $licenseSeat->unassignable = true; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; } diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index 55c95bb54b2b..f79be04d09dc 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), - 'disabled' => $seat->dead, + 'disabled' => $seat->unassignable, ]; if ($seat_count != 0) { diff --git a/app/Models/License.php b/app/Models/License.php index f837fe289586..ac0e5a004903 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ public function freeSeat() { return $this->licenseseats() ->whereNull('deleted_at') - ->where('dead', '=', 0) + ->where('unassignable', '=', false) ->where(function ($query) { $query->whereNull('assigned_to') ->whereNull('asset_id'); diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index 34caeb303831..5fad52cbb3c5 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), - 'dead' => 0, + 'dead' => false, ]; } diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php index be123dc27617..6d41b68b8316 100644 --- a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -14,7 +14,7 @@ public function up(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->addColumn('boolean', 'dead')->default(false)->after('assigned_to'); + $table->addColumn('boolean', 'unassignable')->default(false)->after('assigned_to'); }); } /** @@ -23,7 +23,7 @@ public function up(): void public function down(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->dropColumn('dead'); + $table->dropColumn('unassignable'); }); } }; From 3f3f2bfc6123df441521871ec6fe5efa12ae1de6 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:14:03 -0800 Subject: [PATCH 10/17] fixed factory and test --- database/factories/LicenseSeatFactory.php | 2 +- tests/Feature/Checkins/Ui/LicenseCheckinTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index 5fad52cbb3c5..a4752f738837 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), - 'dead' => false, + 'unassignable' => false, ]; } diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index 1a711306d11f..ed8604d9accb 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ public function testNonReassignableLicenseSeatIsUnavailable() $licenseSeat->refresh(); - $this->assertEquals(1, $licenseSeat->dead); + $this->assertEquals(1, $licenseSeat->unassignable); } public function testCannotCheckinLicenseThatIsNotAssigned() From 52bf0faaa5c557bf4930ea20458195ee82094b50 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:19:59 -0800 Subject: [PATCH 11/17] renamed unassignable to reassignable_seat --- app/Helpers/Helper.php | 2 +- app/Http/Controllers/Api/LicenseSeatsController.php | 4 ++-- app/Http/Controllers/Licenses/LicenseCheckinController.php | 2 +- app/Http/Transformers/LicenseSeatsTransformer.php | 2 +- app/Models/License.php | 2 +- database/factories/LicenseSeatFactory.php | 2 +- ..._01_15_190348_adds_unavailable_to_license_seats_tables.php | 4 ++-- tests/Feature/Checkins/Ui/LicenseCheckinTest.php | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 0d7665f978f4..a51c957c5a11 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ public static function unReassignableCount($license) { if (!$license->reassignable) { - $count = LicenseSeat::where('unassignable', '=', true) + $count = LicenseSeat::where('reassignable_seat', '=', true) ->where('license_id', '=', $license->id) ->count(); return $count; diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index de1cc3b53c4f..5115523c2e6b 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a // nothing to update return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } - if( $touched && $licenseSeat->unassignable) { + if( $touched && $licenseSeat->reassignable_seat) { return response()->json(Helper::formatStandardApiResponse('error', $licenseSeat, trans('admin/licenses/message.checkout.unavailable'))); } // the logging functions expect only one "target". if both asset and user are present in the request, @@ -140,7 +140,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { $licenseSeat->logCheckin($target, $request->input('note')); if(!$licenseSeat->license->reassignable){ - $licenseSeat->unassignable = true; + $licenseSeat->reassignable_seat = true; $licenseSeat->save(); } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 94cf55380aae..6553b9ab12d7 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); if (! $licenseSeat->license->reassignable) { - $licenseSeat->unassignable = true; + $licenseSeat->reassignable_seat = true; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; } diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index f79be04d09dc..ec74d74326ff 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), - 'disabled' => $seat->unassignable, + 'disabled' => $seat->reassignable_seat, ]; if ($seat_count != 0) { diff --git a/app/Models/License.php b/app/Models/License.php index ac0e5a004903..b6fef33e1ed1 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ public function freeSeat() { return $this->licenseseats() ->whereNull('deleted_at') - ->where('unassignable', '=', false) + ->where('reassignable_seat', '=', false) ->where(function ($query) { $query->whereNull('assigned_to') ->whereNull('asset_id'); diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index a4752f738837..09ea283d0cb7 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), - 'unassignable' => false, + 'reassignable_seat' => false, ]; } diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php index 6d41b68b8316..334104d40e75 100644 --- a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -14,7 +14,7 @@ public function up(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->addColumn('boolean', 'unassignable')->default(false)->after('assigned_to'); + $table->addColumn('boolean', 'reassignable_seat')->default(false)->after('assigned_to'); }); } /** @@ -23,7 +23,7 @@ public function up(): void public function down(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->dropColumn('unassignable'); + $table->dropColumn('reassignable_seat'); }); } }; diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index ed8604d9accb..d43ccb593d6b 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ public function testNonReassignableLicenseSeatIsUnavailable() $licenseSeat->refresh(); - $this->assertEquals(1, $licenseSeat->unassignable); + $this->assertEquals(1, $licenseSeat->reassignable_seat); } public function testCannotCheckinLicenseThatIsNotAssigned() From d217c2e2950eb12632db5c0ad1a3b5377fbcd37a Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:24:32 -0800 Subject: [PATCH 12/17] last rename --- app/Helpers/Helper.php | 2 +- app/Http/Controllers/Api/LicenseSeatsController.php | 4 ++-- app/Http/Controllers/Licenses/LicenseCheckinController.php | 2 +- app/Http/Controllers/Licenses/LicensesController.php | 2 +- app/Http/Transformers/LicenseSeatsTransformer.php | 2 +- app/Models/License.php | 2 +- database/factories/LicenseSeatFactory.php | 2 +- ..._01_15_190348_adds_unavailable_to_license_seats_tables.php | 4 ++-- tests/Feature/Checkins/Ui/LicenseCheckinTest.php | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index a51c957c5a11..26301c1010b0 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ public static function unReassignableCount($license) { if (!$license->reassignable) { - $count = LicenseSeat::where('reassignable_seat', '=', true) + $count = LicenseSeat::where('unreassignable_seat', '=', true) ->where('license_id', '=', $license->id) ->count(); return $count; diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 5115523c2e6b..38f8babf9d70 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a // nothing to update return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } - if( $touched && $licenseSeat->reassignable_seat) { + if( $touched && $licenseSeat->unreassignable_seat) { return response()->json(Helper::formatStandardApiResponse('error', $licenseSeat, trans('admin/licenses/message.checkout.unavailable'))); } // the logging functions expect only one "target". if both asset and user are present in the request, @@ -140,7 +140,7 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { $licenseSeat->logCheckin($target, $request->input('note')); if(!$licenseSeat->license->reassignable){ - $licenseSeat->reassignable_seat = true; + $licenseSeat->unreassignable_seat = true; $licenseSeat->save(); } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 6553b9ab12d7..8bd3e34f1157 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->asset_id = null; $licenseSeat->notes = $request->input('notes'); if (! $licenseSeat->license->reassignable) { - $licenseSeat->reassignable_seat = true; + $licenseSeat->unreassignable_seat = true; $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; } diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index 8ddac020b579..f963535375ac 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -251,7 +251,7 @@ public function show($licenseId = null) $total_seats_count = (int) $license->totalSeatsByLicenseID(); $available_seats_count = $license->availCount()->count(); $unreassignable_seats_count = Helper::unReassignableCount($license); - if(!$license->reassignable){ + if(!$license->unreassignable_seat){ $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); } else { diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index ec74d74326ff..e882e74a8899 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) 'reassignable' => (bool) $seat->license->reassignable, 'notes' => e($seat->notes), 'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')), - 'disabled' => $seat->reassignable_seat, + 'disabled' => $seat->unreassignable_seat, ]; if ($seat_count != 0) { diff --git a/app/Models/License.php b/app/Models/License.php index b6fef33e1ed1..0b5eed097a5d 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ public function freeSeat() { return $this->licenseseats() ->whereNull('deleted_at') - ->where('reassignable_seat', '=', false) + ->where('unreassignable_seat', '=', false) ->where(function ($query) { $query->whereNull('assigned_to') ->whereNull('asset_id'); diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index 09ea283d0cb7..ee516b6dac24 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ public function definition() { return [ 'license_id' => License::factory(), - 'reassignable_seat' => false, + 'unreassignable_seat' => false, ]; } diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php index 334104d40e75..9aec0343ac06 100644 --- a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -14,7 +14,7 @@ public function up(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->addColumn('boolean', 'reassignable_seat')->default(false)->after('assigned_to'); + $table->addColumn('boolean', 'unreassignable_seat')->default(false)->after('assigned_to'); }); } /** @@ -23,7 +23,7 @@ public function up(): void public function down(): void { Schema::table('license_seats', function (Blueprint $table) { - $table->dropColumn('reassignable_seat'); + $table->dropColumn('unreassignable_seat'); }); } }; diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index d43ccb593d6b..3c00d37071e3 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ public function testNonReassignableLicenseSeatIsUnavailable() $licenseSeat->refresh(); - $this->assertEquals(1, $licenseSeat->reassignable_seat); + $this->assertEquals(1, $licenseSeat->unreassignable_seat); } public function testCannotCheckinLicenseThatIsNotAssigned() From 6bab6e7151ba3560395bdeccf30ceaa1938e668b Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 16 Jan 2025 12:27:01 -0800 Subject: [PATCH 13/17] remove unintended change --- app/Http/Controllers/Licenses/LicensesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index f963535375ac..8ddac020b579 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -251,7 +251,7 @@ public function show($licenseId = null) $total_seats_count = (int) $license->totalSeatsByLicenseID(); $available_seats_count = $license->availCount()->count(); $unreassignable_seats_count = Helper::unReassignableCount($license); - if(!$license->unreassignable_seat){ + if(!$license->reassignable){ $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); } else { From 2143952a1eacd74bf066a8f4dc84c4539b9c9496 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 21 Jan 2025 11:43:47 -0800 Subject: [PATCH 14/17] removed unused models, castged unreassignable_seat, clean up in general --- app/Helpers/Helper.php | 11 ------- .../Api/LicenseSeatsController.php | 3 +- .../Licenses/LicensesController.php | 11 ++----- .../Transformers/LicenseSeatsTransformer.php | 15 --------- app/Http/Transformers/LicensesTransformer.php | 3 +- app/Models/License.php | 2 +- app/Models/LicenseSeat.php | 31 +++++++++++++++++++ ...ds_unavailable_to_license_seats_tables.php | 3 -- .../Checkins/Ui/LicenseCheckinTest.php | 2 +- 9 files changed, 39 insertions(+), 42 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 26301c1010b0..8f653ff35303 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -2,7 +2,6 @@ namespace App\Helpers; use App\Models\Accessory; -use App\Models\Actionlog; use App\Models\Asset; use App\Models\AssetModel; use App\Models\Component; @@ -10,7 +9,6 @@ use App\Models\CustomField; use App\Models\CustomFieldset; use App\Models\Depreciation; -use App\Models\LicenseSeat; use App\Models\Setting; use App\Models\Statuslabel; use App\Models\License; @@ -1531,14 +1529,5 @@ static public function getRedirectOption($request, $id, $table, $item_id = null) } return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error')); } - public static function unReassignableCount($license) - { - if (!$license->reassignable) { - $count = LicenseSeat::where('unreassignable_seat', '=', true) - ->where('license_id', '=', $license->id) - ->count(); - return $count; - } - } } diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 38f8babf9d70..08b42b5a21a3 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -138,11 +138,12 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($licenseSeat->save()) { if ($is_checkin) { - $licenseSeat->logCheckin($target, $request->input('note')); if(!$licenseSeat->license->reassignable){ + $licenseSeat->notes .= "\n" .trans('admin/licenses/message.checkin.not_reassignable') . "."; $licenseSeat->unreassignable_seat = true; $licenseSeat->save(); } + $licenseSeat->logCheckin($target, $licenseSeat->notes); return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index 8ddac020b579..54a8cb276421 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -248,15 +248,8 @@ public function show($licenseId = null) } $users_count = User::where('autoassign_licenses', '1')->count(); - $total_seats_count = (int) $license->totalSeatsByLicenseID(); - $available_seats_count = $license->availCount()->count(); - $unreassignable_seats_count = Helper::unReassignableCount($license); - if(!$license->reassignable){ - $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); - } - else { - $checkedout_seats_count = ($total_seats_count - $available_seats_count); - } + + [$checkedout_seats_count, $total_seats_count, $available_seats_count, $unreassignable_seats_count] = LicenseSeat::usedSeatCount($license); $this->authorize('view', $license); return view('licenses.view', compact('license')) diff --git a/app/Http/Transformers/LicenseSeatsTransformer.php b/app/Http/Transformers/LicenseSeatsTransformer.php index e882e74a8899..98688762956f 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -2,12 +2,10 @@ namespace App\Http\Transformers; -use App\Models\Actionlog; use App\Models\License; use App\Models\LicenseSeat; use Illuminate\Support\Facades\Gate; use Illuminate\Database\Eloquent\Collection; - class LicenseSeatsTransformer { public function transformLicenseSeats(Collection $seats, $total) @@ -68,17 +66,4 @@ public function transformLicenseSeat(LicenseSeat $seat, $seat_count = 0) return $array; } -// private function unReassignable($seat) -// { -// if (!$seat->license->reassignable) { -// $exists = Actionlog::where('action_type', '=', 'checkin from') -// ->where('item_id', '=', $seat->license->id) -// ->where('updated_at', '=', $seat->updated_at) -// ->exists(); -// if($exists) { -// return true; -// } -// return false; -// } -// } } diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index 6ae57e629273..86940a8deca8 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -4,6 +4,7 @@ use App\Helpers\Helper; use App\Models\License; +use App\Models\LicenseSeat; use Illuminate\Support\Facades\Gate; use Illuminate\Database\Eloquent\Collection; @@ -37,7 +38,7 @@ public function transformLicense(License $license) 'notes' => Helper::parseEscapedMarkedownInline($license->notes), 'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'), 'seats' => (int) $license->seats, - 'free_seats_count' => (int) $license->free_seats_count - Helper::unReassignableCount($license), + 'free_seats_count' => (int) $license->free_seats_count - LicenseSeat::unReassignableCount($license), 'min_amt' => ($license->min_amt) ? (int) ($license->min_amt) : null, 'license_name' => ($license->license_name) ? e($license->license_name) : null, 'license_email' => ($license->license_email) ? e($license->license_email) : null, diff --git a/app/Models/License.php b/app/Models/License.php index 0b5eed097a5d..e082e6c2a07e 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -594,7 +594,7 @@ public function remaincount() { $total = $this->licenseSeatsCount; $taken = $this->assigned_seats_count; - $unreassignable = Helper::unReassignableCount($this); + $unreassignable = LicenseSeat::unReassignableCount($this); $diff = ($total - $taken - $unreassignable); return (int) $diff; diff --git a/app/Models/LicenseSeat.php b/app/Models/LicenseSeat.php index 397a14146870..f491e19c2572 100755 --- a/app/Models/LicenseSeat.php +++ b/app/Models/LicenseSeat.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Helpers\Helper; use App\Models\Traits\Acceptable; use App\Notifications\CheckinLicenseNotification; use App\Notifications\CheckoutLicenseNotification; @@ -21,6 +22,9 @@ class LicenseSeat extends SnipeModel implements ICompanyableChild protected $guarded = 'id'; protected $table = 'license_seats'; + protected $casts = [ + 'unreassignable_seat' => 'boolean', + ]; /** * The attributes that are mass assignable. @@ -113,6 +117,33 @@ public function location() return false; } + public static function usedSeatCount($license): array { + $total_seats_count = (int) $license->totalSeatsByLicenseID(); + $available_seats_count = $license->availCount()->count(); + $unreassignable_seats_count = self::unReassignableCount($license); + if(!$license->reassignable){ + $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); + } + else { + $checkedout_seats_count = ($total_seats_count - $available_seats_count); + } + return [ + $checkedout_seats_count, + $total_seats_count, + $available_seats_count, + $unreassignable_seats_count, + ]; + } + public static function unReassignableCount($license) + { + + if (!$license->reassignable) { + $count = static::query()->where('unreassignable_seat', '=', true) + ->where('license_id', '=', $license->id) + ->count(); + return $count; + } + } /** * Query builder scope to order on department diff --git a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php index 9aec0343ac06..40c8ad53679b 100644 --- a/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php +++ b/database/migrations/2025_01_15_190348_adds_unavailable_to_license_seats_tables.php @@ -1,9 +1,6 @@ refresh(); - $this->assertEquals(1, $licenseSeat->unreassignable_seat); + $this->assertEquals(true, $licenseSeat->unreassignable_seat); } public function testCannotCheckinLicenseThatIsNotAssigned() From 34e8360b1060f8c451a4e5df4133a6034736f6cd Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 22 Jan 2025 10:46:28 -0800 Subject: [PATCH 15/17] moves counts to licenses, allows bulk check in of unreassignable licenses --- .../Api/LicenseSeatsController.php | 1 - .../Licenses/LicenseCheckinController.php | 20 ++++++------- .../Licenses/LicensesController.php | 11 +++++++- app/Http/Transformers/LicensesTransformer.php | 3 +- app/Models/License.php | 22 +++++++++++++-- app/Models/LicenseSeat.php | 28 ------------------- resources/views/licenses/view.blade.php | 9 +----- 7 files changed, 39 insertions(+), 55 deletions(-) diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 08b42b5a21a3..0f752cbb83c9 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -139,7 +139,6 @@ public function update(Request $request, $licenseId, $seatId) : JsonResponse | a if ($is_checkin) { if(!$licenseSeat->license->reassignable){ - $licenseSeat->notes .= "\n" .trans('admin/licenses/message.checkin.not_reassignable') . "."; $licenseSeat->unreassignable_seat = true; $licenseSeat->save(); } diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 8bd3e34f1157..30fcd1cffd51 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -97,8 +97,6 @@ public function store(Request $request, $seatId = null, $backTo = null) $licenseSeat->notes = $request->input('notes'); if (! $licenseSeat->license->reassignable) { $licenseSeat->unreassignable_seat = true; - $licenseSeat->notes .= "\n" . trans('admin/licenses/message.checkin.not_reassignable') . '.'; - } session()->put(['redirect_option' => $request->get('redirect_option')]); @@ -131,21 +129,17 @@ public function bulkCheckin(Request $request, $licenseId) { $license = License::findOrFail($licenseId); $this->authorize('checkin', $license); - if (! $license->reassignable) { - // Not allowed to checkin - Session::flash('error', 'License not reassignable.'); - - return redirect()->back()->withInput(); - } - $licenseSeatsByUser = LicenseSeat::where('license_id', '=', $licenseId) ->whereNotNull('assigned_to') - ->with('user') + ->with('user', 'license') ->get(); + $license = $licenseSeatsByUser->first()?->license; foreach ($licenseSeatsByUser as $user_seat) { $user_seat->assigned_to = null; - + if ($license && ! $license->reassignable) { + $user_seat->unreassignable_seat = true; + } if ($user_seat->save()) { Log::debug('Checking in '.$license->name.' from user '.$user_seat->username); $user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg')); @@ -160,7 +154,9 @@ public function bulkCheckin(Request $request, $licenseId) { $count = 0; foreach ($licenseSeatsByAsset as $asset_seat) { $asset_seat->asset_id = null; - + if ($license && ! $license->reassignable) { + $asset_seat->unreassignable_seat = true; + } if ($asset_seat->save()) { Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag); $asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg')); diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index 54a8cb276421..7ef6eeb30b9e 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -249,7 +249,16 @@ public function show($licenseId = null) $users_count = User::where('autoassign_licenses', '1')->count(); - [$checkedout_seats_count, $total_seats_count, $available_seats_count, $unreassignable_seats_count] = LicenseSeat::usedSeatCount($license); + $total_seats_count = (int) $license->totalSeatsByLicenseID(); + $available_seats_count = $license->availCount()->count(); + $unreassignable_seats_count = License::unReassignableCount($license); + + if(!$license->reassignable){ + $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); + } + else { + $checkedout_seats_count = ($total_seats_count - $available_seats_count); + } $this->authorize('view', $license); return view('licenses.view', compact('license')) diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index 86940a8deca8..3be7b256da8e 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -4,7 +4,6 @@ use App\Helpers\Helper; use App\Models\License; -use App\Models\LicenseSeat; use Illuminate\Support\Facades\Gate; use Illuminate\Database\Eloquent\Collection; @@ -38,7 +37,7 @@ public function transformLicense(License $license) 'notes' => Helper::parseEscapedMarkedownInline($license->notes), 'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'), 'seats' => (int) $license->seats, - 'free_seats_count' => (int) $license->free_seats_count - LicenseSeat::unReassignableCount($license), + 'free_seats_count' => (int) $license->free_seats_count - License::unReassignableCount($license), 'min_amt' => ($license->min_amt) ? (int) ($license->min_amt) : null, 'license_name' => ($license->license_name) ? e($license->license_name) : null, 'license_email' => ($license->license_email) ? e($license->license_email) : null, diff --git a/app/Models/License.php b/app/Models/License.php index e082e6c2a07e..490a8401a4eb 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -533,6 +533,7 @@ public function availCount() return $this->licenseSeatsRelation() ->whereNull('asset_id') ->whereNull('assigned_to') + ->where('unreassignable_seat', '=', false) ->whereNull('deleted_at'); } @@ -582,7 +583,22 @@ public function getAssignedSeatsCountAttribute() return 0; } - + /** + * Calculates the number of unreassignable seats + * + * @author G. Martinez + * @since [v7.1.15] + */ + public static function unReassignableCount($license) : int + { + $count = 0; + if (!$license->reassignable) { + $count = licenseSeat::query()->where('unreassignable_seat', '=', true) + ->where('license_id', '=', $license->id) + ->count(); + } + return $count; + } /** * Calculates the number of remaining seats * @@ -590,11 +606,11 @@ public function getAssignedSeatsCountAttribute() * @since [v1.0] * @return int */ - public function remaincount() + public function remaincount() : int { $total = $this->licenseSeatsCount; $taken = $this->assigned_seats_count; - $unreassignable = LicenseSeat::unReassignableCount($this); + $unreassignable = self::unReassignableCount($this); $diff = ($total - $taken - $unreassignable); return (int) $diff; diff --git a/app/Models/LicenseSeat.php b/app/Models/LicenseSeat.php index f491e19c2572..6243d7d02006 100755 --- a/app/Models/LicenseSeat.php +++ b/app/Models/LicenseSeat.php @@ -2,7 +2,6 @@ namespace App\Models; -use App\Helpers\Helper; use App\Models\Traits\Acceptable; use App\Notifications\CheckinLicenseNotification; use App\Notifications\CheckoutLicenseNotification; @@ -117,33 +116,6 @@ public function location() return false; } - public static function usedSeatCount($license): array { - $total_seats_count = (int) $license->totalSeatsByLicenseID(); - $available_seats_count = $license->availCount()->count(); - $unreassignable_seats_count = self::unReassignableCount($license); - if(!$license->reassignable){ - $checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count ); - } - else { - $checkedout_seats_count = ($total_seats_count - $available_seats_count); - } - return [ - $checkedout_seats_count, - $total_seats_count, - $available_seats_count, - $unreassignable_seats_count, - ]; - } - public static function unReassignableCount($license) - { - - if (!$license->reassignable) { - $count = static::query()->where('unreassignable_seat', '=', true) - ->where('license_id', '=', $license->id) - ->count(); - return $count; - } - } /** * Query builder scope to order on department diff --git a/resources/views/licenses/view.blade.php b/resources/views/licenses/view.blade.php index 7af8676156a8..cc2f10b980a7 100755 --- a/resources/views/licenses/view.blade.php +++ b/resources/views/licenses/view.blade.php @@ -32,7 +32,7 @@ - {{ number_format($license->availCount()->count() - number_format($unreassignable_seats_count) ) }} / {{ number_format($license->seats)}} + {{ number_format($license->availCount()->count()) }} / {{ number_format($license->seats)}} @@ -573,13 +573,6 @@ class="table table-striped snipe-table" {{ trans('admin/licenses/general.bulk.checkin_all.button') }} - @elseif (! $license->reassignable) - - - - {{ trans('admin/licenses/general.bulk.checkin_all.button') }} - - @else From 5da8c86ec7a12a095b9249623aeccb5913b78a8e Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 22 Jan 2025 10:55:41 -0800 Subject: [PATCH 16/17] fix license query for bulk licenses checkin for assets --- app/Http/Controllers/Licenses/LicenseCheckinController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 30fcd1cffd51..011eca5e8150 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -152,6 +152,7 @@ public function bulkCheckin(Request $request, $licenseId) { ->get(); $count = 0; + $license = $licenseSeatsByAsset->first()?->license; foreach ($licenseSeatsByAsset as $asset_seat) { $asset_seat->asset_id = null; if ($license && ! $license->reassignable) { From 1c67d6802de6cbf71d0a85633184696bf942c834 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 27 Jan 2025 12:18:24 -0800 Subject: [PATCH 17/17] added testing to Api check in, renamed other test method --- .../Checkins/Api/LicenseCheckinTest.php | 27 +++++++++++++++++++ .../Checkins/Ui/LicenseCheckinTest.php | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/Checkins/Api/LicenseCheckinTest.php diff --git a/tests/Feature/Checkins/Api/LicenseCheckinTest.php b/tests/Feature/Checkins/Api/LicenseCheckinTest.php new file mode 100644 index 000000000000..e649b9f43b95 --- /dev/null +++ b/tests/Feature/Checkins/Api/LicenseCheckinTest.php @@ -0,0 +1,27 @@ +notReassignable() + ->assignedToUser() + ->create(); + + $this->assertEquals(false, $licenseSeat->unreassignable_seat); + + $this->actingAs(User::factory()->checkoutLicenses()->create()) + ->post(route('licenses.checkin.save', $licenseSeat)); + + $licenseSeat->refresh(); + + $this->assertEquals(true, $licenseSeat->unreassignable_seat); + } +} \ No newline at end of file diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index 5cd906fa3576..f1f912cad454 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -20,7 +20,7 @@ public function testCheckingInLicenseRequiresCorrectPermission() ->assertForbidden(); } - public function testNonReassignableLicenseSeatIsUnavailable() + public function testNonReassignableLicenseSeatCantBeCheckedOut() { $licenseSeat = LicenseSeat::factory() ->notReassignable()