mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-24 05:04:07 -08:00
Added additional helper files to assetmodel importer
Signed-off-by: snipe <snipe@snipe.net>
This commit is contained in:
parent
22c79d8e1b
commit
48713cbddf
|
@ -177,6 +177,9 @@ class ImportController extends Controller
|
|||
case 'asset':
|
||||
$redirectTo = 'hardware.index';
|
||||
break;
|
||||
case 'assetmodel':
|
||||
$redirectTo = 'models.index';
|
||||
break;
|
||||
case 'accessory':
|
||||
$redirectTo = 'accessories.index';
|
||||
break;
|
||||
|
|
|
@ -59,18 +59,22 @@ class AssetModelImporter extends ItemImporter
|
|||
$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['eol'] = trim($this->findCsvMatch($row, 'eol'));
|
||||
$this->item['notes'] = trim($this->findCsvMatch($row, 'notes'));
|
||||
$this->item['user_id'] = auth()->id();
|
||||
$this->item['created_by'] = auth()->id();
|
||||
|
||||
$this->item['requestable'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'))) == 1) ? '1' : 0;
|
||||
$assetmodel->requestable = $this->item['requestable'];
|
||||
|
||||
|
||||
if (!empty($this->item['category'])) {
|
||||
if ($category = $this->createOrFetchCategory($row, 'category')) {
|
||||
$this->item['category_id'] = $category->id;
|
||||
if ($category = $this->createOrFetchCategory($this->item['category'])) {
|
||||
$this->item['category_id'] = $category;
|
||||
}
|
||||
}
|
||||
if (!empty($this->item['manufacturer'])) {
|
||||
if ($manufacturer = $this->createOrFetchManufacturer($row, 'manufacturer')) {
|
||||
$this->item['manufacturer_id'] = $manufacturer->id;
|
||||
if ($manufacturer = $this->createOrFetchManufacturer($this->item['manufacturer'])) {
|
||||
$this->item['manufacturer_id'] = $manufacturer;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,7 @@ class ItemImporter extends Importer
|
|||
$classname = class_basename(get_class($this));
|
||||
$item_type = strtolower(substr($classname, 0, strpos($classname, 'Importer')));
|
||||
|
||||
// If we're importing asset models only (without attached assets), override the category type to asset
|
||||
if ($item_type == 'assetmodel') {
|
||||
$item_type = 'asset';
|
||||
}
|
||||
|
@ -302,7 +303,7 @@ class ItemImporter extends Importer
|
|||
|
||||
|
||||
if ($category) {
|
||||
$this->log('A matching category: '.$asset_category.' already exists');
|
||||
$this->log('A matching category: '.$category->name.' already exists');
|
||||
return $category->id;
|
||||
}
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ class Importer extends Component
|
|||
'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',
|
||||
'eol' => 'eol',
|
||||
|
||||
];
|
||||
|
||||
|
@ -570,15 +570,13 @@ class Importer extends Component
|
|||
$this->message_type = 'success';
|
||||
|
||||
unset($this->files);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->message = trans('admin/hardware/message.import.file_delete_error');
|
||||
$this->message_type = 'danger';
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->message = trans('admin/hardware/message.import.file_delete_error');
|
||||
$this->message_type = 'danger';
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function clearMessage()
|
||||
|
|
|
@ -143,4 +143,23 @@ class ImportFactory extends Factory
|
|||
return $attributes;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an asset model import type.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function assetmodel()
|
||||
{
|
||||
return $this->state(function (array $attributes) {
|
||||
$fileBuilder = Importing\AssetModelsImportFileBuilder::new();
|
||||
|
||||
$attributes['name'] = "{$attributes['name']} Asset Model";
|
||||
$attributes['import_type'] = 'assetmodel';
|
||||
$attributes['header_row'] = $fileBuilder->toCsv()[0];
|
||||
$attributes['first_row'] = $fileBuilder->firstRow();
|
||||
|
||||
return $attributes;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
</p>
|
||||
@endif
|
||||
|
||||
@if ($activeFile->import_type != 'location' && $activeFile->import_type == 'assetmodel' && $update)
|
||||
@if ($this->activeFile->import_type != 'location' && $this->activeFile->import_type == 'assetmodel' && $update)
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="send_welcome" data-livewire-component="{{ $this->getId() }}" wire:model.live="send_welcome">
|
||||
{{ trans('general.send_welcome_email_to_users') }}
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
Category,Category Type,Manufacturer,Name,Notes,Model Number,Fieldset
|
||||
Laptops,asset,Berge Inc,Test Model 1,,1786VM80X07,Laptops and Desktops
|
||||
Laptops,asset,"Botsford, Boyle and Herzog",Test Model 2,ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,9351IS25A51,Laptops and Desktops
|
||||
Laptops,asset,Pollich LLC,Test Model 3,,9929FR08W85,Laptops and Desktops
|
||||
Laptops,asset,Walker-Towne,Test Model 4,neque vestibulum eget vulputate ut ultrices vel augue vestibulum ante ipsum primis in faucibus orci luctus,9139KQ78G81,Laptops and Desktops
|
||||
Laptops,asset,Berge Inc,Test Model 5,turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin at turpis a pede,0910VB28Q61,Laptops and Desktops
|
||||
Laptops,asset,"Heaney, Altenwerth and Emmerich",Test Model 6,,7375EM02N97,Laptops and Desktops
|
||||
Laptops,asset,"Romaguera, Goldner and Crooks",Test Model 7,blandit non interdum in ante vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae,,Laptops and Desktops
|
||||
Laptops,asset,Watsica LLC,Test Model 8,sapien urna pretium nisl ut volutpat sapien arcu sed augue aliquam erat volutpat in,,Laptops and Desktops
|
||||
Laptops,asset,"Fritsch, Sauer and Conn",Test Model 9,orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur,,Laptops and Desktops
|
||||
Laptops,asset,"Upton, Feil and Jast",Test Model 10,velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,,Laptops and Desktops
|
||||
Laptops,asset,Berge Inc,Test Model 11,sed nisl nunc rhoncus dui vel sem sed sagittis nam congue risus semper porta volutpat quam pede lobortis ligula sit,,Laptops and Desktops
|
||||
Laptops,asset,"Kutch, Johnson and Olson",Test Model 12,curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae ipsum aliquam non,,Laptops and Desktops
|
||||
Laptops,asset,Mosciski Inc,Test Model 13,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci,,Laptops and Desktops
|
||||
Laptops,asset,Mosciski Inc,Test Model 14,egestas metus aenean fermentum donec ut mauris eget massa tempor convallis nulla neque libero convallis eget eleifend,,Laptops and Desktops
|
||||
Laptops,asset,"Upton, Feil and Jast",Test Model 15,,,Laptops and Desktops
|
||||
Laptops,asset,"Romaguera, Goldner and Crooks",Test Model 16,dui luctus rutrum nulla tellus in sagittis dui vel nisl duis ac nibh fusce,2315CN41G71,Laptops and Desktops
|
||||
Laptops,asset,Abernathy-Stamm,Test Model 17,maecenas pulvinar lobortis est phasellus sit amet erat nulla tempus,6080UE59E09,Laptops and Desktops
|
||||
Laptops,asset,Mosciski Inc,Test Model 18,,5505YF23M46,Laptops and Desktops
|
||||
Laptops,asset,Walker-Towne,Test Model 19,,8673QP30R80,Laptops and Desktops
|
||||
Mobile Phones,asset,"Heaney, Altenwerth and Emmerich",Test Model 20,nisl ut volutpat sapien arcu sed augue aliquam erat volutpat in congue etiam justo etiam pretium,9088XV67Q94,Mobile Devices
|
||||
Mobile Phones,asset,Okuneva Group,Test One,quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a nibh in quis,,Mobile Devices
|
||||
Name,Category,Manufacturer,Notes,Model Number,Fieldset,Requestable
|
||||
Changed Test Model,Laptops,Berge Inc,"Sphinx of black quartz, judge my vow",1786VM80X07,Laptops and Desktops,Y
|
||||
Test Model 2,Laptops,"Botsford, Boyle and Herzog",ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae mauris viverra diam vitae quam suspendisse potenti nullam,9351IS25A51,Laptops and Desktops,Y
|
||||
Test Model 3,Laptops,Pollich LLC,,9929FR08W85,Laptops and Desktops,Y
|
||||
Test Model 4,Laptops,Walker-Towne,neque vestibulum eget vulputate ut ultrices vel augue vestibulum ante ipsum primis in faucibus orci luctus,9139KQ78G81,Laptops and Desktops,Y
|
||||
Test Model 5,Laptops,Berge Inc,turpis adipiscing lorem vitae mattis nibh ligula nec sem duis aliquam convallis nunc proin at turpis a pede,0910VB28Q61,Laptops and Desktops,Y
|
||||
Test Model 6,Laptops,"Heaney, Altenwerth and Emmerich",,7375EM02N97,Laptops and Desktops,Y
|
||||
Test Model 7,Desktops,"Romaguera, Goldner and Crooks",Test Updated Text,,Laptops and Desktops,Y
|
||||
Test Model 8,Laptops,Watsica LLC,sapien urna pretium nisl ut volutpat sapien arcu sed augue aliquam erat volutpat in,,Laptops and Desktops,Y
|
||||
Test Model 9,Laptops,"Fritsch, Sauer and Conn",orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur,,Laptops and Desktops,Y
|
||||
Test Model 10,Laptops,"Upton, Feil and Jast",velit vivamus vel nulla eget eros elementum pellentesque quisque porta volutpat,,Laptops and Desktops,Y
|
||||
Test Model 11,Laptops,Berge Inc,sed nisl nunc rhoncus dui vel sem sed sagittis nam congue risus semper porta volutpat quam pede lobortis ligula sit,,Laptops and Desktops,Y
|
||||
Test Model 12,Laptops,"Kutch, Johnson and Olson",curae mauris viverra diam vitae quam suspendisse potenti nullam porttitor lacus at turpis donec posuere metus vitae ipsum aliquam non,,Laptops and Desktops,Y
|
||||
Test Model 13,Laptops,Mosciski Inc,molestie hendrerit at vulputate vitae nisl aenean lectus pellentesque eget nunc donec quis orci,,Laptops and Desktops,Y
|
||||
Test Model 14,Laptops,Mosciski Inc,egestas metus aenean fermentum donec ut mauris eget massa tempor convallis nulla neque libero convallis eget eleifend,,Laptops and Desktops,N
|
||||
Test Model 15,Laptops,"Upton, Feil and Jast",,,Laptops and Desktops,N
|
||||
Test Model 16,Laptops,"Romaguera, Goldner and Crooks",dui luctus rutrum nulla tellus in sagittis dui vel nisl duis ac nibh fusce,2315CN41G71,Laptops and Desktops,N
|
||||
Test Model 17,Laptops,Abernathy-Stamm,maecenas pulvinar lobortis est phasellus sit amet erat nulla tempus,6080UE59E09,Laptops and Desktops,N
|
||||
Test Model 18,Laptops,Mosciski Inc,,5505YF23M46,Laptops and Desktops,N
|
||||
Test Model 19,Laptops,Walker-Towne,,8673QP30R80,Laptops and Desktops,Y
|
||||
Test Model 20,Mobile Phones,"Heaney, Altenwerth and Emmerich",nisl ut volutpat sapien arcu sed augue aliquam erat volutpat in congue etiam justo etiam pretium,9088XV67Q94,Mobile Devices,Y
|
||||
Test One,Mobile Phones,Okuneva Group,quis libero nullam sit amet turpis elementum ligula vehicula consequat morbi a ipsum integer a nibh in quis,,Mobile Devices,Y
|
||||
Test Missing Category,,,orci luctus et ultrices posuere cubilia curae duis faucibus accumsan odio curabitur,,,
|
|
146
tests/Feature/Importing/Api/ImportAssetModelsTest.php
Normal file
146
tests/Feature/Importing/Api/ImportAssetModelsTest.php
Normal file
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Importing\Api;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\User;
|
||||
use App\Models\Import;
|
||||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\Concerns\TestsPermissionsRequirement;
|
||||
use Tests\Support\Importing\CleansUpImportFiles;
|
||||
use Tests\Support\Importing\AssetModelsImportFileBuilder as ImportFileBuilder;
|
||||
|
||||
class ImportAssetModelsTest extends ImportDataTestCase implements TestsPermissionsRequirement
|
||||
{
|
||||
use CleansUpImportFiles;
|
||||
use WithFaker;
|
||||
|
||||
protected function importFileResponse(array $parameters = []): TestResponse
|
||||
{
|
||||
if (!array_key_exists('import-type', $parameters)) {
|
||||
$parameters['import-type'] = 'assetmodel';
|
||||
}
|
||||
|
||||
return parent::importFileResponse($parameters);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testRequiresPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create());
|
||||
|
||||
$this->importFileResponse(['import' => 44])->assertForbidden();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function userWithImportAssetsPermissionCanImportUsers(): void
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->canImport()->create());
|
||||
|
||||
$import = Import::factory()->users()->create();
|
||||
|
||||
$this->importFileResponse(['import' => $import->id])->assertOk();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function importAssetModels(): void
|
||||
{
|
||||
$importFileBuilder = ImportFileBuilder::new();
|
||||
$row = $importFileBuilder->firstRow();
|
||||
$import = Import::factory()->assetmodel()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
$this->importFileResponse(['import' => $import->id, 'send-welcome' => 0])
|
||||
->assertOk()
|
||||
->assertExactJson([
|
||||
'payload' => null,
|
||||
'status' => 'success',
|
||||
'messages' => ['redirect_url' => route('models.index')]
|
||||
]);
|
||||
|
||||
$newAssetModel = AssetModel::query()
|
||||
->with(['category'])
|
||||
->where('name', $row['name'])
|
||||
->sole();
|
||||
|
||||
$this->assertEquals($row['name'], $newAssetModel->name);
|
||||
$this->assertEquals($row['model_number'], $newAssetModel->model_number);
|
||||
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function willIgnoreUnknownColumnsWhenFileContainsUnknownColumns(): void
|
||||
{
|
||||
$row = ImportFileBuilder::new()->definition();
|
||||
$row['unknownColumnInCsvFile'] = 'foo';
|
||||
|
||||
$importFileBuilder = new ImportFileBuilder([$row]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
$import = Import::factory()->assetmodel()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
||||
|
||||
$this->importFileResponse(['import' => $import->id])->assertOk();
|
||||
}
|
||||
|
||||
|
||||
#[Test]
|
||||
public function whenRequiredColumnsAreMissingInImportFile(): void
|
||||
{
|
||||
$importFileBuilder = ImportFileBuilder::new(['name' => ''])->forget(['category']);
|
||||
$import = Import::factory()->assetmodel()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
$this->importFileResponse(['import' => $import->id])
|
||||
->assertInternalServerError()
|
||||
->assertExactJson([
|
||||
'status' => 'import-errors',
|
||||
'payload' => null,
|
||||
'messages' => [
|
||||
'' => [
|
||||
'name' => ['The name field is required.'],
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$newAssetModels = AssetModel::query()
|
||||
->where('name', $importFileBuilder->firstRow()['name'])
|
||||
->get();
|
||||
|
||||
$this->assertCount(0, $newAssetModels);
|
||||
}
|
||||
|
||||
|
||||
#[Test]
|
||||
public function updateAssetModelFromImport(): void
|
||||
{
|
||||
$assetmodel = AssetModel::factory()->create()->refresh();
|
||||
$importFileBuilder = ImportFileBuilder::new(['name' => Str::random(), 'model_number' => Str::random()]);
|
||||
|
||||
$row = $importFileBuilder->firstRow();
|
||||
$import = Import::factory()->assetmodel()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
$this->importFileResponse(['import' => $import->id, 'import-update' => true])->assertOk();
|
||||
|
||||
$updatedAssetmodel = AssetModel::query()->find($assetmodel->id);
|
||||
$updatedAttributes = [
|
||||
'name',
|
||||
'model_number'
|
||||
];
|
||||
|
||||
$this->assertEquals($row['model_number'], $updatedAssetmodel->model_number);
|
||||
|
||||
$this->assertEquals(
|
||||
Arr::except($assetmodel->attributesToArray(), $updatedAttributes),
|
||||
Arr::except($updatedAssetmodel->attributesToArray(), $updatedAttributes),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
58
tests/Support/Importing/AssetModelsImportFileBuilder.php
Normal file
58
tests/Support/Importing/AssetModelsImportFileBuilder.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Support\Importing;
|
||||
|
||||
use App\Models\Category;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Build a users import file at runtime for testing.
|
||||
*
|
||||
* @template Row of array{
|
||||
* name?: string,
|
||||
* manufacturer?: string,
|
||||
* category?: string,
|
||||
* model_number?: string,
|
||||
* requestable?: int,
|
||||
* }
|
||||
*
|
||||
* @extends FileBuilder<Row>
|
||||
*/
|
||||
class AssetModelsImportFileBuilder extends FileBuilder
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getDictionary(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'Name',
|
||||
'category' => 'Category',
|
||||
'manufacturer' => 'Manufacturer',
|
||||
'model_number' => 'Model Number',
|
||||
'fieldset' => 'Fieldset',
|
||||
'eol' => 'EOL',
|
||||
'min_amt' => 'Min Amount',
|
||||
'notes' => 'Notes',
|
||||
'requestable' => 'Requestable',
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$faker = fake();
|
||||
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'category' => Str::random(),
|
||||
'model_number' => $faker->creditCardNumber(),
|
||||
'notes' => $faker->sentence(5),
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue