Apply scope to print page

This commit is contained in:
snipe
2026-06-09 12:18:50 +01:00
parent 5257c2ce84
commit f4cac96358
4 changed files with 149 additions and 25 deletions
+13 -2
View File
@@ -10,11 +10,14 @@ use App\Http\Requests\DeleteUserRequest;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\SaveUserRequest;
use App\Mail\UnacceptedAssetReminderMail;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\Group;
use App\Models\License;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\CurrentInventory;
@@ -702,9 +705,17 @@ class UsersController extends Controller
{
$this->authorize('view', User::class);
$user = User::withInventoryRelations($id)->first();
$actor = auth()->user();
$canViewLicenses = $actor->can('view', License::class);
$canViewAccessories = $actor->can('view', Accessory::class);
$canViewConsumables = $actor->can('view', Consumable::class);
$indirectItemsCount = $user?->assets?->flatMap->assignedAssets->count() + $user?->assets?->flatMap->components->count() + $user?->assets?->flatMap->licenses->count() + $user?->assets?->flatMap->assignedAccessories->count();
$user = User::withInventoryRelations($id, $canViewLicenses, $canViewAccessories, $canViewConsumables)->first();
$indirectItemsCount = $user?->assets?->flatMap->assignedAssets->count()
+ $user?->assets?->flatMap->components->count()
+ ($canViewLicenses ? $user?->assets?->flatMap->licenses->count() : 0)
+ ($canViewAccessories ? $user?->assets?->flatMap->assignedAccessories->count() : 0);
if ($user) {
$this->authorize('view', $user);
+38 -23
View File
@@ -1522,28 +1522,38 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
}
public function scopeWithInventoryRelations($query, int $id)
public function scopeWithInventoryRelations($query, int $id, bool $withLicenses = true, bool $withAccessories = true, bool $withConsumables = true)
{
return $query->where('id', $id)
->with([
'assets.log' => fn ($query) => $query->withTrashed()
->where('target_type', User::class)
->where('target_id', $id)
->where('action_type', 'accepted'),
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'assets.assignedAssets.log' => fn ($query) => $query->withTrashed()
->where('target_type', User::class)
->where('target_id', $id)
->where('action_type', 'accepted'),
'assets.assignedAssets.assignedTo',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.components.category',
$with = [
'assets.log' => fn ($query) => $query->withTrashed()
->where('target_type', User::class)
->where('target_id', $id)
->where('action_type', 'accepted'),
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'assets.assignedAssets.log' => fn ($query) => $query->withTrashed()
->where('target_type', User::class)
->where('target_id', $id)
->where('action_type', 'accepted'),
'assets.assignedAssets.assignedTo',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.components.category',
];
if ($withLicenses) {
$with = array_merge($with, [
'assets.licenses',
'assets.licenses.category',
'directLicenses.category',
'licenses.category',
]);
}
if ($withAccessories) {
$with = array_merge($with, [
'assets.assignedAccessories',
'assets.assignedAccessories.accessory.category',
'accessories.log' => fn ($query) => $query->withTrashed()
@@ -1552,16 +1562,21 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
->where('action_type', 'accepted'),
'accessories.category',
'accessories.manufacturer',
]);
}
if ($withConsumables) {
$with = array_merge($with, [
'consumables.log' => fn ($query) => $query->withTrashed()
->where('target_type', User::class)
->where('target_id', $id)
->where('action_type', 'accepted'),
'consumables.category',
'consumables.manufacturer',
'directLicenses.category',
'licenses.category',
])
->withTrashed();
]);
}
return $query->where('id', $id)->with($with)->withTrashed();
}
/**
+10
View File
@@ -176,6 +176,7 @@
</table>
@endif
@can('view', \App\Models\License::class)
@if ($show_user->licenses->count() > 0)
<div id="licenses-toolbar">
<h4>{{ trans_choice('general.countable.licenses', $show_user->licenses->count(), ['count' => $show_user->licenses->count()]) }}</h4>
@@ -236,8 +237,10 @@
@endforeach
</table>
@endif
@endcan
@can('view', \App\Models\Accessory::class)
@if ($show_user->accessories->count() > 0)
<div id="accessories-toolbar">
<h4>{{ trans_choice('general.countable.accessories', $show_user->accessories->count(), ['count' => $show_user->accessories->count()]) }}</h4>
@@ -301,7 +304,9 @@
@endforeach
</table>
@endif
@endcan
@can('view', \App\Models\Consumable::class)
@if ($show_user->consumables->count() > 0)
<div id="consumables-toolbar">
<h4>{{ trans_choice('general.countable.consumables', $show_user->consumables->count(), ['count' => $show_user->consumables->count()]) }}</h4>
@@ -365,6 +370,7 @@
@endforeach
</table>
@endif
@endcan
@if(($indirectItemsCount ?? 0) > 0 && $settings->show_assigned_assets)
<div id="indirect-assignments-toolbar">
<h4>{{ $indirectItemsCount.' '.trans('mail.assigned_to_assets') }}</h4>
@@ -409,6 +415,7 @@
$indirectAssignmentsCounter++
@endphp
@endforeach
@can('view', \App\Models\License::class)
@foreach ($asset->licenses as $indirectLicense)
@if($indirectLicense)
<tr>
@@ -423,6 +430,7 @@
$indirectAssignmentsCounter ++
@endphp
@endforeach
@endcan
@foreach ($asset->components as $component)
@if($component)
<tr>
@@ -437,6 +445,7 @@
$indirectAssignmentsCounter ++
@endphp
@endforeach
@can('view', \App\Models\Accessory::class)
@foreach ($asset->assignedAccessories as $indirectAccessory)
@if($indirectAccessory)
<tr>
@@ -451,6 +460,7 @@
$indirectAssignmentsCounter ++
@endphp
@endforeach
@endcan
@endforeach
</table>
@endif
@@ -2,7 +2,11 @@
namespace Tests\Feature\Users\Ui;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Tests\TestCase;
@@ -51,4 +55,88 @@ class PrintUserInventoryTest extends TestCase
])
->assertOk();
}
public function test_user_without_licenses_view_cannot_see_assigned_licenses_in_print()
{
$subject = User::factory()->create();
$license = License::factory()->create(['name' => 'Unique License XYZ123']);
LicenseSeat::factory()->for($license)->assignedToUser($subject)->create();
$actor = User::factory()->viewUsers()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertDontSee('Unique License XYZ123');
}
public function test_user_with_licenses_view_can_see_assigned_licenses_in_print()
{
$subject = User::factory()->create();
$license = License::factory()->create(['name' => 'Unique License XYZ123']);
LicenseSeat::factory()->for($license)->assignedToUser($subject)->create();
$actor = User::factory()->viewUsers()->viewLicenses()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertSee('Unique License XYZ123');
}
public function test_user_without_accessories_view_cannot_see_assigned_accessories_in_print()
{
$subject = User::factory()->create();
$accessory = Accessory::factory()->create(['name' => 'Unique Accessory ABC789']);
$accessory->checkouts()->create(['assigned_to' => $subject->id, 'assigned_type' => User::class]);
$actor = User::factory()->viewUsers()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertDontSee('Unique Accessory ABC789');
}
public function test_user_with_accessories_view_can_see_assigned_accessories_in_print()
{
$subject = User::factory()->create();
$accessory = Accessory::factory()->create(['name' => 'Unique Accessory ABC789']);
$accessory->checkouts()->create(['assigned_to' => $subject->id, 'assigned_type' => User::class]);
$actor = User::factory()->viewUsers()->viewAccessories()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertSee('Unique Accessory ABC789');
}
public function test_user_without_consumables_view_cannot_see_assigned_consumables_in_print()
{
$subject = User::factory()->create();
$consumable = Consumable::factory()->create(['name' => 'Unique Consumable DEF456']);
$subject->consumables()->attach($consumable->id, ['created_by' => $subject->id]);
$actor = User::factory()->viewUsers()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertDontSee('Unique Consumable DEF456');
}
public function test_user_with_consumables_view_can_see_assigned_consumables_in_print()
{
$subject = User::factory()->create();
$consumable = Consumable::factory()->create(['name' => 'Unique Consumable DEF456']);
$subject->consumables()->attach($consumable->id, ['created_by' => $subject->id]);
$actor = User::factory()->viewUsers()->viewConsumables()->create();
$this->actingAs($actor)
->get(route('users.print', $subject))
->assertOk()
->assertSee('Unique Consumable DEF456');
}
}