diff --git a/.gitignore b/.gitignore
index ee8f53384..8aed658e1 100755
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,7 @@ tests/_support/_generated/*
*.cache
.vagrant
+
+\.php_cs\.dist
+
+phpmd\.xml
diff --git a/.php_cs.dist b/.php_cs.dist
new file mode 100644
index 000000000..87846540f
--- /dev/null
+++ b/.php_cs.dist
@@ -0,0 +1,39 @@
+notPath('bootstrap/cache')
+ ->notPath('storage')
+ ->notPath('vendor')
+ ->notPath('node_modules')
+ ->in(__DIR__)
+ ->name('*.php')
+ ->notName('*.blade.php')
+ ->ignoreDotFiles(true)
+ ->ignoreVCS(true)
+;
+
+return PhpCsFixer\Config::create()
+ ->setRules(array(
+ '@Symfony' => true,
+ 'class_definition' => [
+ 'multiLineExtendsEachSingleLine' => true,
+ ],
+ 'ordered_class_elements' => [
+ 'use_trait', 'constant_public', 'constant_protected', 'constant_private',
+ 'property_public', 'property_protected', 'property_private', 'construct',
+ 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected',
+ 'method_private'
+ ],
+ 'function_declaration' => ['closure_function_spacing' => 'none'],
+ 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'],
+ 'array_syntax' => ['syntax' => 'short'],
+ 'concat_space' => ['spacing' => 'one'],
+ 'blank_line_after_namespace' => true,
+ 'linebreak_after_opening_tag' => true,
+ 'not_operator_with_successor_space' => true,
+ 'ordered_imports' => true,
+ 'phpdoc_order' => true,
+ ))
+ ->setFinder($finder);
diff --git a/app/Console/Commands/SendExpectedCheckinAlerts.php b/app/Console/Commands/SendExpectedCheckinAlerts.php
index a78f0e1ae..d10791200 100644
--- a/app/Console/Commands/SendExpectedCheckinAlerts.php
+++ b/app/Console/Commands/SendExpectedCheckinAlerts.php
@@ -2,17 +2,15 @@
namespace App\Console\Commands;
-
use App\Models\Asset;
use App\Models\Setting;
-use Illuminate\Console\Command;
-use App\Notifications\ExpectedCheckinNotification;
use App\Notifications\ExpectedCheckinAdminNotification;
+use App\Notifications\ExpectedCheckinNotification;
use Carbon\Carbon;
+use Illuminate\Console\Command;
class SendExpectedCheckinAlerts extends Command
{
-
/**
* The console command name.
*
@@ -29,8 +27,6 @@ class SendExpectedCheckinAlerts extends Command
/**
* Create a new command instance.
- *
- * @return void
*/
public function __construct()
{
@@ -44,30 +40,25 @@ class SendExpectedCheckinAlerts extends Command
*/
public function handle()
{
- $settings = Setting::getSettings();
+ $settings = Setting::getSettings();
$whenNotify = Carbon::now()->addDays(7);
- $assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
+ $assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
- $this->info($whenNotify.' is deadline');
- $this->info($assets->count().' assets');
+ $this->info($whenNotify . ' is deadline');
+ $this->info($assets->count() . ' assets');
foreach ($assets as $asset) {
- if ($asset->assigned && $asset->checkedOutToUser()) {
+ if ($asset->assigned && $asset->checkedOutToUser()) {
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
}
}
-
- // Send a rollup to the admin, if settings dictate
- $recipient = new \App\Models\Recipients\AlertRecipient();
-
- if (($assets) && ($assets->count() > 0) && ($settings->alert_email!='')) {
- $recipient->notify(new ExpectedCheckinAdminNotification($assets));
+ if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
+ // Send a rollup to the admin, if settings dictate
+ $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
+ return new AlertRecipient($item);
+ });
+ Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
}
-
-
-
-
-
}
}
diff --git a/app/Console/Commands/SendExpirationAlerts.php b/app/Console/Commands/SendExpirationAlerts.php
index cdc62f8cc..f78768ea5 100644
--- a/app/Console/Commands/SendExpirationAlerts.php
+++ b/app/Console/Commands/SendExpirationAlerts.php
@@ -4,16 +4,14 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\License;
+use App\Models\Recipients\AlertRecipient;
use App\Models\Setting;
-use DB;
-use App\Notifications\ExpiringLicenseNotification;
use App\Notifications\ExpiringAssetsNotification;
-
+use App\Notifications\ExpiringLicenseNotification;
use Illuminate\Console\Command;
class SendExpirationAlerts extends Command
{
-
/**
* The console command name.
*
@@ -30,8 +28,6 @@ class SendExpirationAlerts extends Command
/**
* Create a new command instance.
- *
- * @return void
*/
public function __construct()
{
@@ -45,46 +41,35 @@ class SendExpirationAlerts extends Command
*/
public function handle()
{
-
- $settings = Setting::getSettings();
+ $settings = Setting::getSettings();
$threshold = $settings->alert_interval;
+ if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
- // Expiring Assets
- $assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval);
- $this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count'=>$assets->count(), 'threshold' => $threshold]));
-
- // Expiring licenses
- $licenses = License::getExpiringLicenses($threshold);
-
- $this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count'=>$licenses->count(), 'threshold' => $threshold]));
-
- $recipient = new \App\Models\Recipients\AlertRecipient();
-
- if ((Setting::getSettings()->alert_email!='') && ($settings->alerts_enabled==1)) {
+ // Send a rollup to the admin, if settings dictate
+ $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
+ return new AlertRecipient($item);
+ });
+ // Expiring Assets
+ $assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval);
if ($assets->count() > 0) {
- // Send a rollup to the admin, if settings dictate
- $recipient->notify(new ExpiringAssetsNotification($assets, $threshold));
+ $this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $threshold]));
+ Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
}
+ // Expiring licenses
+ $licenses = License::getExpiringLicenses($threshold);
if ($licenses->count() > 0) {
- $recipient->notify(new ExpiringLicenseNotification($licenses, $threshold));
+ $this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold]));
+ Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold));
}
-
-
} else {
-
- if ($settings->alert_email=='') {
+ if ($settings->alert_email == '') {
$this->error('Could not send email. No alert email configured in settings');
- } elseif ($settings->alerts_enabled!=1) {
+ } elseif (1 != $settings->alerts_enabled) {
$this->info('Alerts are disabled in the settings. No mail will be sent');
}
-
}
-
-
-
-
}
}
diff --git a/app/Console/Commands/SendInventoryAlerts.php b/app/Console/Commands/SendInventoryAlerts.php
index 1f96fca9d..93b04978b 100644
--- a/app/Console/Commands/SendInventoryAlerts.php
+++ b/app/Console/Commands/SendInventoryAlerts.php
@@ -2,13 +2,12 @@
namespace App\Console\Commands;
-use App\Models\Setting;
-use DB;
-use Mail;
use App\Helpers\Helper;
+use App\Models\Recipients\AlertRecipient;
+use App\Models\Setting;
use App\Notifications\InventoryAlert;
-
use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Notification;
class SendInventoryAlerts extends Command
{
@@ -28,8 +27,6 @@ class SendInventoryAlerts extends Command
/**
* Create a new command instance.
- *
- * @return void
*/
public function __construct()
{
@@ -45,28 +42,24 @@ class SendInventoryAlerts extends Command
{
$settings = Setting::getSettings();
- if (($settings->alert_email!='') && ($settings->alerts_enabled==1)) {
-
+ if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
$items = Helper::checkLowInventory();
- // Send a rollup to the admin, if settings dictate
- $recipient = new \App\Models\Recipients\AlertRecipient();
+ if (($items) && (count($items) > 0)) {
+ $this->info(trans_choice('mail.low_inventory_alert', count($items)));
+ // Send a rollup to the admin, if settings dictate
+ $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
+ return new AlertRecipient($item);
+ });
- if (($items) && (count($items) > 0) && ($settings->alert_email!='')) {
-
- $this->info( trans_choice('mail.low_inventory_alert',count($items)) );
-
- $recipient->notify(new InventoryAlert($items, $settings->alert_threshold));
+ Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold));
}
-
} else {
- if (Setting::getSettings()->alert_email=='') {
+ if ($settings->alert_email == '') {
$this->error('Could not send email. No alert email configured in settings');
- } elseif (Setting::getSettings()->alerts_enabled!=1) {
+ } elseif (1 != $settings->alerts_enabled) {
$this->info('Alerts are disabled in the settings. No mail will be sent');
}
}
-
-
}
}
diff --git a/app/Events/CheckoutAccepted.php b/app/Events/CheckoutAccepted.php
new file mode 100644
index 000000000..0b26e6947
--- /dev/null
+++ b/app/Events/CheckoutAccepted.php
@@ -0,0 +1,27 @@
+acceptance = $acceptance;
+ }
+}
diff --git a/app/Events/CheckoutDeclined.php b/app/Events/CheckoutDeclined.php
new file mode 100644
index 000000000..2aae6dd91
--- /dev/null
+++ b/app/Events/CheckoutDeclined.php
@@ -0,0 +1,27 @@
+acceptance = $acceptance;
+ }
+}
diff --git a/app/Events/CheckoutableCheckedIn.php b/app/Events/CheckoutableCheckedIn.php
new file mode 100644
index 000000000..0f6a96491
--- /dev/null
+++ b/app/Events/CheckoutableCheckedIn.php
@@ -0,0 +1,30 @@
+checkoutable = $checkoutable;
+ $this->checkedOutTo = $checkedOutTo;
+ $this->checkedInBy = $checkedInBy;
+ $this->note = $note;
+ }
+}
diff --git a/app/Events/CheckoutableCheckedOut.php b/app/Events/CheckoutableCheckedOut.php
new file mode 100644
index 000000000..5e6ffd243
--- /dev/null
+++ b/app/Events/CheckoutableCheckedOut.php
@@ -0,0 +1,30 @@
+checkoutable = $checkoutable;
+ $this->checkedOutTo = $checkedOutTo;
+ $this->checkedOutBy = $checkedOutBy;
+ $this->note = $note;
+ }
+}
diff --git a/app/Http/Controllers/Accessories/AccessoryCheckinController.php b/app/Http/Controllers/Accessories/AccessoryCheckinController.php
index 83d59ab77..930e9b661 100644
--- a/app/Http/Controllers/Accessories/AccessoryCheckinController.php
+++ b/app/Http/Controllers/Accessories/AccessoryCheckinController.php
@@ -2,10 +2,12 @@
namespace App\Http\Controllers\Accessories;
+use App\Events\CheckoutableCheckedIn;
use App\Http\Controllers\Controller;
use App\Models\Accessory;
use App\Models\User;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
@@ -46,7 +48,7 @@ class AccessoryCheckinController extends Controller
* @throws \Illuminate\Auth\Access\AuthorizationException
* @internal param int $accessoryId
*/
- public function store($accessoryUserId = null, $backto = null)
+ public function store(Request $request, $accessoryUserId = null, $backto = null)
{
// Check if the accessory exists
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
@@ -61,7 +63,8 @@ class AccessoryCheckinController extends Controller
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
$return_to = e($accessory_user->assigned_to);
- $accessory->logCheckin(User::find($return_to), e(Input::get('note')));
+
+ event(new CheckoutableCheckedIn($accessory, User::find($return_to), Auth::user(), $request->input('note')));
return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
}
diff --git a/app/Http/Controllers/Accessories/AccessoryCheckoutController.php b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
index 50c174f0c..5ec8a8704 100644
--- a/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
+++ b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Accessories;
+use App\Events\CheckoutableCheckedOut;
use App\Http\Controllers\Controller;
use App\Models\Accessory;
use App\Models\User;
@@ -77,10 +78,10 @@ class AccessoryCheckoutController extends Controller
'assigned_to' => $request->get('assigned_to')
]);
- $accessory->logCheckout(e(Input::get('note')), $user);
-
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
+ event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note')));
+
// Redirect to the new accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
}
diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php
new file mode 100644
index 000000000..198e11e99
--- /dev/null
+++ b/app/Http/Controllers/Account/AcceptanceController.php
@@ -0,0 +1,125 @@
+pending()->get();
+
+ return view('account/accept.index', compact('acceptances'));
+ }
+
+ /**
+ * Shows a form to either accept or decline the checkout acceptance
+ *
+ * @param int $id
+ * @return mixed
+ */
+ public function create($id) {
+
+ $acceptance = CheckoutAcceptance::find($id);
+
+ if (is_null($acceptance)) {
+ return redirect()->reoute('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
+ }
+
+ if (! $acceptance->isPending()) {
+ return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
+ }
+
+ if (! $acceptance->isCheckedOutTo(Auth::user())) {
+ return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
+ }
+
+ if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
+ return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
+ }
+
+ return view('account/accept.create', compact('acceptance'));
+ }
+
+ /**
+ * Stores the accept/decline of the checkout acceptance
+ *
+ * @param Request $request
+ * @param int $id
+ * @return Redirect
+ */
+ public function store(Request $request, $id) {
+
+ $acceptance = CheckoutAcceptance::find($id);
+
+ if (is_null($acceptance)) {
+ return redirect()->reoute('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
+ }
+
+ if (! $acceptance->isPending()) {
+ return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
+ }
+
+ if (! $acceptance->isCheckedOutTo(Auth::user())) {
+ return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
+ }
+
+ if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
+ return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
+ }
+
+ if (!$request->filled('asset_acceptance')) {
+ return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
+ }
+
+ /**
+ * Get the signature and save it
+ */
+ if ($request->filled('signature_output')) {
+ $path = config('app.private_uploads').'/signatures';
+ $sig_filename = "siglog-" .Str::uuid() . '-'.date('Y-m-d-his').".png";
+ $data_uri = e($request->input('signature_output'));
+ $encoded_image = explode(",", $data_uri);
+ $decoded_image = base64_decode($encoded_image[1]);
+ file_put_contents($path."/".$sig_filename, $decoded_image);
+ }
+
+
+ if ($request->input('asset_acceptance') == 'accepted') {
+
+ $acceptance->accept($sig_filename);
+
+ event(new CheckoutAccepted($acceptance));
+
+ $return_msg = trans('admin/users/message.accepted');
+
+ } else {
+
+ $acceptance->decline($sig_filename);
+
+ event(new CheckoutDeclined($acceptance));
+
+ $return_msg = trans('admin/users/message.declined');
+
+ }
+
+ return redirect()->to('account/accept')->with('success', $return_msg);
+ }
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/Api/AccessoriesController.php b/app/Http/Controllers/Api/AccessoriesController.php
index 1669bd318..4e4793dcf 100644
--- a/app/Http/Controllers/Api/AccessoriesController.php
+++ b/app/Http/Controllers/Api/AccessoriesController.php
@@ -143,13 +143,16 @@ class AccessoriesController extends Controller
$accessory->lastCheckoutArray = $accessory->lastCheckout->toArray();
$accessory_users = $accessory->users;
-
- if($request->filled('search')){
- $accessory_users = $accessory_users->where('first_name', $request->input('search'))->concat($accessory_users->where('last_name', $request->input('search')));
+
+ if ($request->filled('search')) {
+ $accessory_users = $accessory->users()
+ ->where('first_name', 'like', '%'.$request->input('search').'%')
+ ->orWhere('last_name', 'like', '%'.$request->input('search').'%')
+ ->get();
}
$total = $accessory_users->count();
-
+
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
}
diff --git a/app/Http/Controllers/Api/LicensesController.php b/app/Http/Controllers/Api/LicensesController.php
index f85fa2314..5df6c52d3 100644
--- a/app/Http/Controllers/Api/LicensesController.php
+++ b/app/Http/Controllers/Api/LicensesController.php
@@ -150,7 +150,7 @@ class LicensesController extends Controller
public function show($id)
{
$this->authorize('view', License::class);
- $license = License::findOrFail($id);
+ $license = License::withCount('freeSeats')->findOrFail($id);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
return (new LicensesTransformer)->transformLicense($license);
}
diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php
index 2ec5ecc3a..452b5b73b 100644
--- a/app/Http/Controllers/Api/LocationsController.php
+++ b/app/Http/Controllers/Api/LocationsController.php
@@ -106,7 +106,26 @@ class LocationsController extends Controller
public function show($id)
{
$this->authorize('view', Location::class);
- $location = Location::findOrFail($id);
+ $location = Location::with('parent', 'manager', 'childLocations')
+ ->select([
+ 'locations.id',
+ 'locations.name',
+ 'locations.address',
+ 'locations.address2',
+ 'locations.city',
+ 'locations.state',
+ 'locations.zip',
+ 'locations.country',
+ 'locations.parent_id',
+ 'locations.manager_id',
+ 'locations.created_at',
+ 'locations.updated_at',
+ 'locations.image',
+ 'locations.currency'
+ ])
+ ->withCount('assignedAssets')
+ ->withCount('assets')
+ ->withCount('users')->findOrFail($id);
return (new LocationsTransformer)->transformLocation($location);
}
diff --git a/app/Http/Controllers/Api/ManufacturersController.php b/app/Http/Controllers/Api/ManufacturersController.php
index 6c1339a78..a943cc21d 100644
--- a/app/Http/Controllers/Api/ManufacturersController.php
+++ b/app/Http/Controllers/Api/ManufacturersController.php
@@ -83,7 +83,7 @@ class ManufacturersController extends Controller
public function show($id)
{
$this->authorize('view', Manufacturer::class);
- $manufacturer = Manufacturer::findOrFail($id);
+ $manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id);
return (new ManufacturersTransformer)->transformManufacturer($manufacturer);
}
@@ -120,11 +120,21 @@ class ManufacturersController extends Controller
*/
public function destroy($id)
{
+
$this->authorize('delete', Manufacturer::class);
- $manufacturer = Manufacturer::findOrFail($id);
+ $manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id);
$this->authorize('delete', $manufacturer);
- $manufacturer->delete();
- return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
+
+ if (($manufacturer->assets_count == 0) && ($manufacturer->licenses_count==0) && ($manufacturer->consumables_count==0) && ($manufacturer->accessories_count==0) && ($manufacturer->models_count==0) && ($manufacturer->deleted_at=='')) {
+ $manufacturer->delete();
+ return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
+ }
+
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.delete.error')));
+
+
+
+
}
diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php
index ba7854147..4d5f9d016 100644
--- a/app/Http/Controllers/Api/StatuslabelsController.php
+++ b/app/Http/Controllers/Api/StatuslabelsController.php
@@ -238,9 +238,6 @@ class StatuslabelsController extends Controller
*/
public function checkIfDeployable($id) {
$statuslabel = Statuslabel::findOrFail($id);
-
- $this->authorize('view', $statuslabel);
-
if ($statuslabel->getStatuslabelType()=='deployable') {
return '1';
}
diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php
index dca2e9e4f..7fca6bf3a 100644
--- a/app/Http/Controllers/Api/UsersController.php
+++ b/app/Http/Controllers/Api/UsersController.php
@@ -203,6 +203,8 @@ class UsersController extends Controller
if ($user->save()) {
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
+ } else {
+ $user->groups()->sync(array());
}
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.create')));
}
diff --git a/app/Http/Controllers/Assets/AssetCheckinController.php b/app/Http/Controllers/Assets/AssetCheckinController.php
index 7eed360a6..e87a1df23 100644
--- a/app/Http/Controllers/Assets/AssetCheckinController.php
+++ b/app/Http/Controllers/Assets/AssetCheckinController.php
@@ -2,10 +2,12 @@
namespace App\Http\Controllers\Assets;
+use App\Events\CheckoutableCheckedIn;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetCheckinRequest;
use App\Models\Asset;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\View;
@@ -82,8 +84,8 @@ class AssetCheckinController extends Controller
// Was the asset updated?
if ($asset->save()) {
- $asset->logCheckin($target, e(request('note')));
-
+
+ event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note')));
if ($backto=='user') {
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
diff --git a/app/Http/Controllers/Components/ComponentCheckinController.php b/app/Http/Controllers/Components/ComponentCheckinController.php
index 89eab1f5f..dfba1dcf8 100644
--- a/app/Http/Controllers/Components/ComponentCheckinController.php
+++ b/app/Http/Controllers/Components/ComponentCheckinController.php
@@ -2,11 +2,14 @@
namespace App\Http\Controllers\Components;
+use App\Events\CheckoutableCheckedIn;
+use App\Events\ComponentCheckedIn;
use App\Http\Controllers\Controller;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Component;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
@@ -86,22 +89,16 @@ class ComponentCheckinController extends Controller
DB::table('components_assets')->where('id',
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
- $log = new Actionlog();
- $log->user_id = auth()->id();
- $log->action_type = 'checkin from';
- $log->target_type = Asset::class;
- $log->target_id = $component_assets->asset_id;
- $log->item_id = $component_assets->component_id;
- $log->item_type = Component::class;
- $log->note = $request->input('note');
- $log->save();
-
// If the checked-in qty is exactly the same as the assigned_qty,
// we can simply delete the associated components_assets record
if ($qty_remaining_in_checkout == 0) {
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
}
+ $asset = Asset::find($component_assets->asset_id);
+
+ event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note')));
+
return redirect()->route('components.index')->with('success',
trans('admin/components/message.checkout.success'));
}
diff --git a/app/Http/Controllers/Components/ComponentCheckoutController.php b/app/Http/Controllers/Components/ComponentCheckoutController.php
index 8922317fa..bfa9e8967 100644
--- a/app/Http/Controllers/Components/ComponentCheckoutController.php
+++ b/app/Http/Controllers/Components/ComponentCheckoutController.php
@@ -2,6 +2,8 @@
namespace App\Http\Controllers\Components;
+use App\Events\CheckoutableCheckedOut;
+use App\Events\ComponentCheckedOut;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use App\Models\Component;
@@ -86,7 +88,8 @@ class ComponentCheckoutController extends Controller
'asset_id' => $asset_id
]);
- $component->logCheckout(e(Input::get('note')), $asset);
+ event(new CheckoutableCheckedOut($component, $asset, Auth::user(), $request->input('note')));
+
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
}
}
diff --git a/app/Http/Controllers/Consumables/ConsumableCheckoutController.php b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
index 6de35ff9e..e3e3e11b0 100644
--- a/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
+++ b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
@@ -2,10 +2,11 @@
namespace App\Http\Controllers\Consumables;
+use App\Events\CheckoutableCheckedOut;
+use App\Http\Controllers\Controller;
use App\Models\Consumable;
use App\Models\User;
use Illuminate\Http\Request;
-use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
@@ -41,7 +42,7 @@ class ConsumableCheckoutController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store($consumableId)
+ public function store(Request $request, $consumableId)
{
if (is_null($consumable = Consumable::find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
@@ -67,7 +68,7 @@ class ConsumableCheckoutController extends Controller
'assigned_to' => e(Input::get('assigned_to'))
]);
- $consumable->logCheckout(e(Input::get('note')), $user);
+ event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
// Redirect to the new consumable page
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php
index f942aa1e7..4bddbd575 100644
--- a/app/Http/Controllers/Licenses/LicenseCheckinController.php
+++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php
@@ -2,12 +2,14 @@
namespace App\Http\Controllers\Licenses;
+use App\Events\CheckoutableCheckedIn;
use App\Models\Asset;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
@@ -49,7 +51,7 @@ class LicenseCheckinController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store($seatId = null, $backTo = null)
+ public function store(Request $request, $seatId = null, $backTo = null)
{
// Check if the asset exists
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
@@ -88,7 +90,9 @@ class LicenseCheckinController extends Controller
// Was the asset updated?
if ($licenseSeat->save()) {
- $licenseSeat->logCheckin($return_to, e(request('note')));
+
+ event(new CheckoutableCheckedIn($license, $return_to, Auth::user(), $request->input('note')));
+
if ($backTo=='user') {
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
}
diff --git a/app/Http/Controllers/Licenses/LicenseCheckoutController.php b/app/Http/Controllers/Licenses/LicenseCheckoutController.php
index 570cd6b41..5d878a150 100644
--- a/app/Http/Controllers/Licenses/LicenseCheckoutController.php
+++ b/app/Http/Controllers/Licenses/LicenseCheckoutController.php
@@ -2,15 +2,16 @@
namespace App\Http\Controllers\Licenses;
+use App\Events\CheckoutableCheckedOut;
use App\Http\Requests\LicenseCheckoutRequest;
use App\Models\Asset;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Http\Request;
-use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
+use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
class LicenseCheckoutController extends Controller
@@ -103,7 +104,9 @@ class LicenseCheckoutController extends Controller
$licenseSeat->assigned_to = $target->assigned_to;
}
if ($licenseSeat->save()) {
- $licenseSeat->logCheckout(request('note'), $target);
+
+ event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
+
return true;
}
return false;
@@ -118,7 +121,9 @@ class LicenseCheckoutController extends Controller
$licenseSeat->assigned_to = request('assigned_to');
if ($licenseSeat->save()) {
- $licenseSeat->logCheckout(request('note'), $target);
+
+ event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
+
return true;
}
return false;
diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php
index 05e0a0f13..79d41f7b9 100644
--- a/app/Http/Controllers/ReportsController.php
+++ b/app/Http/Controllers/ReportsController.php
@@ -7,6 +7,7 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\CustomField;
+use App\Models\CheckoutAcceptance;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\Setting;
@@ -805,7 +806,20 @@ class ReportsController extends Controller
public function getAssetAcceptanceReport()
{
$this->authorize('reports.view');
- $assetsForReport = Asset::notYetAccepted()->with('company')->get();
+
+ /**
+ * Get all assets with pending checkout acceptances
+ */
+
+ $acceptances = CheckoutAcceptance::pending()->get();
+
+ $assetsForReport = $acceptances
+ ->filter(function($acceptance) {
+ return $acceptance->checkoutable_type == 'App\Models\Asset';
+ })
+ ->map(function($acceptance) {
+ return $acceptance->checkoutable;
+ });
return view('reports/unaccepted_assets', compact('assetsForReport'));
}
diff --git a/app/Http/Controllers/ViewAssetsController.php b/app/Http/Controllers/ViewAssetsController.php
index 2308b804a..8022815ba 100755
--- a/app/Http/Controllers/ViewAssetsController.php
+++ b/app/Http/Controllers/ViewAssetsController.php
@@ -199,124 +199,6 @@ class ViewAssetsController extends Controller
// Get the acceptance screen
public function getAcceptAsset($logID = null)
{
-
- $findlog = Actionlog::where('id', $logID)->first();
-
- if (!$findlog) {
- return redirect()->to('account/view-assets')->with('error', 'No matching record.');
- }
-
- if ($findlog->accepted_id!='') {
- return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
- }
-
- $user = Auth::user();
-
-
- // TODO - Fix this for non-assets
- if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) {
- return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
- }
-
-
- $item = $findlog->item;
-
- // Check if the asset exists
- if (is_null($item)) {
- // Redirect to the asset management page
- return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
- }
- if (!Company::isCurrentUserHasAccess($item)) {
- return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
- }
- return view('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item', $item);
- }
-
- // Save the acceptance
- public function postAcceptAsset(Request $request, $logID = null)
- {
-
- // Check if the asset exists
- if (is_null($findlog = Actionlog::where('id', $logID)->first())) {
- // Redirect to the asset management page
- return redirect()->to('account/view-assets')->with('error', trans('admin/hardware/message.does_not_exist'));
- }
-
-
- if ($findlog->accepted_id!='') {
- // Redirect to the asset management page
- return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
- }
-
- if (!Input::has('asset_acceptance')) {
- return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
- }
-
- $user = Auth::user();
-
- if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) {
- return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
- }
-
- if ($request->filled('signature_output')) {
- $path = config('app.private_uploads').'/signatures';
- $sig_filename = "siglog-".$findlog->id.'-'.date('Y-m-d-his').".png";
- $data_uri = e($request->get('signature_output'));
- $encoded_image = explode(",", $data_uri);
- $decoded_image = base64_decode($encoded_image[1]);
- file_put_contents($path."/".$sig_filename, $decoded_image);
- }
-
-
- $logaction = new Actionlog();
-
- if (Input::get('asset_acceptance')=='accepted') {
- $logaction_msg = 'accepted';
- $accepted="accepted";
- $return_msg = trans('admin/users/message.accepted');
- } else {
- $logaction_msg = 'declined';
- $accepted="rejected";
- $return_msg = trans('admin/users/message.declined');
- }
- $logaction->item_id = $findlog->item_id;
- $logaction->item_type = $findlog->item_type;
-
- // Asset
- if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
- if (Input::get('asset_acceptance')!='accepted') {
- DB::table('assets')
- ->where('id', $findlog->item_id)
- ->update(array('assigned_to' => null));
- }
- }
-
- $logaction->target_id = $findlog->target_id;
- $logaction->target_type = User::class;
- $logaction->note = e(Input::get('note'));
- $logaction->updated_at = date("Y-m-d H:i:s");
-
-
- if (isset($sig_filename)) {
- $logaction->accept_signature = $sig_filename;
- }
- $log = $logaction->logaction($logaction_msg);
-
- $update_checkout = DB::table('action_logs')
- ->where('id', $findlog->id)
- ->update(array('accepted_id' => $logaction->id));
-
- if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
- $affected_asset = $logaction->item;
- $affected_asset->accepted = $accepted;
- $affected_asset->save();
- }
-
- if ($update_checkout) {
- return redirect()->to('account/view-assets')->with('success', $return_msg);
-
- }
- return redirect()->to('account/view-assets')->with('error', 'Something went wrong ');
-
+ return redirect()->route('account.accept');
}
}
diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php
new file mode 100644
index 000000000..e06c6e1e4
--- /dev/null
+++ b/app/Listeners/CheckoutableListener.php
@@ -0,0 +1,184 @@
+checkedOutTo instanceof User) {
+ return;
+ }
+
+ /**
+ * Make a checkout acceptance and attach it in the notification
+ */
+ $acceptance = $this->getCheckoutAcceptance($event);
+
+ Notification::send(
+ $this->getNotifiables($event),
+ $this->getCheckoutNotification($event, $acceptance)
+ );
+ }
+
+ /**
+ * Notify the user about the checked in checkoutable
+ */
+ public function onCheckedIn($event) {
+ /**
+ * When the item wasn't checked out to a user, we can't send notifications
+ */
+ if(!$event->checkedOutTo instanceof User) {
+ return;
+ }
+
+ /**
+ * Send the appropriate notification
+ */
+ Notification::send(
+ $this->getNotifiables($event),
+ $this->getCheckinNotification($event)
+ );
+ }
+
+ /**
+ * Generates a checkout acceptance
+ * @param Event $event
+ * @return mixed
+ */
+ private function getCheckoutAcceptance($event) {
+ if (!$event->checkoutable->requireAcceptance()) {
+ return null;
+ }
+
+ $acceptance = new CheckoutAcceptance;
+ $acceptance->checkoutable()->associate($event->checkoutable);
+ $acceptance->assignedTo()->associate($event->checkedOutTo);
+ $acceptance->save();
+
+ return $acceptance;
+ }
+
+ /**
+ * Gets the entities to be notified of the passed event
+ *
+ * @param Event $event
+ * @return Collection
+ */
+ private function getNotifiables($event) {
+ $notifiables = collect();
+
+ /**
+ * Notify the user who checked out the item
+ */
+ $notifiables->push($event->checkedOutTo);
+
+ /**
+ * Notify Admin users if the settings is activated
+ */
+ if (Setting::getSettings()->admin_cc_email != '') {
+ $notifiables->push(new AdminRecipient());
+ }
+
+ return $notifiables;
+ }
+
+ /**
+ * Get the appropriate notification for the event
+ *
+ * @param CheckoutableCheckedIn $event
+ * @return Notification
+ */
+ private function getCheckinNotification($event) {
+
+ $model = get_class($event->checkoutable);
+
+ $notificationClass = null;
+
+ switch (get_class($event->checkoutable)) {
+ case Accessory::class:
+ $notificationClass = CheckinAccessoryNotification::class;
+ break;
+ case Asset::class:
+ $notificationClass = CheckinAssetNotification::class;
+ break;
+ case LicenseSeat::class:
+ $notificationClass = CheckinLicenseSeatNotification::class;
+ break;
+ }
+
+ return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
+ }
+
+ /**
+ * Get the appropriate notification for the event
+ *
+ * @param CheckoutableCheckedIn $event
+ * @param CheckoutAcceptance $acceptance
+ * @return Notification
+ */
+ private function getCheckoutNotification($event, $acceptance) {
+ $notificationClass = null;
+
+ switch (get_class($event->checkoutable)) {
+ case Accessory::class:
+ $notificationClass = CheckoutAccessoryNotification::class;
+ break;
+ case Asset::class:
+ $notificationClass = CheckoutAssetNotification::class;
+ break;
+ case Consumable::class:
+ $notificationClass = CheckoutConsumableNotification::class;
+ break;
+ case LicenseSeat::class:
+ $notificationClass = CheckoutLicenseSeatNotification::class;
+ break;
+ }
+
+ return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
+ }
+
+ /**
+ * Register the listeners for the subscriber.
+ *
+ * @param Illuminate\Events\Dispatcher $events
+ */
+ public function subscribe($events)
+ {
+ $events->listen(
+ 'App\Events\CheckoutableCheckedIn',
+ 'App\Listeners\CheckoutableListener@onCheckedIn'
+ );
+
+ $events->listen(
+ 'App\Events\CheckoutableCheckedOut',
+ 'App\Listeners\CheckoutableListener@onCheckedOut'
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/app/Listeners/LogListener.php b/app/Listeners/LogListener.php
new file mode 100644
index 000000000..cdb4fda1f
--- /dev/null
+++ b/app/Listeners/LogListener.php
@@ -0,0 +1,90 @@
+checkoutable->logCheckin($event->checkedOutTo, $event->note);
+ }
+
+ public function onCheckoutableCheckedOut(CheckoutableCheckedOut $event) {
+ $event->checkoutable->logCheckout($event->note, $event->checkedOutTo);
+ }
+
+ public function onCheckoutAccepted(CheckoutAccepted $event) {
+ $logaction = new Actionlog();
+
+ $logaction->item()->associate($event->acceptance->checkoutable);
+ $logaction->target()->associate($event->acceptance->assignedTo);
+ $logaction->accept_signature = $event->acceptance->signature_filename;
+ $logaction->action_type = 'accepted';
+
+ // TODO: log the actual license seat that was checked out
+ if($event->acceptance->checkoutable instanceof LicenseSeat) {
+ $logaction->item()->associate($event->acceptance->checkoutable->license);
+ }
+
+ $logaction->save();
+ }
+
+ public function onCheckoutDeclined(CheckoutDeclined $event) {
+ $logaction = new Actionlog();
+ $logaction->item()->associate($event->acceptance->checkoutable);
+ $logaction->target()->associate($event->acceptance->assignedTo);
+ $logaction->accept_signature = $event->acceptance->signature_filename;
+ $logaction->action_type = 'declined';
+
+ // TODO: log the actual license seat that was checked out
+ if($event->acceptance->checkoutable instanceof LicenseSeat) {
+ $logaction->item()->associate($event->acceptance->checkoutable->license);
+ }
+
+ $logaction->save();
+ }
+
+ /**
+ * Register the listeners for the subscriber.
+ *
+ * @param Illuminate\Events\Dispatcher $events
+ */
+ public function subscribe($events)
+ {
+ $list = [
+ 'CheckoutableCheckedIn',
+ 'CheckoutableCheckedOut',
+ 'CheckoutAccepted',
+ 'CheckoutDeclined',
+ ];
+
+ foreach($list as $event) {
+ $events->listen(
+ 'App\Events\\' . $event,
+ 'App\Listeners\LogListener@on' . $event
+ );
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/Models/Accessory.php b/app/Models/Accessory.php
index 8fa27515e..76b50704c 100755
--- a/app/Models/Accessory.php
+++ b/app/Models/Accessory.php
@@ -1,6 +1,7 @@
['name'],
'location' => ['name']
];
-
- /**
- * Set static properties to determine which checkout/checkin handlers we should use
- */
- public static $checkoutClass = CheckoutAccessoryNotification::class;
- public static $checkinClass = CheckinAccessoryNotification::class;
-
/**
* Accessory validation rules
diff --git a/app/Models/Asset.php b/app/Models/Asset.php
index 4d8ca1c89..c2d48cee2 100644
--- a/app/Models/Asset.php
+++ b/app/Models/Asset.php
@@ -1,10 +1,14 @@
assigned_to = null;
+ $this->assigned_type = null;
+ $this->accepted = null;
+ $this->save();
+ }
/**
@@ -252,21 +263,11 @@ class Asset extends Depreciable
$this->location_id = $target->id;
}
}
-
- /**
- * Does the user have to confirm that they accept the asset?
- *
- * If so, set the acceptance-status to "pending".
- * This value is used in the unaccepted assets reports, for example
- *
- * @see https://github.com/snipe/snipe-it/issues/5772
- */
- if ($this->requireAcceptance() && $target instanceof User) {
- $this->accepted = self::ACCEPTANCE_PENDING;
- }
if ($this->save()) {
- $this->logCheckout($note, $target);
+
+ event(new CheckoutableCheckedOut($this, $target, Auth::user(), $note));
+
$this->increment('checkout_counter', 1);
return true;
}
diff --git a/app/Models/CheckoutAcceptance.php b/app/Models/CheckoutAcceptance.php
new file mode 100644
index 000000000..6ff850f41
--- /dev/null
+++ b/app/Models/CheckoutAcceptance.php
@@ -0,0 +1,114 @@
+morphTo();
+ }
+
+ /**
+ * The user that the checkoutable was checked out to
+ *
+ * @return Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function assignedTo() {
+ return $this->belongsTo(User::class);
+ }
+
+ /**
+ * Is this checkout acceptance pending?
+ *
+ * @return boolean
+ */
+ public function isPending() {
+ return $this->accepted_at == null && $this->declined_at == null;
+ }
+
+ /**
+ * Was the checkoutable checked out to this user?
+ *
+ * @param User $user
+ * @return boolean
+ */
+ public function isCheckedOutTo(User $user) {
+ return $this->assignedTo->is($user);
+ }
+
+ /**
+ * Accept the checkout acceptance
+ *
+ * @param string $signature_filename
+ */
+ public function accept($signature_filename) {
+ $this->accepted_at = now();
+ $this->signature_filename = $signature_filename;
+ $this->save();
+
+ /**
+ * Update state for the checked out item
+ */
+ $this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename);
+ }
+
+ /**
+ * Decline the checkout acceptance
+ *
+ * @param string $signature_filename
+ */
+ public function decline($signature_filename) {
+ $this->declined_at = now();
+ $this->signature_filename = $signature_filename;
+ $this->save();
+
+ /**
+ * Update state for the checked out item
+ */
+ $this->checkoutable->declinedCheckout($this->assignedTo, $signature_filename);
+ }
+
+ /**
+ * Filter checkout acceptences by the user
+ * @param Illuminate\Database\Eloquent\Builder $query
+ * @param User $user
+ * @return Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeForUser(Builder $query, User $user) {
+ return $query->where('assigned_to_id', $user->id);
+ }
+
+ /**
+ * Filter to only get pending acceptances
+ * @param Illuminate\Database\Eloquent\Builder $query
+ * @return Illuminate\Database\Eloquent\Builder
+ */
+ public function scopePending(Builder $query) {
+ return $query->whereNull('accepted_at')->whereNull('declined_at');
+ }
+}
diff --git a/app/Models/Component.php b/app/Models/Component.php
index 8ccc3c307..e880234ba 100644
--- a/app/Models/Component.php
+++ b/app/Models/Component.php
@@ -20,13 +20,6 @@ class Component extends SnipeModel
protected $dates = ['deleted_at', 'purchase_date'];
protected $table = 'components';
-
- /**
- * Set static properties to determine which checkout/checkin handlers we should use
- */
- public static $checkoutClass = null;
- public static $checkinClass = null;
-
/**
* Category validation rules
diff --git a/app/Models/Consumable.php b/app/Models/Consumable.php
index b1d3fe222..596106c26 100644
--- a/app/Models/Consumable.php
+++ b/app/Models/Consumable.php
@@ -1,6 +1,7 @@
'boolean'
];
- /**
- * Set static properties to determine which checkout/checkin handlers we should use
- */
- public static $checkoutClass = CheckoutConsumableNotification::class;
- public static $checkinClass = null;
-
/**
* Category validation rules
diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php
index 390c6500b..0d2565db1 100644
--- a/app/Models/CustomField.php
+++ b/app/Models/CustomField.php
@@ -12,9 +12,14 @@ use Illuminate\Validation\Rule;
class CustomField extends Model
{
- use ValidatingTrait, UniqueUndeletedTrait;
- public $guarded=["id"];
- public static $PredefinedFormats=[
+ use ValidatingTrait,
+ UniqueUndeletedTrait;
+
+ public $guarded = [
+ "id"
+ ];
+
+ public static $PredefinedFormats = [
"ANY" => "",
"CUSTOM REGEX" => "",
"ALPHA" => "alpha",
@@ -31,6 +36,14 @@ class CustomField extends Model
"BOOLEAN" => "boolean",
];
+ /**
+ * Validation rules.
+ * At least empty array must be provided if using ValidatingTrait.
+ *
+ * @var array
+ */
+ protected $rules = [];
+
/**
* The attributes that are mass assignable.
*
@@ -57,7 +70,6 @@ class CustomField extends Model
*/
public static $table_name = "assets";
-
/**
* Convert the custom field's name property to a db-safe string.
*
diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php
index e25248f2c..9b83051cb 100644
--- a/app/Models/CustomFieldset.php
+++ b/app/Models/CustomFieldset.php
@@ -7,10 +7,16 @@ use Watson\Validating\ValidatingTrait;
class CustomFieldset extends Model
{
+ use ValidatingTrait;
+
protected $guarded=["id"];
- public $rules=[
- "name" => "required|unique:custom_fieldsets"
+ /**
+ * Validation rules
+ * @var array
+ */
+ protected $rules = [
+ "name" => "required|unique:custom_fieldsets"
];
/**
@@ -21,7 +27,6 @@ class CustomFieldset extends Model
* @var boolean
*/
protected $injectUniqueIdentifier = true;
- use ValidatingTrait;
/**
diff --git a/app/Models/License.php b/app/Models/License.php
index a3ac4c598..c953bf9dd 100755
--- a/app/Models/License.php
+++ b/app/Models/License.php
@@ -18,12 +18,6 @@ class License extends Depreciable
{
protected $presenter = 'App\Presenters\LicensePresenter';
- /**
- * Set static properties to determine which checkout/checkin handlers we should use
- */
- public static $checkoutClass = CheckoutLicenseNotification::class;
- public static $checkinClass = CheckinLicenseNotification::class;
-
use SoftDeletes;
use CompanyableTrait;
diff --git a/app/Models/LicenseSeat.php b/app/Models/LicenseSeat.php
index 500391041..ab514c0a5 100755
--- a/app/Models/LicenseSeat.php
+++ b/app/Models/LicenseSeat.php
@@ -2,32 +2,37 @@
namespace App\Models;
use App\Models\Loggable;
+use App\Models\Traits\Acceptable;
+use App\Notifications\CheckinLicenseNotification;
+use App\Notifications\CheckoutLicenseNotification;
+use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
-use App\Notifications\CheckoutLicenseNotification;
-use App\Notifications\CheckinLicenseNotification;
-class LicenseSeat extends Model implements ICompanyableChild
+class LicenseSeat extends SnipeModel implements ICompanyableChild
{
use CompanyableChildTrait;
use SoftDeletes;
use Loggable;
+ protected $presenter = 'App\Presenters\LicenseSeatPresenter';
+ use Presentable;
+
protected $dates = ['deleted_at'];
protected $guarded = 'id';
protected $table = 'license_seats';
- /**
- * Set static properties to determine which checkout/checkin handlers we should use
- */
- public static $checkoutClass = CheckoutLicenseNotification::class;
- public static $checkinClass = CheckinLicenseNotification::class;
+ use Acceptable;
public function getCompanyableParents()
{
return ['asset', 'license'];
}
+ public function getEula() {
+ return $this->license->getEula();
+ }
+
/**
* Establishes the seat -> license relationship
*
diff --git a/app/Models/Location.php b/app/Models/Location.php
index a6e2007cd..3dec481dd 100755
--- a/app/Models/Location.php
+++ b/app/Models/Location.php
@@ -20,13 +20,13 @@ class Location extends SnipeModel
protected $dates = ['deleted_at'];
protected $table = 'locations';
protected $rules = array(
- 'name' => 'required|min:2|max:255|unique_undeleted',
- 'city' => 'min:2|max:255|nullable',
- 'country' => 'min:2|max:2|nullable',
+ 'name' => 'required|min:2|max:255|unique_undeleted',
+ 'city' => 'min:2|max:255|nullable',
+ 'country' => 'min:2|max:2|nullable',
'address' => 'max:80|nullable',
'address2' => 'max:80|nullable',
- 'zip' => 'min:3|max:10|nullable',
- // 'manager_id' => 'exists:users'
+ 'zip' => 'min:3|max:10|nullable',
+ 'manager_id' => 'exists:users,id|nullable'
);
/**
@@ -56,6 +56,7 @@ class Location extends SnipeModel
'country',
'zip',
'ldap_ou',
+ 'manager_id',
'currency',
'image',
];
diff --git a/app/Models/Loggable.php b/app/Models/Loggable.php
index 61b1d6deb..f3914d9db 100644
--- a/app/Models/Loggable.php
+++ b/app/Models/Loggable.php
@@ -6,14 +6,7 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutRequest;
use App\Models\User;
-use App\Notifications\CheckinAssetNotification;
use App\Notifications\AuditNotification;
-use App\Notifications\CheckoutAssetNotification;
-use App\Notifications\CheckoutAccessoryNotification;
-use App\Notifications\CheckinAccessoryNotification;
-use App\Notifications\CheckoutConsumableNotification;
-use App\Notifications\CheckoutLicenseNotification;
-use App\Notifications\CheckinLicenseNotification;
use Illuminate\Support\Facades\Auth;
@@ -38,7 +31,6 @@ trait Loggable
*/
public function logCheckout($note, $target /* What are we checking out to? */)
{
- $settings = Setting::getSettings();
$log = new Actionlog;
$log = $this->determineLogItemType($log);
$log->user_id = Auth::user()->id;
@@ -63,29 +55,6 @@ trait Loggable
$log->note = $note;
$log->logaction('checkout');
- $params = [
- 'item' => $log->item,
- 'target_type' => $log->target_type,
- 'target' => $target,
- 'admin' => $log->user,
- 'note' => $note,
- 'log_id' => $log->id,
- 'settings' => $settings,
- ];
-
- $checkoutClass = null;
-
- if (method_exists($target, 'notify')) {
- $target->notify(new static::$checkoutClass($params));
- }
-
- // Send to the admin, if settings dictate
- $recipient = new \App\Models\Recipients\AdminRecipient();
-
- if (($settings->admin_cc_email!='') && (static::$checkoutClass!='')) {
- $recipient->notify(new static::$checkoutClass($params));
- }
-
return $log;
}
@@ -112,7 +81,6 @@ trait Loggable
*/
public function logCheckin($target, $note)
{
- $settings = Setting::getSettings();
$log = new Actionlog;
$log->target_type = get_class($target);
$log->target_id = $target->id;
@@ -140,29 +108,6 @@ trait Loggable
$log->user_id = Auth::user()->id;
$log->logaction('checkin from');
- $params = [
- 'target' => $target,
- 'item' => $log->item,
- 'admin' => $log->user,
- 'note' => $note,
- 'target_type' => $log->target_type,
- 'settings' => $settings,
- ];
-
-
- $checkinClass = null;
-
- if (method_exists($target, 'notify')) {
- $target->notify(new static::$checkinClass($params));
- }
-
- // Send to the admin, if settings dictate
- $recipient = new \App\Models\Recipients\AdminRecipient();
-
- if (($settings->admin_cc_email!='') && (static::$checkinClass!='')) {
- $recipient->notify(new static::$checkinClass($params));
- }
-
return $log;
}
diff --git a/app/Models/Recipients/AlertRecipient.php b/app/Models/Recipients/AlertRecipient.php
index af9e3a012..07557649c 100644
--- a/app/Models/Recipients/AlertRecipient.php
+++ b/app/Models/Recipients/AlertRecipient.php
@@ -1,14 +1,11 @@
email = $settings->alert_email;
+ $this->email = trim($email);
}
-
}
diff --git a/app/Models/Recipients/Recipient.php b/app/Models/Recipients/Recipient.php
index 888dd8e61..d04fd1f11 100644
--- a/app/Models/Recipients/Recipient.php
+++ b/app/Models/Recipients/Recipient.php
@@ -1,12 +1,12 @@
+ */
+trait Acceptable {
+ /**
+ * Run after the checkout acceptance was accepted by the user
+ *
+ * @param User $acceptedBy
+ * @param string $signature
+ */
+ public function acceptedCheckout(User $acceptedBy, $signature) {}
+
+ /**
+ * Run after the checkout acceptance was declined by the user
+ *
+ * @param User $acceptedBy
+ * @param string $signature
+ */
+ public function declinedCheckout(User $declinedBy, $signature) {}
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index 71fa797dc..1dc59b1ba 100755
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -126,12 +126,13 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
$user_permissions = json_decode($this->permissions, true);
+ $is_user_section_permissions_set = ($user_permissions != '') && array_key_exists($section, $user_permissions);
//If the user is explicitly granted, return true
- if (($user_permissions!='') && ((array_key_exists($section, $user_permissions)) && ($user_permissions[$section]=='1'))) {
+ if ($is_user_section_permissions_set && ($user_permissions[$section]=='1')) {
return true;
}
// If the user is explicitly denied, return false
- if (($user_permissions=='') || array_key_exists($section, $user_permissions) && ($user_permissions[$section]=='-1')) {
+ if ($is_user_section_permissions_set && ($user_permissions[$section]=='-1')) {
return false;
}
diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php
index 052279892..ee3bcac6a 100644
--- a/app/Notifications/CheckinAccessoryNotification.php
+++ b/app/Notifications/CheckinAccessoryNotification.php
@@ -2,6 +2,7 @@
namespace App\Notifications;
+use App\Models\Accessory;
use App\Models\Setting;
use App\Models\SnipeModel;
use App\Models\User;
@@ -15,31 +16,19 @@ use Illuminate\Support\Facades\Mail;
class CheckinAccessoryNotification extends Notification
{
use Queueable;
- /**
- * @var
- */
- private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(Accessory $accessory, $checkedOutTo, User $checkedInby, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->note = '';
- $this->target_type = $params['target'];
- $this->settings = $params['settings'];
-
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
-
-
-
+ $this->item = $accessory;
+ $this->target = $checkedOutTo;
+ $this->admin = $checkedInby;
+ $this->note = $note;
+ $this->settings = Setting::getSettings();
}
/**
diff --git a/app/Notifications/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php
index 78f3f0066..4053f22ff 100644
--- a/app/Notifications/CheckinAssetNotification.php
+++ b/app/Notifications/CheckinAssetNotification.php
@@ -2,13 +2,14 @@
namespace App\Notifications;
+use App\Models\Asset;
use App\Models\Setting;
-use Illuminate\Bus\Queueable;
use App\Models\User;
-use Illuminate\Notifications\Notification;
+use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
+use Illuminate\Notifications\Notification;
class CheckinAssetNotification extends Notification
{
@@ -20,19 +21,15 @@ class CheckinAssetNotification extends Notification
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(Asset $asset, $checkedOutTo, User $checkedInBy, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->note = '';
- $this->expected_checkin = '';
- $this->target_type = $params['target_type'];
- $this->settings = $params['settings'];
+ $this->target = $checkedOutTo;
+ $this->item = $asset;
+ $this->admin = $checkedInBy;
+ $this->note = $note;
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
+ $this->settings = Setting::getSettings();
+ $this->expected_checkin = '';
if ($this->item->expected_checkin) {
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
diff --git a/app/Notifications/CheckinLicenseNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php
similarity index 86%
rename from app/Notifications/CheckinLicenseNotification.php
rename to app/Notifications/CheckinLicenseSeatNotification.php
index f8a52ccf3..69554d493 100644
--- a/app/Notifications/CheckinLicenseNotification.php
+++ b/app/Notifications/CheckinLicenseSeatNotification.php
@@ -2,6 +2,8 @@
namespace App\Notifications;
+use App\Models\License;
+use App\Models\LicenseSeat;
use App\Models\Setting;
use App\Models\SnipeModel;
use App\Models\User;
@@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
-class CheckinLicenseNotification extends Notification
+class CheckinLicenseSeatNotification extends Notification
{
use Queueable;
/**
@@ -25,19 +27,13 @@ class CheckinLicenseNotification extends Notification
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedInBy, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->note = '';
- $this->settings = $params['settings'];
- $this->target_type = $params['target_type'];
-
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
-
+ $this->target = $checkedOutTo;
+ $this->item = $licenseSeat->license;
+ $this->admin = $checkedInBy;
+ $this->note = $note;
+ $this->settings = Setting::getSettings();
}
/**
diff --git a/app/Notifications/CheckoutAccessoryNotification.php b/app/Notifications/CheckoutAccessoryNotification.php
index 4e8950619..11368bf06 100644
--- a/app/Notifications/CheckoutAccessoryNotification.php
+++ b/app/Notifications/CheckoutAccessoryNotification.php
@@ -2,6 +2,7 @@
namespace App\Notifications;
+use App\Models\Accessory;
use App\Models\Setting;
use App\Models\SnipeModel;
use App\Models\User;
@@ -15,33 +16,20 @@ use Illuminate\Support\Facades\Mail;
class CheckoutAccessoryNotification extends Notification
{
use Queueable;
- /**
- * @var
- */
- private $params;
/**
* Create a new notification instance.
- *
- * @param $params
*/
- public function __construct($params)
+ public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->log_id = $params['log_id'];
- $this->note = '';
- $this->last_checkout = '';
- $this->expected_checkin = '';
- $this->target_type = $params['target_type'];
- $this->settings = $params['settings'];
-
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
-
+ $this->item = $accessory;
+ $this->admin = $checkedOutBy;
+ $this->note = $note;
+ $this->target = $checkedOutTo;
+ $this->acceptance = $acceptance;
+
+ $this->settings = Setting::getSettings();
}
@@ -132,6 +120,8 @@ class CheckoutAccessoryNotification extends Notification
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
+ $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
+
return (new MailMessage)->markdown('notifications.markdown.checkout-accessory',
[
'item' => $this->item,
@@ -140,7 +130,7 @@ class CheckoutAccessoryNotification extends Notification
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
- 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
+ 'accept_url' => $accept_url,
])
->subject(trans('mail.Confirm_accessory_delivery'));
diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php
index 8451d6dcd..db4ba294f 100644
--- a/app/Notifications/CheckoutAssetNotification.php
+++ b/app/Notifications/CheckoutAssetNotification.php
@@ -2,6 +2,7 @@
namespace App\Notifications;
+use App\Models\Asset;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Bus\Queueable;
@@ -13,31 +14,25 @@ use Illuminate\Contracts\Queue\ShouldQueue;
class CheckoutAssetNotification extends Notification
{
use Queueable;
- /**
- * @var
- */
- private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->log_id = $params['log_id'];
- $this->note = '';
+
+ $this->item = $asset;
+ $this->admin = $checkedOutBy;
+ $this->note = $note;
+ $this->target = $checkedOutTo;
+ $this->acceptance = $acceptance;
+
+ $this->settings = Setting::getSettings();
+
$this->last_checkout = '';
$this->expected_checkin = '';
- $this->target_type = $params['target_type'];
- $this->settings = $params['settings'];
-
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
if ($this->item->last_checkout) {
$this->last_checkout = \App\Helpers\Helper::getFormattedDateObject($this->item->last_checkout, 'date',
@@ -146,17 +141,18 @@ class CheckoutAssetNotification extends Notification
$fields = $this->item->model->fieldset->fields;
}
+ $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
+
$message = (new MailMessage)->markdown('notifications.markdown.checkout-asset',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
- 'log_id' => $this->note,
'target' => $this->target,
'fields' => $fields,
'eula' => $eula,
'req_accept' => $req_accept,
- 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
+ 'accept_url' => $accept_url,
'last_checkout' => $this->last_checkout,
'expected_checkin' => $this->expected_checkin,
])
diff --git a/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php
index d9a80bfc3..40780c7ab 100644
--- a/app/Notifications/CheckoutConsumableNotification.php
+++ b/app/Notifications/CheckoutConsumableNotification.php
@@ -2,6 +2,7 @@
namespace App\Notifications;
+use App\Models\Consumable;
use App\Models\Setting;
use App\Models\SnipeModel;
use App\Models\User;
@@ -25,21 +26,16 @@ class CheckoutConsumableNotification extends Notification
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(Consumable $consumable, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->log_id = $params['log_id'];
- $this->note = '';
- $this->last_checkout = '';
- $this->expected_checkin = '';
- $this->target_type = $params['target_type'];
- $this->settings = $params['settings'];
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
+ $this->item = $consumable;
+ $this->admin = $checkedOutBy;
+ $this->note = $note;
+ $this->target = $checkedOutTo;
+ $this->acceptance = $acceptance;
+
+ $this->settings = Setting::getSettings();
}
@@ -126,16 +122,17 @@ class CheckoutConsumableNotification extends Notification
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
+ $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
+
return (new MailMessage)->markdown('notifications.markdown.checkout-consumable',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
- 'log_id' => $this->note,
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
- 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
+ 'accept_url' => $accept_url,
])
->subject(trans('mail.Confirm_consumable_delivery'));
diff --git a/app/Notifications/CheckoutLicenseNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php
similarity index 85%
rename from app/Notifications/CheckoutLicenseNotification.php
rename to app/Notifications/CheckoutLicenseSeatNotification.php
index 93530e2cd..74df6e2f4 100644
--- a/app/Notifications/CheckoutLicenseNotification.php
+++ b/app/Notifications/CheckoutLicenseSeatNotification.php
@@ -2,6 +2,8 @@
namespace App\Notifications;
+use App\Models\License;
+use App\Models\LicenseSeat;
use App\Models\Setting;
use App\Models\SnipeModel;
use App\Models\User;
@@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
-class CheckoutLicenseNotification extends Notification
+class CheckoutLicenseSeatNotification extends Notification
{
use Queueable;
/**
@@ -25,23 +27,15 @@ class CheckoutLicenseNotification extends Notification
*
* @param $params
*/
- public function __construct($params)
+ public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
{
- $this->target = $params['target'];
- $this->item = $params['item'];
- $this->admin = $params['admin'];
- $this->log_id = $params['log_id'];
- $this->note = '';
- $this->target_type = $params['target_type'];
- $this->settings = $params['settings'];
- $this->target_type = $params['target_type'];
-
- if (array_key_exists('note', $params)) {
- $this->note = $params['note'];
- }
-
-
+ $this->item = $licenseSeat->license;
+ $this->admin = $checkedOutBy;
+ $this->note = $note;
+ $this->target = $checkedOutTo;
+ $this->acceptance = $acceptance;
+ $this->settings = Setting::getSettings();
}
/**
@@ -125,6 +119,8 @@ class CheckoutLicenseNotification extends Notification
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
$req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
+ $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
+
return (new MailMessage)->markdown('notifications.markdown.checkout-license',
[
'item' => $this->item,
@@ -133,7 +129,7 @@ class CheckoutLicenseNotification extends Notification
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
- 'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
+ 'accept_url' => $accept_url,
])
->subject(trans('mail.Confirm_license_delivery'));
diff --git a/app/Notifications/InventoryAlert.php b/app/Notifications/InventoryAlert.php
index 3dee49134..0d9a26fc2 100644
--- a/app/Notifications/InventoryAlert.php
+++ b/app/Notifications/InventoryAlert.php
@@ -3,8 +3,8 @@
namespace App\Notifications;
use Illuminate\Bus\Queueable;
-use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
+use Illuminate\Notifications\Messages\MailMessage;
class InventoryAlert extends Notification
{
@@ -33,14 +33,13 @@ class InventoryAlert extends Notification
*/
public function via($notifiable)
{
- $notifyBy = [];
- $notifyBy[]='mail';
+ $notifyBy[] = 'mail';
+
return $notifyBy;
}
public function toSlack($notifiable)
{
-
}
/**
@@ -51,17 +50,16 @@ class InventoryAlert extends Notification
*/
public function toMail($params)
{
-
- $message = (new MailMessage)->markdown('notifications.markdown.report-low-inventory',
+ $message = (new MailMessage)->markdown(
+ 'notifications.markdown.report-low-inventory',
[
'items' => $this->items,
'threshold' => $this->threshold,
- ])
+ ]
+ )
->subject(trans('mail.Low_Inventory_Report'));
return $message;
-
-
}
/**
diff --git a/app/Presenters/LicenseSeatPresenter.php b/app/Presenters/LicenseSeatPresenter.php
new file mode 100644
index 000000000..5267aa729
--- /dev/null
+++ b/app/Presenters/LicenseSeatPresenter.php
@@ -0,0 +1,18 @@
+model->license->name;
+ }
+}
diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php
index 9d3e0f8a9..28c3aecf0 100644
--- a/app/Providers/EventServiceProvider.php
+++ b/app/Providers/EventServiceProvider.php
@@ -3,6 +3,8 @@
namespace App\Providers;
use Illuminate\Support\Facades\Event;
+use App\Listeners\CheckoutableListener;
+use App\Listeners\LogListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
@@ -23,6 +25,15 @@ class EventServiceProvider extends ServiceProvider
],
];
+ /**
+ * The subscriber classes to register.
+ *
+ * @var array
+ */
+ protected $subscribe = [
+ LogListener::class,
+ CheckoutableListener::class
+ ];
/**
* Register any events for your application.
diff --git a/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php b/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php
new file mode 100644
index 000000000..67bc3b800
--- /dev/null
+++ b/database/migrations/2018_07_28_023826_create_checkout_acceptances_table.php
@@ -0,0 +1,41 @@
+increments('id');
+
+ $table->morphs('checkoutable');
+ $table->integer('assigned_to_id')->unsigned();
+
+ $table->string('signature_filename')->nullable();
+
+ $table->timestamp('accepted_at')->nullable();
+ $table->timestamp('declined_at')->nullable();
+
+ $table->timestamps();
+ $table->softDeletes();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('checkout_acceptances');
+ }
+}
diff --git a/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php b/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php
new file mode 100644
index 000000000..ddf6949b6
--- /dev/null
+++ b/database/migrations/2018_09_10_082212_create_checkout_acceptances_for_unaccepted_assets.php
@@ -0,0 +1,43 @@
+where('assigned_type', 'App\Models\User')->where('accepted', 'pending')->get();
+
+ $acceptances = [];
+
+ foreach($assets as $asset) {
+ $acceptances[] = [
+ 'checkoutable_type' => 'App\Models\Asset',
+ 'checkoutable_id' => $asset->id,
+ 'assigned_to_id' => $asset->assigned_to,
+ ];
+ }
+
+ DB::table('checkout_acceptances')->insert($acceptances);
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ //
+ }
+}
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
index 0486302c9..2a1e48940 100644
--- a/docker/entrypoint.sh
+++ b/docker/entrypoint.sh
@@ -17,8 +17,24 @@ else
fi
# create data directories
-for dir in 'data/private_uploads' 'data/uploads' 'data/uploads/avatars' 'data/uploads/barcodes' 'data/uploads/categories' 'data/uploads/companies' 'data/uploads/departments' 'data/uploads/locations' 'data/uploads/manufacturers' 'data/uploads/models' 'data/uploads/suppliers' 'dumps' 'keys'; do
- mkdir -p "/var/lib/snipeit/$dir"
+for dir in \
+ 'data/private_uploads' \
+ 'data/uploads/accessories' \
+ 'data/uploads/avatars' \
+ 'data/uploads/barcodes' \
+ 'data/uploads/categories' \
+ 'data/uploads/companies' \
+ 'data/uploads/components' \
+ 'data/uploads/consumables' \
+ 'data/uploads/departments' \
+ 'data/uploads/locations' \
+ 'data/uploads/manufacturers' \
+ 'data/uploads/models' \
+ 'data/uploads/suppliers' \
+ 'dumps' \
+ 'keys'
+do
+ [ ! -d "/var/lib/snipeit/$dir" ] && mkdir -p "/var/lib/snipeit/$dir"
done
chown -R docker:root /var/lib/snipeit/data/*
@@ -26,9 +42,10 @@ chown -R docker:root /var/lib/snipeit/dumps
chown -R docker:root /var/lib/snipeit/keys
# If the Oauth DB files are not present copy the vendor files over to the db migrations
-if [ ! -f "/var/www/html/database/migrations/*create_oauth*" ]; then
+if [ ! -f "/var/www/html/database/migrations/*create_oauth*" ]
+then
cp -ax /var/www/html/vendor/laravel/passport/database/migrations/* /var/www/html/database/migrations/
fi
-. /etc/apache2/envvars
+. /etc/apache2/envvars
exec apache2 -DNO_DETACH < /dev/null
diff --git a/phpmd.xml b/phpmd.xml
new file mode 100644
index 000000000..d991b90fb
--- /dev/null
+++ b/phpmd.xml
@@ -0,0 +1,54 @@
+
+
Name | +Actions | +
---|---|
{{ $acceptance->checkoutable->present()->name }} | +Accept/Decline | +
Checking this box will edit the asset record to reflect this new location. Leaving it unchecked will simply note the location in the audit log.
+ + + + diff --git a/resources/views/hardware/quickscan.blade.php b/resources/views/hardware/quickscan.blade.php index b3df1139d..620b4aad0 100644 --- a/resources/views/hardware/quickscan.blade.php +++ b/resources/views/hardware/quickscan.blade.php @@ -51,7 +51,7 @@ diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index 8e1663f2b..09b3291a5 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -309,7 +309,11 @@ Requested Assets - +{{ Illuminate\Mail\Markdown::parse($slot) }} - {{ $subcopy or '' }} + {{ $subcopy ?? '' }} |