Files
snipe-it/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
T

174 lines
6.6 KiB
PHP

<?php
namespace App\Http\Controllers\Consumables;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\CheckoutAcceptance;
use App\Models\Consumable;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class ConsumableCheckoutController extends Controller
{
/**
* Return a view to checkout a consumable to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @see ConsumableCheckoutController::store() method that stores the data.
* @since [v1.0]
*
* @param int $id
*/
public function create($id): View|RedirectResponse
{
if ($consumable = Consumable::find($id)) {
$this->authorize('checkout', $consumable);
// Make sure the category is valid
if ($consumable->category) {
// Make sure there is at least one available to checkout
if ($consumable->numRemaining() <= 0) {
return redirect()->route('consumables.index')
->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => 1, 'remaining' => $consumable->numRemaining()]));
}
// Return the checkout view
return view('consumables/checkout', compact('consumable'));
}
// Invalid category
return redirect()->route('consumables.edit', ['consumable' => $consumable->id])
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.consumable')]));
}
// Not found
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
}
/**
* Saves the checkout information
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @see ConsumableCheckoutController::create() method that returns the form.
* @since [v1.0]
*
* @param int $consumableId
* @return RedirectResponse
*
* @throws AuthorizationException
*/
public function store(Request $request, $consumableId)
{
if (is_null($consumable = Consumable::with('users')->find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
}
$this->authorize('checkout', $consumable);
// If the quantity is not present in the request or is not a positive integer, set it to 1
$quantity = $request->input('checkout_qty');
if (! isset($quantity) || ! ctype_digit((string) $quantity) || $quantity <= 0) {
$quantity = 1;
}
// Make sure there is at least one available to checkout
if ($consumable->numRemaining() <= 0 || $quantity > $consumable->numRemaining()) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => $quantity, 'remaining' => $consumable->numRemaining()]));
}
$admin_user = auth()->user();
$assigned_to = e($request->input('assigned_to'));
// Check if the user exists
if (is_null($user = User::find($assigned_to))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.checkout.show', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'))->withInput();
}
if (! $consumable->canCheckoutTo($user)) {
return redirect()->back()->with('error', trans('general.error_checkout_company_mismatch', [
'item' => trans('general.consumable').' "'.$consumable->name.'"',
'item_company' => $consumable->company?->name ?? trans('general.unassigned'),
'target' => trans('general.user').' "'.$user->username.'"',
]));
}
// Update the consumable data
$consumable->assigned_to = e($request->input('assigned_to'));
for ($i = 0; $i < $quantity; $i++) {
$consumable->users()->attach($consumable->id, [
'consumable_id' => $consumable->id,
'created_by' => $admin_user->id,
'assigned_to' => e($request->input('assigned_to')),
'note' => $request->input('note'),
]);
}
$consumable->checkout_qty = $quantity;
event(new CheckoutableCheckedOut(
$consumable,
$user,
auth()->user(),
$request->input('note'),
[],
$consumable->checkout_qty,
$request->boolean('sign_in_place'),
));
$request->request->add(['checkout_to_type' => 'user']);
$request->request->add(['assigned_user' => $user->id]);
session()->put([
'redirect_option' => $request->input('redirect_option'),
'checkout_to_type' => $request->input('checkout_to_type'),
'sign_in_place' => $request->boolean('sign_in_place'),
]);
// When sign_in_place is requested, redirect to the acceptance/signature page
// so the user can sign in person. The signature is attributed to the target user.
if ($request->boolean('sign_in_place')) {
$acceptance = CheckoutAcceptance::where('checkoutable_type', Consumable::class)
->where('checkoutable_id', $consumable->id)
->where('assigned_to_id', $user->id)
->pending()
->latest()
->first();
// If requireAcceptance() is false the listener won't have created one; create it now.
if (! $acceptance) {
$acceptance = new CheckoutAcceptance;
$acceptance->checkoutable()->associate($consumable);
$acceptance->assignedTo()->associate($user);
$acceptance->qty = $quantity;
$acceptance->save();
}
session([
'sign_in_place_acceptance_id' => $acceptance->id,
'sign_in_place_item_id' => $consumable->id,
'sign_in_place_resource_type' => 'Consumables',
]);
return redirect()->route('account.accept.item', $acceptance->id)
->with('success', trans('admin/consumables/message.checkout.success'));
}
// Redirect to the new consumable page
return Helper::getRedirectOption($request, $consumable->id, 'Consumables')
->with('success', trans('admin/consumables/message.checkout.success'));
}
}