From 6872f8da7beacb1d1c468cad721c6154bdd33673 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 19 Apr 2023 17:31:09 -0700 Subject: [PATCH 01/74] adding total cost to user view --- app/Models/User.php | 20 +++++++++++++++++++ resources/lang/en/admin/users/table.php | 1 + resources/views/users/view.blade.php | 26 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/app/Models/User.php b/app/Models/User.php index 44bffe156d..efd7d537ba 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -766,4 +766,24 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo { return $this->locale; } + public function getUserTotalCost(){ + $total_cost= array(); + $asset_cost= 0; + $license_cost= 0; + $accessory_cost= 0; + foreach ($this->assets as $asset){ + $asset_cost += $asset->purchase_cost; + array_push($total_cost, $asset_cost); + } + foreach ($this->licenses as $license){ + $license_cost += $license->purchase_cost; + array_push($total_cost, $license_cost); + } + foreach ($this->accessories as $accessory){ + $accessory_cost += $accessory->purchase_cost; + array_push($total_cost, $accessory_cost); + } + + return $total_cost; + } } diff --git a/resources/lang/en/admin/users/table.php b/resources/lang/en/admin/users/table.php index e318d51545..21e2154280 100644 --- a/resources/lang/en/admin/users/table.php +++ b/resources/lang/en/admin/users/table.php @@ -29,6 +29,7 @@ return array( 'show_deleted' => 'Show Deleted Users', 'title' => 'Title', 'to_restore_them' => 'to restore them.', + 'total_assets_cost' => "Total Assets Cost", 'updateuser' => 'Update User', 'username' => 'Username', 'user_deleted_text' => 'This user has been marked as deleted.', diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index 47d6dea328..f6f6abd7f2 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -638,6 +638,26 @@ @endif +
+ +
+ {{ trans('admin/users/table.total_assets_cost') }} +
+
+ {{Helper::formatCurrencyOutput(array_sum(array ($user->getUserTotalCost())))}} + + + {{ trans('admin/hardware/form.optional_infos') }} + +
+ +
@@ -1109,6 +1129,12 @@ $(function () { } }); + $("#optional_info").on("click",function(){ + $('#optional_details').fadeToggle(100); + $('#optional_info_icon').toggleClass('fa-caret-right fa-caret-down'); + var optional_info_open = $('#optional_info_icon').hasClass('fa-caret-down'); + document.cookie = "optional_info_open="+optional_info_open+'; path=/'; + }); }); From 97df39001dec0ee9529ebce8fcdbd94a58d70b8b Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 19 Apr 2023 17:51:37 -0700 Subject: [PATCH 02/74] adds optional breakdowns for total cost --- app/Models/User.php | 12 +++++++----- resources/views/users/view.blade.php | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index efd7d537ba..32a11c8a09 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -767,23 +767,25 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo return $this->locale; } public function getUserTotalCost(){ - $total_cost= array(); $asset_cost= 0; $license_cost= 0; $accessory_cost= 0; foreach ($this->assets as $asset){ $asset_cost += $asset->purchase_cost; - array_push($total_cost, $asset_cost); + $this->asset_cost = $asset_cost; } foreach ($this->licenses as $license){ $license_cost += $license->purchase_cost; - array_push($total_cost, $license_cost); + $this->license_cost = $license_cost; } foreach ($this->accessories as $accessory){ $accessory_cost += $accessory->purchase_cost; - array_push($total_cost, $accessory_cost); + $this->accessory_cost = $accessory_cost; } - return $total_cost; + $this->total_user_cost = ($asset_cost + $accessory_cost + $license_cost); + + + return $this; } } diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index f6f6abd7f2..50937e9e6a 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -644,7 +644,7 @@ {{ trans('admin/users/table.total_assets_cost') }} - From 56fb45f1eafb6855669218cae72603b23ec814da Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Thu, 17 Aug 2023 18:01:26 -0700 Subject: [PATCH 04/74] WIP: Add last_checkin to assets table --- ...8_17_202638_add_last_checkin_to_assets.php | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php diff --git a/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php b/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php new file mode 100644 index 0000000000..c00a9d5c7b --- /dev/null +++ b/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php @@ -0,0 +1,36 @@ +dateTime('last_checkin')->after('last_checkout')->nullable(); + }); + + DB::statement( + "UPDATE " . DB::getTablePrefix() . "assets SET last_checkin=(SELECT MAX(" . DB::getTablePrefix() . "action_logs.action_date) FROM " . DB::getTablePrefix() . "action_logs WHERE item_type='App\\\Models\\\Asset' AND " . DB::getTablePrefix() . "action_logs.item_id=" . DB::getTablePrefix() . "assets.id AND " . DB::getTablePrefix() . "action_logs.action_type='checkin from'" + ); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('assets', function (Blueprint $table) { + $table->dropColumn('last_checkin'); + }); + } +} From 8b2716d2b70a047ba2e4dace921771c8aedd3ce8 Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Thu, 17 Aug 2023 18:33:01 -0700 Subject: [PATCH 05/74] Fix update statement --- .../migrations/2023_08_17_202638_add_last_checkin_to_assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php b/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php index c00a9d5c7b..74048ce941 100644 --- a/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php +++ b/database/migrations/2023_08_17_202638_add_last_checkin_to_assets.php @@ -18,7 +18,7 @@ class AddLastCheckinToAssets extends Migration }); DB::statement( - "UPDATE " . DB::getTablePrefix() . "assets SET last_checkin=(SELECT MAX(" . DB::getTablePrefix() . "action_logs.action_date) FROM " . DB::getTablePrefix() . "action_logs WHERE item_type='App\\\Models\\\Asset' AND " . DB::getTablePrefix() . "action_logs.item_id=" . DB::getTablePrefix() . "assets.id AND " . DB::getTablePrefix() . "action_logs.action_type='checkin from'" + "UPDATE " . DB::getTablePrefix() . "assets SET last_checkin=(SELECT MAX(" . DB::getTablePrefix() . "action_logs.action_date) FROM " . DB::getTablePrefix() . "action_logs WHERE item_type='App\\\Models\\\Asset' AND " . DB::getTablePrefix() . "action_logs.item_id=" . DB::getTablePrefix() . "assets.id AND " . DB::getTablePrefix() . "action_logs.action_type='checkin from')" ); } From 489d30c68569ed9206cf7b57a2128ecfda90d4e2 Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Mon, 21 Aug 2023 11:57:33 -0700 Subject: [PATCH 06/74] Set last_checkin in ui and api controllers --- app/Http/Controllers/Api/AssetsController.php | 1 + app/Http/Controllers/Assets/AssetCheckinController.php | 1 + app/Models/Asset.php | 1 + 3 files changed, 3 insertions(+) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index e8f37d8574..584e4693d2 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -905,6 +905,7 @@ class AssetsController extends Controller $asset->expected_checkin = null; $asset->last_checkout = null; + $asset->last_checkin = now(); $asset->assigned_to = null; $asset->assignedTo()->disassociate($asset); $asset->accepted = null; diff --git a/app/Http/Controllers/Assets/AssetCheckinController.php b/app/Http/Controllers/Assets/AssetCheckinController.php index fd5cee30ea..5f79e7b19c 100644 --- a/app/Http/Controllers/Assets/AssetCheckinController.php +++ b/app/Http/Controllers/Assets/AssetCheckinController.php @@ -68,6 +68,7 @@ class AssetCheckinController extends Controller $asset->expected_checkin = null; $asset->last_checkout = null; + $asset->last_checkin = now(); $asset->assigned_to = null; $asset->assignedTo()->disassociate($asset); $asset->assigned_type = null; diff --git a/app/Models/Asset.php b/app/Models/Asset.php index 95e1c3a166..ccdabdb2e4 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -73,6 +73,7 @@ class Asset extends Depreciable protected $casts = [ 'purchase_date' => 'date', 'last_checkout' => 'datetime', + 'last_checkin' => 'datetime', 'expected_checkin' => 'date', 'last_audit_date' => 'datetime', 'next_audit_date' => 'date', From 6fc06f2ee1710ef30d3e59c10167addc6dc1f8d0 Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Mon, 21 Aug 2023 12:31:51 -0700 Subject: [PATCH 07/74] Add simple tests around asset check in --- tests/Feature/Api/Assets/AssetCheckinTest.php | 30 +++++++++++++++++ tests/Feature/Assets/AssetCheckinTest.php | 32 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/Feature/Api/Assets/AssetCheckinTest.php create mode 100644 tests/Feature/Assets/AssetCheckinTest.php diff --git a/tests/Feature/Api/Assets/AssetCheckinTest.php b/tests/Feature/Api/Assets/AssetCheckinTest.php new file mode 100644 index 0000000000..f71191d80c --- /dev/null +++ b/tests/Feature/Api/Assets/AssetCheckinTest.php @@ -0,0 +1,30 @@ +superuser()->create(); + $asset = Asset::factory()->create(['last_checkin' => null]); + + $asset->checkOut(User::factory()->create(), $admin, now()); + + $this->actingAsForApi($admin) + ->postJson(route('api.asset.checkin', $asset)) + ->assertOk(); + + $this->assertNotNull( + $asset->fresh()->last_checkin, + 'last_checkin field should be set on checkin' + ); + } +} diff --git a/tests/Feature/Assets/AssetCheckinTest.php b/tests/Feature/Assets/AssetCheckinTest.php new file mode 100644 index 0000000000..059fb1294f --- /dev/null +++ b/tests/Feature/Assets/AssetCheckinTest.php @@ -0,0 +1,32 @@ +superuser()->create(); + $asset = Asset::factory()->create(['last_checkin' => null]); + + $asset->checkOut(User::factory()->create(), $admin, now()); + + $this->actingAs($admin) + ->post(route('hardware.checkin.store', [ + 'assetId' => $asset->id, + ])) + ->assertRedirect(); + + $this->assertNotNull( + $asset->fresh()->last_checkin, + 'last_checkin field should be set on checkin' + ); + } +} From c332b98456c9a8e982dbbbc6d44e1ad1891aa2af Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Mon, 21 Aug 2023 13:44:49 -0700 Subject: [PATCH 08/74] Add last checkin options to report front end --- app/Http/Controllers/ReportsController.php | 17 +++++++++++++++ resources/lang/en/admin/hardware/table.php | 1 + resources/views/reports/custom.blade.php | 22 +++++++++++++++++++ tests/Feature/Reports/CustomReportTest.php | 25 ++++++++++++++++++++++ 4 files changed, 65 insertions(+) diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index c9a88ea0f1..ed67c6e625 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -545,6 +545,10 @@ class ReportsController extends Controller $header[] = trans('admin/hardware/table.checkout_date'); } + if ($request->filled('checkin_date')) { + $header[] = trans('admin/hardware/table.last_checkin_date'); + } + if ($request->filled('expected_checkin')) { $header[] = trans('admin/hardware/form.expected_checkin'); } @@ -651,6 +655,13 @@ class ReportsController extends Controller $assets->whereBetween('assets.last_checkout', [$checkout_start, $checkout_end]); } + if (($request->filled('checkin_date_start')) && ($request->filled('checkin_date_end'))) { + $assets->whereBetween('last_checkin', [ + Carbon::parse($request->input('checkin_date_start'))->startOfDay(), + Carbon::parse($request->input('checkin_date_end'))->endOfDay(), + ]); + } + if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) { $assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]); } @@ -835,6 +846,12 @@ class ReportsController extends Controller $row[] = ($asset->last_checkout) ? $asset->last_checkout : ''; } + if ($request->filled('checkin_date')) { + $row[] = ($asset->last_checkin) + ? Carbon::parse($asset->last_checkin)->format('Y-m-d') + : ''; + } + if ($request->filled('expected_checkin')) { $row[] = ($asset->expected_checkin) ? $asset->expected_checkin : ''; } diff --git a/resources/lang/en/admin/hardware/table.php b/resources/lang/en/admin/hardware/table.php index 10629fd22c..06b60bfd83 100644 --- a/resources/lang/en/admin/hardware/table.php +++ b/resources/lang/en/admin/hardware/table.php @@ -14,6 +14,7 @@ return [ 'dl_csv' => 'Download CSV', 'eol' => 'EOL', 'id' => 'ID', + 'last_checkin_date' => 'Last Checkin Date', 'location' => 'Location', 'purchase_cost' => 'Cost', 'purchase_date' => 'Purchased', diff --git a/resources/views/reports/custom.blade.php b/resources/views/reports/custom.blade.php index ff78f21686..5b0bd384ee 100644 --- a/resources/views/reports/custom.blade.php +++ b/resources/views/reports/custom.blade.php @@ -141,6 +141,11 @@ {{ trans('admin/hardware/table.checkout_date') }} + +