From 5066eb58f4590821bf2d4e1deaf7f87c3eb68815 Mon Sep 17 00:00:00 2001 From: snipe Date: Sat, 17 Aug 2024 02:31:03 +0100 Subject: [PATCH 01/41] Added asset model import to importer Signed-off-by: snipe --- app/Importer/AssetModelImporter.php | 100 ++++++++++++++++++++ app/Importer/ItemImporter.php | 12 ++- app/Livewire/Importer.php | 36 +++++-- resources/lang/en-US/general.php | 2 +- resources/views/livewire/importer.blade.php | 3 + sample_csvs/models-sample.csv | 22 +++++ 6 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 app/Importer/AssetModelImporter.php create mode 100644 sample_csvs/models-sample.csv diff --git a/app/Importer/AssetModelImporter.php b/app/Importer/AssetModelImporter.php new file mode 100644 index 0000000000..888265a95e --- /dev/null +++ b/app/Importer/AssetModelImporter.php @@ -0,0 +1,100 @@ +createAssetModelIfNotExists($row); + } + + /** + * Create a model if a duplicate does not exist. + * @todo Investigate how this should interact with Importer::createModelIfNotExists + * + * @author A. Gianotto + * @since 6.1.0 + * @param array $row + */ + public function createAssetModelIfNotExists(array $row) + { + + $editingAssetModel = false; + $assetmodel = AssetModel::where('name', '=', $this->findCsvMatch($row, 'name'))->first(); + + if ($assetmodel) { + if (! $this->updating) { + $this->log('A matching Model '.$this->item['name'].' already exists'); + return; + } + + $this->log('Updating Model'); + $editingAssetModel = true; + } else { + $this->log('No Matching Model, Create a new one'); + $assetmodel = new AssetModel(); + } + + // Pull the records from the CSV to determine their values + $this->item['name'] = trim($this->findCsvMatch($row, 'name')); + $this->item['category'] = trim($this->findCsvMatch($row, 'category')); + $this->item['manufacturer'] = trim($this->findCsvMatch($row, 'manufacturer')); + $this->item['min_amt'] = trim($this->findCsvMatch($row, 'min_amt')); + $this->item['model_number'] = trim($this->findCsvMatch($row, 'model_number')); + $this->item['notes'] = trim($this->findCsvMatch($row, 'notes')); + $this->item['user_id'] = auth()->id(); + + + if (!empty($this->item['category'])) { + if ($category = $this->createOrFetchCategory($row, 'category')) { + $this->item['category_id'] = $category->id; + } + } + if (!empty($this->item['manufacturer'])) { + if ($manufacturer = $this->createOrFetchManufacturer($row, 'manufacturer')) { + $this->item['manufacturer_id'] = $manufacturer->id; + } + } + + Log::debug('Item array is: '); + Log::debug(print_r($this->item, true)); + + + if ($editingAssetModel) { + Log::debug('Updating existing model'); + $assetmodel->update($this->sanitizeItemForUpdating($assetmodel)); + } else { + Log::debug('Creating model'); + $assetmodel->fill($this->sanitizeItemForStoring($assetmodel)); + } + + if ($assetmodel->save()) { + $this->log('AssetModel '.$assetmodel->name.' created or updated from CSV import'); + return $assetmodel; + + } else { + Log::debug($assetmodel->getErrors()); + return $assetmodel->errors; + } + + + } +} \ No newline at end of file diff --git a/app/Importer/ItemImporter.php b/app/Importer/ItemImporter.php index 29197ca5dc..56c9a3cb09 100644 --- a/app/Importer/ItemImporter.php +++ b/app/Importer/ItemImporter.php @@ -113,7 +113,7 @@ class ItemImporter extends Importer protected function determineCheckout($row) { // Locations don't get checked out to anyone/anything - if (get_class($this) == LocationImporter::class) { + if ((get_class($this) == LocationImporter::class) || (get_class($this) == AssetModelImporter::class)) { return; } @@ -287,14 +287,22 @@ class ItemImporter extends Importer $classname = class_basename(get_class($this)); $item_type = strtolower(substr($classname, 0, strpos($classname, 'Importer'))); + if ($item_type == 'assetmodel') { + $item_type = 'asset'; + } + + \Log::error('Item Type: '.$item_type); + if (empty($asset_category)) { $asset_category = 'Unnamed Category'; } + + $category = Category::where(['name' => $asset_category, 'category_type' => $item_type])->first(); + if ($category) { $this->log('A matching category: '.$asset_category.' already exists'); - return $category->id; } diff --git a/app/Livewire/Importer.php b/app/Livewire/Importer.php index 32dd7912fb..5af99b35ba 100644 --- a/app/Livewire/Importer.php +++ b/app/Livewire/Importer.php @@ -79,6 +79,7 @@ class Importer extends Component private function getColumns($type) { + \Log::error($type); switch ($type) { case 'asset': $results = $this->assets_fields; @@ -101,10 +102,14 @@ class Importer extends Component case 'location': $results = $this->locations_fields; break; + case 'assetmodel': + $results = $this->assetmodels_fields; + break; default: $results = []; } asort($results, SORT_FLAG_CASE | SORT_STRING); + if ($type == "asset") { // add Custom Fields after a horizontal line $results['-'] = "———" . trans('admin/custom_fields/general.custom_fields') . "———’"; @@ -143,6 +148,7 @@ class Importer extends Component } // if you got here, we didn't find a match. Try the $aliases_fields foreach ($this->aliases_fields as $key => $alias_values) { + \Log::error('No matches'); foreach ($alias_values as $alias_value) { if (strcasecmp($alias_value, $header) === 0) { // aLsO CaSe-INSENSitiVE! // Make *absolutely* sure that this key actually _exists_ in this import type - @@ -172,13 +178,14 @@ class Importer extends Component $this->progress = -1; // '-1' means 'don't show the progressbar' $this->progress_bar_class = 'progress-bar-warning'; $this->importTypes = [ - 'asset' => trans('general.assets'), - 'accessory' => trans('general.accessories'), - 'consumable' => trans('general.consumables'), - 'component' => trans('general.components'), - 'license' => trans('general.licenses'), - 'user' => trans('general.users'), - 'location' => trans('general.locations'), + 'asset' => trans('general.assets'), + 'accessory' => trans('general.accessories'), + 'consumable' => trans('general.consumables'), + 'component' => trans('general.components'), + 'license' => trans('general.licenses'), + 'user' => trans('general.users'), + 'location' => trans('general.locations'), + 'assetmodel' => trans('general.asset_models'), ]; /** @@ -352,6 +359,18 @@ class Importer extends Component 'parent_location' => trans('admin/locations/table.parent'), ]; + $this->assetmodels_fields = [ + 'item_name' => trans('general.item_name_var', ['item' => trans('general.asset_model')]), + 'category' => trans('general.category'), + 'manufacturer' => trans('general.manufacturer'), + 'model_number' => trans('general.model_no'), + 'notes' => trans('general.item_notes', ['item' => trans('admin/hardware/form.model')]), + 'min_amt' => trans('mail.min_QTY'), + 'fieldset' => trans('admin/models/general.fieldset'), + 'category_type' => 'category type', + + ]; + // "real fieldnames" to a list of aliases for that field $this->aliases_fields = [ 'item_name' => @@ -527,18 +546,19 @@ class Importer extends Component if (!$this->activeFile) { $this->message = trans('admin/hardware/message.import.file_missing'); $this->message_type = 'danger'; - return; } $this->field_map = null; foreach($this->activeFile->header_row as $element) { + if(isset($this->activeFile->field_map[$element])) { $this->field_map[] = $this->activeFile->field_map[$element]; } else { $this->field_map[] = null; // re-inject the 'nulls' if a file was imported with some 'Do Not Import' settings } } + $this->file_id = $id; $this->import_errors = null; $this->statusText = null; diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index 7634387906..5e54bab83e 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -557,7 +557,7 @@ return [ 'something_went_wrong' => 'Something went wrong with your request.', 'close' => 'Close', 'expires' => 'Expires', - 'map_fields'=> 'Map :item_type Field', + 'map_fields'=> 'Map :item_type Fields', 'remaining_var' => ':count Remaining', 'assets_in_var' => 'Assets in :name :type', 'label' => 'Label', diff --git a/resources/views/livewire/importer.blade.php b/resources/views/livewire/importer.blade.php index 92dfd128ad..7371dd2fe8 100644 --- a/resources/views/livewire/importer.blade.php +++ b/resources/views/livewire/importer.blade.php @@ -170,16 +170,19 @@ {{ trans('general.update_existing_values') }} + @if ($activeFile->import_type === 'asset' && $snipeSettings->auto_increment_assets == 1 && $update)

{{ trans('general.auto_incrementing_asset_tags_enabled_so_now_assets_will_be_created') }}

@endif + @if ($activeFile->import_type != 'location' && $activeFile->import_type == 'assetmodel' && $update) + @endif diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 837a95b3be..f24552d753 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -78,7 +78,7 @@ return newParams; }, formatLoadingMessage: function () { - return '

{{ trans('general.loading') }}

'; + return '

{{ trans('general.loading') }}

'; }, icons: { advancedSearchIcon: 'fas fa-search-plus', @@ -299,14 +299,14 @@ } if ((row.available_actions) && (row.available_actions.clone === true)) { - actions += 'Clone '; + actions += '{{ trans('general.clone_item') }} '; } if ((row.available_actions) && (row.available_actions.update === true)) { - actions += '{{ trans('general.update') }} '; + actions += '{{ trans('general.update') }} '; } else { if ((row.available_actions) && (row.available_actions.update != true)) { - actions += ' '; + actions += ' '; } } @@ -323,11 +323,11 @@ + ' data-toggle="modal" ' + ' data-content="{{ trans('general.sure_to_delete') }} ' + name_for_box + '?" ' + ' data-title="{{ trans('general.delete') }}" onClick="return false;">' - + '{{ trans('general.delete') }} '; + + '{{ trans('general.delete') }} '; } else { // Do not show the delete button on things that are already deleted if ((row.available_actions) && (row.available_actions.restore != true)) { - actions += ' '; + actions += '{{ trans('general.cannot_be_deleted') }} '; } } @@ -336,7 +336,7 @@ if ((row.available_actions) && (row.available_actions.restore === true)) { actions += '
'; actions += '@csrf'; - actions += ' '; + actions += ' '; } actions +=''; @@ -556,7 +556,7 @@ } else if (row.custom_fields[field_column_plain].field_format=='BOOLEAN') { return (row.custom_fields[field_column_plain].value == 1) ? "" : ""; } else if (row.custom_fields[field_column_plain].field_format=='EMAIL') { - return ' ' + row.custom_fields[field_column_plain].value + ''; + return ' ' + row.custom_fields[field_column_plain].value + ''; } } return row.custom_fields[field_column_plain].value; @@ -576,7 +576,7 @@ if (value) { if ((value.indexOf("{") === -1) || (value.indexOf("}") ===-1)) { - return ' ' + value + ''; + return ' ' + value + ''; } return value; } @@ -612,7 +612,7 @@ extra_pretty_index = prettyLog(pretty_index); - result += extra_pretty_index + ': ' + value[index].old + ' ' + value[index].new + '
' + result += extra_pretty_index + ': ' + value[index].old + ' ' + value[index].new + '
' } return result; @@ -643,7 +643,7 @@ // Create a linked phone number in the table list function phoneFormatter(value) { if (value) { - return ' ' + value + ''; + return ' ' + value + ''; } } @@ -664,7 +664,7 @@ function assetTagLinkFormatter(value, row) { if ((row.asset) && (row.asset.id)) { if (row.asset.deleted_at!='') { - return '{{ trans('admin/hardware/general.deleted') }} ' + row.asset.asset_tag + ''; + return '{{ trans('admin/hardware/general.deleted') }} ' + row.asset.asset_tag + ''; } return '' + row.asset.asset_tag + ''; } @@ -689,7 +689,7 @@ if ((row.asset) && (row.asset.serial)) { if (row.asset.deleted_at!='') { - return 'deleted ' + row.asset.serial + ''; + return 'deleted ' + row.asset.serial + ''; } return '' + row.asset.serial + ''; } @@ -698,9 +698,9 @@ function trueFalseFormatter(value) { if ((value) && ((value == 'true') || (value == '1'))) { - return '{{ trans('general.true') }}'; + return '{{ trans('general.true') }}'; } else { - return '{{ trans('general.false') }}'; + return '{{ trans('general.false') }}'; } } @@ -718,7 +718,7 @@ function emailFormatter(value) { if (value) { - return ' ' + value + ''; + return ' ' + value + ''; } } @@ -787,7 +787,7 @@ } function downloadFormatter(value) { if (value) { - return ''; + return ''; } } @@ -795,7 +795,7 @@ if ((value) && (value.url) && (value.inlineable)) { return ''; } else if ((value) && (value.url)) { - return ''; + return ''; } } diff --git a/resources/views/partials/forms/checkout-selector.blade.php b/resources/views/partials/forms/checkout-selector.blade.php index c24c90d25e..268089a7d2 100644 --- a/resources/views/partials/forms/checkout-selector.blade.php +++ b/resources/views/partials/forms/checkout-selector.blade.php @@ -4,7 +4,7 @@
@if ((isset($user_select)) && ($user_select!='false')) @endif @if ((isset($asset_select)) && ($asset_select!='false')) diff --git a/resources/views/partials/forms/edit/accessory-select.blade.php b/resources/views/partials/forms/edit/accessory-select.blade.php index 12be9bf7b7..d34b6b2fe0 100644 --- a/resources/views/partials/forms/edit/accessory-select.blade.php +++ b/resources/views/partials/forms/edit/accessory-select.blade.php @@ -1,8 +1,8 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
- @if ((!isset($unselect)) && ($accessory_id = old($fieldname, (isset($accessory) ? $accessory->id : (isset($item) ? $item->{$fieldname} : '')))))
- {{ Form::label('city', trans('general.city'), array('class' => 'col-md-3 control-label', 'maxlength'=>'191')) }} + {{ Form::label('city', trans('general.city'), array('class' => 'col-md-3 control-label')) }}
- {{Form::text('city', old('city', $item->city), array('class' => 'form-control', 'aria-label'=>'city')) }} + {{Form::text('city', old('city', $item->city), array('class' => 'form-control', 'aria-label'=>'city', 'maxlength'=>'191')) }} {!! $errors->first('city', '') !!}
- {{ Form::label('state', trans('general.state'), array('class' => 'col-md-3 control-label', 'maxlength'=>'191')) }} + {{ Form::label('state', trans('general.state'), array('class' => 'col-md-3 control-label')) }}
- {{Form::text('state', old('state', $item->state), array('class' => 'form-control', 'aria-label'=>'state')) }} + {{Form::text('state', old('state', $item->state), array('class' => 'form-control', 'aria-label'=>'state', 'maxlength'=>'191')) }} {!! $errors->first('state', '') !!}
@@ -35,6 +35,7 @@ {{ Form::label('country', trans('general.country'), array('class' => 'col-md-3 control-label')) }}
{!! Form::countries('country', old('country', $item->country), 'select2') !!} +

{{ trans('general.countries_manually_entered_help') }}

{!! $errors->first('country', '') !!}
diff --git a/resources/views/partials/forms/edit/asset-select.blade.php b/resources/views/partials/forms/edit/asset-select.blade.php index 86dba8206f..9867a8e552 100644 --- a/resources/views/partials/forms/edit/asset-select.blade.php +++ b/resources/views/partials/forms/edit/asset-select.blade.php @@ -1,8 +1,9 @@ -
+
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
- @if ((!isset($unselect)) && ($asset_id = old($fieldname, (isset($asset) ? $asset->id : (isset($item) ? $item->{$fieldname} : ''))))) + @else + @if(isset($asset_ids)) + @foreach($asset_ids as $asset_id) + + @endforeach + @endif @endif @endif diff --git a/resources/views/partials/forms/edit/category-select.blade.php b/resources/views/partials/forms/edit/category-select.blade.php index 66800deedf..f610f68470 100644 --- a/resources/views/partials/forms/edit/category-select.blade.php +++ b/resources/views/partials/forms/edit/category-select.blade.php @@ -3,14 +3,12 @@ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
+
diff --git a/resources/views/partials/forms/edit/category.blade.php b/resources/views/partials/forms/edit/category.blade.php index 715c54184e..158cc3508b 100644 --- a/resources/views/partials/forms/edit/category.blade.php +++ b/resources/views/partials/forms/edit/category.blade.php @@ -1,8 +1,8 @@
-
- {{ Form::select('category_id', $category_list , old('category_id', $item->category_id), array('class'=>'select2', 'style'=>'width:100%')) }} +
+ {{ Form::select('category_id', $category_list , old('category_id', $item->category_id), array('class'=>'select2', 'style'=>'width:100%', 'required' => Helper::checkIfRequired($item, 'category_id') ? true : '')) }} {!! $errors->first('category_id', '') !!}
diff --git a/resources/views/partials/forms/edit/company-select.blade.php b/resources/views/partials/forms/edit/company-select.blade.php index 9aaa5cafdf..59de71a6ab 100644 --- a/resources/views/partials/forms/edit/company-select.blade.php +++ b/resources/views/partials/forms/edit/company-select.blade.php @@ -10,7 +10,7 @@ {{ (\App\Models\Company::find($company_id)) ? \App\Models\Company::find($company_id)->name : '' }} @else - + {!! (!isset($multiple) || ($multiple=='false')) ? '' : '' !!} @endif
@@ -20,14 +20,14 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
+
diff --git a/resources/views/partials/forms/edit/company.blade.php b/resources/views/partials/forms/edit/company.blade.php index 4e64dbd1a8..22cb623584 100644 --- a/resources/views/partials/forms/edit/company.blade.php +++ b/resources/views/partials/forms/edit/company.blade.php @@ -3,8 +3,8 @@
{{ Form::label('company_id', trans('general.company'), array('class' => 'col-md-3 control-label', 'for' => 'company_id')) }}
-
- {{ Form::select('company_id', $company_list , old('company_id', $item->company_id), array('class'=>'select2', 'style'=>'width:100%')) }} +
+ {{ Form::select('company_id', $company_list , old('company_id', $item->company_id), array('class'=>'select2', 'style'=>'width:100%', 'required' => Helper::checkIfRequired($item, 'company_id') ? true : '')) }} {!! $errors->first('company_id', '') !!}
diff --git a/resources/views/partials/forms/edit/datepicker.blade.php b/resources/views/partials/forms/edit/datepicker.blade.php index 9d2a714bb7..3bd0200d0a 100644 --- a/resources/views/partials/forms/edit/datepicker.blade.php +++ b/resources/views/partials/forms/edit/datepicker.blade.php @@ -4,7 +4,7 @@
- +
{!! $errors->first($fieldname, '') !!}
diff --git a/resources/views/partials/forms/edit/department-select.blade.php b/resources/views/partials/forms/edit/department-select.blade.php index c695d04ef4..7d67416f5f 100644 --- a/resources/views/partials/forms/edit/department-select.blade.php +++ b/resources/views/partials/forms/edit/department-select.blade.php @@ -8,8 +8,6 @@ - @else - @endif
diff --git a/resources/views/partials/forms/edit/email.blade.php b/resources/views/partials/forms/edit/email.blade.php index 0e10b7d766..171367a830 100644 --- a/resources/views/partials/forms/edit/email.blade.php +++ b/resources/views/partials/forms/edit/email.blade.php @@ -1,7 +1,7 @@
- {{ Form::label('email', trans('admin/suppliers/table.email'), array('class' => 'col-md-3 control-label')) }} -
- {{Form::text('email', old('email', $item->email), array('class' => 'form-control')) }} + +
+ {!! $errors->first('email', '') !!}
-
+
\ No newline at end of file diff --git a/resources/views/partials/forms/edit/eol_date.blade.php b/resources/views/partials/forms/edit/eol_date.blade.php index fb461cf44e..5efba06a85 100644 --- a/resources/views/partials/forms/edit/eol_date.blade.php +++ b/resources/views/partials/forms/edit/eol_date.blade.php @@ -3,8 +3,8 @@
- - + +
{!! $errors->first('asset_eol_date', '') !!}
diff --git a/resources/views/partials/forms/edit/fax.blade.php b/resources/views/partials/forms/edit/fax.blade.php index 6e8a1d7fd4..7ed4d3070d 100644 --- a/resources/views/partials/forms/edit/fax.blade.php +++ b/resources/views/partials/forms/edit/fax.blade.php @@ -1,7 +1,7 @@
{{ Form::label('fax', trans('admin/suppliers/table.fax'), array('class' => 'col-md-3 control-label')) }}
- {{Form::text('fax', old('fax', $item->fax), array('class' => 'form-control')) }} + {!! $errors->first('fax', '') !!}
\ No newline at end of file diff --git a/resources/views/partials/forms/edit/item_number.blade.php b/resources/views/partials/forms/edit/item_number.blade.php index 1c9654cb45..1adeb89be4 100644 --- a/resources/views/partials/forms/edit/item_number.blade.php +++ b/resources/views/partials/forms/edit/item_number.blade.php @@ -1,8 +1,8 @@
-
- +
+ {!! $errors->first('item_no', '') !!}
diff --git a/resources/views/partials/forms/edit/kit-select.blade.php b/resources/views/partials/forms/edit/kit-select.blade.php index a9b6525202..d8c6ba1013 100644 --- a/resources/views/partials/forms/edit/kit-select.blade.php +++ b/resources/views/partials/forms/edit/kit-select.blade.php @@ -2,8 +2,8 @@ {{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }} -
- @if ($kit_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))