Component Importer and various Importer Fixes (#3132)

* Importer fix: we were trimming the wrong part of the classname when creating a category.  This led to categories not being recognized.

* Add a component importer.  Uses same fields as consumable importer.  Only trick: If an asset_tag is present, we checkout a component to that asset on import

Enable component importer.  Also calculate the importer classname in a cleaner fashion.

* Fix comparisons.  find can return an index of 0, which is falsy.
This commit is contained in:
Daniel Meltzer 2017-01-05 17:45:12 -06:00 committed by snipe
parent 816d2fd095
commit 6ce20c32b1
11 changed files with 132 additions and 42 deletions

View file

@ -68,23 +68,9 @@ class ObjectImportCommand extends Command
public function fire()
{
$filename = $this->argument('filename');
$importerClass = Importer::class;
switch (strtolower($this->option('item-type'))) {
case "asset":
$importerClass = AssetImporter::class;
break;
case "accessory":
$importerClass = AccessoryImporter::class;
break;
case "component":
die("This is not implemented yet");
$importerClass = ComponentImporter::class;
break;
case "consumable":
$importerClass = ConsumableImporter::class;
break;
}
$importer = new $importerClass(
$class = title_case($this->option('item-type'));
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString(
$filename,
[$this, 'log'],
[$this, 'progress'],

View file

@ -812,6 +812,9 @@ class AssetsController extends Controller
case "consumable":
$redirectTo = "consumables.index";
break;
case "component":
$redirectTo = "components.index";
break;
}
if ($errors) { //Failure

View file

@ -31,25 +31,11 @@ class ItemImportRequest extends FormRequest
public function import()
{
$filename = config('app.private_uploads') . '/imports/assets/' . $this->get('filename');
$importerClass = Importer::class;
switch ($this->get('import-type')) {
case "asset":
$importerClass = 'App\Importer\AssetImporter';
break;
case "accessory":
$importerClass = 'App\Importer\AccessoryImporter';
break;
case "component":
die("This is not implemented yet");
$importerClass = ComponentImporter::class;
break;
case "consumable":
$importerClass = 'App\Importer\ConsumableImporter';
break;
}
$importer = new $importerClass(
$filename = config('app.private_uploads') . '/imports/assets/' . $this->get('filename');
$class = title_case($this->input('import-type'));
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString(
$filename,
[$this, 'log'],
[$this, 'progress'],

View file

@ -40,7 +40,7 @@ class AccessoryImporter extends ItemImporter
$accessory = $this->accessories->search(function ($key) {
return strcasecmp($key->name, $this->item['item_name']) == 0;
});
if ($accessory) {
if ($accessory !== false) {
$editingAccessory = true;
if (!$this->updating) {
$this->log('A matching Accessory ' . $this->item["item_name"] . ' already exists. ');

View file

@ -51,7 +51,7 @@ class AssetImporter extends ItemImporter
$asset = $this->assets->search(function ($key) {
return strcasecmp($key->asset_tag, $this->item['asset_tag']) == 0;
});
if ($asset) {
if ($asset !== false) {
$editingAsset = true;
if (!$this->updating) {
$this->log('A matching Asset ' . $this->item['asset_tag'] . ' already exists');

View file

@ -0,0 +1,114 @@
<?php
/**
* Created by PhpStorm.
* User: parallelgrapefruit
* Date: 12/24/16
* Time: 1:03 PM
*/
namespace App\Importer;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\Component;
class ComponentImporter extends ItemImporter
{
protected $components;
function __construct($filename, $logCallback, $progressCallback, $errorCallback, $testRun = false, $user_id = -1, $updating = false, $usernameFormat = null)
{
parent::__construct($filename, $logCallback, $progressCallback, $errorCallback, $testRun, $user_id, $updating, $usernameFormat);
$this->components = Component::all();
}
protected function handle($row)
{
parent::handle($row); // TODO: Change the autogenerated stub
$this->createComponentIfNotExists();
}
/**
* Create a component if a duplicate does not exist
*
* @author Daniel Melzter
* @since 3.0
*/
public function createComponentIfNotExists()
{
$component = null;
$editingComponent = false;
$this->log("Creating Component");
$component = $this->components->search(function ($key) {
return strcasecmp($key->name, $this->item['item_name']) == 0;
});
if ($component !== false) {
$editingComponent = true;
if (!$this->updating) {
$this->log('A matching Component ' . $this->item["item_name"] . ' already exists. ');
return;
}
} else {
$this->log("No matching component, creating one");
$component = new Component();
}
if (!$editingComponent) {
$component->name = $this->item["item_name"];
}
if (!empty($this->item["purchase_date"])) {
$component->purchase_date = $this->item["purchase_date"];
} else {
$component->purchase_date = null;
}
if (!empty($this->item["purchase_cost"])) {
$component->purchase_cost = Helper::ParseFloat($this->item["purchase_cost"]);
}
if (isset($this->item["location"])) {
$component->location_id = $this->item["location"]->id;
}
$component->user_id = $this->user_id;
if (isset($this->item["company"])) {
$component->company_id = $this->item["company"]->id;
}
if (!empty($this->item["order_number"])) {
$component->order_number = $this->item["order_number"];
}
if (isset($this->item["category"])) {
$component->category_id = $this->item["category"]->id;
}
// TODO:Implement
//$component->notes= e($this->item_notes);
if (!empty($this->item["requestable"])) {
$component->requestable = filter_var($this->item["requestable"], FILTER_VALIDATE_BOOLEAN);
}
$component->qty = 1;
if ( (!empty($this->item["quantity"])) && ($this->item["quantity"] > -1)) {
$component->qty = $this->item["quantity"];
}
if ($this->testRun) {
$this->log('TEST RUN - Component ' . $this->item['item_name'] . ' not created');
return;
}
if ($component->save()) {
$component->logCreate('Imported using CSV Importer');
$this->log("Component " . $this->item["item_name"] . ' was created');
// If we have an asset tag, checkout to that asset.
if(isset($this->item['asset_tag']) && ($asset = Asset::where('asset_tag', $this->item['asset_tag'])->first()) ) {
$component->assets()->attach($component->id, [
'component_id' => $component->id,
'user_id' => $this->user_id,
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => 1, // Only assign the first one to the asset
'asset_id' => $asset->id
]);
}
return;
}
$this->jsonError($component, 'Component', $component->getErrors());
}
}

View file

@ -40,7 +40,7 @@ class ConsumableImporter extends ItemImporter
$consumable = $this->consumables->search(function ($key) {
return strcasecmp($key->name, $this->item['item_name']) == 0;
});
if ($consumable) {
if ($consumable !== false) {
$editingConsumable = true;
if (!$this->updating) {
$this->log('A matching Consumable ' . $this->item["item_name"] . ' already exists. ');

View file

@ -78,7 +78,7 @@ abstract class Importer
$updating = false,
$usernameFormat = null
) {
$this->filename = $filename;
$this->csv = Reader::createFromPath($filename);
$this->csv->setNewLine('\r\n');

View file

@ -138,7 +138,7 @@ class ItemImporter extends Importer
public function createOrFetchCategory($asset_category)
{
// Magic to transform "AssetImporter" to "asset" or similar.
$classname = get_class($this);
$classname = class_basename(get_class($this));
$item_type = strtolower(substr($classname, 0, strpos($classname, 'Importer')));
if (empty($asset_category)) {
$asset_category = 'Unnamed Category';
@ -150,6 +150,7 @@ class ItemImporter extends Importer
// We need strict compare here because the index returned above can be 0.
// This casts to false and causes false positives
if ($category !== false) {
$this->log("A matching category: " . $asset_category . " already exists");
return $this->categories[$category];
}

View file

@ -97,7 +97,7 @@
<i class="fa fa-plus icon-white"></i>
<span>Select Import File...</span>
<!-- The file input field used as target for the file upload widget -->
<input id="fileupload" type="file" name="files[]" data-url="{{ url('/') }}/api/hardware/import" accept="text/csv">
<input id="fileupload" type="file" name="files[]" data-url="{{ route('api.hardware.importFile') }}" accept="text/csv">
</span>
</div>
<div class="col-md-9" id="progress-container" style="visibility: hidden; padding-bottom: 20px;">

View file

@ -23,7 +23,7 @@ Route::group(['prefix' => 'v1', 'middleware' => 'auth:api'], function () {
Route::get('list/{status?}', [ 'as' => 'api.hardware.list', 'uses' => 'AssetsController@getDatatable' ]);
Route::post('import', 'AssetsController@postAPIImportUpload');
Route::post('import', [ 'as' => 'api.hardware.importFile', 'uses'=> 'AssetsController@postAPIImportUpload']);
});
/*---Status Label API---*/