mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
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
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:
commit
6f3fb21fef
|
@ -78,6 +78,10 @@ class AssetModelsController extends Controller
|
||||||
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
|
$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')) {
|
if ($request->filled('search')) {
|
||||||
$assetmodels->TextSearch($request->input('search'));
|
$assetmodels->TextSearch($request->input('search'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,22 @@ class DepreciationsController extends Controller
|
||||||
public function index(Request $request) : JsonResponse | array
|
public function index(Request $request) : JsonResponse | array
|
||||||
{
|
{
|
||||||
$this->authorize('view', Depreciation::class);
|
$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')) {
|
if ($request->filled('search')) {
|
||||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||||
|
|
|
@ -193,13 +193,20 @@ class DepreciationsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function show($id) : View | RedirectResponse
|
public function show($id) : View | RedirectResponse
|
||||||
{
|
{
|
||||||
if (is_null($depreciation = Depreciation::find($id))) {
|
$depreciation = Depreciation::withCount('assets as assets_count')
|
||||||
// Redirect to the blogs management page
|
->withCount('models as models_count')
|
||||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
->withCount('licenses as licenses_count')
|
||||||
}
|
->find($id);
|
||||||
|
|
||||||
$this->authorize('view', $depreciation);
|
$this->authorize('view', $depreciation);
|
||||||
|
|
||||||
return view('depreciations/view', compact('depreciation'));
|
if ($depreciation) {
|
||||||
|
return view('depreciations/view', compact('depreciation'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ class DepreciationsTransformer
|
||||||
'name' => e($depreciation->name),
|
'name' => e($depreciation->name),
|
||||||
'months' => $depreciation->months.' '.trans('general.months'),
|
'months' => $depreciation->months.' '.trans('general.months'),
|
||||||
'depreciation_min' => $depreciation->depreciation_type === 'percent' ? $depreciation->depreciation_min.'%' : $depreciation->depreciation_min,
|
'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'),
|
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
|
||||||
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
|
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
|
||||||
];
|
];
|
||||||
|
|
|
@ -79,7 +79,12 @@ class AssetModel extends SnipeModel
|
||||||
*
|
*
|
||||||
* @var array
|
* @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.
|
* The relations and their attributes that should be included when searching the model.
|
||||||
|
|
|
@ -75,4 +75,17 @@ class Depreciation extends SnipeModel
|
||||||
{
|
{
|
||||||
return $this->hasMany(\App\Models\License::class, 'depreciation_id');
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,26 @@ class DepreciationPresenter extends Presenter
|
||||||
"title" => trans('admin/depreciations/table.depreciation_min'),
|
"title" => trans('admin/depreciations/table.depreciation_min'),
|
||||||
"visible" => true,
|
"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',
|
'field' => 'actions',
|
||||||
'searchable' => false,
|
'searchable' => false,
|
||||||
|
|
|
@ -30,15 +30,38 @@
|
||||||
<!-- Custom Tabs -->
|
<!-- Custom Tabs -->
|
||||||
<div class="nav-tabs-custom">
|
<div class="nav-tabs-custom">
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="active"><a href="#assets" data-toggle="tab">{{ trans('general.assets') }}</a></li>
|
<li class="active">
|
||||||
<li><a href="#licenses" data-toggle="tab">{{ trans('general.licenses') }}</a></li>
|
<a href="#assets" data-toggle="tab">
|
||||||
<li><a href="#models" data-toggle="tab">{{ trans('general.asset_models') }}</a></li>
|
{{ trans('general.assets') }}
|
||||||
</ul>
|
|
||||||
|
{!! ($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-content">
|
||||||
|
|
||||||
<div class="tab-pane active" id="assets">
|
<div class="tab-pane active" id="assets">
|
||||||
|
|
||||||
|
@include('partials.asset-bulk-actions', [
|
||||||
|
'id_divname' => 'assetsBulkEditToolbar',
|
||||||
|
'id_formname' => 'assetsBulkForm',
|
||||||
|
'id_button' => 'assetEditButton'
|
||||||
|
])
|
||||||
|
|
||||||
<table
|
<table
|
||||||
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
|
||||||
|
@ -53,6 +76,10 @@
|
||||||
data-show-refresh="true"
|
data-show-refresh="true"
|
||||||
data-sort-order="asc"
|
data-sort-order="asc"
|
||||||
data-sort-name="name"
|
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"
|
class="table table-striped snipe-table"
|
||||||
data-url="{{ route('api.assets.index',['depreciation_id'=> $depreciation->id]) }}"
|
data-url="{{ route('api.assets.index',['depreciation_id'=> $depreciation->id]) }}"
|
||||||
data-export-options='{
|
data-export-options='{
|
||||||
|
@ -107,7 +134,7 @@
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'route' => ['models.bulkedit.index'],
|
'route' => ['models.bulkedit.index'],
|
||||||
'class' => 'form-inline',
|
'class' => 'form-inline',
|
||||||
'id' => 'bulkForm']
|
'id' => 'bulkForm']
|
||||||
) }}
|
) }}
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
|
@ -116,7 +143,7 @@
|
||||||
<option value="edit">{{ trans('general.bulk_edit') }}</option>
|
<option value="edit">{{ trans('general.bulk_edit') }}</option>
|
||||||
<option value="delete">{{ trans('general.bulk_delete') }}</option>
|
<option value="delete">{{ trans('general.bulk_delete') }}</option>
|
||||||
</select>
|
</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>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
@ -134,6 +161,9 @@
|
||||||
data-show-refresh="true"
|
data-show-refresh="true"
|
||||||
data-sort-order="asc"
|
data-sort-order="asc"
|
||||||
data-sort-name="name"
|
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"
|
class="table table-striped snipe-table"
|
||||||
data-url="{{ route('api.models.index',['depreciation_id'=> $depreciation->id]) }}"
|
data-url="{{ route('api.models.index',['depreciation_id'=> $depreciation->id]) }}"
|
||||||
data-export-options='{
|
data-export-options='{
|
||||||
|
|
|
@ -242,6 +242,7 @@
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'route' => ['hardware/bulkedit'],
|
'route' => ['hardware/bulkedit'],
|
||||||
'class' => 'form-inline',
|
'class' => 'form-inline',
|
||||||
|
'target'=>'_blank',
|
||||||
'id' => 'bulkForm']) }}
|
'id' => 'bulkForm']) }}
|
||||||
<input type="hidden" name="bulk_actions" value="labels" />
|
<input type="hidden" name="bulk_actions" value="labels" />
|
||||||
<input type="hidden" name="ids[{{$asset->id}}]" value="{{ $asset->id }}" />
|
<input type="hidden" name="ids[{{$asset->id}}]" value="{{ $asset->id }}" />
|
||||||
|
|
17
tests/Feature/Depreciations/Api/DepreciationsIndexTest.php
Normal file
17
tests/Feature/Depreciations/Api/DepreciationsIndexTest.php
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
tests/Feature/Depreciations/Ui/DepreciationsIndexTest.php
Normal file
23
tests/Feature/Depreciations/Ui/DepreciationsIndexTest.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue