Merge remote-tracking branch 'origin/develop'
Some checks are pending
CodeQL Security Scan / CodeQL Security Scan (javascript) (push) Waiting to run
Codacy Security Scan / Codacy Security Scan (push) Waiting to run
Docker images (Alpine) / docker (push) Waiting to run
Docker images / docker (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.1) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.2) (push) Waiting to run
Tests in MySQL / PHP ${{ matrix.php-version }} (8.3) (push) Waiting to run
Tests in SQLite / PHP ${{ matrix.php-version }} (8.1.1) (push) Waiting to run

This commit is contained in:
snipe 2024-08-28 12:50:19 +01:00
commit 6f3fb21fef
11 changed files with 150 additions and 14 deletions

View file

@ -78,6 +78,10 @@ class AssetModelsController extends Controller
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
}
if ($request->filled('depreciation_id')) {
$assetmodels = $assetmodels->where('models.depreciation_id', '=', $request->input('depreciation_id'));
}
if ($request->filled('search')) {
$assetmodels->TextSearch($request->input('search'));
}

View file

@ -20,9 +20,22 @@ class DepreciationsController extends Controller
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$allowed_columns = ['id','name','months','depreciation_min', 'depreciation_type','created_at'];
$allowed_columns = [
'id',
'name',
'months',
'depreciation_min',
'depreciation_type',
'created_at',
'assets_count',
'models_count',
'licenses_count',
];
$depreciations = Depreciation::select('id','name','months','depreciation_min','depreciation_type','user_id','created_at','updated_at');
$depreciations = Depreciation::select('id','name','months','depreciation_min','depreciation_type','user_id','created_at','updated_at')
->withCount('assets as assets_count')
->withCount('models as models_count')
->withCount('licenses as licenses_count');
if ($request->filled('search')) {
$depreciations = $depreciations->TextSearch($request->input('search'));

View file

@ -193,13 +193,20 @@ class DepreciationsController extends Controller
*/
public function show($id) : View | RedirectResponse
{
if (is_null($depreciation = Depreciation::find($id))) {
// Redirect to the blogs management page
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
$depreciation = Depreciation::withCount('assets as assets_count')
->withCount('models as models_count')
->withCount('licenses as licenses_count')
->find($id);
$this->authorize('view', $depreciation);
if ($depreciation) {
return view('depreciations/view', compact('depreciation'));
}
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
}

View file

@ -28,6 +28,9 @@ class DepreciationsTransformer
'name' => e($depreciation->name),
'months' => $depreciation->months.' '.trans('general.months'),
'depreciation_min' => $depreciation->depreciation_type === 'percent' ? $depreciation->depreciation_min.'%' : $depreciation->depreciation_min,
'assets_count' => $depreciation->assets_count,
'models_count' => $depreciation->models_count,
'licenses_count' => $depreciation->licenses_count,
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
];

View file

@ -79,7 +79,12 @@ class AssetModel extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'model_number', 'notes', 'eol'];
protected $searchableAttributes = [
'name',
'model_number',
'notes',
'eol'
];
/**
* The relations and their attributes that should be included when searching the model.

View file

@ -75,4 +75,17 @@ class Depreciation extends SnipeModel
{
return $this->hasMany(\App\Models\License::class, 'depreciation_id');
}
/**
* Establishes the depreciation -> assets relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v5.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
{
return $this->hasManyThrough(\App\Models\Asset::class, \App\Models\AssetModel::class, 'depreciation_id', 'model_id');
}
}

View file

@ -46,6 +46,26 @@ class DepreciationPresenter extends Presenter
"title" => trans('admin/depreciations/table.depreciation_min'),
"visible" => true,
],
[
'field' => 'assets_count',
'searchable' => false,
'sortable' => true,
'title' => trans('general.assets'),
'visible' => true,
],
[
'field' => 'models_count',
'searchable' => false,
'sortable' => true,
'title' => trans('general.asset_models'),
'visible' => true,
], [
'field' => 'licenses_count',
'searchable' => false,
'sortable' => true,
'title' => trans('general.licenses'),
'visible' => true,
],
[
'field' => 'actions',
'searchable' => false,

View file

@ -30,15 +30,38 @@
<!-- Custom Tabs -->
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#assets" data-toggle="tab">{{ trans('general.assets') }}</a></li>
<li><a href="#licenses" data-toggle="tab">{{ trans('general.licenses') }}</a></li>
<li><a href="#models" data-toggle="tab">{{ trans('general.asset_models') }}</a></li>
<li class="active">
<a href="#assets" data-toggle="tab">
{{ trans('general.assets') }}
{!! ($depreciation->assets()->AssetsForShow()->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($depreciation->assets()->AssetsForShow()->count()).'</badge>' : '' !!}
</a>
</li>
<li>
<a href="#licenses" data-toggle="tab">
{{ trans('general.licenses') }}
{!! ($depreciation->licenses_count > 0 ) ? '<badge class="badge badge-secondary">'.number_format($depreciation->licenses_count).'</badge>' : '' !!}
</a>
</li>
<li>
<a href="#models" data-toggle="tab">
{{ trans('general.asset_models') }}
{!! ($depreciation->models_count > 0 ) ? '<badge class="badge badge-secondary">'.number_format($depreciation->models_count).'</badge>' : '' !!}
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="assets">
@include('partials.asset-bulk-actions', [
'id_divname' => 'assetsBulkEditToolbar',
'id_formname' => 'assetsBulkForm',
'id_button' => 'assetEditButton'
])
<table
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
@ -53,6 +76,10 @@
data-show-refresh="true"
data-sort-order="asc"
data-sort-name="name"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#assetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
class="table table-striped snipe-table"
data-url="{{ route('api.assets.index',['depreciation_id'=> $depreciation->id]) }}"
data-export-options='{
@ -116,7 +143,7 @@
<option value="edit">{{ trans('general.bulk_edit') }}</option>
<option value="delete">{{ trans('general.bulk_delete') }}</option>
</select>
<button class="btn btn-primary" id="bulkEdit" disabled>{{ trans('button.go') }}</button>
<button class="btn btn-primary" id="AssetModelsBulkEditButton" disabled>{{ trans('button.go') }}</button>
</div>
<div class="table-responsive">
@ -134,6 +161,9 @@
data-show-refresh="true"
data-sort-order="asc"
data-sort-name="name"
data-bulk-button-id="#AssetModelsBulkEditButton"
data-bulk-form-id="#bulkForm"
data-click-to-select="true"
class="table table-striped snipe-table"
data-url="{{ route('api.models.index',['depreciation_id'=> $depreciation->id]) }}"
data-export-options='{

View file

@ -242,6 +242,7 @@
'method' => 'POST',
'route' => ['hardware/bulkedit'],
'class' => 'form-inline',
'target'=>'_blank',
'id' => 'bulkForm']) }}
<input type="hidden" name="bulk_actions" value="labels" />
<input type="hidden" name="ids[{{$asset->id}}]" value="{{ $asset->id }}" />

View file

@ -0,0 +1,17 @@
<?php
namespace Tests\Feature\Depreciations\Api;
use App\Models\User;
use Tests\TestCase;
class DepreciationsIndexTest extends TestCase
{
public function testViewingDepreciationIndexRequiresPermission()
{
$this->actingAsForApi(User::factory()->create())
->getJson(route('api.departments.index'))
->assertForbidden();
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace Tests\Feature\Categories\Ui;
use App\Models\User;
use Tests\TestCase;
class DepreciationsIndexTest extends TestCase
{
public function testPermissionRequiredToViewDepreciationsList()
{
$this->actingAs(User::factory()->create())
->get(route('depreciations.index'))
->assertForbidden();
}
public function testUserCanListDepreciations()
{
$this->actingAs(User::factory()->admin()->create())
->get(route('depreciations.index'))
->assertOk();
}
}