refactor: move absence logic to service

This commit is contained in:
Miguel Nogueira 2022-04-03 20:09:33 +01:00
parent 69eecca7a8
commit 7bf5c1fbe1
2 changed files with 135 additions and 39 deletions

View File

@ -6,7 +6,9 @@ use App\Absence;
use App\Exceptions\AbsenceNotActionableException; use App\Exceptions\AbsenceNotActionableException;
use App\Http\Requests\StoreAbsenceRequest; use App\Http\Requests\StoreAbsenceRequest;
use App\Http\Requests\UpdateAbsenceRequest; use App\Http\Requests\UpdateAbsenceRequest;
use App\Services\AbsenceService;
use App\User; use App\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -15,28 +17,12 @@ use Illuminate\Support\Facades\Auth;
class AbsenceController extends Controller class AbsenceController extends Controller
{ {
/** private AbsenceService $absenceService;
* Determines whether someone already has an active leave of absence request
*
* @param User $user The user to check
* @return bool Their status
*/
private function hasActiveRequest(Authenticatable $user): bool {
$absences = Absence::where('requesterID', $user->id)->get(); public function __construct (AbsenceService $absenceService) {
foreach ($absences as $absence) { $this->absenceService = $absenceService;
// Or we could adjust the query (using a model scope) to only return valid absences;
// If there are any, refuse to store more, but this approach also works
// A model scope that only returns cancelled, declined and ended absences could also be implemented for future use
if (in_array($absence->getRawOriginal('status'), ['PENDING', 'APPROVED']))
{
return true;
}
}
return false;
} }
/** /**
@ -57,7 +43,7 @@ class AbsenceController extends Controller
* Display a listing of absences belonging to the current user. * Display a listing of absences belonging to the current user.
* *
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws AuthorizationException
*/ */
public function showUserAbsences() public function showUserAbsences()
{ {
@ -76,14 +62,14 @@ class AbsenceController extends Controller
/** /**
* Show the form for creating a new absence request. * Show the form for creating a new absence request.
* *
* @return \Illuminate\Http\Response * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/ */
public function create() public function create()
{ {
$this->authorize('create', Absence::class); $this->authorize('create', Absence::class);
return view('dashboard.absences.create') return view('dashboard.absences.create')
->with('activeRequest', $this->hasActiveRequest(Auth::user())); ->with('activeRequest', $this->absenceService->hasActiveRequest(Auth::user()));
} }
/** /**
@ -102,15 +88,7 @@ class AbsenceController extends Controller
->with('error', __('You already have an active request. Cancel it or let it expire first.')); ->with('error', __('You already have an active request. Cancel it or let it expire first.'));
} }
$absence = $this->absenceService->createAbsence(Auth::user(), $request);
$absence = Absence::create([
'requesterID' => Auth::user()->id,
'start' => $request->start_date,
'predicted_end' => $request->predicted_end,
'available_assist' => $request->available_assist == "on",
'reason' => $request->reason,
'status' => 'PENDING',
]);
return redirect() return redirect()
->to(route('absences.show', ['absence' => $absence->id])) ->to(route('absences.show', ['absence' => $absence->id]))
@ -120,7 +98,8 @@ class AbsenceController extends Controller
/** /**
* Display the specified absence request. * Display the specified absence request.
* *
* @param \App\Absence $absence * @param \App\Absence $absence
* @throws AuthorizationException
*/ */
public function show(Absence $absence) public function show(Absence $absence)
{ {
@ -138,7 +117,7 @@ class AbsenceController extends Controller
* *
* @param Absence $absence * @param Absence $absence
* @return RedirectResponse * @return RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws AuthorizationException
*/ */
public function approveAbsence(Absence $absence): RedirectResponse public function approveAbsence(Absence $absence): RedirectResponse
{ {
@ -146,7 +125,7 @@ class AbsenceController extends Controller
try try
{ {
$absence->setApproved(); $this->absenceService->approveAbsence($absence);
} }
catch (AbsenceNotActionableException $notActionableException) catch (AbsenceNotActionableException $notActionableException)
{ {
@ -166,7 +145,7 @@ class AbsenceController extends Controller
* *
* @param Absence $absence * @param Absence $absence
* @return RedirectResponse * @return RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws AuthorizationException
*/ */
public function declineAbsence(Absence $absence): RedirectResponse public function declineAbsence(Absence $absence): RedirectResponse
{ {
@ -174,7 +153,7 @@ class AbsenceController extends Controller
try try
{ {
$absence->setDeclined(); $this->absenceService->declineAbsence($absence);
} catch (AbsenceNotActionableException $notActionableException) } catch (AbsenceNotActionableException $notActionableException)
{ {
return redirect() return redirect()
@ -193,7 +172,7 @@ class AbsenceController extends Controller
* *
* @param Absence $absence * @param Absence $absence
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws AuthorizationException
*/ */
public function cancelAbsence(Absence $absence): \Illuminate\Http\RedirectResponse public function cancelAbsence(Absence $absence): \Illuminate\Http\RedirectResponse
{ {
@ -201,7 +180,7 @@ class AbsenceController extends Controller
try try
{ {
$absence->setCancelled(); $this->absenceService->cancelAbsence($absence);
} }
catch (AbsenceNotActionableException $notActionableException) catch (AbsenceNotActionableException $notActionableException)
{ {
@ -225,7 +204,7 @@ class AbsenceController extends Controller
{ {
$this->authorize('delete', $absence); $this->authorize('delete', $absence);
if ($absence->delete()) { if ($this->absenceService->removeAbsence($absence)) {
return redirect() return redirect()
->to(route('absences.index')) ->to(route('absences.index'))
->with('success', __('Absence request deleted.')); ->with('success', __('Absence request deleted.'));

View File

@ -0,0 +1,117 @@
<?php
namespace App\Services;
use App\Absence;
use App\Exceptions\AbsenceNotActionableException;
use App\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class AbsenceService
{
/**
* Determines whether someone already has an active leave of absence request
*
* @param User $user The user to check
* @return bool Their status
*/
public function hasActiveRequest(Authenticatable $user): bool {
$absences = Absence::where('requesterID', $user->id)->get();
foreach ($absences as $absence) {
// Or we could adjust the query (using a model scope) to only return valid absences;
// If there are any, refuse to store more, but this approach also works
// A model scope that only returns cancelled, declined and ended absences could also be implemented for future use
if (in_array($absence->getRawOriginal('status'), ['PENDING', 'APPROVED']))
{
return true;
}
}
return false;
}
public function createAbsence(Authenticatable $requester, Request $request)
{
$absence = Absence::create([
'requesterID' => $user->id,
'start' => $request->start_date,
'predicted_end' => $request->predicted_end,
'available_assist' => $request->available_assist == "on",
'reason' => $request->reason,
'status' => 'PENDING',
]);
Log::info('Processing new leave of absence request.', [
'userid' => $user->email,
'absenceid' => $absence->id,
'reason' => $request->reason
]);
return $absence;
}
/**
* Sets an absence as Approved.
*
* @param Absence $absence The absence to approve.
* @return Absence The approved absence.
* @throws AbsenceNotActionableException
*/
public function approveAbsence(Absence $absence): Absence
{
return $absence->setApproved();
}
/**
* Sets an absence as Declined.
*
* @param Absence $absence The absence to decline.
* @return Absence The declined absence.
* @throws AbsenceNotActionableException
*/
public function declineAbsence(Absence $absence): Absence
{
return $absence->setDeclined();
}
/**
* Sets an absence as Cancelled.
*
* @param Absence $absence The absence to cancel.
* @return Absence The cancelled absence.
* @throws AbsenceNotActionableException
*/
public function cancelAbsence(Absence $absence)
{
return $absence->setCancelled();
}
/**
* Removes an absence
*
* @param Absence $absence The absence to remove.
* @return bool Whether the absence was removed.
*/
public function removeAbsence(Absence $absence): bool
{
return $absence->delete();
}
}