From 8a0ed496235b6aa0a6b106261fdfa3fed018214b Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 13 Jan 2025 13:35:48 -0800 Subject: [PATCH 001/515] 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 373a167642..f70c01bfd3 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -69,12 +69,7 @@ class LicenseCheckinController extends Controller $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 @@ class LicenseCheckinController extends Controller $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 7ae68e9e44..742fc865e1 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 @@ class LicenseSeatsTransformer '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 @@ class LicenseSeatsTransformer 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 b297a4f720..f5b490fa14 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -156,7 +156,7 @@ class CheckoutableListener $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 4256c2c686..faac314e87 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -284,6 +284,15 @@ class LicensePresenter extends Presenter '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 74e1d7af5a..3cda5e00e5 100644 --- a/resources/lang/en-US/admin/licenses/message.php +++ b/resources/lang/en-US/admin/licenses/message.php @@ -50,7 +50,7 @@ return array( '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 099640f0b6..51e9c7299b 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -431,13 +431,16 @@ // 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 002/515] 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 95a344dce9..7230917684 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\Consumable; 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 @@ class Helper } 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 6098423ba3..8ddac020b5 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -248,16 +248,23 @@ class LicensesController extends Controller } $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 673ac06b3d..6ae57e6292 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -7,7 +7,7 @@ use App\Models\License; use Illuminate\Support\Facades\Gate; use Illuminate\Database\Eloquent\Collection; -class LicensesTransformer +class LicensesTransformer { public function transformLicenses(Collection $licenses, $total) { @@ -37,7 +37,7 @@ class LicensesTransformer '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 0997c1e57b..5ca621bce7 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -594,7 +594,8 @@ class License extends Depreciable { $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 3cda5e00e5..9a0219d857 100644 --- a/resources/lang/en-US/admin/licenses/message.php +++ b/resources/lang/en-US/admin/licenses/message.php @@ -50,7 +50,7 @@ return array( '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 2de0f9d6e0..7af8676156 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 003/515] 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 f5b490fa14..b297a4f720 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -156,7 +156,7 @@ class CheckoutableListener $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 004/515] 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 51e9c7299b..136428870d 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -432,7 +432,7 @@ 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 005/515] 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 7230917684..263204853c 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,8 +1535,8 @@ class Helper { 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 f70c01bfd3..1581fc1419 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,6 +96,7 @@ class LicenseCheckinController extends Controller $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 742fc865e1..f04c593393 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ class LicenseSeatsTransformer '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 @@ class LicenseSeatsTransformer 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 5ca621bce7..a9966c16b0 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,6 +653,7 @@ class License extends Depreciable { 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 faac314e87..4256c2c686 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -284,15 +284,6 @@ class LicensePresenter extends Presenter '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 0000000000..b0ec692ea0 --- /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 006/515] 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 1581fc1419..07b063af5e 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -95,9 +95,10 @@ class LicenseCheckinController extends Controller $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 aaf75bdc2d..2aa1c55f37 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,6 +14,7 @@ class LicenseSeatFactory extends Factory { return [ 'license_id' => License::factory(), + 'unavailable' => 0, ]; } diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index 7a6553d8ba..093455c5e7 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -20,7 +20,7 @@ class LicenseCheckinTest extends TestCase ->assertForbidden(); } - public function testCannotCheckinNonReassignableLicense() + public function testNonReassignableLicenseSeatIsUnavailable() { $licenseSeat = LicenseSeat::factory() ->notReassignable() @@ -28,13 +28,11 @@ class LicenseCheckinTest extends TestCase ->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)); - $this->assertNotNull($licenseSeat->fresh()->assigned_to); + $licenseSeat->refresh(); + + $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 007/515] 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 263204853c..a980b0efac 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ class Helper { 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 2ed7097322..1017797937 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,9 @@ class LicenseSeatsController extends Controller // 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 @@ class LicenseSeatsController extends Controller 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 07b063af5e..9d61b5e2f1 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ class LicenseCheckinController extends Controller $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 f04c593393..55c95bb54b 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ class LicenseSeatsTransformer '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 2aa1c55f37..34caeb3038 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ class LicenseSeatFactory extends Factory { 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 b0ec692ea0..be123dc276 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 @@ return new class extends Migration 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 @@ return new class extends Migration */ 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 093455c5e7..1a711306d1 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ class LicenseCheckinTest extends TestCase $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 008/515] 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 1017797937..d9a34c32be 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -139,7 +139,7 @@ class LicenseSeatsController extends Controller 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 a9966c16b0..f837fe2895 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ class License extends Depreciable { 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 009/515] 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 a980b0efac..0d7665f978 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ class Helper { 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 d9a34c32be..de1cc3b53c 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ class LicenseSeatsController extends Controller // 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 @@ class LicenseSeatsController extends Controller 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 9d61b5e2f1..94cf55380a 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ class LicenseCheckinController extends Controller $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 55c95bb54b..f79be04d09 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ class LicenseSeatsTransformer '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 f837fe2895..ac0e5a0049 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ class License extends Depreciable { 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 34caeb3038..5fad52cbb3 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ class LicenseSeatFactory extends Factory { 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 be123dc276..6d41b68b83 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 @@ return new class extends Migration 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 @@ return new class extends Migration 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 010/515] 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 5fad52cbb3..a4752f7388 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ class LicenseSeatFactory extends Factory { 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 1a711306d1..ed8604d9ac 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ class LicenseCheckinTest extends TestCase $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 011/515] 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 0d7665f978..a51c957c5a 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ class Helper { 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 de1cc3b53c..5115523c2e 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ class LicenseSeatsController extends Controller // 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 @@ class LicenseSeatsController extends Controller 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 94cf55380a..6553b9ab12 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ class LicenseCheckinController extends Controller $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 f79be04d09..ec74d74326 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ class LicenseSeatsTransformer '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 ac0e5a0049..b6fef33e1e 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ class License extends Depreciable { 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 a4752f7388..09ea283d0c 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ class LicenseSeatFactory extends Factory { 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 6d41b68b83..334104d40e 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 @@ return new class extends Migration 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 @@ return new class extends Migration 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 ed8604d9ac..d43ccb593d 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ class LicenseCheckinTest extends TestCase $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 012/515] 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 a51c957c5a..26301c1010 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1535,7 +1535,7 @@ class Helper { 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 5115523c2e..38f8babf9d 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -119,7 +119,7 @@ class LicenseSeatsController extends Controller // 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 @@ class LicenseSeatsController extends Controller 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 6553b9ab12..8bd3e34f11 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -96,7 +96,7 @@ class LicenseCheckinController extends Controller $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 8ddac020b5..f963535375 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -251,7 +251,7 @@ class LicensesController extends Controller $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 ec74d74326..e882e74a88 100644 --- a/app/Http/Transformers/LicenseSeatsTransformer.php +++ b/app/Http/Transformers/LicenseSeatsTransformer.php @@ -49,7 +49,7 @@ class LicenseSeatsTransformer '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 b6fef33e1e..0b5eed097a 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -653,7 +653,7 @@ class License extends Depreciable { 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 09ea283d0c..ee516b6dac 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -14,7 +14,7 @@ class LicenseSeatFactory extends Factory { 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 334104d40e..9aec0343ac 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 @@ return new class extends Migration 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 @@ return new class extends Migration 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 d43ccb593d..3c00d37071 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -32,7 +32,7 @@ class LicenseCheckinTest extends TestCase $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 013/515] 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 f963535375..8ddac020b5 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -251,7 +251,7 @@ class LicensesController extends Controller $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 014/515] 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 26301c1010..8f653ff353 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\Consumable; 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 @@ class Helper } 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 38f8babf9d..08b42b5a21 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -138,11 +138,12 @@ class LicenseSeatsController extends Controller 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 8ddac020b5..54a8cb2764 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -248,15 +248,8 @@ class LicensesController extends Controller } $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 e882e74a88..9868876295 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 @@ class LicenseSeatsTransformer 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 6ae57e6292..86940a8dec 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -4,6 +4,7 @@ namespace App\Http\Transformers; 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 @@ class LicensesTransformer '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 0b5eed097a..e082e6c2a0 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -594,7 +594,7 @@ class License extends Depreciable { $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 397a141468..f491e19c25 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 @@ class LicenseSeat extends SnipeModel implements ICompanyableChild 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 9aec0343ac..40c8ad5367 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 015/515] 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 08b42b5a21..0f752cbb83 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -139,7 +139,6 @@ class LicenseSeatsController extends Controller 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 8bd3e34f11..30fcd1cffd 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -97,8 +97,6 @@ class LicenseCheckinController extends Controller $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 @@ class LicenseCheckinController extends Controller $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 @@ class LicenseCheckinController extends Controller $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 54a8cb2764..7ef6eeb30b 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -249,7 +249,16 @@ class LicensesController extends Controller $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 86940a8dec..3be7b256da 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -4,7 +4,6 @@ namespace App\Http\Transformers; 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 @@ class LicensesTransformer '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 e082e6c2a0..490a8401a4 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -533,6 +533,7 @@ class License extends Depreciable return $this->licenseSeatsRelation() ->whereNull('asset_id') ->whereNull('assigned_to') + ->where('unreassignable_seat', '=', false) ->whereNull('deleted_at'); } @@ -582,7 +583,22 @@ class License extends Depreciable 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 @@ class License extends Depreciable * @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 f491e19c25..6243d7d020 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 @@ class LicenseSeat extends SnipeModel implements ICompanyableChild 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 7af8676156..cc2f10b980 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 @@ {{ 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 016/515] 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 30fcd1cffd..011eca5e81 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -152,6 +152,7 @@ class LicenseCheckinController extends Controller ->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 017/515] 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 0000000000..e649b9f43b --- /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 5cd906fa35..f1f912cad4 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -20,7 +20,7 @@ class LicenseCheckinTest extends TestCase ->assertForbidden(); } - public function testNonReassignableLicenseSeatIsUnavailable() + public function testNonReassignableLicenseSeatCantBeCheckedOut() { $licenseSeat = LicenseSeat::factory() ->notReassignable() From 0d28165c0449d100b0e73509e72daef18838f9a1 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 21 Apr 2025 10:54:01 -0700 Subject: [PATCH 018/515] merged develop, fix conflicts --- .../Checkins/Api/LicenseCheckinTest.php | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/Feature/Checkins/Api/LicenseCheckinTest.php b/tests/Feature/Checkins/Api/LicenseCheckinTest.php index e649b9f43b..385933655c 100644 --- a/tests/Feature/Checkins/Api/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Api/LicenseCheckinTest.php @@ -1,27 +1,45 @@ notReassignable() - ->assignedToUser() - ->create(); + $authUser = User::factory()->superuser()->create(); + $this->actingAsForApi($authUser); - $this->assertEquals(false, $licenseSeat->unreassignable_seat); + $license = License::factory()->create(); + $oldUser = User::factory()->create(); - $this->actingAs(User::factory()->checkoutLicenses()->create()) - ->post(route('licenses.checkin.save', $licenseSeat)); + $licenseSeat = LicenseSeat::factory()->for($license)->create([ + 'assigned_to' => $oldUser->id, + 'notes' => 'Previously checked out', + ]); + + $payload = [ + 'assigned_to' => null, + 'asset_id' => null, + 'notes' => 'Checking in the seat', + ]; + + $response = $this->patchJson( + route('api.licenses.seats.update', [$license->id, $licenseSeat->id]), + $payload); + + $response->assertStatus(200) + ->assertJsonFragment([ + 'status' => 'success', + ]); $licenseSeat->refresh(); - $this->assertEquals(true, $licenseSeat->unreassignable_seat); + $this->assertNull($licenseSeat->assigned_to); + $this->assertNull($licenseSeat->asset_id); + + $this->assertEquals('Checking in the seat', $licenseSeat->notes); } } \ No newline at end of file From 843f001bf6496b8f4568ee81da7c983b97675d10 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 23 Apr 2025 09:33:56 -0700 Subject: [PATCH 019/515] rename test class --- tests/Feature/Checkins/Api/LicenseCheckinTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/Checkins/Api/LicenseCheckinTest.php b/tests/Feature/Checkins/Api/LicenseCheckinTest.php index 385933655c..5cc983102f 100644 --- a/tests/Feature/Checkins/Api/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Api/LicenseCheckinTest.php @@ -6,7 +6,7 @@ use App\Models\LicenseSeat; use App\Models\User; use Tests\TestCase; -class LicenseCheckInTest extends TestCase { +class LicenseCheckinTest extends TestCase { public function testLicenseCheckin() { $authUser = User::factory()->superuser()->create(); From f435ebb1103d17f88d2f3cf4b73a492c97e8b2fb Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 23 Apr 2025 10:15:26 -0700 Subject: [PATCH 020/515] fix the ghosts --- tests/Feature/Checkins/Api/LicenseCheckinTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/Checkins/Api/LicenseCheckinTest.php b/tests/Feature/Checkins/Api/LicenseCheckinTest.php index 5cc983102f..385933655c 100644 --- a/tests/Feature/Checkins/Api/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Api/LicenseCheckinTest.php @@ -6,7 +6,7 @@ use App\Models\LicenseSeat; use App\Models\User; use Tests\TestCase; -class LicenseCheckinTest extends TestCase { +class LicenseCheckInTest extends TestCase { public function testLicenseCheckin() { $authUser = User::factory()->superuser()->create(); From 63ce2a14fec2551300d4c5f66a26c083a6f5b918 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 23 Apr 2025 10:17:11 -0700 Subject: [PATCH 021/515] fix the ghosts pt2 --- .../Checkins/Api/LicenseCheckInTest.php | 45 ------------------- .../Checkins/Api/LicenseCheckinTest.php | 45 ------------------- 2 files changed, 90 deletions(-) delete mode 100644 tests/Feature/Checkins/Api/LicenseCheckInTest.php delete mode 100644 tests/Feature/Checkins/Api/LicenseCheckinTest.php diff --git a/tests/Feature/Checkins/Api/LicenseCheckInTest.php b/tests/Feature/Checkins/Api/LicenseCheckInTest.php deleted file mode 100644 index 385933655c..0000000000 --- a/tests/Feature/Checkins/Api/LicenseCheckInTest.php +++ /dev/null @@ -1,45 +0,0 @@ -superuser()->create(); - $this->actingAsForApi($authUser); - - $license = License::factory()->create(); - $oldUser = User::factory()->create(); - - $licenseSeat = LicenseSeat::factory()->for($license)->create([ - 'assigned_to' => $oldUser->id, - 'notes' => 'Previously checked out', - ]); - - $payload = [ - 'assigned_to' => null, - 'asset_id' => null, - 'notes' => 'Checking in the seat', - ]; - - $response = $this->patchJson( - route('api.licenses.seats.update', [$license->id, $licenseSeat->id]), - $payload); - - $response->assertStatus(200) - ->assertJsonFragment([ - 'status' => 'success', - ]); - - $licenseSeat->refresh(); - - $this->assertNull($licenseSeat->assigned_to); - $this->assertNull($licenseSeat->asset_id); - - $this->assertEquals('Checking in the seat', $licenseSeat->notes); - } -} \ No newline at end of file diff --git a/tests/Feature/Checkins/Api/LicenseCheckinTest.php b/tests/Feature/Checkins/Api/LicenseCheckinTest.php deleted file mode 100644 index 385933655c..0000000000 --- a/tests/Feature/Checkins/Api/LicenseCheckinTest.php +++ /dev/null @@ -1,45 +0,0 @@ -superuser()->create(); - $this->actingAsForApi($authUser); - - $license = License::factory()->create(); - $oldUser = User::factory()->create(); - - $licenseSeat = LicenseSeat::factory()->for($license)->create([ - 'assigned_to' => $oldUser->id, - 'notes' => 'Previously checked out', - ]); - - $payload = [ - 'assigned_to' => null, - 'asset_id' => null, - 'notes' => 'Checking in the seat', - ]; - - $response = $this->patchJson( - route('api.licenses.seats.update', [$license->id, $licenseSeat->id]), - $payload); - - $response->assertStatus(200) - ->assertJsonFragment([ - 'status' => 'success', - ]); - - $licenseSeat->refresh(); - - $this->assertNull($licenseSeat->assigned_to); - $this->assertNull($licenseSeat->asset_id); - - $this->assertEquals('Checking in the seat', $licenseSeat->notes); - } -} \ No newline at end of file From 8c129c10af1ec052fc7849e1e8c588ec612eaf8d Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 30 Apr 2025 11:11:53 -0700 Subject: [PATCH 022/515] removed payload from api error message --- app/Http/Controllers/Api/LicenseSeatsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php index 2b5cff5e5a..d8a0dc119b 100644 --- a/app/Http/Controllers/Api/LicenseSeatsController.php +++ b/app/Http/Controllers/Api/LicenseSeatsController.php @@ -120,7 +120,7 @@ class LicenseSeatsController extends Controller return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success'))); } if( $touched && $licenseSeat->unreassignable_seat) { - return response()->json(Helper::formatStandardApiResponse('error', $licenseSeat, trans('admin/licenses/message.checkout.unavailable'))); + return response()->json(Helper::formatStandardApiResponse('error', null, 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... From 0b1be3e63b641f20e0016854c0acb3c5978172fd Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 12 May 2025 11:44:34 -0700 Subject: [PATCH 023/515] add migration, model and controller update --- .../Controllers/AssetModelsController.php | 3 +- app/Http/Controllers/LabelsController.php | 2 +- app/Models/AssetModel.php | 1 + ...03_add_req_serial_bool_to_models_table.php | 28 +++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 0795588776..1e387f149b 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -82,6 +82,7 @@ class AssetModelsController extends Controller $model->notes = $request->input('notes'); $model->created_by = auth()->id(); $model->requestable = $request->has('requestable'); + $model->require_serial = $request->has('require_serial'); if ($request->input('fieldset_id') != '') { $model->fieldset_id = $request->input('fieldset_id'); @@ -142,7 +143,7 @@ class AssetModelsController extends Controller $model->category_id = $request->input('category_id'); $model->notes = $request->input('notes'); $model->requestable = $request->input('requestable', '0'); - + $model->require_serial = $request->has('require_serial'); $model->fieldset_id = $request->input('fieldset_id'); if ($model->save()) { diff --git a/app/Http/Controllers/LabelsController.php b/app/Http/Controllers/LabelsController.php index ce5bf7d249..ed1574b77c 100755 --- a/app/Http/Controllers/LabelsController.php +++ b/app/Http/Controllers/LabelsController.php @@ -32,7 +32,7 @@ class LabelsController extends Controller $exampleAsset->id = 999999; $exampleAsset->name = 'JEN-867-5309'; - $exampleAsset->asset_tag = '100001'; + $exampleAsset->asset_tag = 'Inet Workstation (13th Gen)'; $exampleAsset->serial = 'SN9876543210'; $exampleAsset->asset_eol_date = '2025-01-01'; $exampleAsset->order_number = '12345'; diff --git a/app/Models/AssetModel.php b/app/Models/AssetModel.php index 8d60474b96..fc32e8a60f 100755 --- a/app/Models/AssetModel.php +++ b/app/Models/AssetModel.php @@ -69,6 +69,7 @@ class AssetModel extends SnipeModel 'name', 'notes', 'requestable', + 'req_serial' ]; use Searchable; diff --git a/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php new file mode 100644 index 0000000000..8288d25d95 --- /dev/null +++ b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php @@ -0,0 +1,28 @@ +boolean( 'require_serial')->after('category_id')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('models', function (Blueprint $table) { + $table->dropColumn('require_serial'); + }); + } +}; From b48f309ab63bba0304c9f63e25fa088f5d2a1e80 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 13 May 2025 10:58:05 -0700 Subject: [PATCH 024/515] add require_serial to bulk asset model blades and lang --- .../Controllers/BulkAssetModelsController.php | 4 +++- .../lang/en-US/admin/hardware/general.php | 2 ++ resources/views/models/bulk-edit.blade.php | 20 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/BulkAssetModelsController.php b/app/Http/Controllers/BulkAssetModelsController.php index 5f64ea0838..c1ecf309fb 100644 --- a/app/Http/Controllers/BulkAssetModelsController.php +++ b/app/Http/Controllers/BulkAssetModelsController.php @@ -92,7 +92,9 @@ class BulkAssetModelsController extends Controller $update_array['min_amt'] = $request->input('min_amt'); } - + if ($request->filled('require_serial')) { + $update_array['require_serial'] = $request->input('require_serial'); + } if (count($update_array) > 0) { AssetModel::whereIn('id', $models_raw_array)->update($update_array); diff --git a/resources/lang/en-US/admin/hardware/general.php b/resources/lang/en-US/admin/hardware/general.php index 6740476574..85d6d19480 100644 --- a/resources/lang/en-US/admin/hardware/general.php +++ b/resources/lang/en-US/admin/hardware/general.php @@ -21,6 +21,8 @@ return [ 'requested' => 'Requested', 'not_requestable' => 'Not Requestable', 'requestable_status_warning' => 'Do not change requestable status', + 'require_serial' => 'Require Serial Number', + 'require_serial_help' => 'A serial number will be required when creating an asset of this model.', 'restore' => 'Restore Asset', 'pending' => 'Pending', 'undeployable' => 'Undeployable', diff --git a/resources/views/models/bulk-edit.blade.php b/resources/views/models/bulk-edit.blade.php index 8131a470bc..2e8d4925b4 100644 --- a/resources/views/models/bulk-edit.blade.php +++ b/resources/views/models/bulk-edit.blade.php @@ -91,7 +91,27 @@ @include ('partials.forms.edit.minimum_quantity') + +
From f2bca9491cd6f43085609e184b9303bd9917f104 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 13 May 2025 10:59:02 -0700 Subject: [PATCH 025/515] changed name of field in model fillable --- app/Models/AssetModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/AssetModel.php b/app/Models/AssetModel.php index fc32e8a60f..cd1376c475 100755 --- a/app/Models/AssetModel.php +++ b/app/Models/AssetModel.php @@ -69,7 +69,7 @@ class AssetModel extends SnipeModel 'name', 'notes', 'requestable', - 'req_serial' + 'require_serial' ]; use Searchable; From fcbfbca6d01666909c3202ecd07891950da81f88 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 13 May 2025 11:10:46 -0700 Subject: [PATCH 026/515] add checkbox to model edit and create --- .../Controllers/AssetModelsController.php | 4 ++-- .../lang/en-US/admin/hardware/general.php | 2 +- resources/views/models/edit.blade.php | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 1e387f149b..e99641d68a 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -82,7 +82,7 @@ class AssetModelsController extends Controller $model->notes = $request->input('notes'); $model->created_by = auth()->id(); $model->requestable = $request->has('requestable'); - $model->require_serial = $request->has('require_serial'); + $model->require_serial = $request->input('require_serial'); if ($request->input('fieldset_id') != '') { $model->fieldset_id = $request->input('fieldset_id'); @@ -143,7 +143,7 @@ class AssetModelsController extends Controller $model->category_id = $request->input('category_id'); $model->notes = $request->input('notes'); $model->requestable = $request->input('requestable', '0'); - $model->require_serial = $request->has('require_serial'); + $model->require_serial = $request->input('require_serial'); $model->fieldset_id = $request->input('fieldset_id'); if ($model->save()) { diff --git a/resources/lang/en-US/admin/hardware/general.php b/resources/lang/en-US/admin/hardware/general.php index 85d6d19480..235e1a3dc5 100644 --- a/resources/lang/en-US/admin/hardware/general.php +++ b/resources/lang/en-US/admin/hardware/general.php @@ -22,7 +22,7 @@ return [ 'not_requestable' => 'Not Requestable', 'requestable_status_warning' => 'Do not change requestable status', 'require_serial' => 'Require Serial Number', - 'require_serial_help' => 'A serial number will be required when creating an asset of this model.', + 'require_serial_help' => 'A serial number will be required when creating a new asset of this model.', 'restore' => 'Restore Asset', 'pending' => 'Pending', 'undeployable' => 'Undeployable', diff --git a/resources/views/models/edit.blade.php b/resources/views/models/edit.blade.php index 9c72107ef8..6bc187a1b3 100755 --- a/resources/views/models/edit.blade.php +++ b/resources/views/models/edit.blade.php @@ -17,6 +17,27 @@ @include ('partials.forms.edit.depreciation') @include ('partials.forms.edit.minimum_quantity') + +
+ + +
+
+ require_serial)) id="require_serial" aria-label="require_serial" /> + + + {{ trans('admin/hardware/general.require_serial_help') }} + +
+
+
From 7fd93645b3928a7889ca8a12ea9a2bec7654655a Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 13 May 2025 12:17:58 -0700 Subject: [PATCH 027/515] valdiation fires for asset creation --- app/Http/Controllers/Assets/AssetsController.php | 11 ++++++++++- resources/lang/en-US/admin/hardware/form.php | 1 + resources/views/partials/forms/edit/serial.blade.php | 6 +++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index 12cb93ff3e..35cfade51e 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -120,9 +120,18 @@ class AssetsController extends Controller for ($a = 1; $a <= count($asset_tags); $a++) { $asset = new Asset(); - $asset->model()->associate(AssetModel::find($request->input('model_id'))); + $model = AssetModel::find($request->input('model_id')); + $asset->model()->associate($model); $asset->name = $request->input('name'); + //Validate required serial based on model setting + if ($model && $model->require_serial === 1 && empty($serials[$a] ?? null)) { + return redirect()->back() + ->withInput() + ->withErrors([ + "serials.$a" => trans('admin/hardware/form.serial_required'), + ]); + } // Check for a corresponding serial if (($serials) && (array_key_exists($a, $serials))) { $asset->serial = $serials[$a]; diff --git a/resources/lang/en-US/admin/hardware/form.php b/resources/lang/en-US/admin/hardware/form.php index 8fbd0b4e87..b741e1ba1a 100644 --- a/resources/lang/en-US/admin/hardware/form.php +++ b/resources/lang/en-US/admin/hardware/form.php @@ -44,6 +44,7 @@ return [ 'redirect_to_checked_out_to' => 'Go to Checked Out to', 'select_statustype' => 'Select Status Type', 'serial' => 'Serial', + 'serial_required' => 'This asset model requires a serial number', 'status' => 'Status', 'tag' => 'Asset Tag', 'update' => 'Asset Update', diff --git a/resources/views/partials/forms/edit/serial.blade.php b/resources/views/partials/forms/edit/serial.blade.php index 636204a564..4ed4ad66a1 100644 --- a/resources/views/partials/forms/edit/serial.blade.php +++ b/resources/views/partials/forms/edit/serial.blade.php @@ -3,6 +3,10 @@
- {!! $errors->first('serial', '') !!} + @error($old_val_name ?? $fieldname) + + @enderror
From 720a4bc4a248a6372a0d3bc5b91c9c25ab32dd2e Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 13 May 2025 12:54:28 -0700 Subject: [PATCH 028/515] add warning to update method for missing a serial --- app/Http/Controllers/Assets/AssetsController.php | 7 +++++++ resources/lang/en-US/admin/hardware/form.php | 1 + 2 files changed, 8 insertions(+) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index 35cfade51e..da59fdb1a1 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -422,6 +422,13 @@ class AssetsController extends Controller session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]); + //Validate required serial based on model setting + if ($model && $model->require_serial === 1 && empty($serial[1] ?? null)) { + return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) + ->with('warning', trans('admin/hardware/form.serial_required_post_model_update', [ + 'asset_model' => $model->name + ])); + } if ($asset->save()) { return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) ->with('success', trans('admin/hardware/message.update.success')); diff --git a/resources/lang/en-US/admin/hardware/form.php b/resources/lang/en-US/admin/hardware/form.php index b741e1ba1a..0516ecbc18 100644 --- a/resources/lang/en-US/admin/hardware/form.php +++ b/resources/lang/en-US/admin/hardware/form.php @@ -45,6 +45,7 @@ return [ 'select_statustype' => 'Select Status Type', 'serial' => 'Serial', 'serial_required' => 'This asset model requires a serial number', + 'serial_required_post_model_update' => ':asset_model have been updated to require a serial number. Please add a serial number for this asset.', 'status' => 'Status', 'tag' => 'Asset Tag', 'update' => 'Asset Update', From 8c0281bf70387e4373f414bb389ab7121a112138 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 14 May 2025 12:31:27 -0700 Subject: [PATCH 029/515] adds tests for requiring serial to asset model --- tests/Feature/Assets/Ui/StoreAssetsTest.php | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/Feature/Assets/Ui/StoreAssetsTest.php b/tests/Feature/Assets/Ui/StoreAssetsTest.php index 8abea545cf..baa9babcc0 100644 --- a/tests/Feature/Assets/Ui/StoreAssetsTest.php +++ b/tests/Feature/Assets/Ui/StoreAssetsTest.php @@ -2,6 +2,8 @@ namespace Tests\Feature\Assets\Ui; +use App\Models\Asset; +use App\Models\AssetModel; use App\Models\User; use Tests\TestCase; @@ -13,4 +15,63 @@ class StoreAssetsTest extends TestCase ->get(route('hardware.create')) ->assertOk(); } + + public function testAssetCanBeStoredWithSerialRequiredAndSerialProvided() + { + $user = User::factory()->superuser()->create(); + $this->actingAs($user); + + $model = AssetModel::factory()->create([ + 'require_serial' => 1, + ]); + + $response = $this->post(route('hardware.store'), [ + 'model_id' => $model->id, + 'serials' => [1 => 'ABC123'], + 'asset_tags' =>[1 => '1234'], + 'status_id' => 1, + // other required fields... + ]); + + $response->assertRedirect(); + $response->assertSessionHas('success-unescaped'); + $this->assertNotEquals( + trans('admin/hardware/form.serial_required'), + session('error') + ); + $this->assertDatabaseHas('assets', [ + 'model_id' => $model->id, + 'serial' => 'ABC123', + 'asset_tag' => '1234', + ]); + + + } + + public function testAssetCannotBeStoredIfSerialRequiredAndMissing() + { + $user = User::factory()->superuser()->create(); + $this->actingAs($user); + + $model = AssetModel::factory()->create([ + 'require_serial' => 1, + ]); + + $response = $this->post(route('hardware.store'), [ + 'model_id' => $model->id, + 'serials' => [], // ← serial missing + 'asset_tags' => [1 => '1234'], + 'status_id' => 1, + ]); + + $response->assertRedirect(); + $response->assertSessionHasErrors(['serials.1']); + + $this->assertDatabaseMissing('assets', [ + 'model_id' => $model->id, + 'asset_tag' => '1234', + ]); + + $response->assertSessionMissing('success-unescaped'); + } } From c22efc2c3db08cddac74709b42bbdf57afbc0af7 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 14 May 2025 12:55:41 -0700 Subject: [PATCH 030/515] add to present and transformer and api --- app/Http/Controllers/Api/AssetModelsController.php | 2 ++ app/Http/Transformers/AssetModelsTransformer.php | 1 + app/Presenters/AssetModelPresenter.php | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/app/Http/Controllers/Api/AssetModelsController.php b/app/Http/Controllers/Api/AssetModelsController.php index 954da30870..ad1ddf6543 100644 --- a/app/Http/Controllers/Api/AssetModelsController.php +++ b/app/Http/Controllers/Api/AssetModelsController.php @@ -50,6 +50,7 @@ class AssetModelsController extends Controller 'fieldset', 'deleted_at', 'updated_at', + 'require_serial', ]; $assetmodels = AssetModel::select([ @@ -69,6 +70,7 @@ class AssetModelsController extends Controller 'models.fieldset_id', 'models.deleted_at', 'models.updated_at', + 'models.require_serial' ]) ->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues', 'adminuser') ->withCount('assets as assets_count'); diff --git a/app/Http/Transformers/AssetModelsTransformer.php b/app/Http/Transformers/AssetModelsTransformer.php index 2d47ca47db..9c21d72422 100644 --- a/app/Http/Transformers/AssetModelsTransformer.php +++ b/app/Http/Transformers/AssetModelsTransformer.php @@ -65,6 +65,7 @@ class AssetModelsTransformer 'default_fieldset_values' => $default_field_values, 'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol.' months' : 'None', 'requestable' => ($assetmodel->requestable == '1') ? true : false, + 'require_serial' => $assetmodel->require_serial, 'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes), 'created_by' => ($assetmodel->adminuser) ? [ 'id' => (int) $assetmodel->adminuser->id, diff --git a/app/Presenters/AssetModelPresenter.php b/app/Presenters/AssetModelPresenter.php index 2ed019eaea..601a59fabe 100644 --- a/app/Presenters/AssetModelPresenter.php +++ b/app/Presenters/AssetModelPresenter.php @@ -142,6 +142,14 @@ class AssetModelPresenter extends Presenter 'title' => trans('admin/hardware/general.requestable'), 'formatter' => 'trueFalseFormatter', ], + [ + 'field' => 'require_serial', + 'searchable' => false, + 'sortable' => true, + 'visible' => false, + 'title' => trans('admin/hardware/general.require_serial'), + 'formatter' => 'trueFalseFormatter', + ], [ 'field' => 'notes', 'searchable' => true, From 3fbbff5a4733d81ac0355aed9dd8e71f2dc369f4 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 14 May 2025 12:57:01 -0700 Subject: [PATCH 031/515] revert unnecessary change to laels --- app/Http/Controllers/LabelsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/LabelsController.php b/app/Http/Controllers/LabelsController.php index ed1574b77c..ce5bf7d249 100755 --- a/app/Http/Controllers/LabelsController.php +++ b/app/Http/Controllers/LabelsController.php @@ -32,7 +32,7 @@ class LabelsController extends Controller $exampleAsset->id = 999999; $exampleAsset->name = 'JEN-867-5309'; - $exampleAsset->asset_tag = 'Inet Workstation (13th Gen)'; + $exampleAsset->asset_tag = '100001'; $exampleAsset->serial = 'SN9876543210'; $exampleAsset->asset_eol_date = '2025-01-01'; $exampleAsset->order_number = '12345'; From 9200de5032a368dc5abdb9d3c1a9a9271449a436 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 19 May 2025 09:58:37 -0700 Subject: [PATCH 032/515] made require_serial column nullable --- .../2025_05_12_183803_add_req_serial_bool_to_models_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php index 8288d25d95..58a57a871a 100644 --- a/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php +++ b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php @@ -12,7 +12,7 @@ return new class extends Migration public function up(): void { Schema::table('models', function (Blueprint $table) { - $table->boolean( 'require_serial')->after('category_id')->default(false); + $table->boolean( 'require_serial')->after('category_id')->default(0)->nullable(); }); } From d45bd67cae267727690bc25f97a9526592a2e9f2 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 20 May 2025 09:51:02 -0700 Subject: [PATCH 033/515] added corrections --- app/Http/Controllers/AssetModelsController.php | 4 ++-- app/Http/Controllers/Assets/AssetsController.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index e99641d68a..0bbe19bdc6 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -82,7 +82,7 @@ class AssetModelsController extends Controller $model->notes = $request->input('notes'); $model->created_by = auth()->id(); $model->requestable = $request->has('requestable'); - $model->require_serial = $request->input('require_serial'); + $model->require_serial = $request->input('require_serial', 0); if ($request->input('fieldset_id') != '') { $model->fieldset_id = $request->input('fieldset_id'); @@ -143,7 +143,7 @@ class AssetModelsController extends Controller $model->category_id = $request->input('category_id'); $model->notes = $request->input('notes'); $model->requestable = $request->input('requestable', '0'); - $model->require_serial = $request->input('require_serial'); + $model->require_serial = $request->input('require_serial', 0); $model->fieldset_id = $request->input('fieldset_id'); if ($model->save()) { diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index da59fdb1a1..dd369f07b8 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -125,7 +125,7 @@ class AssetsController extends Controller $asset->name = $request->input('name'); //Validate required serial based on model setting - if ($model && $model->require_serial === 1 && empty($serials[$a] ?? null)) { + if ($model && $model->require_serial === 1 && empty($serials[$a])) { return redirect()->back() ->withInput() ->withErrors([ @@ -423,7 +423,7 @@ class AssetsController extends Controller session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]); //Validate required serial based on model setting - if ($model && $model->require_serial === 1 && empty($serial[1] ?? null)) { + if ($model && $model->require_serial === 1 && empty($serial[1])) { return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) ->with('warning', trans('admin/hardware/form.serial_required_post_model_update', [ 'asset_model' => $model->name From 732c3dae899bab46c18bdc206f0440cd334619b8 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 20 May 2025 09:53:51 -0700 Subject: [PATCH 034/515] added require_serial to model factory --- database/factories/AssetModelFactory.php | 1 + .../2025_05_12_183803_add_req_serial_bool_to_models_table.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/database/factories/AssetModelFactory.php b/database/factories/AssetModelFactory.php index 3adb933e3e..ac31b57984 100644 --- a/database/factories/AssetModelFactory.php +++ b/database/factories/AssetModelFactory.php @@ -33,6 +33,7 @@ class AssetModelFactory extends Factory 'category_id' => Category::factory(), 'model_number' => $this->faker->creditCardNumber(), 'notes' => 'Created by demo seeder', + 'require_serial' => 0, ]; } diff --git a/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php index 58a57a871a..ee0e37a628 100644 --- a/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php +++ b/database/migrations/2025_05_12_183803_add_req_serial_bool_to_models_table.php @@ -12,7 +12,7 @@ return new class extends Migration public function up(): void { Schema::table('models', function (Blueprint $table) { - $table->boolean( 'require_serial')->after('category_id')->default(0)->nullable(); + $table->boolean( 'require_serial')->after('category_id')->default(0); }); } From b0067fee510de306655e45e0c08fedb15245e281 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 20 May 2025 12:31:34 -0700 Subject: [PATCH 035/515] remove some N+1s, collect an array of missing serial errors --- .../Controllers/Assets/AssetsController.php | 36 +++++++++++-------- resources/lang/en-US/admin/hardware/form.php | 2 +- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index dd369f07b8..7f10f6ff62 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -110,28 +110,37 @@ class AssetsController extends Controller // This is only necessary on create, not update, since bulk editing is handled // differently $asset_tags = $request->input('asset_tags'); + $model = AssetModel::find($request->input('model_id')); + $serial_errors = []; + $serials = $request->input('serials'); $settings = Setting::getSettings(); + //Validate required serial based on model setting + for ($a = 1, $aMax = count($asset_tags); $a <= $aMax; $a++) { + if ($model && $model->require_serial === 1 && empty($serials[$a])) { + $serial_errors["serials.$a"] = trans('admin/hardware/form.serial_required', ['number' => $a]); + } + + } + + if (!empty($serial_errors)) { + return redirect()->back() + ->withInput() + ->withErrors($serial_errors); + } + + $asset = null; + $companyId = Company::getIdForCurrentUser($request->input('company_id')); $successes = []; $failures = []; - $serials = $request->input('serials'); - $asset = null; - for ($a = 1; $a <= count($asset_tags); $a++) { + for ($a = 1, $aMax = count($asset_tags); $a <= $aMax; $a++) { $asset = new Asset(); - $model = AssetModel::find($request->input('model_id')); + $asset->model()->associate($model); $asset->name = $request->input('name'); - //Validate required serial based on model setting - if ($model && $model->require_serial === 1 && empty($serials[$a])) { - return redirect()->back() - ->withInput() - ->withErrors([ - "serials.$a" => trans('admin/hardware/form.serial_required'), - ]); - } // Check for a corresponding serial if (($serials) && (array_key_exists($a, $serials))) { $asset->serial = $serials[$a]; @@ -141,7 +150,7 @@ class AssetsController extends Controller $asset->asset_tag = $asset_tags[$a]; } - $asset->company_id = Company::getIdForCurrentUser($request->input('company_id')); + $asset->company_id = $companyId; $asset->model_id = $request->input('model_id'); $asset->order_number = $request->input('order_number'); $asset->notes = $request->input('notes'); @@ -173,7 +182,6 @@ class AssetsController extends Controller // Update custom fields in the database. // Validation for these fields is handled through the AssetRequest form request - $model = AssetModel::find($request->get('model_id')); if (($model) && ($model->fieldset)) { foreach ($model->fieldset->fields as $field) { diff --git a/resources/lang/en-US/admin/hardware/form.php b/resources/lang/en-US/admin/hardware/form.php index 0516ecbc18..dc4754e71a 100644 --- a/resources/lang/en-US/admin/hardware/form.php +++ b/resources/lang/en-US/admin/hardware/form.php @@ -44,7 +44,7 @@ return [ 'redirect_to_checked_out_to' => 'Go to Checked Out to', 'select_statustype' => 'Select Status Type', 'serial' => 'Serial', - 'serial_required' => 'This asset model requires a serial number', + 'serial_required' => 'Asset :number requires a serial number', 'serial_required_post_model_update' => ':asset_model have been updated to require a serial number. Please add a serial number for this asset.', 'status' => 'Status', 'tag' => 'Asset Tag', From 2b8ea9a233a4c26267de7c37538c9ee736bd65d7 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 7 Jul 2025 10:46:54 -0700 Subject: [PATCH 036/515] add required to input validation --- resources/views/partials/forms/edit/serial.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/partials/forms/edit/serial.blade.php b/resources/views/partials/forms/edit/serial.blade.php index 4ed4ad66a1..057fae0eea 100644 --- a/resources/views/partials/forms/edit/serial.blade.php +++ b/resources/views/partials/forms/edit/serial.blade.php @@ -2,7 +2,7 @@
- + model && $item->model->require_serial)) ? ' required' : '' }} maxlength="191" /> @error($old_val_name ?? $fieldname)