<?php

namespace App\Http\Controllers\Asset\Meter;

use App\Http\Controllers\Controller as BaseController;
use App\Http\Requests\Asset\MeterRequest;
use App\Repositories\Asset\MeterRepository;
use App\Repositories\Asset\Repository as AssetRepository;

class Controller extends BaseController
{
    /**
     * @var AssetRepository
     */
    protected $asset;

    /**
     * @var MeterRepository
     */
    protected $meter;

    /**
     * Constructor.
     *
     * @param AssetRepository $asset
     * @param MeterRepository $meter
     */
    public function __construct(AssetRepository $asset, MeterRepository $meter)
    {
        $this->asset = $asset;
        $this->meter = $meter;
    }

    /**
     * Displays all meters for the specified asset.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function index($id)
    {
        $asset = $this->asset->model()->findOrFail($id);

        return view('assets.meters.index', compact('asset'));
    }

    /**
     * Displays the form for creating a new meter for the specified asset.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function create($id)
    {
        $asset = $this->asset->model()->findOrFail($id);

        return view('assets.meters.create', compact('asset'));
    }

    /**
     * Creates a new meter for the specified asset.
     *
     * @param MeterRequest $request
     * @param int|string   $id
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(MeterRequest $request, $id)
    {
        $meter = $this->meter->create($request, $id);

        if ($meter) {
            $message = 'Successfully created meter.';

            return redirect()->route('maintenance.assets.meters.index', [$id])->withSuccess($message);
        } else {
            $message = 'There was an issue creating a meter. Please try again.';

            return redirect()->route('maintenance.assets.meters.create', [$id])->withErrors($message);
        }
    }

    /**
     * Displays the specified meter for the specified asset.
     *
     * @param int|string $id
     * @param int|string $meterId
     *
     * @return \Illuminate\View\View
     */
    public function show($id, $meterId)
    {
        $asset = $this->asset->model()->findOrFail($id);

        $meter = $asset->meters()->findOrFail($meterId);

        return view('assets.meters.show', compact('asset', 'meter'));
    }

    /**
     * Displays the form for editing the
     * specified meter for the specified asset.
     *
     * @param int|string $id
     * @param int|string $meterId
     *
     * @return \Illuminate\View\View
     */
    public function edit($id, $meterId)
    {
        $asset = $this->asset->model()->findOrFail($id);

        $meter = $asset->meters()->findOrFail($meterId);

        $lastReading = $meter->getLastReading();

        return view('assets.meters.edit', compact('asset', 'meter', 'lastReading'));
    }

    /**
     * Updates the specified meter attached to the specified asset.
     *
     * @param MeterRequest $request
     * @param int|string   $id
     * @param int|string   $meterId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(MeterRequest $request, $id, $meterId)
    {
        $meter = $this->meter->update($request, $id, $meterId);

        if ($meter) {
            $message = 'Successfully updated meter.';

            return redirect()->route('maintenance.assets.meters.show', [$id, $meter->id])->withSuccess($message);
        } else {
            $message = 'There was an issue updating this meter. Please try again.';

            return redirect()->route('maintenance.assets.meters.edit', [$id, $meterId])->withErrors($message);
        }
    }

    /**
     * Deletes the specified meter for the specified asset.
     *
     * @param int|string $id
     * @param int|string $meterId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($id, $meterId)
    {
        $asset = $this->asset->model()->findOrFail($id);

        $meter = $asset->meters()->findOrFail($meterId);

        if ($meter->delete()) {
            $message = 'Successfully deleted meter.';

            return redirect()->route('maintenance.assets.meters.index', [$id])->withSuccess($message);
        } else {
            $message = 'There was an issue deleting this meter. Please try again.';

            return redirect()->route('maintenance.assets.meters.show', [$id, $meterId])->withErrors($message);
        }
    }
}


<?php

namespace App\Http\Controllers\WorkOrder;

use App\Http\Controllers\Controller as BaseController;
use App\Services\WorkOrder\NotificationService;
use App\Services\WorkOrder\WorkOrderService;
use App\Validators\WorkOrder\NotificationValidator;

class NotificationController extends BaseController
{
    /**
     * @var NotificationService
     */
    protected $workOrderNotification;

    /**
     * @var NotificationValidator
     */
    protected $workOrderNotificationValidator;

    /**
     * @var WorkOrderService
     */
    protected $workOrder;

    /**
     * Constructor.
     *
     * @param WorkOrderService      $workOrder
     * @param NotificationService   $workOrderNotification
     * @param NotificationValidator $workOrderNotificationValidator
     */
    public function __construct(
        WorkOrderService $workOrder,
        NotificationService $workOrderNotification,
        NotificationValidator $workOrderNotificationValidator
    ) {
        $this->workOrderNotification = $workOrderNotification;
        $this->workOrderNotificationValidator = $workOrderNotificationValidator;
        $this->workOrder = $workOrder;
    }

    /**
     * Creates a new notification for the specified work order.
     *
     * @param string|int $workOrderId
     *
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
     */
    public function store($workOrderId)
    {
        if ($this->workOrderNotificationValidator->passes()) {
            $workOrder = $this->workOrder->find($workOrderId);

            $data = $this->inputAll();
            $data['work_order_id'] = $workOrder->id;

            $this->workOrderNotification->setInput($data)->create();

            $this->message = 'Successfully updated notifications';
            $this->messageType = 'success';
            $this->redirect = route('maintenance.work-orders.show', [$workOrder->id]);
        } else {
            $this->errors = $this->workOrderNotificationValidator->getErrors();
            $this->redirect = route('maintenance.work-orders.show', [$workOrderId]);
        }

        return $this->response();
    }

    /**
     * Updates the specified notification for the specified work order.
     *
     * @param string|int $workOrderId
     * @param string|int $notificationId
     *
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
     */
    public function update($workOrderId, $notificationId)
    {
        if ($this->workOrderNotificationValidator->passes()) {
            $workOrder = $this->workOrder->find($workOrderId);

            $notifications = $this->workOrderNotification->find($notificationId);

            $data = $this->inputAll();
            $data['work_order_id'] = $workOrder->id;

            $this->workOrderNotification->setInput($data)->update($notifications->id);

            $this->message = 'Successfully updated notifications';
            $this->messageType = 'success';
            $this->redirect = route('maintenance.work-orders.show', [$workOrder->id]);
        } else {
            $this->errors = $this->workOrderNotificationValidator->getErrors();
            $this->redirect = route('maintenance.work-orders.show', [$workOrderId]);
        }

        return $this->response();
    }
}


<?php

namespace App\Viewers\WorkOrder;

use App\Viewers\BaseViewer;
use Illuminate\Database\Eloquent\Collection;

class WorkOrderViewer extends BaseViewer
{
    /**
     * The work order profile view.
     *
     * @return \Illuminate\View\View
     */
    public function profile()
    {
        return view('viewers.work-order.profile', ['workOrder' => $this->entity]);
    }

    /**
     * The work order work request view.
     *
     * @return \Illuminate\View\View
     */
    public function workRequest()
    {
        return view('viewers.work-order.work-request', ['workOrder' => $this->entity]);
    }

    /**
     * The work order calendar view.
     *
     * @return \Illuminate\View\View
     */
    public function calendar()
    {
        return view('viewers.work-order.calendar', ['workOrder' => $this->entity]);
    }

    /**
     * The work order report view.
     *
     * @return \Illuminate\View\View
     */
    public function report()
    {
        return view('viewers.work-order.report', ['workOrder' => $this->entity]);
    }

    /**
     * The work order sessions view.
     *
     * @return \Illuminate\View\View
     */
    public function sessions(Collection $sessions)
    {
        return view('viewers.work-order.sessions', [
                'workOrder' => $this->entity,
                'sessions'  => $sessions,
            ]
        );
    }

    /**
     * The work order attachments view.
     *
     * @return \Illuminate\View\View
     */
    public function attachments()
    {
        return view('viewers.work-order.attachments', ['workOrder' => $this->entity]);
    }

    /**
     * The work order parts view.
     *
     * @return \Illuminate\View\View
     */
    public function parts()
    {
        return view('viewers.work-order.parts', ['workOrder' => $this->entity]);
    }

    /**
     * The work order updates view.
     *
     * @return \Illuminate\View\View
     */
    public function updates()
    {
        return view('viewers.work-order.updates', ['workOrder' => $this->entity]);
    }

    /**
     * The work order started at formatted string.
     *
     * @return null|string
     */
    public function startedAtFormatted()
    {
        if ($this->entity->started_at) {
            $date = new \DateTime();

            $date->setTimestamp(strtotime($this->entity->started_at));

            return $date->format('M dS Y - h:ia');
        }

        return;
    }

    /**
     * The work order completed at formatted string.
     *
     * @return null|string
     */
    public function completedAtFormatted()
    {
        if ($this->entity->completed_at) {
            $date = new \DateTime();

            $date->setTimestamp(strtotime($this->entity->completed_at));

            return $date->format('M dS Y - h:ia');
        }

        return;
    }

    /**
     * The work order edit button.
     *
     * @return \Illuminate\View\View
     */
    public function btnEdit()
    {
        return view('viewers.work-order.buttons.edit', ['workOrder' => $this->entity]);
    }

    /**
     * The work order delete button.
     *
     * @return \Illuminate\View\View
     */
    public function btnDelete()
    {
        return view('viewers.work-order.buttons.delete', ['workOrder' => $this->entity]);
    }

    /**
     * The work order delete button for the archive.
     *
     * @return \Illuminate\View\View
     */
    public function btnDeleteArchive()
    {
        return view('viewers.work-order.buttons.delete-archive', ['workOrder' => $this->entity]);
    }

    /**
     * The work order events button.
     *
     * @return \Illuminate\View\View
     */
    public function btnEvents()
    {
        return view('viewers.work-order.buttons.events', ['workOrder' => $this->entity]);
    }

    /**
     * The work order check in button.
     *
     * @return \Illuminate\View\View
     */
    public function btnCheckIn()
    {
        return view('viewers.work-order.buttons.check-in', ['workOrder' => $this->entity]);
    }

    /**
     * The work order workers button.
     *
     * @return \Illuminate\View\View
     */
    public function btnWorkers()
    {
        return view('viewers.work-order.buttons.workers', ['workOrder' => $this->entity]);
    }

    /**
     * The work order notifications button.
     *
     * @return \Illuminate\View\View
     */
    public function btnNotifications()
    {
        return view('viewers.work-order.buttons.notifications', ['workOrder' => $this->entity]);
    }

    /**
     * The work order complete button.
     *
     * @return \Illuminate\View\View
     */
    public function btnComplete()
    {
        return view('viewers.work-order.buttons.complete', ['workOrder' => $this->entity]);
    }

    /**
     * The work order parts button.
     *
     * @return \Illuminate\View\View
     */
    public function btnParts()
    {
        return view('viewers.work-order.buttons.parts', ['workOrder' => $this->entity]);
    }

    /**
     * The work order add parts button.
     *
     * @return \Illuminate\View\View
     */
    public function btnAddParts()
    {
        return view('viewers.work-order.buttons.add-parts', ['workOrder' => $this->entity]);
    }

    /**
     * The work order attachments button.
     *
     * @return \Illuminate\View\View
     */
    public function btnAttachments()
    {
        return view('viewers.work-order.buttons.attachments', ['workOrder' => $this->entity]);
    }

    /**
     * The work order add attachments button.
     *
     * @return \Illuminate\View\View
     */
    public function btnAddAttachments()
    {
        return view('viewers.work-order.buttons.add-attachments', ['workOrder' => $this->entity]);
    }

    /**
     * The work order event tag button.
     *
     * @return \Illuminate\View\View
     */
    public function btnEventTag()
    {
        return view('viewers.work-order.buttons.event-tag', [
            'workOrder' => $this->entity,
        ]);
    }

    /**
     * The work order restore button.
     *
     * @return \Illuminate\View\View
     */
    public function btnRestore()
    {
        return view('viewers.work-order.buttons.restore', ['workOrder' => $this->entity]);
    }

    /**
     * The work order actions button.
     *
     * @return \Illuminate\View\View
     */
    public function btnActions()
    {
        return view('viewers.work-order.buttons.actions', ['workOrder' => $this->entity]);
    }

    /**
     * The work order archive actions button.
     *
     * @return \Illuminate\View\View
     */
    public function btnActionsArchive()
    {
        return view('viewers.work-order.buttons.actions-archive', ['workOrder' => $this->entity]);
    }

    /**
     * The work order started at label.
     *
     * @return \Illuminate\View\View
     */
    public function lblStartedAt()
    {
        return view('viewers.work-order.labels.started-at', ['workOrder' => $this->entity]);
    }

    /**
     * The work order completed at label.
     *
     * @return \Illuminate\View\View
     */
    public function lblCompletedAt()
    {
        return view('viewers.work-order.labels.completed-at', ['workOrder' => $this->entity]);
    }

    /**
     * The work order completed check mark at label.
     *
     * @return \Illuminate\View\View
     */
    public function lblCheckCompleted()
    {
        return view('viewers.work-order.labels.check-completed', ['workOrder' => $this->entity]);
    }

    /**
     * The work order priority label.
     *
     * @return \Illuminate\View\View
     */
    public function lblPriority()
    {
        return view('viewers.work-order.labels.priority', ['workOrder' => $this->entity])->render();
    }

    /**
     * The work order status label.
     *
     * @return \Illuminate\View\View
     */
    public function lblStatus()
    {
        return view('viewers.work-order.labels.status', ['workOrder' => $this->entity])->render();
    }
}


<?php

namespace App\Jobs\WorkRequest;

use App\Http\Requests\WorkRequest as WorkHttpRequest;
use App\Jobs\Job;
use App\Models\WorkRequest;

class Update extends Job
{
    /**
     * @var WorkHttpRequest
     */
    protected $request;

    /**
     * @var WorkRequest
     */
    protected $workRequest;

    /**
     * Constructor.
     *
     * @param WorkHttpRequest $request
     * @param WorkRequest     $workRequest
     */
    public function __construct(WorkHttpRequest $request, WorkRequest $workRequest)
    {
        $this->request = $request;
        $this->workRequest = $workRequest;
    }

    /**
     * Execute the job.
     *
     * @return bool
     */
    public function handle()
    {
        $this->workRequest->subject = $this->request->input('subject', $this->workRequest->subject);
        $this->workRequest->best_time = $this->request->input('best_time', $this->workRequest->best_time);
        $this->workRequest->description = $this->request->clean($this->request->input('description', $this->workRequest->description));

        return $this->workRequest->save();
    }
}


<?php

namespace App\Processors\WorkOrder;

use App\Http\Presenters\WorkOrder\WorkOrderPresenter;
use App\Models\WorkOrder;
use App\Processors\Processor;

class WorkOrderAssignedProcessor extends Processor
{
    /**
     * @var WorkOrder
     */
    protected $workOrder;

    /**
     * @var WorkOrderPresenter
     */
    protected $presenter;

    /**
     * Constructor.
     *
     * @param WorkOrder          $workOrder
     * @param WorkOrderPresenter $presenter
     */
    public function __construct(WorkOrder $workOrder, WorkOrderPresenter $presenter)
    {
        $this->workOrder = $workOrder;
        $this->presenter = $presenter;
    }

    /**
     * Displays the current users assigned work orders.
     *
     * @return \Illuminate\View\View
     */
    public function index()
    {
        $workOrders = $this->presenter->tableAssigned($this->workOrder);

        $navbar = $this->presenter->navbar();

        return view('work-orders.assigned.index', compact('workOrders', 'navbar'));
    }
}


<?php

namespace App\Http\Presenters\WorkOrder;

use App\Http\Presenters\Presenter;
use App\Models\Comment;
use App\Models\WorkOrder;
use Orchestra\Contracts\Html\Form\Fieldset;
use Orchestra\Contracts\Html\Form\Grid as FormGrid;

class WorkOrderCommentPresenter extends Presenter
{
    /**
     * Returns a new form for the specified comment.
     *
     * @param WorkOrder $workOrder
     * @param Comment   $comment
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function form(WorkOrder $workOrder, Comment $comment)
    {
        return $this->form->of('work-orders.comments', function (FormGrid $form) use ($workOrder, $comment) {
            if ($comment->exists) {
                $method = 'PATCH';
                $url = route('work-orders.comments.update', [$workOrder->getKey(), $comment->getKey()]);

                $form->submit = 'Save';
            } else {
                $method = 'POST';
                $url = route('work-orders.comments.store', [$workOrder->getKey()]);

                $form->submit = 'Create';
            }

            $form->attributes(compact('method', 'url'));

            $form->with($comment);

            $form->fieldset(function (Fieldset $fieldset) {

                $fieldset->control('input:text', 'content');

            });
        });
    }
}


<?php

namespace App\Models;

use App\Models\Traits\HasUserTrait;
use App\Viewers\WorkOrder\SessionViewer;
use Illuminate\Database\Eloquent\Builder;
use Orchestra\Support\Facades\HTML;

class WorkOrderSession extends Model
{
    use HasUserTrait;

    /**
     * The work order sessions table.
     *
     * @var string
     */
    protected $table = 'work_order_sessions';

    /**
     * The work order session viewer.
     *
     * @var string
     */
    protected $viewer = SessionViewer::class;

    /**
     * The fillable work order session attributes.
     *
     * @var array
     */
    protected $fillable = [
        'user_id',
        'work_order_id',
        'in',
        'out',
        'hours',
    ];

    /**
     * The hasOne work order relationship.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function workOrder()
    {
        return $this->hasOne(WorkOrder::class, 'work_order_id');
    }

    /**
     * Returns a query scope of sessions grouped by users.
     *
     * @param Builder $builder
     *
     * @return Builder
     */
    public function scopeUnique(Builder $builder)
    {
        $select = 'user_id, TRUNCATE(ABS(SUM(TIME_TO_SEC(TIMEDIFF(work_order_sessions.in, work_order_sessions.out)) / 3600)), 2) as total_hours';

        return $builder->selectRaw($select)->groupBy('user_id');
    }

    /**
     * Returns the number of hours a session lasted with decimals.
     *
     * @return null|int
     */
    public function getHours()
    {
        if (array_key_exists('out', $this->attributes)) {
            if ($this->attributes['out']) {
                $hours = abs(round((strtotime($this->attributes['in']) - strtotime($this->attributes['out'])) / 3600, 2));

                return $hours;
            }
        }

        return;
    }

    /**
     * Returns a label if the current users session is open,
     * otherwise it will return the out datetime.
     *
     * @return string
     */
    public function getOutLabel()
    {
        if (is_null($this->out)) {
            return HTML::create('span', 'Open', ['class' => 'label label-success']);
        } else {
            return $this->out;
        }
    }
}


<?php

namespace App\Jobs\Inventory\Stock;

use App\Http\Requests\Inventory\InventoryStockRequest;
use App\Jobs\Job;
use App\Models\Inventory;
use App\Models\InventoryStock;

class Store extends Job
{
    /**
     * @var InventoryStockRequest
     */
    protected $request;

    /**
     * @var Inventory
     */
    protected $inventory;

    /**
     * @var InventoryStock
     */
    protected $stock;

    /**
     * Constructor.
     *
     * @param InventoryStockRequest $request
     * @param Inventory             $inventory
     * @param InventoryStock        $stock
     */
    public function __construct(InventoryStockRequest $request, Inventory $inventory, InventoryStock $stock)
    {
        $this->request = $request;
        $this->inventory = $inventory;
        $this->stock = $stock;
    }

    /**
     * Execute the job.
     *
     * @return bool
     */
    public function handle()
    {
        $this->stock->user_id = auth()->id();
        $this->stock->inventory_id = $this->inventory->getKey();
        $this->stock->location_id = $this->request->input('location');
        $this->stock->quantity = $this->request->input('quantity');
        $this->stock->cost = $this->request->input('cost');
        $this->stock->reason = $this->request->input('reason');

        return $this->stock->save();
    }
}


<?php

namespace App\Viewers\Event;

use App\Viewers\BaseViewer;
use Stevebauman\CalendarHelper\Objects\Event;

class EventViewer extends BaseViewer
{
    /**
     * Returns the API events profile view.
     *
     * @param Event $apiObject
     *
     * @return \Illuminate\View\View
     */
    public function profile(Event $apiObject)
    {
        return view('viewers.event.profile', [
            'event'     => $this->entity,
            'apiObject' => $apiObject,
        ]);
    }

    /**
     * Returns the API events recurrences
     * view with the specified recurrences.
     *
     * @return \Illuminate\View\View
     */
    public function recurrences()
    {
        return view('viewers.event.recurrences', [
            'event' => $this->entity,
        ]);
    }

    /**
     * Returns the API events attendees view.
     *
     * @return \Illuminate\View\View
     */
    public function attendees()
    {
        return view('viewers.event.attendees', [
            'event' => $this->entity,
        ]);
    }

    /**
     * Returns the API events recurrence warning view.
     *
     * @return \Illuminate\View\View
     */
    public function recurrenceWarning()
    {
        return view('viewers.event.recurrence-warning', [
            'event' => $this->entity,
        ]);
    }

    /**
     * Presents the correct date timestamp depending if the event is all day.
     *
     * @param Event $apiObject
     *
     * @return string
     */
    public function startFormatted(Event $apiObject)
    {
        $start = new \DateTime();

        $start->setTimestamp(strtotime($apiObject->start));

        if ($apiObject->all_day) {
            return $start->format('M dS Y');
        } else {
            return $start->format('M dS Y - h:ia');
        }
    }

    /**
     * Presents the correct start date formatted for editing.
     *
     * @param Event $apiObject
     *
     * @return string
     */
    public function startDateFormatted(Event $apiObject)
    {
        $start = new \DateTime();

        $start->setTimestamp(strtotime($apiObject->start));

        return $start->format('m/d/Y');
    }

    /**
     * Presents the correct start time formatted for editing.
     *
     * @param Event $apiObject
     *
     * @return string|null
     */
    public function startTimeFormatted(Event $apiObject)
    {
        if (!$apiObject->all_day) {
            $start = new \DateTime();

            $start->setTimestamp(strtotime($apiObject->start));

            return $start->format('h:i A');
        }

        return;
    }

    /**
     * Presents the correct date timestamp depending if the event is all day.
     *
     * @param Event $apiObject
     *
     * @return string
     */
    public function endFormatted(Event $apiObject)
    {
        $end = new \DateTime();

        $end->setTimestamp(strtotime($apiObject->end));

        if ($apiObject->all_day) {
            return $end->format('M dS Y');
        }

        return $end->format('M dS Y - h:ia');
    }

    /**
     * Presents the correct end date formatted for editing.
     *
     * @param Event $apiObject
     *
     * @return string
     */
    public function endDateFormatted(Event $apiObject)
    {
        $end = new \DateTime();

        $end->setTimestamp(strtotime($apiObject->start));

        return $end->format('m/d/Y');
    }

    /**
     * Presents the correct end time formatted for editing.
     *
     * @param Event $apiObject
     *
     * @return string|null
     */
    public function endTimeFormatted(Event $apiObject)
    {
        if (!$apiObject->all_day) {
            $end = new \DateTime();

            $end->setTimestamp(strtotime($apiObject->start));

            return $end->format('h:i A');
        }

        return;
    }

    /**
     * Presents the API events recurrence frequency in a nicer format.
     *
     * @param Event $apiObject
     *
     * @return string
     */
    public function recurFrequencyFormatted(Event $apiObject)
    {
        if ($this->recurFrequency($apiObject)) {
            return ucfirst(strtolower($this->recurFrequency($apiObject)));
        }

        return 'None';
    }

    /**
     * Returns the API events actual recurrence frequency array.
     *
     * @param Event $apiObject
     *
     * @return array|null
     */
    public function recurFrequency(Event $apiObject)
    {
        if ($apiObject->rruleArray && array_key_exists('FREQ', $apiObject->rruleArray)) {
            $freq = $apiObject->rruleArray['FREQ'];

            return $freq;
        }

        return;
    }

    /**
     * Returns the API events actual recurring days array.
     *
     * @return array|null
     */
    public function recurDays(Event $apiObject)
    {
        if ($apiObject->rruleArray && array_key_exists('BYDAY', $apiObject->rruleArray)) {
            $freq = $apiObject->rruleArray['BYDAY'];

            return $freq;
        }

        return;
    }

    /**
     * Returns the events tags view.
     *
     * @return \Illuminate\View\View
     */
    public function tags()
    {
        /*
         * Make sure we pass in the parent event if this event is a recurrence
         * so we can use it's tags
         */
        if ($this->entity->parentEvent) {
            $event = $this->entity->parentEvent;
        } else {
            $event = $this->entity;
        }

        return view('viewers.event.tags', [
            'event' => $event,
        ]);
    }

    /**
     * Returns the events report view.
     *
     * @return \Illuminate\View\View
     */
    public function report()
    {
        return view('viewers.event.report', [
            'event' => $this->entity,
        ]);
    }

    /**
     * Returns the events report created label view.
     *
     * @return \Illuminate\View\View
     */
    public function lblReportCreated()
    {
        return view('viewers.event.labels.report-created', [
            'event' => $this->entity,
        ]);
    }

    /**
     * Returns the API events recurring label view.
     *
     * @return \Illuminate\View\View
     */
    public function lblRecurring()
    {
        return view('viewers.event.labels.recurring', ['event' => $this->entity]);
    }

    /**
     * Returns the API events all day label view.
     *
     * @return \Illuminate\View\View
     */
    public function lblAllDay()
    {
        return view('viewers.event.labels.all-day', ['event' => $this->entity]);
    }

    /**
     * Returns events actions button view
     * for the specified eventable model.
     *
     * @param Model $eventable
     *
     * @return \Illuminate\View\View
     */
    public function btnEventableActions(Model $eventable)
    {
        return view('viewers.event.buttons.eventable-actions', [
            'event'     => $this->entity,
            'eventable' => $eventable,
        ]);
    }

    /**
     * Returns events edit button view
     * for the specified eventable model.
     *
     * @param Model $eventable
     *
     * @return \Illuminate\View\View
     */
    public function btnEventableEdit(Model $eventable)
    {
        return view('viewers.event.buttons.eventable-edit', [
            'event'     => $this->entity,
            'eventable' => $eventable,
        ]);
    }

    /**
     * Returns events actions delete button view
     * for the specified eventable model.
     *
     * @param Model $eventable
     *
     * @return \Illuminate\View\View
     */
    public function btnEventableDelete(Model $eventable)
    {
        return view('viewers.event.buttons.eventable-delete', [
            'event'     => $this->entity,
            'eventable' => $eventable,
        ]);
    }

    /**
     * Returns the events edit button view.
     *
     * @param string $url
     *
     * @return \Illuminate\View\View
     */
    public function btnEdit($url)
    {
        return view('viewers.event.buttons.edit', [
            'event' => $this->entity,
            'url'   => $url,
        ]);
    }

    /**
     * Returns the events delete button view.
     *
     * @param string $url
     *
     * @return \Illuminate\View\View
     */
    public function btnDelete($url)
    {
        return view('viewers.event.buttons.delete', [
            'event' => $this->entity,
            'url'   => $url,
        ]);
    }

    /**
     * Returns the events action buttons view.
     *
     * @return \Illuminate\View\View
     */
    public function btnActions()
    {
        return view('viewers.event.buttons.actions', ['event' => $this->entity]);
    }
}


<?php

namespace App\Http\Controllers\Inventory;

use App\Http\Controllers\Controller as BaseController;
use App\Http\Requests\Inventory\InventoryStockRequest;
use App\Processors\Inventory\InventoryStockProcessor;

class StockController extends BaseController
{
    /**
     * @var InventoryStockProcessor
     */
    protected $processor;

    /**
     * Constructor.
     *
     * @param InventoryStockProcessor $processor
     */
    public function __construct(InventoryStockProcessor $processor)
    {
        $this->processor = $processor;
    }

    /**
     * Displays all inventory stock entries.
     *
     * @param int|string $itemId
     *
     * @return \Illuminate\View\View
     */
    public function index($itemId)
    {
        return $this->processor->index($itemId);
    }

    /**
     * Displays the form for creating a new stock entry for the inventory.
     *
     * @param int|string $itemId
     *
     * @return \Illuminate\View\View
     */
    public function create($itemId)
    {
        return $this->processor->create($itemId);
    }

    /**
     * Create a new stock entry for the specified inventory item.
     *
     * @param InventoryStockRequest $request
     * @param int|string            $itemId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(InventoryStockRequest $request, $itemId)
    {
        if ($this->processor->store($request, $itemId)) {
            flash()->success('Success!', 'Successfully created stock.');

            return redirect()->route('maintenance.inventory.stocks.index', [$itemId]);
        } else {
            flash()->error('Error!', 'There was an issue creating an inventory stock. Please try again.');

            return redirect()->route('maintenance.inventory.stocks.create', [$itemId]);
        }
    }

    /**
     * Displays the specified stock entry for the specified inventory.
     *
     * @param int|string $itemId
     * @param int|string $stockId
     *
     * @return \Illuminate\View\View
     */
    public function show($itemId, $stockId)
    {
        return $this->processor->show($itemId, $stockId);
    }

    /**
     * Displays the edit form for the specified stock for the specified inventory.
     *
     * @param int|string $itemId
     * @param int|string $stockId
     *
     * @return \Illuminate\View\View
     */
    public function edit($itemId, $stockId)
    {
        return $this->processor->edit($itemId, $stockId);
    }

    /**
     * Updates the specified stock for the specified inventory.
     *
     * @param InventoryStockRequest $request
     * @param int|string            $itemId
     * @param int|string            $stockId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(InventoryStockRequest $request, $itemId, $stockId)
    {
        if ($this->processor->update($request, $itemId, $stockId)) {
            flash()->success('Success!', 'Successfully updated stock.');

            return redirect()->route('maintenance.inventory.stocks.show', [$itemId, $stockId]);
        } else {
            flash()->error('Error!', 'There was an issue updating this stock. Please try again.');

            return redirect()->route('maintenance.inventory.stocks.update', [$itemId, $stockId]);
        }
    }

    /**
     * Removes the specified stock from the specified inventory.
     *
     * @param int|string $itemId
     * @param int|string $stockId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($itemId, $stockId)
    {
        if ($this->processor->destroy($itemId, $stockId)) {
            flash()->success('Success!', 'Successfully deleted stock.');

            return redirect()->route('maintenance.inventory.stocks.index', [$itemId]);
        } else {
            flash()->error('Error!', 'There was an issue deleting this stock. Please try again.');

            return redirect()->route('maintenance.inventory.stocks.show', [$itemId, $stockId]);
        }
    }
}


<?php

namespace App\Http\Presenters\WorkOrder;

use App\Http\Presenters\Presenter;
use App\Models\Attachment;
use App\Models\User;
use App\Models\WorkOrder;
use Orchestra\Contracts\Html\Form\Fieldset;
use Orchestra\Contracts\Html\Form\Grid as FormGrid;
use Orchestra\Contracts\Html\Table\Column;
use Orchestra\Contracts\Html\Table\Grid as TableGrid;

class WorkOrderAttachmentPresenter extends Presenter
{
    /**
     * Returns a new table of all the specified work orders attachments.
     *
     * @param WorkOrder $workOrder
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function table(WorkOrder $workOrder)
    {
        $attachments = $workOrder->attachments();

        return $this->table->of('work-orders.attachments', function (TableGrid $table) use ($workOrder, $attachments) {
            $table->with($attachments)->paginate($this->perPage);

            $table->column('type', function (Column $column) {
                $column->value = function (Attachment $attachment) {
                    return $attachment->icon;
                };
            });

            $table->column('name', function (Column $column) use ($workOrder) {
                $column->value = function (Attachment $attachment) use ($workOrder) {
                    $route = 'maintenance.work-orders.attachments.show';

                    $params = [$workOrder->getKey(), $attachment->getKey()];

                    return link_to_route($route, $attachment->name, $params);
                };
            });

            $table->column('uploaded_by', function (Column $column) {
               $column->value = function (Attachment $attachment) {
                    if ($attachment->user instanceof User) {
                        return $attachment->user->getRecipientName();
                    }
               };
            });

            $table->column('Uploaded On', 'created_at');
        });
    }

    /**
     * Returns a new form for the specified work order attachment.
     *
     * @param WorkOrder  $workOrder
     * @param Attachment $attachment
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function form(WorkOrder $workOrder, Attachment $attachment)
    {
        return $this->form->of('work-orders.attachments', function (FormGrid $form) use ($workOrder, $attachment) {
            $files = true;

            if ($attachment->exists) {
                $url = route('maintenance.work-orders.attachments.update', [$workOrder->getKey(), $attachment->getKey()]);
                $method = 'PATCH';
                $form->submit = 'Save';
                $form->with($attachment);
            } else {
                $url = route('maintenance.work-orders.attachments.store', [$workOrder->getKey()]);
                $method = 'POST';
                $form->submit = 'Upload';
            }

            $form->attributes(compact('url', 'method', 'files'));

            $form->fieldset(function (Fieldset $fieldset) use ($attachment) {
                if ($attachment->exists) {
                    // If the attachment exists we'll provide the ability
                    // to only change the attachments name.
                    $fieldset
                        ->control('input:text', 'name')
                        ->label('Attachment Name');
                } else {
                    // Otherwise we'll allow the user to upload multiple
                    // attachments at once for the specified work order.
                    $fieldset
                        ->control('input:file', 'files[]')
                        ->label('Files')
                        ->attributes([
                            'multiple' => true,
                        ]);
                }
            });
        });
    }

    /**
     * Returns a new navbar for the work order attachment index.
     *
     * @param WorkOrder $workOrder
     *
     * @return \Illuminate\Support\Fluent
     */
    public function navbar(WorkOrder $workOrder)
    {
        return $this->fluent([
            'id'         => 'work-orders-attachments',
            'title'      => 'Attachments',
            'menu'       => view('work-orders.attachments._nav', compact('workOrder')),
            'attributes' => [
                'class' => 'navbar-default',
            ],
        ]);
    }
}


<?php

namespace App\Http\Controllers;

use Adldap\Models\User as AdldapUser;
use App\Http\Presenters\LoginPresenter;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Exception;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Orchestra\Model\Role;

class AuthController extends Controller
{
    use ThrottlesLogins;

    /**
     * @var LoginPresenter
     */
    protected $presenter;

    /**
     * The username string to use for authentication.
     *
     * @var string
     */
    protected $username = 'email';

    /**
     * Constructor.
     *
     * @param LoginPresenter $presenter
     */
    public function __construct(LoginPresenter $presenter)
    {
        $this->presenter = $presenter;
    }

    /**
     * Show the application login form.
     *
     * @return \Illuminate\View\View
     */
    public function login()
    {
        $form = $this->presenter->form();

        return view('auth.login.index', compact('form'));
    }

    /**
     * Handle a login request to the application.
     *
     * @param LoginRequest $request
     *
     * @return \Illuminate\Http\Response
     */
    public function authenticate(LoginRequest $request)
    {
        $throttles = $this->isUsingThrottlesLoginsTrait();

        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->getCredentials($request);

        try {
            if (Auth::attempt($credentials, $request->has('remember'))) {
                return $this->handleUserWasAuthenticated($request, $throttles);
            }
        } catch (Exception $e) {
            // Catch LDAP bind errors.
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        if ($throttles) {
            $this->incrementLoginAttempts($request);
        }

        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param \Illuminate\Http\Request $request
     * @param bool                     $throttles
     *
     * @return \Illuminate\Http\Response
     */
    protected function handleUserWasAuthenticated(Request $request, $throttles)
    {
        if ($throttles) {
            $this->clearLoginAttempts($request);
        }

        $user = auth()->user();

        if ($user instanceof User && $user->adldapUser instanceof AdldapUser) {
            $this->handleLdapUserWasAuthenticated($user, $user->adldapUser);
        }

        flash()->success('Success!', "You're logged in!");

        return redirect()->intended($this->redirectPath());
    }

    /**
     * Attaches roles depending on the users active directory group.
     *
     * @param User       $user
     * @param AdldapUser $adldapUser
     */
    protected function handleLdapUserWasAuthenticated(User $user, AdldapUser $adldapUser)
    {
        if ($adldapUser->inGroup('Help Desk')) {
            $admin = Role::admin();

            if ($admin instanceof Role) {
                $user->attachRole($admin->getKey());
            }
        }
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    protected function getCredentials(Request $request)
    {
        return $request->only($this->loginUsername(), 'password');
    }

    /**
     * Log the user out of the application.
     *
     * @return \Illuminate\Http\Response
     */
    public function logout()
    {
        // Log the user out
        Auth::logout();

        // Flush their session
        Session::flush();

        flash()->success('Success!', "You've been logged out!");

        return redirect('/');
    }

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function loginUsername()
    {
        return property_exists($this, 'username') ? $this->username : 'email';
    }

    /**
     * Returns the failed login message.
     *
     * @return string
     */
    public function getFailedLoginMessage()
    {
        return 'The email or password was incorrect.';
    }

    /**
     * Returns the login path.
     *
     * @return string
     */
    public function loginPath()
    {
        return route('maintenance.login.index');
    }

    /**
     * Get the redirect path when users are authenticated.
     *
     * @return string
     */
    public function redirectPath()
    {
        return route('maintenance.dashboard.index');
    }

    /**
     * Determine if the class is using the ThrottlesLogins trait.
     *
     * @return bool
     */
    protected function isUsingThrottlesLoginsTrait()
    {
        return in_array(
            ThrottlesLogins::class, class_uses_recursive(get_class($this))
        );
    }
}


<?php

namespace App\Models\Observers;

use App\Models\InventoryStock;

class InventoryStockObserver
{
    /**
     * Captures the Inventory Stock models deleted event
     * and cascades the delete to all of it's movements.
     *
     * @param InventoryStock $stock
     */
    public function deleted(InventoryStock $stock)
    {
        $movements = $stock->movements()->get();

        if (count($movements) > 0) {
            foreach ($movements as $movement) {
                $movement->delete();
            }
        }
    }

    /**
     * Captures the Inventory Stock models restored event
     * and cascades the restore to all of it's movements.
     *
     * @param InventoryStock $stock
     */
    public function restored(InventoryStock $stock)
    {
        $movements = $stock->movements()->onlyTrashed()->get();

        if (count($movements) > 0) {
            foreach ($movements as $movement) {
                $movement->restore();
            }
        }
    }
}


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateInventorySupplierTables extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('suppliers', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();

            $table->string('name');
            $table->string('address')->nullable();
            $table->string('postal_code')->nullable();
            $table->string('zip_code')->nullable();
            $table->string('region')->nullable();
            $table->string('city')->nullable();
            $table->string('country')->nullable();
            $table->string('contact_title')->nullable();
            $table->string('contact_name')->nullable();
            $table->string('contact_phone')->nullable();
            $table->string('contact_fax')->nullable();
            $table->string('contact_email')->nullable();
        });

        Schema::create('inventory_suppliers', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();

            $table->integer('inventory_id')->unsigned();
            $table->integer('supplier_id')->unsigned();

            $table->foreign('inventory_id')->references('id')->on('inventories')
                ->onUpdate('restrict')
                ->onDelete('cascade');

            $table->foreign('supplier_id')->references('id')->on('suppliers')
                ->onUpdate('restrict')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::dropIfExists('inventory_suppliers');
        Schema::dropIfExists('suppliers');
    }
}


<?php

namespace App\Http\Presenters\WorkOrder;

use App\Http\Presenters\Presenter;
use App\Models\Priority;
use App\Models\User;
use Orchestra\Contracts\Html\Form\Fieldset;
use Orchestra\Contracts\Html\Form\Grid as FormGrid;
use Orchestra\Contracts\Html\Table\Column;
use Orchestra\Contracts\Html\Table\Grid as TableGrid;
use Orchestra\Support\Facades\HTML;

class WorkOrderPriorityPresenter extends Presenter
{
    /**
     * Returns a new table of all priorities.
     *
     * @param Priority $priority
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function table(Priority $priority)
    {
        return $this->table->of('work-orders.priorities', function (TableGrid $table) use ($priority) {
            $table->with($priority);

            $table->column('priority', function (Column $column) {
                $column->value = function (Priority $priority) {
                    return link_to_route('maintenance.work-orders.priorities.edit', $priority->getLabel(), [$priority->getKey()]);
                };
            });

            $table->column('created_at');

            $table->column('created_by', function (Column $column) {
                $column->value = function (Priority $priority) {
                    if ($priority->user instanceof User) {
                        return $priority->user->getRecipientName();
                    } else {
                        return HTML::create('em', 'None');
                    }
                };
            });
        });
    }

    /**
     * Returns a new form for priorities.
     *
     * @param Priority $priority
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function form(Priority $priority)
    {
        return $this->form->of('work-orders.priorities', function (FormGrid $form) use ($priority) {
            if ($priority->exists) {
                $url = route('maintenance.work-orders.priorities.update', [$priority->getKey()]);
                $method = 'PATCH';
                $form->submit = 'Save';
            } else {
                $url = route('maintenance.work-orders.priorities.store');
                $method = 'POST';
                $form->submit = 'Create';
            }

            $colors = config('maintenance.colors', []);

            $form->attributes(compact('method', 'url'));

            $form->with($priority);

            $form->fieldset(function (Fieldset $fieldset) use ($colors) {
                $fieldset
                    ->control('input:text', 'name')
                    ->attributes([
                        'placeholder' => 'ex. High / Low',
                    ]);

                $fieldset
                    ->control('select', 'color')
                    ->options($colors)
                    ->value(function (Priority $priority) {
                        return $priority->color;
                    })
                    ->attributes([
                        'class' => 'select2-color',
                    ]);
            });
        });
    }

    /**
     * Returns a new navbar for the priorities index.
     *
     * @return \Illuminate\Support\Fluent
     */
    public function navbar()
    {
        return $this->fluent([
            'id'         => 'work-orders-priorities',
            'title'      => 'Priorities',
            'menu'       => view('work-orders.priorities._nav'),
            'attributes' => [
                'class' => 'navbar-default',
            ],
        ]);
    }
}


<?php

namespace App\Jobs\Inventory;

use App\Http\Requests\Inventory\InventoryRequest;
use App\Jobs\Job;
use App\Models\Inventory;

class Store extends Job
{
    /**
     * @var InventoryRequest
     */
    protected $request;

    /**
     * @var Inventory
     */
    protected $inventory;

    /**
     * Constructor.
     *
     * @param InventoryRequest $request
     * @param Inventory        $inventory
     */
    public function __construct(InventoryRequest $request, Inventory $inventory)
    {
        $this->request = $request;
        $this->inventory = $inventory;
    }

    /**
     * Execute the job.
     *
     * @return bool
     */
    public function handle()
    {
        $this->inventory->user_id = auth()->id();
        $this->inventory->category_id = $this->request->input('category');
        $this->inventory->metric_id = $this->request->input('metric');
        $this->inventory->name = $this->request->input('name');
        $this->inventory->description = $this->request->clean($this->request->input('description'));

        return $this->inventory->save();
    }
}


<?php

namespace App\Http\Requests;

use Orchestra\Http\FormRequest;
use Stevebauman\Purify\Facades\Purify;

abstract class Request extends FormRequest
{
    /**
     * Cleans a string or array of HTML input.
     *
     * @param string|array $input
     *
     * @return string|array
     */
    public function clean($input)
    {
        return Purify::clean($input);
    }

    /**
     * @param string      $date
     * @param string|null $time
     *
     * @return bool|null|string
     */
    public function formatDateWithTime($date, $time = null)
    {
        if (!empty($date)) {
            if (!empty($time)) {
                return date('Y-m-d H:i:s', strtotime($date.' '.$time));
            }

            return date('Y-m-d H:i:s', strtotime($date));
        }

        return;
    }
}


<?php

namespace App\Http\Presenters\WorkOrder;

use App\Http\Presenters\Presenter;
use App\Models\Inventory;
use App\Models\InventoryStock;
use App\Models\WorkOrder;
use Orchestra\Contracts\Html\Form\Field;
use Orchestra\Contracts\Html\Form\Fieldset;
use Orchestra\Contracts\Html\Form\Grid as FormGrid;
use Orchestra\Contracts\Html\Table\Column;
use Orchestra\Contracts\Html\Table\Grid as TableGrid;

class WorkOrderPartStockPresenter extends Presenter
{
    /**
     * Returns a new table of stocks for the specified inventory
     * item for work order part selection.
     *
     * @param WorkOrder $workOrder
     * @param Inventory $item
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function table(WorkOrder $workOrder, Inventory $item)
    {
        $stocks = $item->stocks();

        return $this->table->of('work-orders.parts.stocks', function (TableGrid $table) use ($workOrder, $item, $stocks) {
            $table->with($stocks)->paginate($this->perPage);

            $table->column('location', function (Column $column) use ($item) {
                $column->value = function (InventoryStock $stock) use ($item) {
                    $name = $stock->location->trail;

                    return link_to_route('maintenance.inventory.stocks.show', $name, [$item->getKey(), $stock->getKey()]);
                };
            });

            $table->column('quantity');

            $table->column('select', function (Column $column) use ($workOrder, $item) {
                $column->value = function (InventoryStock $stock) use ($workOrder, $item) {
                    $route = 'maintenance.work-orders.parts.stocks.take';

                    $params = [$workOrder->getKey(), $item->getKey(), $stock->getKey()];

                    $attributes = [
                        'class' => 'btn btn-default btn-sm',
                    ];

                    return link_to_route($route, 'Select', $params, $attributes);
                };
            });
        });
    }

    /**
     * Returns a new table of specified items variants available
     * for selection on the current work order.
     *
     * @param WorkOrder $workOrder
     * @param Inventory $item
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function tableVariants(WorkOrder $workOrder, Inventory $item)
    {
        $variants = $item->variants();

        return $this->table->of('work-orders.parts.variants', function (TableGrid $table) use ($variants, $workOrder) {
            $table->with($variants)->paginate($this->perPage);

            $table->column('ID', 'id');

            $table->column('sku', function (Column $column) {
                $column->label = 'SKU';

                $column->value = function (Inventory $item) {
                    return $item->getSku();
                };
            });

            $table->column('name', function (Column $column) {
                $column->value = function (Inventory $item) {
                    return link_to_route('maintenance.inventory.show', $item->name, [$item->getKey()]);
                };
            });

            $table->column('category', function (Column $column) {
                $column->value = function (Inventory $item) {
                    return $item->category->trail;
                };
            });

            $table->column('current_stock', function (Column $column) {
                $column->value = function (Inventory $item) {
                    return $item->getTotalStock();
                };
            });

            $table->column('select', function (Column $column) use ($workOrder) {
                $column->value = function (Inventory $item) use ($workOrder) {
                    $route = 'maintenance.work-orders.parts.stocks.index';

                    $params = [$workOrder->getKey(), $item->getKey()];

                    $attributes = [
                        'class' => 'btn btn-default btn-sm',
                    ];

                    return link_to_route($route, 'Select', $params, $attributes);
                };
            });
        });
    }

    /**
     * Returns a new form for taking stock from the specified
     * inventory for the specified work order.
     *
     * @param WorkOrder      $workOrder
     * @param Inventory      $inventory
     * @param InventoryStock $stock
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function formTake(WorkOrder $workOrder, Inventory $inventory, InventoryStock $stock)
    {
        return $this->form->of('work-orders.parts.stocks.take', function (FormGrid $form) use ($workOrder, $inventory, $stock) {
            $form->attributes([
                'method' => 'POST',
                'url'    => route('maintenance.work-orders.parts.stocks.take', [$workOrder->getKey(), $inventory->getKey(), $stock->getKey()]),
            ]);

            $form->submit = 'Save';

            $form->fieldset(function (Fieldset $fieldset) use ($inventory) {
                $metric = $inventory->getMetricSymbol();

                $fieldset
                    ->control('input:text', 'quantity')
                    ->value(0)
                    ->attribute([
                        'placeholder' => "Enter Quantity in $metric",
                    ]);
            });
        });
    }

    /**
     * Returns a new form for putting the stock from the
     * specified work order back into inventory.
     *
     * @param WorkOrder      $workOrder
     * @param Inventory      $inventory
     * @param InventoryStock $stock
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function formPut(WorkOrder $workOrder, Inventory $inventory, InventoryStock $stock)
    {
        return $this->form->of('work-orders.parts.stocks.put', function (FormGrid $form) use ($workOrder, $inventory, $stock) {
            $form->attributes([
                'method' => 'POST',
                'url'    => route('maintenance.work-orders.parts.stocks.put', [$workOrder->getKey(), $inventory->getKey(), $stock->getKey()]),
            ]);

            $form->submit = 'Save';

            $form->fieldset(function (Fieldset $fieldset) use ($inventory, $stock) {
                $metric = $inventory->getMetricSymbol();

                $fieldset
                    ->control('input:text', 'quantity', function (Field $field) {
                        $field->label = 'Return Quantity';
                    })
                    ->value($stock->pivot->quantity)
                    ->attribute([
                        'placeholder' => "Enter Quantity in $metric",
                    ]);
            });
        });
    }
}


<?php

namespace App\Http\Controllers\Inventory;

use App\Http\Controllers\Controller;
use App\Http\Requests\Inventory\InventoryRequest;
use App\Processors\Inventory\InventoryProcessor;

class InventoryController extends Controller
{
    /**
     * @var InventoryProcessor
     */
    protected $processor;

    /**
     * Constructor.
     *
     * @param InventoryProcessor $processor
     */
    public function __construct(InventoryProcessor $processor)
    {
        $this->processor = $processor;
    }

    /**
     * Display all inventory entries (paginated with search functionality).
     *
     * @return \Illuminate\View\View
     */
    public function index()
    {
        return $this->processor->index();
    }

    /**
     * Show the form for creating an inventory item.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        return $this->processor->create();
    }

    /**
     * Creates a new inventory item.
     *
     * @param InventoryRequest $request
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(InventoryRequest $request)
    {
        if ($this->processor->store($request)) {
            flash()->success('Success!', 'Successfully created inventory item.');

            return redirect()->route('maintenance.inventory.index');
        } else {
            flash()->error('Error!', 'There was an issue creating an inventory item. Please try again.');

            return redirect()->route('maintenance.inventory.create');
        }
    }

    /**
     * Display the specified inventory.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function show($id)
    {
        return $this->processor->show($id);
    }

    /**
     * Displays the form for editing the specified inventory item.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function edit($id)
    {
        return $this->processor->edit($id);
    }

    /**
     * Updates the specified inventory item.
     *
     * @param InventoryRequest $request
     * @param int|string       $id
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(InventoryRequest $request, $id)
    {
        if ($this->processor->update($request, $id)) {
            flash()->success('Success!', 'Successfully updated inventory item.');

            return redirect()->route('maintenance.inventory.show', [$id]);
        } else {
            flash()->error('Error!', 'There was an issue updating this inventory item. Please try again.');

            return redirect()->route('maintenance.inventory.edit', [$id]);
        }
    }

    /**
     * Deletes the specified inventory item.
     *
     * @param int|string $id
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($id)
    {
        if ($this->processor->destroy($id)) {
            flash()->success('Success!', 'Successfully deleted inventory item.');

            return redirect()->route('maintenance.inventory.index');
        } else {
            flash()->error('Error!', 'There was an issue deleting this inventory item. Please try again.');

            return redirect()->route('maintenance.inventory.show', [$id]);
        }
    }
}


<?php

namespace App\Http;

class Flash
{
    /**
     * The time in milliseconds of the flash message popup.
     *
     * @var bool|int
     */
    protected $timer = 2000;

    /**
     * Sets the popup timer in milliseconds.
     *
     * @param int|bool $ms
     *
     * @return Flash
     */
    public function setTimer($ms = 2000)
    {
        $this->timer = $ms;

        return $this;
    }

    /**
     * Generates a new session flash message.
     *
     * @param string $title
     * @param string $message
     * @param string $level
     * @param string $key
     */
    public function create($title, $message, $level = 'info', $key = 'flash_message')
    {
        $timer = $this->timer;

        session()->flash($key, compact('title', 'message', 'level', 'info', 'timer'));
    }

    /**
     * Generates an info flash message.
     *
     * @param string $title
     * @param string $message
     */
    public function info($title, $message)
    {
        $this->create($title, $message, 'info');
    }

    /**
     * Generates an success flash message.
     *
     * @param string $title
     * @param string $message
     */
    public function success($title, $message)
    {
        $this->create($title, $message, 'success');
    }

    /**
     * Generates an warning flash message.
     *
     * @param string $title
     * @param string $message
     */
    public function warning($title, $message)
    {
        $this->create($title, $message, 'warning');
    }

    /**
     * Generates an error flash message.
     *
     * @param string $title
     * @param string $message
     */
    public function error($title, $message)
    {
        $this->create($title, $message, 'error');
    }

    /**
     * Generates an overlay flash message.
     *
     * @param string $title
     * @param string $message
     * @param string $level
     */
    public function overlay($title, $message, $level)
    {
        $this->create($title, $message, $level, 'flash_message_overlay');
    }
}


<?php

namespace App\Http\Controllers\WorkOrder;

use App\Exceptions\WorkOrder\ReportExistsException;
use App\Http\Controllers\Controller;
use App\Http\Requests\WorkOrder\ReportRequest;
use App\Processors\WorkOrder\WorkOrderReportProcessor;

class WorkOrderReportController extends Controller
{
    /**
     * @var WorkOrderReportProcessor
     */
    protected $processor;

    /**
     * Constructor.
     *
     * @param WorkOrderReportProcessor $processor
     */
    public function __construct(WorkOrderReportProcessor $processor)
    {
        $this->processor = $processor;
    }

    /**
     * Displays the form for creating a report
     * for the specified work order.
     *
     * @param int|string $workOrderId
     *
     * @return \Illuminate\View\View
     */
    public function create($workOrderId)
    {
        try {
            return $this->processor->create($workOrderId);
        } catch (ReportExistsException $e) {
            flash()->error('Error!', 'This work order already has already been completed.');

            return redirect()->route('maintenance.work-orders.show', [$workOrderId]);
        }
    }

    /**
     * Creates a new report for the specified work order.
     *
     * @param ReportRequest $request
     * @param int|string    $workOrderId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(ReportRequest $request, $workOrderId)
    {
        if ($this->processor->store($request, $workOrderId)) {
            flash()->success('Success!', 'Successfully created work order report.');

            return redirect()->route('maintenance.work-orders.show', [$workOrderId]);
        } else {
            flash()->error('Error!', 'There was an issue creating a work order report. Please try again');

            return redirect()->route('maintenance.work-orders.report.create', [$workOrderId]);
        }
    }

    /**
     * Display the specified resource.
     *
     * @param $workOrderId
     * @param $reportId
     */
    public function show($workOrderId, $reportId)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param $workOrderId
     * @param $reportId
     */
    public function edit($workOrderId, $reportId)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param $workOrderId
     * @param $reportId
     */
    public function update($workOrderId, $reportId)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param $workOrderId
     * @param $reportId
     */
    public function destroy($workOrderId, $reportId)
    {
        //
    }
}


<?php

namespace App\Http\Controllers\Event;

use App\Http\Controllers\Controller as BaseController;
use App\Http\Requests\Event\Request as EventRequest;
use App\Repositories\EventRepository;

abstract class EventableController extends BaseController
{
    /**
     * @var EventRepository
     */
    protected $event;

    /**
     * The eventable's routes.
     *
     * @var array
     */
    protected $routes = [];

    /**
     * Constructor.
     *
     * @param EventRepository $event
     */
    public function __construct(EventRepository $event)
    {
        $this->event = $event->setCalendarId($this->getEventableCalendarId());
    }

    /**
     * Displays all of the specified eventables events.
     *
     * @param int|string $resourceId
     *
     * @return \Illuminate\View\View
     */
    public function index($resourceId)
    {
        $routes = $this->routes;

        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        return view('events.eventables.index', compact('eventable', 'routes'));
    }

    /**
     * Displays the form for creating a new event.
     *
     * @param int|string $resourceId
     *
     * @return \Illuminate\View\View
     */
    public function create($resourceId)
    {
        $routes = $this->routes;

        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        return view('events.eventables.create', compact('eventable', 'routes'));
    }

    /**
     * Creates a new event and attaches it to the specified eventable.
     *
     * @param EventRequest $request
     * @param int|string   $resourceId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(EventRequest $request, $resourceId)
    {
        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        $event = $this->event->create($request);

        if ($event && method_exists($eventable, 'events')) {
            $eventable->events()->attach($event->id);

            $message = 'Successfully created event.';

            return redirect()->route($this->routes['index'], $eventable->id)->withSuccess($message);
        } else {
            $message = 'There was an issue creating an event. Please try again.';

            return redirect()->route($this->routes['create'])->withErrors($message);
        }
    }

    /**
     * Displays the specified event attached to the specified eventable.
     *
     * @param int|string $resourceId
     * @param int|string $eventId
     *
     * @return \Illuminate\View\View
     */
    public function show($resourceId, $eventId)
    {
        $routes = $this->routes;

        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        if (method_exists($eventable, 'events')) {
            $event = $eventable->events()->find($eventId);

            if ($event) {
                $apiObject = $this->event->findApiObject($event->api_id);

                return view('events.eventables.show', compact('routes', 'eventable', 'event', 'apiObject'));
            }
        }

        abort(404);
    }

    /**
     * @param int|string $resourceId
     * @param int|string $eventId
     *
     * @return mixed
     */
    public function edit($resourceId, $eventId)
    {
        $routes = $this->routes;

        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        if (method_exists($eventable, 'events')) {
            $event = $eventable->events()->find($eventId);

            if ($event) {
                $apiObject = $this->event->findApiObject($event->api_id);

                return view('events.eventables.edit', compact('routes', 'eventable', 'event', 'apiObject'));
            }
        }

        abort(404);
    }

    /**
     * Updates the specified event attached to the specified eventable.
     *
     * @param EventRequest $request
     * @param int|string   $resourceId
     * @param int|string   $eventId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(EventRequest $request, $resourceId, $eventId)
    {
        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        $event = $this->event->update($request, $eventId);

        if ($event) {
            $message = 'Successfully updated event.';

            return redirect()->route($this->routes['show'], [$eventable->id, $event->id])->withSuccess($message);
        } else {
            $message = 'There was an issue updating this event. Please try again.';

            return redirect()->route($this->routes['edit'], [$eventable->id])->withErrors($message);
        }
    }

    /**
     * Deletes the specified event attached to the specified eventable.
     *
     * @param int|string $resourceId
     * @param int|string $eventId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($resourceId, $eventId)
    {
        $eventable = $this->getEventableRepository()->model()->findOrFail($resourceId);

        if (method_exists($eventable, 'events')) {
            $event = $eventable->events()->find($eventId);

            if ($event && $this->event->delete($event->id)) {
                $message = 'Successfully deleted event.';

                return redirect()->route($this->routes['index'], $eventable->id)->withSuccess($message);
            } else {
                $message = 'There was an issue deleting this event. Please try again.';

                return redirect()->route($this->routes['show'], $eventable->id, $event->id)->withErrors($message);
            }
        }

        abort(404);
    }

    /**
     * Retrieves the eventable respository.
     *
     * @return \App\Repositories\Repository
     */
    abstract protected function getEventableRepository();

    /**
     * @return string
     */
    abstract protected function getEventableCalendarId();
}


<?php

namespace App\Models\Traits;

use App\Models\Category;

trait HasCategoryTrait
{
    /**
     * The has one category relationship.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function category()
    {
        return $this->hasOne(Category::class, 'id', 'category_id');
    }

    /**
     * Retrieves the revised location attribute.
     *
     * @param int|string $id
     *
     * @return null|string
     */
    public function getRevisedCategoryAttribute($id)
    {
        if ($id) {
            $category = $this->category()->find($id);

            if ($category instanceof Category) {
                return $category->trail;
            }
        }

        return;
    }

    /**
     * Filters results by specified category.
     *
     * @param mixed      $query
     * @param int|string $categoryId
     *
     * @return mixed
     */
    public function scopeCategory($query, $categoryId = null)
    {
        if ($categoryId) {
            // Get descendants and self inventory category nodes
            $categories = Category::find($categoryId)->getDescendantsAndSelf();

            // Perform a sub-query on main query
            $query->where(function ($query) use ($categories) {
                // For each category, apply a orWhere query to the sub-query
                foreach ($categories as $category) {
                    $query->orWhere('category_id', $category->id);
                }
            });
        }

        return $query;
    }
}


<?php

namespace App\Seeders;

use App\Repositories\WorkOrder\StatusRepository;
use App\Services\ConfigService;
use Illuminate\Database\Seeder;

class StatusSeeder extends Seeder
{
    /**
     * @var StatusRepository
     */
    protected $status;

    /**
     * @var ConfigService
     */
    protected $config;

    /**
     * Constructor.
     *
     * @param StatusRepository $status
     * @param ConfigService    $config
     */
    public function __construct(StatusRepository $status, ConfigService $config)
    {
        $this->status = $status;
        $this->config = $config->setPrefix('maintenance');
    }

    /**
     * Runs the seeding operations.
     */
    public function run()
    {
        $statuses = $this->getSeedData();

        foreach ($statuses as $status) {
            $this->status->model()->create($status);
        }
    }

    /**
     * Retrieves the seed data from the maintenance configuration.
     *
     * @return mixed
     */
    private function getSeedData()
    {
        return $this->config->get('seed.statuses');
    }
}


<?php

namespace App\Http\Presenters;

use Orchestra\Contracts\Html\Form\Fieldset;
use Orchestra\Contracts\Html\Form\Grid as FormGrid;

class LoginPresenter extends Presenter
{
    /**
     * Returns a form for the login page.
     *
     * @return \Orchestra\Contracts\Html\Builder
     */
    public function form()
    {
        return $this->form->of('label', function (FormGrid $form) {
            $form->attributes(['url' => route('maintenance.login.index')]);

            $form->submit = 'Sign In';

            $form->fieldset(function (Fieldset $fieldset) {
                $fieldset->control('input:text', 'email')
                    ->label('Email')
                    ->attributes(['placeholder' => 'Enter your Email']);

                $fieldset->control('input:password', 'password')
                    ->label('Password')
                    ->attributes(['placeholder' => 'Enter your Password']);
            });
        });
    }
}


<?php

namespace App\Http\Controllers\Asset;

use App\Http\Controllers\Controller as BaseController;
use App\Http\Requests\Asset\ManualRequest;
use App\Http\Requests\AttachmentUpdateRequest;
use App\Repositories\Asset\ManualRepository;
use App\Repositories\Asset\Repository as AssetRepository;

class ManualController extends BaseController
{
    /**
     * @var AssetRepository
     */
    protected $asset;

    /**
     * Constructor.
     *
     * @param AssetRepository  $asset
     * @param ManualRepository $manual
     */
    public function __construct(AssetRepository $asset, ManualRepository $manual)
    {
        $this->asset = $asset;
        $this->manual = $manual;
    }

    /**
     * Displays all of the specified asset manuals.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function index($id)
    {
        $asset = $this->asset->find($id);

        return view('assets.manuals.index', compact('asset'));
    }

    /**
     * Displays the asset manual upload form.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function create($id)
    {
        $asset = $this->asset->find($id);

        return view('assets.manuals.create', compact('asset'));
    }

    /**
     * Uploads manuals and attaches them to the specified asset.
     *
     * @param ManualRequest $request
     * @param int|string    $id
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(ManualRequest $request, $id)
    {
        $asset = $this->asset->find($id);

        $attachments = $this->manual->upload($request, $asset, $asset->manuals());

        if ($attachments) {
            $message = 'Successfully uploaded files.';

            return redirect()->route('maintenance.assets.manuals.index', [$asset->id])->withSuccess($message);
        } else {
            $message = 'There was an issue uploading the files you selected. Please try again.';

            return redirect()->route('maintenance.assets.manuals.create', [$id])->withErrors($message);
        }
    }

    /**
     * Displays the asset manual.
     *
     * @param int|string $id
     * @param int|string $manualId
     *
     * @return \Illuminate\View\View
     */
    public function show($id, $manualId)
    {
        $asset = $this->asset->find($id);

        $manual = $asset->manuals()->find($manualId);

        if ($manual) {
            return view('assets.manuals.show', compact('asset', 'manual'));
        }

        abort(404);
    }

    /**
     * Displays the form for editing an uploaded manual.
     *
     * @param int|string $id
     * @param int|string $manualId
     *
     * @return \Illuminate\View\View
     */
    public function edit($id, $manualId)
    {
        $asset = $this->asset->find($id);

        $manual = $asset->manuals()->find($manualId);

        if ($manual) {
            return view('assets.manuals.edit', compact('asset', 'manual'));
        }

        abort(404);
    }

    /**
     * Updates the specified asset manual upload.
     *
     * @param AttachmentUpdateRequest $request
     * @param int|string              $id
     * @param int|string              $manualId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(AttachmentUpdateRequest $request, $id, $manualId)
    {
        $asset = $this->asset->find($id);

        $manual = $this->manual->update($request, $asset->manuals(), $manualId);

        if ($manual) {
            $message = 'Successfully updated manual.';

            return redirect()->route('maintenance.assets.manuals.show', [$asset->id, $manual->id])->withSuccess($message);
        } else {
            $message = 'There was an issue updating this manual. Please try again.';

            return redirect()->route('maintenance.assets.manuals.show', [$id, $manualId])->withErrors($message);
        }
    }

    /**
     * Processes deleting an attachment record and the file itself.
     *
     * @param int|string $id
     * @param int|string $manualId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($id, $manualId)
    {
        $asset = $this->asset->find($id);

        $manual = $asset->manuals()->find($manualId);

        if ($manual && $manual->delete()) {
            $message = 'Successfully deleted manual.';

            return redirect()->route('maintenance.assets.manuals.index', [$asset->id])->withSuccess($message);
        } else {
            $message = 'There was an issue deleting this manual. Please try again.';

            return redirect()->route('maintenance.assets.manuals.show', [$asset->id, $manual->id])->withErrors($message);
        }
    }

    /**
     * Prompts the user to download the specified uploaded file.
     *
     * @param int|string $id
     * @param int|string $manualId
     *
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function download($id, $manualId)
    {
        $asset = $this->asset->find($id);

        $manual = $asset->manuals()->find($manualId);

        if ($manual) {
            return response()->download($manual->download_path);
        }

        abort(404);
    }
}


<?php

namespace App\Http\Controllers\Asset;

use App\Http\Controllers\Controller as BaseController;
use App\Repositories\Asset\Repository as AssetRepository;

class WorkOrderController extends BaseController
{
    /**
     * @var AssetRepository
     */
    protected $asset;

    /**
     * Constructor.
     *
     * @param AssetRepository $asset
     */
    public function __construct(AssetRepository $asset)
    {
        $this->asset = $asset;
    }

    /**
     * Displays all work orders attached to the specified asset.
     *
     * @param int|string $assetId
     *
     * @return \Illuminate\View\View
     */
    public function index($assetId)
    {
        $asset = $this->asset->find($assetId);

        return view('assets.work-orders.index', compact('asset'));
    }

    /**
     * Displays all work orders available to be attached to the specified asset.
     *
     * @param int|string $assetId
     *
     * @return \Illuminate\View\View
     */
    public function attach($assetId)
    {
        $asset = $this->asset->find($assetId);

        return view('assets.work-orders.attach.index', compact('asset'));
    }

    /**
     * Attaches the specified work order to the specified asset.
     *
     * @param int|string $assetId
     * @param int|string $workOrderId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store($assetId, $workOrderId)
    {
        if ($this->asset->attachWorkOrder($assetId, $workOrderId)) {
            $message = 'Successfully attached work order.';

            return redirect()->route('maintenance.assets.work-orders.index', [$assetId])->withSuccess($message);
        } else {
            $message = 'There was an issue attaching this work order. Please try again.';

            return redirect()->route('maintenance.assets.work-orders.attach.index', [$assetId])->withErrors($message);
        }
    }

    /**
     * Removes the specified work order from the specified asset.
     *
     * @param int|string $assetId
     * @param int|string $workOrderId
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function remove($assetId, $workOrderId)
    {
        if ($this->asset->detachWorkOrder($assetId, $workOrderId)) {
            $message = 'Successfully detached work order.';

            return redirect()->route('maintenance.assets.work-orders.index', [$assetId])->withSuccess($message);
        } else {
            $message = 'There was an issue detaching this work order. Please try again.';

            return redirect()->route('maintenance.assets.work-orders.index', [$assetId])->withErrors($message);
        }
    }
}


<?php

namespace App\Http\Controllers\WorkRequest;

use App\Http\Controllers\Controller as BaseController;
use App\Services\UpdateService;
use App\Services\WorkRequestService;
use App\Validators\UpdateValidator;

class UpdateController extends BaseController
{
    /**
     * @var UpdateService
     */
    protected $update;

    /**
     * @var WorkRequestService
     */
    protected $workRequest;

    /**
     * @var UpdateValidator
     */
    protected $updateValidator;

    /**
     * @param UpdateService      $update
     * @param WorkRequestService $workRequest
     * @param UpdateValidator    $updateValidator
     */
    public function __construct(UpdateService $update, WorkRequestService $workRequest, UpdateValidator $updateValidator)
    {
        $this->update = $update;
        $this->workRequest = $workRequest;
        $this->updateValidator = $updateValidator;
    }

    /**
     * Creates a new work order customer update.
     *
     * @param int $workRequestId
     *
     * @return mixed
     */
    public function store($workRequestId)
    {
        if ($this->updateValidator->passes()) {
            $workRequest = $this->workRequest->find($workRequestId);

            $update = $this->update->setInput($this->inputAll())->create();

            $this->workRequest->saveUpdate($workRequest, $update);

            $this->message = 'Successfully added update';
            $this->messageType = 'success';
            $this->redirect = routeBack('maintenance.work-requests.show', [$workRequest->id]);
        } else {
            $this->errors = $this->updateValidator->getErrors();
            $this->redirect = routeBack('maintenance.work-requests.show', [$workRequestId]);
        }

        return $this->response();
    }

    /**
     * Processes deleting a work order update.
     *
     * @param $workRequestId
     * @param $updateId
     *
     * @return \Illuminate\Http\JsonResponse|mixed
     */
    public function destroy($workRequestId, $updateId)
    {
        $workRequest = $this->workRequest->find($workRequestId);

        if ($this->update->destroy($updateId)) {
            $this->message = 'Successfully deleted update';
            $this->messageType = 'success';
            $this->redirect = route('maintenance.work-requests.show', [$workRequest->id, '#tab_updates']);
        } else {
            $this->message = 'There was an error trying to delete this update. Please try again.';
            $this->messageType = 'danger';
            $this->redirect = route('maintenance.work-requests.show', [$workRequest->id, '#tab_updates']);
        }

        return $this->response();
    }
}


<?php

namespace App\Processors\WorkOrder;

use App\Http\Presenters\WorkOrder\WorkOrderPartStockPresenter;
use App\Http\Requests\WorkOrder\PartReturnRequest;
use App\Http\Requests\WorkOrder\PartTakeRequest;
use App\Jobs\WorkOrder\Part\Put;
use App\Jobs\WorkOrder\Part\Take;
use App\Models\Inventory;
use App\Models\WorkOrder;
use App\Processors\Processor;

class WorkOrderPartStockProcessor extends Processor
{
    /**
     * @var WorkOrder
     */
    protected $workOrder;

    /**
     * @var Inventory
     */
    protected $inventory;

    /**
     * Constructor.
     *
     * @param WorkOrder                   $workOrder
     * @param Inventory                   $inventory
     * @param WorkOrderPartStockPresenter $presenter
     */
    public function __construct(WorkOrder $workOrder, Inventory $inventory, WorkOrderPartStockPresenter $presenter)
    {
        $this->workOrder = $workOrder;
        $this->inventory = $inventory;
        $this->presenter = $presenter;
    }

    /**
     * Displays all stocks and variants available for selection.
     *
     * @param int|string $workOrderId
     * @param int|string $itemId
     *
     * @return \Illuminate\View\View
     */
    public function index($workOrderId, $itemId)
    {
        $workOrder = $this->workOrder->findOrFail($workOrderId);

        $item = $this->inventory->findOrFail($itemId);

        $stocks = $this->presenter->table($workOrder, $item);

        $variants = $this->presenter->tableVariants($workOrder, $item);

        return view('work-orders.parts.stocks.index', compact('stocks', 'variants'));
    }

    /**
     * Displays the form for taking inventory for the specified work order.
     *
     * @param int|string $workOrderId
     * @param int|string $itemId
     * @param int|string $stockId
     *
     * @return \Illuminate\View\View
     */
    public function getTake($workOrderId, $itemId, $stockId)
    {
        $workOrder = $this->workOrder->findOrFail($workOrderId);

        $item = $this->inventory->findOrFail($itemId);

        $stock = $item->stocks()->findOrFail($stockId);

        $form = $this->presenter->formTake($workOrder, $item, $stock);

        return view('work-orders.parts.stocks.take', compact('workOrder', 'item', 'stock', 'form'));
    }

    /**
     * Processes taking inventory for the specified work order.
     *
     * @param PartTakeRequest $request
     * @param int|string      $workOrderId
     * @param int|string      $itemId
     * @param int|string      $stockId
     *
     * @throws \Stevebauman\Inventory\Exceptions\InvalidQuantityException
     * @throws \Stevebauman\Inventory\Exceptions\NotEnoughStockException
     *
     * @return bool
     */
    public function postTake(PartTakeRequest $request, $workOrderId, $itemId, $stockId)
    {
        $workOrder = $this->workOrder->findOrFail($workOrderId);

        $item = $this->inventory->findOrFail($itemId);

        $stock = $item->stocks()->findOrFail($stockId);

        return $this->dispatch(new Take($request, $workOrder, $stock));
    }

    /**
     * Displays the form for putting inventory from the
     * work order back into the specified stock.
     *
     * @param int|string $workOrderId
     * @param int|string $itemId
     * @param int|string $stockId
     *
     * @return \Illuminate\View\View
     */
    public function getPut($workOrderId, $itemId, $stockId)
    {
        $workOrder = $this->workOrder->findOrFail($workOrderId);

        $item = $this->inventory->findOrFail($itemId);

        $stock = $workOrder->parts()->findOrFail($stockId);

        $form = $this->presenter->formPut($workOrder, $item, $stock);

        return view('work-orders.parts.stocks.put', compact('workOrder', 'item', 'stock', 'form'));
    }

    /**
     * Processes returning stock from the work order back into the specified inventory.
     *
     * @param PartReturnRequest $request
     * @param int|string        $workOrderId
     * @param int|string        $itemId
     * @param int|string        $stockId
     *
     * @throws \Stevebauman\Inventory\Exceptions\InvalidQuantityException
     *
     * @return bool
     */
    public function postPut(PartReturnRequest $request, $workOrderId, $itemId, $stockId)
    {
        $workOrder = $this->workOrder->findOrFail($workOrderId);

        // Even though the inventory item isn't necessary here, we'll
        // find it anyway so we can check for the requests validity
        // and ensure the specified stock is actually attached to
        // the one requested.
        $item = $this->inventory->findOrFail($itemId);

        $item->stocks()->findOrFail($stockId);

        $stock = $workOrder->parts()->findOrFail($stockId);

        return $this->dispatch(new Put($request, $workOrder, $stock));
    }
}


<?php

namespace App\Processors\WorkRequest;

use App\Http\Presenters\WorkRequest\WorkRequestPresenter;
use App\Http\Requests\WorkRequest as WorkHttpRequest;
use App\Jobs\WorkOrder\StoreFromWorkRequest;
use App\Jobs\WorkRequest\Store;
use App\Jobs\WorkRequest\Update;
use App\Models\WorkRequest;
use App\Processors\Processor;

class WorkRequestProcessor extends Processor
{
    /**
     * @var WorkRequest
     */
    protected $workRequest;

    /**
     * @var WorkRequestPresenter
     */
    protected $presenter;

    /**
     * Constructor.
     *
     * @param WorkRequest          $workRequest
     * @param WorkRequestPresenter $presenter
     */
    public function __construct(WorkRequest $workRequest, WorkRequestPresenter $presenter)
    {
        $this->workRequest = $workRequest;
        $this->presenter = $presenter;
    }

    /**
     * Displays all work requests.
     *
     * @return \Illuminate\View\View
     */
    public function index()
    {
        $workRequests = $this->presenter->table($this->workRequest);

        $navbar = $this->presenter->navbar();

        return view('work-requests.index', compact('workRequests', 'navbar'));
    }

    /**
     * Displays the form for creating a new work request.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        $form = $this->presenter->form($this->workRequest);

        return view('work-requests.create', compact('form'));
    }

    /**
     * Creates a work request.
     *
     * @param WorkHttpRequest $request
     *
     * @return bool
     */
    public function store(WorkHttpRequest $request)
    {
        $workRequest = $this->workRequest->newInstance();

        if ($this->dispatch(new Store($request, $workRequest))) {
            $this->dispatch(new StoreFromWorkRequest($workRequest));

            return true;
        }

        return false;
    }

    /**
     * Displays the specified work request.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function show($id)
    {
        $workRequest = $this->workRequest->findOrFail($id);

        return view('work-requests.show', compact('workRequest'));
    }

    /**
     * Displays the form for editing the specified work request.
     *
     * @param int|string $id
     *
     * @return \Illuminate\View\View
     */
    public function edit($id)
    {
        $workRequest = $this->workRequest->findOrFail($id);

        $form = $this->presenter->form($workRequest);

        return view('work-requests.edit', compact('form'));
    }

    /**
     * Updates the specified work request.
     *
     * @param WorkHttpRequest $request
     * @param int|string      $id
     *
     * @return bool
     */
    public function update(WorkHttpRequest $request, $id)
    {
        $workRequest = $this->workRequest->findOrFail($id);

        return $this->dispatch(new Update($request, $workRequest));
    }

    /**
     * Deletes the specified work request.
     *
     * @param int|string $id
     *
     * @return bool
     */
    public function destroy($id)
    {
        $workRequest = $this->workRequest->findOrFail($id);

        return $workRequest->delete();
    }
}