Merge remote-tracking branch 'origin/develop'
This commit is contained in:
@@ -54,6 +54,15 @@ class BulkAssetsController extends Controller
|
||||
$asset_ids = $request->input('ids');
|
||||
|
||||
if ($request->input('bulk_actions') === 'checkout') {
|
||||
$status_check =$this->hasUndeployableStatus($asset_ids);
|
||||
if($status_check && $status_check['status'] === true){
|
||||
|
||||
$asset_tags = implode(', ', array_column($status_check['tags'], 'asset_tag'));
|
||||
$asset_ids = $status_check['asset_ids'];
|
||||
|
||||
session()->flash('warning', trans('admin/hardware/message.undeployable', ['asset_tags' => $asset_tags]));
|
||||
}
|
||||
|
||||
$request->session()->flashInput(['selected_assets' => $asset_ids]);
|
||||
return redirect()->route('hardware.bulkcheckout.show');
|
||||
}
|
||||
@@ -220,6 +229,21 @@ class BulkAssetsController extends Controller
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
// find custom field input attributes that start with 'null_'
|
||||
$null_custom_fields_inputs = array_filter($request->all(), function ($key) {
|
||||
// filter out all keys that start with 'null_'
|
||||
return (strpos($key, 'null_') === 0);
|
||||
}, ARRAY_FILTER_USE_KEY);;
|
||||
// remove 'null' from the keys
|
||||
$custom_fields_to_null = [];
|
||||
foreach ($null_custom_fields_inputs as $key => $value) {
|
||||
$custom_fields_to_null[str_replace('null', '', $key)] = $value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (! $request->filled('ids') || count($request->input('ids')) == 0) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
@@ -258,6 +282,7 @@ class BulkAssetsController extends Controller
|
||||
|| ($request->filled('null_next_audit_date'))
|
||||
|| ($request->filled('null_asset_eol_date'))
|
||||
|| ($request->anyFilled($custom_field_columns))
|
||||
|| ($request->anyFilled(array_keys($null_custom_fields_inputs)))
|
||||
|
||||
) {
|
||||
// Let's loop through those assets and build an update array
|
||||
@@ -284,6 +309,9 @@ class BulkAssetsController extends Controller
|
||||
foreach ($custom_field_columns as $key => $custom_field_column) {
|
||||
$this->conditionallyAddItem($custom_field_column);
|
||||
}
|
||||
foreach ($custom_fields_to_null as $key => $custom_field_to_null) {
|
||||
$this->conditionallyAddItem($key);
|
||||
}
|
||||
|
||||
if (!($asset->eol_explicit)) {
|
||||
if ($request->filled('model_id')) {
|
||||
@@ -374,10 +402,12 @@ class BulkAssetsController extends Controller
|
||||
// This could probably be added to a form request.
|
||||
// If the asset isn't assigned, we don't care what the status is.
|
||||
// Otherwise we need to make sure the status type is still a deployable one.
|
||||
if (
|
||||
($asset->assigned_to == '')
|
||||
|| ($updated_status->deployable == '1') && ($asset->assetstatus?->deployable == '1')
|
||||
) {
|
||||
|
||||
$unassigned = $asset->assigned_to == '';
|
||||
$deployable = $updated_status->deployable == '1' && $asset->assetstatus?->deployable == '1';
|
||||
$pending = $updated_status->pending === 1;
|
||||
|
||||
if ($unassigned || $deployable || $pending) {
|
||||
$this->update_array['status_id'] = $updated_status->id;
|
||||
}
|
||||
|
||||
@@ -429,6 +459,7 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Start all the custom fields shenanigans
|
||||
*/
|
||||
|
||||
@@ -436,6 +467,15 @@ class BulkAssetsController extends Controller
|
||||
if ($asset->model->fieldset) {
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
// null custom fields
|
||||
if ($custom_fields_to_null) {
|
||||
foreach ($custom_fields_to_null as $key => $custom_field_to_null) {
|
||||
if ($field->db_column == $key) {
|
||||
$this->update_array[$field->db_column] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
|
||||
if (Gate::allows('admin')) {
|
||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
@@ -665,4 +705,25 @@ class BulkAssetsController extends Controller
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
|
||||
}
|
||||
}
|
||||
public function hasUndeployableStatus (array $asset_ids)
|
||||
{
|
||||
$undeployable = Asset::whereIn('id', $asset_ids)
|
||||
->undeployable()
|
||||
->get();
|
||||
|
||||
$undeployableTags = $undeployable->map(function ($asset) {
|
||||
return [
|
||||
'id' => $asset->id,
|
||||
'asset_tag' => $asset->asset_tag,
|
||||
];
|
||||
})->toArray();
|
||||
|
||||
$undeployableIds = array_column($undeployableTags, 'id');
|
||||
$filtered_ids = array_diff($asset_ids, $undeployableIds);
|
||||
|
||||
if($undeployable->isNotEmpty()) {
|
||||
return ['status' => true, 'tags' => $undeployableTags, 'asset_ids' => $filtered_ids];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
{
|
||||
return $this->hasMany(Actionlog::class, 'target_id')
|
||||
->with('item')
|
||||
->select(['id', 'target_id', 'target_type', 'action_type', 'filename', 'accept_signature', 'created_at', 'note'])
|
||||
->select(['id', 'target_id', 'target_type', 'action_type', 'filename', 'accept_signature', 'created_at', 'note', 'item_id', 'item_type'])
|
||||
->where('target_type', self::class)
|
||||
->where('action_type', 'accepted')
|
||||
->whereNotNull('filename')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
|
||||
'undeployable' => '<strong>Warning: </strong> This asset has been marked as currently undeployable. If this status has changed, please update the asset status.',
|
||||
'undeployable' => 'The following assets cannot be deployed and have been removed from checkout: :asset_tags',
|
||||
'does_not_exist' => 'Asset does not exist.',
|
||||
'does_not_exist_var' => 'Asset with tag :asset_tag not found.',
|
||||
'no_tag' => 'No asset tag provided.',
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
:selected="old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id)))"
|
||||
class="format form-control"
|
||||
/>
|
||||
<div class="col-md-5">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="null_asset_eol_date" value="1">
|
||||
{{ trans_choice('general.set_to_null', count($assets),['selection_count' => count($assets)]) }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@elseif ($field->element=='textarea')
|
||||
@if($field->is_unique)
|
||||
@@ -45,7 +51,6 @@
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
|
||||
@endforeach
|
||||
@elseif ($field->element=='radio')
|
||||
@foreach ($field->formatFieldValuesAsArray() as $value)
|
||||
@@ -119,8 +124,14 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="col-md-5">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="{{ 'null'.$field->db_column_name() }}" value="1">
|
||||
{{ trans_choice('general.set_to_null', count($assets),['selection_count' => count($assets)]) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@@ -197,6 +197,47 @@ class BulkEditAssetsTest extends TestCase
|
||||
});
|
||||
}
|
||||
|
||||
public function testBulkEditAssetsNullsCustomFieldsIfSelected()
|
||||
{
|
||||
$this->markIncompleteIfMySQL('Custom Fields tests do not work on MySQL');
|
||||
|
||||
CustomField::factory()->ram()->create();
|
||||
CustomField::factory()->cpu()->create();
|
||||
CustomField::factory()->phone()->create();
|
||||
|
||||
// when getting the custom field directly from the factory the field has not been fully created yet
|
||||
// so we have to do a query afterwards to get the actual model :shrug:
|
||||
|
||||
$ram = CustomField::where('name', 'RAM')->first();
|
||||
$cpu = CustomField::where('name', 'CPU')->first();
|
||||
$phone = CustomField::where('name', 'Phone Number')->first();
|
||||
|
||||
$assets = Asset::factory()->count(10)->hasMultipleCustomFields([$ram, $cpu])->create([
|
||||
$ram->db_column => 8,
|
||||
$cpu->db_column => '2.1',
|
||||
]);
|
||||
|
||||
$id_array = $assets->pluck('id')->toArray();
|
||||
|
||||
$this->actingAs(User::factory()->editAssets()->create())->post(route('hardware/bulksave'), [
|
||||
'ids' => $id_array,
|
||||
$ram->db_column => 16,
|
||||
$cpu->db_column => '4.1',
|
||||
'null'.$phone->db_column => '8304997586',
|
||||
])->assertStatus(302);
|
||||
|
||||
$this->actingAs(User::factory()->editAssets()->create())->post(route('hardware/bulksave'), [
|
||||
'ids' => $id_array,
|
||||
null.$phone->db_column => 1,
|
||||
]);
|
||||
|
||||
Asset::findMany($id_array)->each(function (Asset $asset) use ($ram, $cpu, $phone) {
|
||||
$this->assertEquals(16, $asset->{$ram->db_column});
|
||||
$this->assertEquals('4.1', $asset->{$cpu->db_column});
|
||||
$this->assertEquals(null, $asset->{$phone->db_column});
|
||||
});
|
||||
}
|
||||
|
||||
public function testBulkEditAssetsAcceptsAndUpdatesEncryptedCustomFields()
|
||||
{
|
||||
$this->markIncompleteIfMySQL('Custom Fields tests do not work on MySQL');
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?php
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Http\Controllers\Assets\BulkAssetsController;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Tests\TestCase;
|
||||
@@ -238,4 +240,52 @@ class AssetTest extends TestCase
|
||||
|
||||
$this->assertFalse($asset->refresh()->getImageUrl());
|
||||
}
|
||||
public function testUndeployableStatusReturnsFalseifAssetIsDeployable()
|
||||
{
|
||||
$assets = Asset::factory()->count(3)->create();
|
||||
$asset_ids = $assets->pluck('id')->toArray();
|
||||
|
||||
$bulk_assets = new BulkAssetsController();
|
||||
|
||||
$result = $bulk_assets->hasUndeployableStatus($asset_ids);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
public function testUndeployableStatusReturnsTrueandTagsIfAssetIsUnDeployable()
|
||||
{
|
||||
$deployable = Asset::factory()->create();
|
||||
$undeployableStatus = Statuslabel::factory()->create(['deployable' => 0]);
|
||||
$undeployable = Asset::factory()->create(
|
||||
[
|
||||
'status_id' => $undeployableStatus->id
|
||||
]);
|
||||
|
||||
$bulk_assets = new BulkAssetsController();
|
||||
|
||||
$result = $bulk_assets->hasUndeployableStatus([$deployable->id, $undeployable->id]);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertTrue($result['status']);
|
||||
$this->assertEquals($undeployable->id, $result['tags'][0]['id']);
|
||||
$this->assertEquals($undeployable->asset_tag, $result['tags'][0]['asset_tag']);
|
||||
}
|
||||
|
||||
public function testUndeployableStatusCheckFiltersOutUndeployableIds()
|
||||
{
|
||||
$deployable = Asset::factory()->create();
|
||||
$undeployableStatus = Statuslabel::factory()->create(['deployable' => 0]);
|
||||
$undeployable = Asset::factory()->create(
|
||||
[
|
||||
'status_id' => $undeployableStatus->id
|
||||
]);
|
||||
|
||||
$bulk_assets = new BulkAssetsController();
|
||||
|
||||
$result = $bulk_assets->hasUndeployableStatus([$deployable->id, $undeployable->id]);
|
||||
|
||||
$undeployableIds = array_column($result['tags'], 'id');
|
||||
$filtered = array_diff([$deployable->id, $undeployable->id], $undeployableIds);
|
||||
|
||||
$this->assertEquals([$deployable->id], array_values($filtered));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user