mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Merge pull request #5913 from tilldeeke/refactore-checkout-checkin-notification-sending
Refactor: Decouple checkin/checkout notifications from logging
This commit is contained in:
commit
c97db3259f
27
app/Events/CheckoutAccepted.php
Normal file
27
app/Events/CheckoutAccepted.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Actionlog;
|
||||||
|
use App\Models\CheckoutAcceptance;
|
||||||
|
use App\Models\Contracts\Acceptable;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Broadcasting\Channel;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CheckoutAccepted
|
||||||
|
{
|
||||||
|
use Dispatchable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(CheckoutAcceptance $acceptance)
|
||||||
|
{
|
||||||
|
$this->acceptance = $acceptance;
|
||||||
|
}
|
||||||
|
}
|
27
app/Events/CheckoutDeclined.php
Normal file
27
app/Events/CheckoutDeclined.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Actionlog;
|
||||||
|
use App\Models\CheckoutAcceptance;
|
||||||
|
use App\Models\Contracts\Acceptable;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Broadcasting\Channel;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CheckoutDeclined
|
||||||
|
{
|
||||||
|
use Dispatchable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(CheckoutAcceptance $acceptance)
|
||||||
|
{
|
||||||
|
$this->acceptance = $acceptance;
|
||||||
|
}
|
||||||
|
}
|
30
app/Events/CheckoutableCheckedIn.php
Normal file
30
app/Events/CheckoutableCheckedIn.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CheckoutableCheckedIn
|
||||||
|
{
|
||||||
|
use Dispatchable, SerializesModels;
|
||||||
|
|
||||||
|
public $checkoutable;
|
||||||
|
public $checkedOutTo;
|
||||||
|
public $checkedInBy;
|
||||||
|
public $note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($checkoutable, $checkedOutTo, User $checkedInBy, $note)
|
||||||
|
{
|
||||||
|
$this->checkoutable = $checkoutable;
|
||||||
|
$this->checkedOutTo = $checkedOutTo;
|
||||||
|
$this->checkedInBy = $checkedInBy;
|
||||||
|
$this->note = $note;
|
||||||
|
}
|
||||||
|
}
|
30
app/Events/CheckoutableCheckedOut.php
Normal file
30
app/Events/CheckoutableCheckedOut.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CheckoutableCheckedOut
|
||||||
|
{
|
||||||
|
use Dispatchable, SerializesModels;
|
||||||
|
|
||||||
|
public $checkoutable;
|
||||||
|
public $checkedOutTo;
|
||||||
|
public $checkedOutBy;
|
||||||
|
public $note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($checkoutable, $checkedOutTo, User $checkedOutBy, $note)
|
||||||
|
{
|
||||||
|
$this->checkoutable = $checkoutable;
|
||||||
|
$this->checkedOutTo = $checkedOutTo;
|
||||||
|
$this->checkedOutBy = $checkedOutBy;
|
||||||
|
$this->note = $note;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Accessories;
|
namespace App\Http\Controllers\Accessories;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedIn;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ class AccessoryCheckinController extends Controller
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
* @internal param int $accessoryId
|
* @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
|
// Check if the accessory exists
|
||||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||||
|
@ -61,7 +63,8 @@ class AccessoryCheckinController extends Controller
|
||||||
// Was the accessory updated?
|
// Was the accessory updated?
|
||||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||||
$return_to = e($accessory_user->assigned_to);
|
$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'));
|
return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Accessories;
|
namespace App\Http\Controllers\Accessories;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -77,10 +78,10 @@ class AccessoryCheckoutController extends Controller
|
||||||
'assigned_to' => $request->get('assigned_to')
|
'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();
|
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
|
// Redirect to the new accessory page
|
||||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
|
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
|
||||||
}
|
}
|
||||||
|
|
125
app/Http/Controllers/Account/AcceptanceController.php
Normal file
125
app/Http/Controllers/Account/AcceptanceController.php
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Http\Controllers\Account;
|
||||||
|
|
||||||
|
use App\Events\CheckoutAccepted;
|
||||||
|
use App\Events\CheckoutDeclined;
|
||||||
|
use App\Events\ItemAccepted;
|
||||||
|
use App\Events\ItemDeclined;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\CheckoutAcceptance;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Consumable;
|
||||||
|
use App\Models\Contracts\Acceptable;
|
||||||
|
use App\Models\License;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class AcceptanceController extends Controller {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a listing of pending checkout acceptances for the current user
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function index() {
|
||||||
|
$acceptances = CheckoutAcceptance::forUser(Auth::user())->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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Assets;
|
namespace App\Http\Controllers\Assets;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedIn;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\AssetCheckinRequest;
|
use App\Http\Requests\AssetCheckinRequest;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Redirect;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
|
|
||||||
|
@ -82,8 +84,8 @@ class AssetCheckinController extends Controller
|
||||||
|
|
||||||
// Was the asset updated?
|
// Was the asset updated?
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
$asset->logCheckin($target, e(request('note')));
|
|
||||||
|
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note')));
|
||||||
|
|
||||||
if ($backto=='user') {
|
if ($backto=='user') {
|
||||||
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Components;
|
namespace App\Http\Controllers\Components;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedIn;
|
||||||
|
use App\Events\ComponentCheckedIn;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Component;
|
use App\Models\Component;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
@ -86,22 +89,16 @@ class ComponentCheckinController extends Controller
|
||||||
DB::table('components_assets')->where('id',
|
DB::table('components_assets')->where('id',
|
||||||
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
$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,
|
// If the checked-in qty is exactly the same as the assigned_qty,
|
||||||
// we can simply delete the associated components_assets record
|
// we can simply delete the associated components_assets record
|
||||||
if ($qty_remaining_in_checkout == 0) {
|
if ($qty_remaining_in_checkout == 0) {
|
||||||
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
|
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',
|
return redirect()->route('components.index')->with('success',
|
||||||
trans('admin/components/message.checkout.success'));
|
trans('admin/components/message.checkout.success'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Components;
|
namespace App\Http\Controllers\Components;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
|
use App\Events\ComponentCheckedOut;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Component;
|
use App\Models\Component;
|
||||||
|
@ -86,7 +88,8 @@ class ComponentCheckoutController extends Controller
|
||||||
'asset_id' => $asset_id
|
'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'));
|
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Consumables;
|
namespace App\Http\Controllers\Consumables;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Consumable;
|
use App\Models\Consumable;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ class ConsumableCheckoutController extends Controller
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function store($consumableId)
|
public function store(Request $request, $consumableId)
|
||||||
{
|
{
|
||||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
|
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'))
|
'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
|
// Redirect to the new consumable page
|
||||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
|
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Licenses;
|
namespace App\Http\Controllers\Licenses;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedIn;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
@ -49,7 +51,7 @@ class LicenseCheckinController extends Controller
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @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
|
// Check if the asset exists
|
||||||
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
|
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
|
||||||
|
@ -88,7 +90,9 @@ class LicenseCheckinController extends Controller
|
||||||
|
|
||||||
// Was the asset updated?
|
// Was the asset updated?
|
||||||
if ($licenseSeat->save()) {
|
if ($licenseSeat->save()) {
|
||||||
$licenseSeat->logCheckin($return_to, e(request('note')));
|
|
||||||
|
event(new CheckoutableCheckedIn($license, $return_to, Auth::user(), $request->input('note')));
|
||||||
|
|
||||||
if ($backTo=='user') {
|
if ($backTo=='user') {
|
||||||
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Licenses;
|
namespace App\Http\Controllers\Licenses;
|
||||||
|
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
use App\Http\Requests\LicenseCheckoutRequest;
|
use App\Http\Requests\LicenseCheckoutRequest;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class LicenseCheckoutController extends Controller
|
class LicenseCheckoutController extends Controller
|
||||||
|
@ -103,7 +104,9 @@ class LicenseCheckoutController extends Controller
|
||||||
$licenseSeat->assigned_to = $target->assigned_to;
|
$licenseSeat->assigned_to = $target->assigned_to;
|
||||||
}
|
}
|
||||||
if ($licenseSeat->save()) {
|
if ($licenseSeat->save()) {
|
||||||
$licenseSeat->logCheckout(request('note'), $target);
|
|
||||||
|
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -118,7 +121,9 @@ class LicenseCheckoutController extends Controller
|
||||||
$licenseSeat->assigned_to = request('assigned_to');
|
$licenseSeat->assigned_to = request('assigned_to');
|
||||||
|
|
||||||
if ($licenseSeat->save()) {
|
if ($licenseSeat->save()) {
|
||||||
$licenseSeat->logCheckout(request('note'), $target);
|
|
||||||
|
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetMaintenance;
|
use App\Models\AssetMaintenance;
|
||||||
use App\Models\CustomField;
|
use App\Models\CustomField;
|
||||||
|
use App\Models\CheckoutAcceptance;
|
||||||
use App\Models\Depreciation;
|
use App\Models\Depreciation;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
|
@ -805,7 +806,20 @@ class ReportsController extends Controller
|
||||||
public function getAssetAcceptanceReport()
|
public function getAssetAcceptanceReport()
|
||||||
{
|
{
|
||||||
$this->authorize('reports.view');
|
$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'));
|
return view('reports/unaccepted_assets', compact('assetsForReport'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,124 +199,6 @@ class ViewAssetsController extends Controller
|
||||||
// Get the acceptance screen
|
// Get the acceptance screen
|
||||||
public function getAcceptAsset($logID = null)
|
public function getAcceptAsset($logID = null)
|
||||||
{
|
{
|
||||||
|
return redirect()->route('account.accept');
|
||||||
$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 ');
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
184
app/Listeners/CheckoutableListener.php
Normal file
184
app/Listeners/CheckoutableListener.php
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\CheckoutAcceptance;
|
||||||
|
use App\Models\Consumable;
|
||||||
|
use App\Models\LicenseSeat;
|
||||||
|
use App\Models\Recipients\AdminRecipient;
|
||||||
|
use App\Models\Setting;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Notifications\CheckinAccessoryNotification;
|
||||||
|
use App\Notifications\CheckinAssetNotification;
|
||||||
|
use App\Notifications\CheckinLicenseNotification;
|
||||||
|
use App\Notifications\CheckinLicenseSeatNotification;
|
||||||
|
use App\Notifications\CheckoutAccessoryNotification;
|
||||||
|
use App\Notifications\CheckoutAssetNotification;
|
||||||
|
use App\Notifications\CheckoutConsumableNotification;
|
||||||
|
use App\Notifications\CheckoutLicenseNotification;
|
||||||
|
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
class CheckoutableListener
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the user about the checked out checkoutable
|
||||||
|
*/
|
||||||
|
public function onCheckedOut($event) {
|
||||||
|
/**
|
||||||
|
* When the item wasn't checked out to a user, we can't send notifications
|
||||||
|
*/
|
||||||
|
if(! $event->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'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
app/Listeners/LogListener.php
Normal file
90
app/Listeners/LogListener.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\AccessoryCheckedIn;
|
||||||
|
use App\Events\AccessoryCheckedOut;
|
||||||
|
use App\Events\AssetCheckedIn;
|
||||||
|
use App\Events\AssetCheckedOut;
|
||||||
|
use App\Events\CheckoutAccepted;
|
||||||
|
use App\Events\CheckoutDeclined;
|
||||||
|
use App\Events\CheckoutableCheckedIn;
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
|
use App\Events\ComponentCheckedIn;
|
||||||
|
use App\Events\ComponentCheckedOut;
|
||||||
|
use App\Events\ConsumableCheckedOut;
|
||||||
|
use App\Events\ItemAccepted;
|
||||||
|
use App\Events\ItemDeclined;
|
||||||
|
use App\Events\LicenseCheckedIn;
|
||||||
|
use App\Events\LicenseCheckedOut;
|
||||||
|
use App\Models\Actionlog;
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\Component;
|
||||||
|
use App\Models\LicenseSeat;
|
||||||
|
|
||||||
|
|
||||||
|
class LogListener
|
||||||
|
{
|
||||||
|
|
||||||
|
public function onCheckoutableCheckedIn(CheckoutableCheckedIn $event) {
|
||||||
|
$event->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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Traits\Acceptable;
|
||||||
use App\Models\Traits\Searchable;
|
use App\Models\Traits\Searchable;
|
||||||
use App\Presenters\Presentable;
|
use App\Presenters\Presentable;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
@ -27,6 +28,8 @@ class Accessory extends SnipeModel
|
||||||
];
|
];
|
||||||
|
|
||||||
use Searchable;
|
use Searchable;
|
||||||
|
|
||||||
|
use Acceptable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be included when searching the model.
|
* The attributes that should be included when searching the model.
|
||||||
|
@ -47,13 +50,6 @@ class Accessory extends SnipeModel
|
||||||
'supplier' => ['name'],
|
'supplier' => ['name'],
|
||||||
'location' => ['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
|
* Accessory validation rules
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Events\AssetCheckedOut;
|
||||||
|
use App\Events\CheckoutableCheckedOut;
|
||||||
use App\Exceptions\CheckoutNotAllowed;
|
use App\Exceptions\CheckoutNotAllowed;
|
||||||
use App\Http\Traits\UniqueSerialTrait;
|
use App\Http\Traits\UniqueSerialTrait;
|
||||||
use App\Http\Traits\UniqueUndeletedTrait;
|
use App\Http\Traits\UniqueUndeletedTrait;
|
||||||
|
use App\Models\Traits\Acceptable;
|
||||||
use App\Models\Traits\Searchable;
|
use App\Models\Traits\Searchable;
|
||||||
|
use App\Models\User;
|
||||||
use App\Presenters\Presentable;
|
use App\Presenters\Presentable;
|
||||||
use AssetPresenter;
|
use AssetPresenter;
|
||||||
use Auth;
|
use Auth;
|
||||||
|
@ -17,7 +21,6 @@ use Watson\Validating\ValidatingTrait;
|
||||||
use DB;
|
use DB;
|
||||||
use App\Notifications\CheckinAssetNotification;
|
use App\Notifications\CheckinAssetNotification;
|
||||||
use App\Notifications\CheckoutAssetNotification;
|
use App\Notifications\CheckoutAssetNotification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for Assets.
|
* Model for Assets.
|
||||||
*
|
*
|
||||||
|
@ -32,12 +35,20 @@ class Asset extends Depreciable
|
||||||
const ASSET = 'asset';
|
const ASSET = 'asset';
|
||||||
const USER = 'user';
|
const USER = 'user';
|
||||||
|
|
||||||
const ACCEPTANCE_PENDING = 'pending';
|
use Acceptable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set static properties to determine which checkout/checkin handlers we should use
|
* Run after the checkout acceptance was declined by the user
|
||||||
*/
|
*
|
||||||
public static $checkoutClass = CheckoutAssetNotification::class;
|
* @param User $acceptedBy
|
||||||
public static $checkinClass = CheckinAssetNotification::class;
|
* @param string $signature
|
||||||
|
*/
|
||||||
|
public function declinedCheckout(User $declinedBy, $signature) {
|
||||||
|
$this->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;
|
$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()) {
|
if ($this->save()) {
|
||||||
$this->logCheckout($note, $target);
|
|
||||||
|
event(new CheckoutableCheckedOut($this, $target, Auth::user(), $note));
|
||||||
|
|
||||||
$this->increment('checkout_counter', 1);
|
$this->increment('checkout_counter', 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
114
app/Models/CheckoutAcceptance.php
Normal file
114
app/Models/CheckoutAcceptance.php
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class CheckoutAcceptance extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be mutated to dates.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $dates = [
|
||||||
|
'accepted_at',
|
||||||
|
'declined_at',
|
||||||
|
|
||||||
|
'deleted_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The resource that was is out
|
||||||
|
*
|
||||||
|
* @return Illuminate\Database\Eloquent\Relations\MorphTo
|
||||||
|
*/
|
||||||
|
public function checkoutable() {
|
||||||
|
return $this->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');
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,13 +20,6 @@ class Component extends SnipeModel
|
||||||
|
|
||||||
protected $dates = ['deleted_at', 'purchase_date'];
|
protected $dates = ['deleted_at', 'purchase_date'];
|
||||||
protected $table = 'components';
|
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
|
* Category validation rules
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Traits\Acceptable;
|
||||||
use App\Models\Traits\Searchable;
|
use App\Models\Traits\Searchable;
|
||||||
use App\Presenters\Presentable;
|
use App\Presenters\Presentable;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
@ -14,18 +15,14 @@ class Consumable extends SnipeModel
|
||||||
use Loggable, Presentable;
|
use Loggable, Presentable;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
|
use Acceptable;
|
||||||
|
|
||||||
protected $dates = ['deleted_at', 'purchase_date'];
|
protected $dates = ['deleted_at', 'purchase_date'];
|
||||||
protected $table = 'consumables';
|
protected $table = 'consumables';
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'requestable' => 'boolean'
|
'requestable' => '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
|
* Category validation rules
|
||||||
|
|
|
@ -18,12 +18,6 @@ class License extends Depreciable
|
||||||
{
|
{
|
||||||
protected $presenter = 'App\Presenters\LicensePresenter';
|
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 SoftDeletes;
|
||||||
use CompanyableTrait;
|
use CompanyableTrait;
|
||||||
|
|
|
@ -2,32 +2,37 @@
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Models\Loggable;
|
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\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
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 CompanyableChildTrait;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
use Loggable;
|
use Loggable;
|
||||||
|
|
||||||
|
protected $presenter = 'App\Presenters\LicenseSeatPresenter';
|
||||||
|
use Presentable;
|
||||||
|
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
protected $guarded = 'id';
|
protected $guarded = 'id';
|
||||||
protected $table = 'license_seats';
|
protected $table = 'license_seats';
|
||||||
|
|
||||||
/**
|
use Acceptable;
|
||||||
* Set static properties to determine which checkout/checkin handlers we should use
|
|
||||||
*/
|
|
||||||
public static $checkoutClass = CheckoutLicenseNotification::class;
|
|
||||||
public static $checkinClass = CheckinLicenseNotification::class;
|
|
||||||
|
|
||||||
public function getCompanyableParents()
|
public function getCompanyableParents()
|
||||||
{
|
{
|
||||||
return ['asset', 'license'];
|
return ['asset', 'license'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEula() {
|
||||||
|
return $this->license->getEula();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establishes the seat -> license relationship
|
* Establishes the seat -> license relationship
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,14 +6,7 @@ use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\CheckoutRequest;
|
use App\Models\CheckoutRequest;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Notifications\CheckinAssetNotification;
|
|
||||||
use App\Notifications\AuditNotification;
|
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;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +31,6 @@ trait Loggable
|
||||||
*/
|
*/
|
||||||
public function logCheckout($note, $target /* What are we checking out to? */)
|
public function logCheckout($note, $target /* What are we checking out to? */)
|
||||||
{
|
{
|
||||||
$settings = Setting::getSettings();
|
|
||||||
$log = new Actionlog;
|
$log = new Actionlog;
|
||||||
$log = $this->determineLogItemType($log);
|
$log = $this->determineLogItemType($log);
|
||||||
$log->user_id = Auth::user()->id;
|
$log->user_id = Auth::user()->id;
|
||||||
|
@ -63,29 +55,6 @@ trait Loggable
|
||||||
$log->note = $note;
|
$log->note = $note;
|
||||||
$log->logaction('checkout');
|
$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;
|
return $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +81,6 @@ trait Loggable
|
||||||
*/
|
*/
|
||||||
public function logCheckin($target, $note)
|
public function logCheckin($target, $note)
|
||||||
{
|
{
|
||||||
$settings = Setting::getSettings();
|
|
||||||
$log = new Actionlog;
|
$log = new Actionlog;
|
||||||
$log->target_type = get_class($target);
|
$log->target_type = get_class($target);
|
||||||
$log->target_id = $target->id;
|
$log->target_id = $target->id;
|
||||||
|
@ -140,29 +108,6 @@ trait Loggable
|
||||||
$log->user_id = Auth::user()->id;
|
$log->user_id = Auth::user()->id;
|
||||||
$log->logaction('checkin from');
|
$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;
|
return $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
app/Models/Traits/Acceptable.php
Normal file
31
app/Models/Traits/Acceptable.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\Traits;
|
||||||
|
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\CustomField;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This trait allows models to have a callback after their checkout gets accepted or declined.
|
||||||
|
*
|
||||||
|
* @author Till Deeke <kontakt@tilldeeke.de>
|
||||||
|
*/
|
||||||
|
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) {}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Accessory;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -15,31 +16,19 @@ use Illuminate\Support\Facades\Mail;
|
||||||
class CheckinAccessoryNotification extends Notification
|
class CheckinAccessoryNotification extends Notification
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
/**
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
private $params;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new notification instance.
|
* Create a new notification instance.
|
||||||
*
|
*
|
||||||
* @param $params
|
* @param $params
|
||||||
*/
|
*/
|
||||||
public function __construct($params)
|
public function __construct(Accessory $accessory, $checkedOutTo, User $checkedInby, $note)
|
||||||
{
|
{
|
||||||
$this->target = $params['target'];
|
$this->item = $accessory;
|
||||||
$this->item = $params['item'];
|
$this->target = $checkedOutTo;
|
||||||
$this->admin = $params['admin'];
|
$this->admin = $checkedInby;
|
||||||
$this->note = '';
|
$this->note = $note;
|
||||||
$this->target_type = $params['target'];
|
$this->settings = Setting::getSettings();
|
||||||
$this->settings = $params['settings'];
|
|
||||||
|
|
||||||
if (array_key_exists('note', $params)) {
|
|
||||||
$this->note = $params['note'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Asset;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Notifications\Notification;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
use Illuminate\Notifications\Messages\SlackMessage;
|
use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
class CheckinAssetNotification extends Notification
|
class CheckinAssetNotification extends Notification
|
||||||
{
|
{
|
||||||
|
@ -20,19 +21,15 @@ class CheckinAssetNotification extends Notification
|
||||||
*
|
*
|
||||||
* @param $params
|
* @param $params
|
||||||
*/
|
*/
|
||||||
public function __construct($params)
|
public function __construct(Asset $asset, $checkedOutTo, User $checkedInBy, $note)
|
||||||
{
|
{
|
||||||
$this->target = $params['target'];
|
$this->target = $checkedOutTo;
|
||||||
$this->item = $params['item'];
|
$this->item = $asset;
|
||||||
$this->admin = $params['admin'];
|
$this->admin = $checkedInBy;
|
||||||
$this->note = '';
|
$this->note = $note;
|
||||||
$this->expected_checkin = '';
|
|
||||||
$this->target_type = $params['target_type'];
|
|
||||||
$this->settings = $params['settings'];
|
|
||||||
|
|
||||||
if (array_key_exists('note', $params)) {
|
$this->settings = Setting::getSettings();
|
||||||
$this->note = $params['note'];
|
$this->expected_checkin = '';
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->item->expected_checkin) {
|
if ($this->item->expected_checkin) {
|
||||||
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\License;
|
||||||
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
use Illuminate\Notifications\Notification;
|
use Illuminate\Notifications\Notification;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
class CheckinLicenseNotification extends Notification
|
class CheckinLicenseSeatNotification extends Notification
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
/**
|
/**
|
||||||
|
@ -25,19 +27,13 @@ class CheckinLicenseNotification extends Notification
|
||||||
*
|
*
|
||||||
* @param $params
|
* @param $params
|
||||||
*/
|
*/
|
||||||
public function __construct($params)
|
public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedInBy, $note)
|
||||||
{
|
{
|
||||||
$this->target = $params['target'];
|
$this->target = $checkedOutTo;
|
||||||
$this->item = $params['item'];
|
$this->item = $licenseSeat->license;
|
||||||
$this->admin = $params['admin'];
|
$this->admin = $checkedInBy;
|
||||||
$this->note = '';
|
$this->note = $note;
|
||||||
$this->settings = $params['settings'];
|
$this->settings = Setting::getSettings();
|
||||||
$this->target_type = $params['target_type'];
|
|
||||||
|
|
||||||
if (array_key_exists('note', $params)) {
|
|
||||||
$this->note = $params['note'];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Accessory;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -15,33 +16,20 @@ use Illuminate\Support\Facades\Mail;
|
||||||
class CheckoutAccessoryNotification extends Notification
|
class CheckoutAccessoryNotification extends Notification
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
/**
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
private $params;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new notification instance.
|
* 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();
|
$eula = $this->item->getEula();
|
||||||
$req_accept = $this->item->requireAcceptance();
|
$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',
|
return (new MailMessage)->markdown('notifications.markdown.checkout-accessory',
|
||||||
[
|
[
|
||||||
'item' => $this->item,
|
'item' => $this->item,
|
||||||
|
@ -140,7 +130,7 @@ class CheckoutAccessoryNotification extends Notification
|
||||||
'target' => $this->target,
|
'target' => $this->target,
|
||||||
'eula' => $eula,
|
'eula' => $eula,
|
||||||
'req_accept' => $req_accept,
|
'req_accept' => $req_accept,
|
||||||
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
|
'accept_url' => $accept_url,
|
||||||
])
|
])
|
||||||
->subject(trans('mail.Confirm_accessory_delivery'));
|
->subject(trans('mail.Confirm_accessory_delivery'));
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Asset;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
@ -13,31 +14,25 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
class CheckoutAssetNotification extends Notification
|
class CheckoutAssetNotification extends Notification
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
/**
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
private $params;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new notification instance.
|
* Create a new notification instance.
|
||||||
*
|
*
|
||||||
* @param $params
|
* @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->item = $asset;
|
||||||
$this->admin = $params['admin'];
|
$this->admin = $checkedOutBy;
|
||||||
$this->log_id = $params['log_id'];
|
$this->note = $note;
|
||||||
$this->note = '';
|
$this->target = $checkedOutTo;
|
||||||
|
$this->acceptance = $acceptance;
|
||||||
|
|
||||||
|
$this->settings = Setting::getSettings();
|
||||||
|
|
||||||
$this->last_checkout = '';
|
$this->last_checkout = '';
|
||||||
$this->expected_checkin = '';
|
$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) {
|
if ($this->item->last_checkout) {
|
||||||
$this->last_checkout = \App\Helpers\Helper::getFormattedDateObject($this->item->last_checkout, 'date',
|
$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;
|
$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',
|
$message = (new MailMessage)->markdown('notifications.markdown.checkout-asset',
|
||||||
[
|
[
|
||||||
'item' => $this->item,
|
'item' => $this->item,
|
||||||
'admin' => $this->admin,
|
'admin' => $this->admin,
|
||||||
'note' => $this->note,
|
'note' => $this->note,
|
||||||
'log_id' => $this->note,
|
|
||||||
'target' => $this->target,
|
'target' => $this->target,
|
||||||
'fields' => $fields,
|
'fields' => $fields,
|
||||||
'eula' => $eula,
|
'eula' => $eula,
|
||||||
'req_accept' => $req_accept,
|
'req_accept' => $req_accept,
|
||||||
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
|
'accept_url' => $accept_url,
|
||||||
'last_checkout' => $this->last_checkout,
|
'last_checkout' => $this->last_checkout,
|
||||||
'expected_checkin' => $this->expected_checkin,
|
'expected_checkin' => $this->expected_checkin,
|
||||||
])
|
])
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\Consumable;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -25,21 +26,16 @@ class CheckoutConsumableNotification extends Notification
|
||||||
*
|
*
|
||||||
* @param $params
|
* @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->item = $consumable;
|
||||||
$this->note = $params['note'];
|
$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();
|
$eula = $this->item->getEula();
|
||||||
$req_accept = $this->item->requireAcceptance();
|
$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',
|
return (new MailMessage)->markdown('notifications.markdown.checkout-consumable',
|
||||||
[
|
[
|
||||||
'item' => $this->item,
|
'item' => $this->item,
|
||||||
'admin' => $this->admin,
|
'admin' => $this->admin,
|
||||||
'note' => $this->note,
|
'note' => $this->note,
|
||||||
'log_id' => $this->note,
|
|
||||||
'target' => $this->target,
|
'target' => $this->target,
|
||||||
'eula' => $eula,
|
'eula' => $eula,
|
||||||
'req_accept' => $req_accept,
|
'req_accept' => $req_accept,
|
||||||
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
|
'accept_url' => $accept_url,
|
||||||
])
|
])
|
||||||
->subject(trans('mail.Confirm_consumable_delivery'));
|
->subject(trans('mail.Confirm_consumable_delivery'));
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Models\License;
|
||||||
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -12,7 +14,7 @@ use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
use Illuminate\Notifications\Notification;
|
use Illuminate\Notifications\Notification;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
class CheckoutLicenseNotification extends Notification
|
class CheckoutLicenseSeatNotification extends Notification
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
/**
|
/**
|
||||||
|
@ -25,23 +27,15 @@ class CheckoutLicenseNotification extends Notification
|
||||||
*
|
*
|
||||||
* @param $params
|
* @param $params
|
||||||
*/
|
*/
|
||||||
public function __construct($params)
|
public function __construct(LicenseSeat $licenseSeat, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||||
{
|
{
|
||||||
$this->target = $params['target'];
|
$this->item = $licenseSeat->license;
|
||||||
$this->item = $params['item'];
|
$this->admin = $checkedOutBy;
|
||||||
$this->admin = $params['admin'];
|
$this->note = $note;
|
||||||
$this->log_id = $params['log_id'];
|
$this->target = $checkedOutTo;
|
||||||
$this->note = '';
|
$this->acceptance = $acceptance;
|
||||||
$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->settings = Setting::getSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,6 +119,8 @@ class CheckoutLicenseNotification extends Notification
|
||||||
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
|
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
|
||||||
$req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
|
$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',
|
return (new MailMessage)->markdown('notifications.markdown.checkout-license',
|
||||||
[
|
[
|
||||||
'item' => $this->item,
|
'item' => $this->item,
|
||||||
|
@ -133,7 +129,7 @@ class CheckoutLicenseNotification extends Notification
|
||||||
'target' => $this->target,
|
'target' => $this->target,
|
||||||
'eula' => $eula,
|
'eula' => $eula,
|
||||||
'req_accept' => $req_accept,
|
'req_accept' => $req_accept,
|
||||||
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
|
'accept_url' => $accept_url,
|
||||||
])
|
])
|
||||||
->subject(trans('mail.Confirm_license_delivery'));
|
->subject(trans('mail.Confirm_license_delivery'));
|
||||||
|
|
18
app/Presenters/LicenseSeatPresenter.php
Normal file
18
app/Presenters/LicenseSeatPresenter.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Presenters;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LicensePresenter
|
||||||
|
* @package App\Presenters
|
||||||
|
*/
|
||||||
|
class LicenseSeatPresenter extends Presenter
|
||||||
|
{
|
||||||
|
public function name()
|
||||||
|
{
|
||||||
|
return $this->model->license->name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use App\Listeners\CheckoutableListener;
|
||||||
|
use App\Listeners\LogListener;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
class EventServiceProvider extends 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.
|
* Register any events for your application.
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateCheckoutAcceptancesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('checkout_acceptances', function (Blueprint $table) {
|
||||||
|
$table->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');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Actionlog;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateCheckoutAcceptancesForUnacceptedAssets extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
// Get all assets not accepted
|
||||||
|
$assets = DB::table('assets')->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()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
135
resources/views/account/accept/create.blade.php
Normal file
135
resources/views/account/accept/create.blade.php
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
@extends('layouts/default')
|
||||||
|
|
||||||
|
{{-- Page title --}}
|
||||||
|
@section('title')
|
||||||
|
Accept {{ $acceptance->checkoutable->present()->name() }}
|
||||||
|
@parent
|
||||||
|
@stop
|
||||||
|
|
||||||
|
|
||||||
|
{{-- Page content --}}
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/signature-pad.css') }}">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline {
|
||||||
|
padding-top: 17px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#eula_div {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<form class="form-horizontal" method="post" action="" autocomplete="off">
|
||||||
|
<!-- CSRF Token -->
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2">
|
||||||
|
<div class="panel box box-default">
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="asset_acceptance" id="accepted" value="accepted">
|
||||||
|
I accept
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="asset_acceptance" id="declined" value="declined">
|
||||||
|
I decline
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if ($acceptance->checkoutable->getEula())
|
||||||
|
<div class="col-md-12" style="padding-top: 20px">
|
||||||
|
<div id="eula_div">
|
||||||
|
{!! $acceptance->checkoutable->getEula() !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($snipeSettings->require_accept_signature=='1')
|
||||||
|
<div class="col-md-12 col-sm-12 text-center" style="padding-top: 20px">
|
||||||
|
|
||||||
|
<h3>Sign below to indicate that you agree to the terms of service:</h3>
|
||||||
|
|
||||||
|
<div id="signature-pad" class="m-signature-pad">
|
||||||
|
<div class="m-signature-pad--body col-md-12 col-sm-12 col-lg-12 col-xs-12">
|
||||||
|
<canvas></canvas>
|
||||||
|
<input type="hidden" name="signature_output" id="signature_output">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 col-sm-12 col-lg-12 col-xs-12 text-center">
|
||||||
|
<button type="button" class="btn btn-sm btn-default clear" data-action="clear" id="clear_button">Clear Signature</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- .col-md-12.text-center-->
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div><!-- / col-md-12 -->
|
||||||
|
|
||||||
|
</div> <!-- / box-body -->
|
||||||
|
<div class="box-footer text-right">
|
||||||
|
<button type="submit" class="btn btn-success" id="submit-button"><i class="fa fa-check icon-white"></i> {{ trans('general.submit') }}</button>
|
||||||
|
</div><!-- /.box-footer -->
|
||||||
|
</div> <!-- / box-default -->
|
||||||
|
</div> <!-- / col -->
|
||||||
|
</div> <!-- / row -->
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('moar_scripts')
|
||||||
|
|
||||||
|
<script src="{{ asset('js/signature_pad.min.js') }}"></script>
|
||||||
|
<script nonce="{{ csrf_token() }}">
|
||||||
|
var wrapper = document.getElementById("signature-pad"),
|
||||||
|
clearButton = wrapper.querySelector("[data-action=clear]"),
|
||||||
|
saveButton = wrapper.querySelector("[data-action=save]"),
|
||||||
|
canvas = wrapper.querySelector("canvas"),
|
||||||
|
signaturePad;
|
||||||
|
|
||||||
|
// Adjust canvas coordinate space taking into account pixel ratio,
|
||||||
|
// to make it look crisp on mobile devices.
|
||||||
|
// This also causes canvas to be cleared.
|
||||||
|
function resizeCanvas() {
|
||||||
|
// When zoomed out to less than 100%, for some very strange reason,
|
||||||
|
// some browsers report devicePixelRatio as less than 1
|
||||||
|
// and only part of the canvas is cleared then.
|
||||||
|
var ratio = Math.max(window.devicePixelRatio || 1, 1);
|
||||||
|
canvas.width = canvas.offsetWidth * ratio;
|
||||||
|
canvas.height = canvas.offsetHeight * ratio;
|
||||||
|
canvas.getContext("2d").scale(ratio, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onresize = resizeCanvas;
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
signaturePad = new SignaturePad(canvas);
|
||||||
|
|
||||||
|
$('#clear_button').on("click", function (event) {
|
||||||
|
signaturePad.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#submit-button').on("click", function (event) {
|
||||||
|
if (signaturePad.isEmpty()) {
|
||||||
|
alert("Please provide signature first.");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$('#signature_output').val(signaturePad.toDataURL());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@stop
|
61
resources/views/account/accept/index.blade.php
Executable file
61
resources/views/account/accept/index.blade.php
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
@extends('layouts/default')
|
||||||
|
|
||||||
|
{{-- Page title --}}
|
||||||
|
@section('title')
|
||||||
|
Accept assets {{ $user->present()->fullName() }}
|
||||||
|
@parent
|
||||||
|
@stop
|
||||||
|
|
||||||
|
{{-- Account page content --}}
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="box box-default">
|
||||||
|
|
||||||
|
<div class="box-body">
|
||||||
|
<!-- checked out Accessories table -->
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table
|
||||||
|
data-cookie-id-table="pendingAcceptances"
|
||||||
|
data-pagination="true"
|
||||||
|
data-id-table="pendingAcceptances"
|
||||||
|
data-search="true"
|
||||||
|
data-side-pagination="client"
|
||||||
|
data-show-columns="true"
|
||||||
|
data-show-export="true"
|
||||||
|
data-show-refresh="true"
|
||||||
|
data-sort-order="asc"
|
||||||
|
id="pendingAcceptances"
|
||||||
|
class="table table-striped snipe-table"
|
||||||
|
data-export-options='{
|
||||||
|
"fileName": "my-pending-acceptances-{{ date('Y-m-d') }}",
|
||||||
|
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||||
|
}'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($acceptances as $acceptance)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $acceptance->checkoutable->present()->name }}</td>
|
||||||
|
<td><a href="{{ route('account.accept.item', $acceptance) }}" class="btn btn-default btn-sm">Accept/Decline</a></td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div> <!-- .box-body-->
|
||||||
|
</div><!--.box.box-default-->
|
||||||
|
</div> <!-- .col-md-12-->
|
||||||
|
</div> <!-- .row-->
|
||||||
|
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('moar_scripts')
|
||||||
|
@include ('partials.bootstrap-table')
|
||||||
|
@stop
|
|
@ -309,7 +309,11 @@
|
||||||
<i class="fa fa-check fa-disk fa-fw"></i>
|
<i class="fa fa-check fa-disk fa-fw"></i>
|
||||||
Requested Assets
|
Requested Assets
|
||||||
</a></li>
|
</a></li>
|
||||||
|
<li {!! (Request::is('account/accept') ? ' class="active"' : '') !!}>
|
||||||
|
<a href="{{ route('account.accept') }}">
|
||||||
|
<i class="fa fa-check fa-disk fa-fw"></i>
|
||||||
|
Accept Assets
|
||||||
|
</a></li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -251,10 +251,6 @@ Route::group([ 'prefix' => 'account', 'middleware' => ['auth']], function () {
|
||||||
'accept-asset/{logID}',
|
'accept-asset/{logID}',
|
||||||
[ 'as' => 'account/accept-assets', 'uses' => 'ViewAssetsController@getAcceptAsset' ]
|
[ 'as' => 'account/accept-assets', 'uses' => 'ViewAssetsController@getAcceptAsset' ]
|
||||||
);
|
);
|
||||||
Route::post(
|
|
||||||
'accept-asset/{logID}',
|
|
||||||
[ 'as' => 'account/asset-accepted', 'uses' => 'ViewAssetsController@postAcceptAsset' ]
|
|
||||||
);
|
|
||||||
|
|
||||||
# Profile
|
# Profile
|
||||||
Route::get(
|
Route::get(
|
||||||
|
@ -274,6 +270,15 @@ Route::group([ 'prefix' => 'account', 'middleware' => ['auth']], function () {
|
||||||
# Account Dashboard
|
# Account Dashboard
|
||||||
Route::get('/', [ 'as' => 'account', 'uses' => 'ViewAssetsController@getIndex' ]);
|
Route::get('/', [ 'as' => 'account', 'uses' => 'ViewAssetsController@getIndex' ]);
|
||||||
|
|
||||||
|
|
||||||
|
Route::get('accept', 'Account\AcceptanceController@index')
|
||||||
|
->name('account.accept');
|
||||||
|
|
||||||
|
Route::get('accept/{id}', 'Account\AcceptanceController@create')
|
||||||
|
->name('account.accept.item');
|
||||||
|
|
||||||
|
Route::post('accept/{id}', 'Account\AcceptanceController@store');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue