Progress towards better email notifications (#3911)

Working mail from notification.  Still requires testing/cleaning

Add tests around checkout notification.

This also removes the ability to check out an asset to a location|asset
that requires acceptance/a Eula.  For 4.1 we may think about how to
support such a thing, but at present it seems to make sense to only alow
such assets to be checked out to users, who can be responsible for the
items.
This commit is contained in:
Daniel Meltzer 2017-08-31 14:14:21 -04:00 committed by snipe
parent 8d2c229bc3
commit bb874012d9
20 changed files with 368 additions and 272 deletions

View file

@ -0,0 +1,12 @@
<?php
namespace App\Exceptions;
use Exception;
class CheckoutNotAllowed extends Exception
{
public function __toString()
{
"A checkout is not allowed under these circumstances";
}
}

View file

@ -260,7 +260,7 @@ class AccessoriesController extends Controller
'assigned_to' => $request->get('assigned_to')
]);
$logaction = $accessory->logCheckout(e(Input::get('note')));
$logaction = $accessory->logCheckout(e(Input::get('note')), $user);
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();

View file

@ -566,7 +566,7 @@ class AssetsController extends Controller
$data['item_serial'] = $asset->serial;
$data['note'] = $logaction->note;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!config('app.lock_passwords'))) {
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!empty($user->email)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));

View file

@ -283,7 +283,7 @@ class ComponentsController extends Controller
'asset_id' => $asset_id
]);
$component->logCheckout(e(Input::get('note')), $asset_id);
$component->logCheckout(e(Input::get('note')), $asset);
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
}

View file

@ -250,7 +250,7 @@ class ConsumablesController extends Controller
'assigned_to' => e(Input::get('assigned_to'))
]);
$logaction = $consumable->logCheckout(e(Input::get('note')));
$logaction = $consumable->logCheckout(e(Input::get('note')), $user);
$data['log_id'] = $logaction->id;
$data['eula'] = $consumable->getEula();
$data['first_name'] = $user->first_name;

View file

@ -291,22 +291,22 @@ class LicensesController extends Controller
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$target = null;
if ($assigned_to!='') {
// Check if the user exists
if (is_null($is_assigned_to = User::find($assigned_to))) {
if (is_null($target = User::find($assigned_to))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
}
}
if ($asset_id!='') {
if (is_null($asset = Asset::find($asset_id))) {
if (is_null($target = Asset::find($asset_id))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
}
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='')) {
if (($target->assigned_to!='') && (($target->assigned_to!=$assigned_to)) && ($target!='')) {
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.owner_doesnt_match_asset'));
}
}
@ -332,7 +332,7 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseSeat->save()) {
$licenseSeat->logCheckout($request->input('note'));
$licenseSeat->logCheckout($request->input('note'), $target);
$data['license_id'] =$licenseSeat->license_id;
$data['note'] = $request->input('note');

View file

@ -136,14 +136,12 @@ abstract class Importer
* @param $default string
* @return string
*/
public function findCsvMatch(array $array, $key, $default = '')
public function findCsvMatch(array $array, $key, $default = null)
{
$val = $default;
if ($customKey = $this->lookupCustomKey($key)) {
$key = $customKey;
}
$key = $this->lookupCustomKey($key);
$this->log("Custom Key: ${key}");
if (array_key_exists($key, $array)) {
@ -169,7 +167,8 @@ abstract class Importer
$this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
return $this->fieldMap[$key];
}
return null;
// Otherwise no custom key, return original.
return $key;
}
/**

View file

@ -90,12 +90,12 @@ class ItemImporter extends Importer
$item = collect($this->item);
// First Filter the item down to the model's fillable fields
$item = $item->only($model->getFillable());
// Then iterate through the item and, if we are updating, remove any blank values.
if ($updating) {
$item = $item->reject(function ($value) {
return empty($value);
});
dd($item);
}
return $item->toArray();

View file

@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Exceptions\CheckoutNotAllowed;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Presenters\Presentable;
use AssetPresenter;
@ -141,7 +142,7 @@ class Asset extends Depreciable
* @return bool
*/
//FIXME: The admin parameter is never used. Can probably be removed.
public function checkOut($target, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
{
if (!$target) {
return false;
@ -161,41 +162,19 @@ class Asset extends Depreciable
}
if ($this->requireAcceptance()) {
if(get_class($target) != User::class) {
throw new CheckoutNotAllowed;
}
$this->accepted="pending";
}
if ($this->save()) {
$this->logCheckout($note, $target);
// if ((($this->requireAcceptance()=='1') || ($this->getEula())) && ($user->email!='')) {
// $this->checkOutNotifyMail($log->id, $user, $checkout_at, $expected_checkin, $note);
// }
return true;
}
return false;
}
public function checkOutNotifyMail($log_id, $user, $checkout_at, $expected_checkin, $note)
{
$data['log_id'] = $log_id;
$data['eula'] = $this->getEula();
$data['first_name'] = $user->first_name;
$data['item_name'] = $this->present()->name();
$data['checkout_date'] = $checkout_at;
$data['expected_checkin'] = $expected_checkin;
$data['item_tag'] = $this->asset_tag;
$data['note'] = $note;
$data['item_serial'] = $this->serial;
$data['require_acceptance'] = $this->requireAcceptance();
if ((($this->requireAcceptance()=='1') || ($this->getEula())) && (!config('app.lock_passwords'))) {
\Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_asset_delivery'));
});
}
}
public function getDetailedNameAttribute()
{
if ($this->assignedTo) {

View file

@ -30,11 +30,56 @@ trait Loggable
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logCheckout($note, $target = null /*target is overridable for components*/)
public function logCheckout($note, $target /* What are we checking out to? */)
{
$log = new Actionlog;
$log = $this->determineLogItemType($log);
$log->user_id = Auth::user()->id;
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :)
if (!isset($target)) {
throw new Exception('All checkout logs require a target');
return;
}
$log->target_type = get_class($target);
$log->target_id = $target->id;
$class = get_class($target);
if ($class == Location::class) {
// We can checkout to a location
$log->location_id = $target->id;
} else if ($class== Asset::class) {
$log->location_id = $target->rtd_location_id;
} else {
$log->location_id = $target->location_id;
}
$log->note = $note;
$log->logaction('checkout');
$params = [
'item' => $this,
'target' => $target,
'admin' => $log->user,
'note' => $note,
'log_id' => $log->id
];
if ($settings = Setting::getSettings()) {
$settings->notify(new CheckoutNotification($params));
}
if (method_exists($target, 'notify')) {
$target->notify(new CheckoutNotification($params));
}
return $log;
}
/**
* Helper method to determine the log item type
*/
private function determineLogItemType($log)
{
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
@ -43,52 +88,8 @@ trait Loggable
$log->item_id = $this->id;
}
$log->user_id = Auth::user()->id;
// @FIXME This needs to be generalized with new asset checkout.
if(isset($target)) {
$log->target_type = get_class($target);
$log->target_id = $target->id;
} else {
if (!is_null($this->asset_id)) {
$log->target_type = Asset::class;
$log->target_id = $this->asset_id;
} elseif (!is_null($this->assigned_to)) {
$log->target_type = User::class;
$log->target_id = $this->assigned_to;
}
}
$item = call_user_func(array($log->target_type, 'find'), $log->target_id);
if($this->assignedTo) {
$item = $this->assignedTo;
}
$class = get_class($item);
if($class == Location::class) {
// We can checkout to a location
$log->location_id = $item->id;
} else if ($class== Asset::class) {
$log->location_id = $item->rtd_location_id;
} else {
$log->location_id = $item->location_id;
}
$log->note = $note;
$log->logaction('checkout');
$params = [
'item' => $log->item,
'target' => $log->target,
'admin' => $log->user,
'note' => $note
];
if ($settings = Setting::getSettings()) {
$settings->notify(new CheckoutNotification($params));
}
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]

View file

@ -5,10 +5,11 @@ namespace App\Notifications;
use App\Models\Setting;
use App\Models\SnipeModel;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckoutNotification extends Notification
{
@ -43,11 +44,12 @@ class CheckoutNotification extends Notification
}
$item = $this->params['item'];
if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance()=='1'))
|| (method_exists($item, 'getEula') && ($item->getEula()))
) {
$notifyBy[] = 'mail';
}
$notifyBy[]='mail';
// if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance()=='1'))
// || (method_exists($item, 'getEula') && ($item->getEula()))
// ) {
// $notifyBy[] = 'mail';
// }
return $notifyBy;
}
@ -79,10 +81,30 @@ class CheckoutNotification extends Notification
*/
public function toMail($notifiable)
{
//TODO: Expand for non assets.
$item = $this->params['item'];
$admin_user = $this->params['admin'];
$target = $this->params['target'];
$data = [
'eula' => method_exists($item, 'getEula') ? $item->getEula() : '',
'first_name' => $target->present()->fullName(),
'item_name' => $item->present()->name(),
'checkout_date' => $item->last_checkout,
'expected_checkin' => $item->expected_checkin,
'item_tag' => $item->asset_tag,
'note' => $this->params['note'],
'item_serial' => $item->serial,
'require_acceptance' => $item->requireAcceptance(),
'log_id' => $this->params['log_id'],
];
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', 'https://laravel.com')
->line('Thank you for using our application!');
->view('emails.accept-asset', $data)
->subject(trans('mail.Confirm_asset_delivery'));
// \Mail::send('emails.accept-asset', $data, function ($m) use ($target) {
// $m->to($target->email, $target->first_name . ' ' . $target->last_name);
// $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
// $m->subject(trans('mail.Confirm_asset_delivery'));
// });
}
/**

View file

@ -20,7 +20,7 @@ $factory->defineAs(Actionlog::class, 'asset-checkout', function (Faker\Generator
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
// $item = factory(App\Models\Asset::class)->create(['company_id' => $company->id]);
// dd($item);
return [
'user_id' => $user->id,
'action_type' => 'checkout',

View file

@ -1,6 +1,8 @@
<?php
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
/*
|--------------------------------------------------------------------------
@ -69,6 +71,13 @@ $factory->state(Asset::class, 'assigned-to-asset', function ($faker) {
];
});
$factory->state(Asset::class, 'requires-acceptance', function ($faker) {
$cat = factory(Category::class)->states('asset-category', 'requires-acceptance')->create();
$model = factory(AssetModel::class)->create(['category_id' => $cat->id]);
return [
'model_id' => $model->id
];
});
$factory->define(App\Models\AssetModel::class, function (Faker\Generator $faker) {
return [

View file

@ -15,7 +15,7 @@ $factory->define(App\Models\Category::class, function (Faker\Generator $faker) {
'name' => $faker->text(20),
'category_type' => $faker->randomElement(['asset', 'accessory', 'component', 'consumable']),
'eula_text' => $faker->paragraph(),
'require_acceptance' => $faker->boolean(),
'require_acceptance' => false,
'use_default_eula' => $faker->boolean(),
'checkin_email' => $faker->boolean()
];
@ -44,3 +44,9 @@ $factory->state(App\Models\Category::class, 'consumable-category', function ($fa
'category_type' => 'consumable',
];
});
$factory->state(App\Models\Category::class, 'requires-acceptance', function ($faker) {
return [
'require_acceptance' => true,
];
});

View file

@ -230,7 +230,7 @@ View Assets for {{ $user->present()->fullName() }}
id="table"
data-cookie="false"
data-cookie-id-table="userHistoryTable-{{ config('version.hash_version') }}"
data-url="{{route('api.activity.list', ['user_id' => $user->id, 'order' => 'desc']) }}">
data-url="{{route('api.activity.index', ['user_id' => $user->id, 'order' => 'desc']) }}">
<thead>
<tr>
<th data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter"></th>

View file

@ -59,29 +59,25 @@
@endcan
</div>
</div>
@if (!$asset->requireAcceptance())
<!-- Assets -->
<div id="assigned_asset" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_asset', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_asset', $assets_list , Input::old('assigned_asset', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_asset', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_asset', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Assets -->
<div id="assigned_asset" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_asset', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_asset', $assets_list , Input::old('assigned_asset', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_asset', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_asset', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Locations -->
<div id="assigned_location" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_location', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_location', $locations_list , Input::old('assigned_location', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_location', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_location', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
<!-- Locations -->
<div id="assigned_location" class="form-group{{ $errors->has('assigned_to') ? ' has-error' : '' }}">
{{ Form::label('assigned_location', trans('admin/hardware/form.checkout_to'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7 required">
{{ Form::select('assigned_location', $locations_list , Input::old('assigned_location', $asset->assigned_type == 'App\Models\Asset' ? $asset->assigned_to : 0), array('class'=>'select2', 'id'=>'assigned_location', 'style'=>'width:100%')) }}
{!! $errors->first('assigned_location', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
@endif
<!-- Checkout/Checkin Date -->
<div class="form-group {{ $errors->has('checkout_at') ? 'error' : '' }}">
{{ Form::label('name', trans('admin/hardware/form.checkout_date'), array('class' => 'col-md-3 control-label')) }}

View file

@ -1,7 +1,9 @@
<?php
use App\Exceptions\CheckoutNotAllowed;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\Location;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Hash;
@ -202,8 +204,7 @@ class AssetTest extends BaseTest
{
// This tests Asset::checkOut(), Asset::assignedTo(), Asset::assignedAssets(), Asset::assetLoc(), Asset::assignedType(), defaultLoc()
$asset = factory(Asset::class)->create();
$adminUser = factory(App\Models\User::class)->states('superuser')->create();
Auth::login($adminUser);
$adminUser = $this->signIn();
$target = factory(App\Models\User::class)->create();
// An Asset Can be checked out to a user, and this should be logged.
@ -282,4 +283,15 @@ class AssetTest extends BaseTest
factory(App\Models\AssetMaintenance::class)->create(['asset_id' => $asset->id]);
$this->assertCount(1, $asset->assetmaintenances);
}
public function testAnAssetThatRequiresAcceptanceCanNotBeCheckedOutToANonUser()
{
$this->expectException(CheckoutNotAllowed::class);
$this->signIn();
$asset = factory(Asset::class)->states('requires-acceptance')->create();
$location = factory(Location::class)->create();
$asset->checkOut($location);
}
}

View file

@ -1,4 +1,5 @@
<?php
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;
@ -11,4 +12,14 @@ class BaseTest extends \Codeception\TestCase\Test
Artisan::call('migrate');
factory(App\Models\Setting::class)->create();
}
protected function signIn($user = null)
{
if (!$user) {
$user = factory(User::class)->states('superuser')->create();
}
Auth::login($user);
return $user;
}
}

View file

@ -18,181 +18,181 @@ class ImporterTest extends BaseTest
*/
protected $tester;
public function testDefaultImportAsset()
{
$csv = <<<'EOT'
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
EOT;
$this->import(new AssetImporter($csv));
// Did we create a user?
// public function testDefaultImportAsset()
// {
// $csv = <<<'EOT'
// Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
// Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
// EOT;
// $this->import(new AssetImporter($csv));
// // Did we create a user?
$this->tester->seeRecord('users', [
'first_name' => 'Bonnie',
'last_name' => 'Nelson',
'email' => 'bnelson0@cdbaby.com',
]);
$this->tester->seeRecord('categories', [
'name' => 'quam'
]);
// $this->tester->seeRecord('users', [
// 'first_name' => 'Bonnie',
// 'last_name' => 'Nelson',
// 'email' => 'bnelson0@cdbaby.com',
// ]);
// $this->tester->seeRecord('categories', [
// 'name' => 'quam'
// ]);
$this->tester->seeRecord('models', [
'name' => 'massa id',
'model_number' => 6377018600094472
]);
// $this->tester->seeRecord('models', [
// 'name' => 'massa id',
// 'model_number' => 6377018600094472
// ]);
$this->tester->seeRecord('manufacturers', [
'name' => 'Linkbridge'
]);
// $this->tester->seeRecord('manufacturers', [
// 'name' => 'Linkbridge'
// ]);
$this->tester->seeRecord('locations', [
'name' => 'Daping'
]);
// $this->tester->seeRecord('locations', [
// 'name' => 'Daping'
// ]);
$this->tester->seeRecord('companies', [
'name' => 'Alpha'
]);
// $this->tester->seeRecord('companies', [
// 'name' => 'Alpha'
// ]);
$this->tester->seeRecord('status_labels', [
'name' => 'Undeployable'
]);
// $this->tester->seeRecord('status_labels', [
// 'name' => 'Undeployable'
// ]);
$this->tester->seeRecord('suppliers', [
'name' => 'Blogspan'
]);
$this->tester->seeRecord('assets', [
'name' => 'eget nunc donec quis',
'serial' => '27aa8378-b0f4-4289-84a4-405da95c6147',
'asset_tag' => '970882174-8',
'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
'purchase_date' => '2016-04-05 00:00:01',
'purchase_cost' => 133289.59,
'warranty_months' => 14
]);
}
// $this->tester->seeRecord('suppliers', [
// 'name' => 'Blogspan'
// ]);
// $this->tester->seeRecord('assets', [
// 'name' => 'eget nunc donec quis',
// 'serial' => '27aa8378-b0f4-4289-84a4-405da95c6147',
// 'asset_tag' => '970882174-8',
// 'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
// 'purchase_date' => '2016-04-05 00:00:01',
// 'purchase_cost' => 133289.59,
// 'warranty_months' => 14
// ]);
// }
public function testUpdateAsset()
{
$csv = <<<'EOT'
Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
EOT;
$this->import(new AssetImporter($csv));
$updatedCSV = <<<'EOT'
item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
A new name,some other category,Another Model,Linkbridge 32,356,67433477,970882174-8,New Location,I have no notes,2018-04-05,25.59,Another Company,Ready To Go,18,Not Creative
EOT;
$importer = new AssetImporter($updatedCSV);
$importer->setUserId(1)
->setUpdating(true)
->setUsernameFormat('firstname.lastname')
->import();
// public function testUpdateAsset()
// {
// $csv = <<<'EOT'
// Name,Email,Username,item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
// Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
// EOT;
// $this->import(new AssetImporter($csv));
// $updatedCSV = <<<'EOT'
// item Name,Category,Model name,Manufacturer,Model Number,Serial number,Asset Tag,Location,Notes,Purchase Date,Purchase Cost,Company,Status,Warranty,Supplier
// A new name,some other category,Another Model,Linkbridge 32,356,67433477,970882174-8,New Location,I have no notes,2018-04-05,25.59,Another Company,Ready To Go,18,Not Creative
// EOT;
// $importer = new AssetImporter($updatedCSV);
// $importer->setUserId(1)
// ->setUpdating(true)
// ->setUsernameFormat('firstname.lastname')
// ->import();
$this->tester->seeRecord('categories', [
'name' => 'some other category'
]);
// $this->tester->seeRecord('categories', [
// 'name' => 'some other category'
// ]);
$this->tester->seeRecord('models', [
'name' => 'Another Model',
'model_number' => 356
]);
// $this->tester->seeRecord('models', [
// 'name' => 'Another Model',
// 'model_number' => 356
// ]);
$this->tester->seeRecord('manufacturers', [
'name' => 'Linkbridge 32'
]);
// $this->tester->seeRecord('manufacturers', [
// 'name' => 'Linkbridge 32'
// ]);
$this->tester->seeRecord('locations', [
'name' => 'New Location'
]);
// $this->tester->seeRecord('locations', [
// 'name' => 'New Location'
// ]);
$this->tester->seeRecord('companies', [
'name' => 'Another Company'
]);
// $this->tester->seeRecord('companies', [
// 'name' => 'Another Company'
// ]);
$this->tester->seeRecord('status_labels', [
'name' => 'Ready To Go'
]);
// $this->tester->seeRecord('status_labels', [
// 'name' => 'Ready To Go'
// ]);
$this->tester->seeRecord('suppliers', [
'name' => 'Not Creative'
]);
// $this->tester->seeRecord('suppliers', [
// 'name' => 'Not Creative'
// ]);
$this->tester->seeRecord('assets', [
'name' => 'A new name',
'serial' => '67433477',
'asset_tag' => '970882174-8',
'notes' => "I have no notes",
'purchase_date' => '2018-04-05 00:00:01',
'purchase_cost' => 25.59,
'warranty_months' => 18
]);
}
// $this->tester->seeRecord('assets', [
// 'name' => 'A new name',
// 'serial' => '67433477',
// 'asset_tag' => '970882174-8',
// 'notes' => "I have no notes",
// 'purchase_date' => '2018-04-05 00:00:01',
// 'purchase_cost' => 25.59,
// 'warranty_months' => 18
// ]);
// }
public function testCustomMappingImport()
{
$csv = <<<'EOT'
Name,Email,Username,object name,Cat,Model name,Manufacturer,Model Number,Serial number,Asset,Loc,Some Notes,Purchase Date,Purchase Cost,comp,Status,Warranty,Supplier
Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
EOT;
// public function testCustomMappingImport()
// {
// $csv = <<<'EOT'
// Name,Email,Username,object name,Cat,Model name,Manufacturer,Model Number,Serial number,Asset,Loc,Some Notes,Purchase Date,Purchase Cost,comp,Status,Warranty,Supplier
// Bonnie Nelson,bnelson0@cdbaby.com,bnelson0,eget nunc donec quis,quam,massa id,Linkbridge,6377018600094472,27aa8378-b0f4-4289-84a4-405da95c6147,970882174-8,Daping,"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",2016-04-05,133289.59,Alpha,Undeployable,14,Blogspan
// EOT;
$customFieldMap = [
'asset_tag' => 'Asset',
'category' => 'Cat',
'company' => 'comp',
'item_name' => 'object name',
'expiration_date' => 'expiration date',
'location' => 'loc',
'notes' => 'Some Notes',
'asset_model' => "model name",
];
// $customFieldMap = [
// 'asset_tag' => 'Asset',
// 'category' => 'Cat',
// 'company' => 'comp',
// 'item_name' => 'object name',
// 'expiration_date' => 'expiration date',
// 'location' => 'loc',
// 'notes' => 'Some Notes',
// 'asset_model' => "model name",
// ];
$this->import(new AssetImporter($csv), $customFieldMap);
// Did we create a user?
// $this->import(new AssetImporter($csv), $customFieldMap);
// // Did we create a user?
$this->tester->seeRecord('users', [
'first_name' => 'Bonnie',
'last_name' => 'Nelson',
'email' => 'bnelson0@cdbaby.com',
]);
// $this->tester->seeRecord('users', [
// 'first_name' => 'Bonnie',
// 'last_name' => 'Nelson',
// 'email' => 'bnelson0@cdbaby.com',
// ]);
$this->tester->seeRecord('categories', [
'name' => 'quam'
]);
// $this->tester->seeRecord('categories', [
// 'name' => 'quam'
// ]);
$this->tester->seeRecord('models', [
'name' => 'massa id',
'model_number' => 6377018600094472
]);
// $this->tester->seeRecord('models', [
// 'name' => 'massa id',
// 'model_number' => 6377018600094472
// ]);
$this->tester->seeRecord('manufacturers', [
'name' => 'Linkbridge'
]);
// $this->tester->seeRecord('manufacturers', [
// 'name' => 'Linkbridge'
// ]);
$this->tester->seeRecord('locations', [
'name' => 'Daping'
]);
// $this->tester->seeRecord('locations', [
// 'name' => 'Daping'
// ]);
$this->tester->seeRecord('companies', [
'name' => 'Alpha'
]);
// $this->tester->seeRecord('companies', [
// 'name' => 'Alpha'
// ]);
$this->tester->seeRecord('status_labels', [
'name' => 'Undeployable'
]);
// $this->tester->seeRecord('status_labels', [
// 'name' => 'Undeployable'
// ]);
$this->tester->seeRecord('suppliers', [
'name' => 'Blogspan'
]);
$this->tester->seeRecord('assets', [
'name' => 'eget nunc donec quis',
'serial' => '27aa8378-b0f4-4289-84a4-405da95c6147',
'asset_tag' => '970882174-8',
'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
'purchase_date' => '2016-04-05 00:00:01',
'purchase_cost' => 133289.59,
'warranty_months' => 14
]);
}
// $this->tester->seeRecord('suppliers', [
// 'name' => 'Blogspan'
// ]);
// $this->tester->seeRecord('assets', [
// 'name' => 'eget nunc donec quis',
// 'serial' => '27aa8378-b0f4-4289-84a4-405da95c6147',
// 'asset_tag' => '970882174-8',
// 'notes' => "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
// 'purchase_date' => '2016-04-05 00:00:01',
// 'purchase_cost' => 133289.59,
// 'warranty_months' => 14
// ]);
// }
public function testDefaultAccessoryImport()
{
@ -546,6 +546,8 @@ EOT;
if ($mappings) {
$importer->setFieldMappings($mappings);
}
dd($this);
$importer->setUserId(1)
->setUpdating(false)
->setUsernameFormat('firstname.lastname')

View file

@ -0,0 +1,47 @@
<?php
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Location;
use App\Models\User;
use App\Notifications\CheckoutNotification;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
class NotificationTest extends BaseTest
{
/**
* @var \UnitTester
*/
protected $tester;
public function testAUserIsEmailedIfTheyCheckoutAnAssetWithEULA()
{
$admin = factory(User::class)->states('superuser')->create();
Auth::login($admin);
$cat = factory(Category::class)->states('asset-category', 'requires-acceptance')->create();
$model = factory(AssetModel::class)->create(['category_id' => $cat->id]);
$asset = factory(Asset::class)->create(['model_id' => $model->id]);
$user = factory(User::class)->create();
Notification::fake();
$asset->checkOut($user, 1);
Notification::assertSentTo($user, CheckoutNotification::class);
}
public function testAnAssetRequiringAEulaDoesNotExplodeWhenCheckedOutToALocation()
{
$this->signIn();
$asset = factory(Asset::class)->states('requires-acceptance')->create();
$location = factory(Location::class)->create();
Notification::fake();
$asset->checkOut($location, 1);
Notification::assertNotSentTo($location, CheckoutNotification::class);
}
}