feat: add loa requests

This commit adds a feature that allows users to request periods of inactivity from their managers. This is effectively known as a leave of absence.

The commit also introduces new permissions and migrations, therefore, you'll need to adapt your database according to these changes.
This commit is contained in:
2022-02-24 00:56:46 +00:00
parent f61a287c78
commit e567094f40
16 changed files with 607 additions and 63 deletions

View File

@@ -2,6 +2,8 @@
namespace App;
use App\Exceptions\AbsenceNotActionableException;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -25,4 +27,99 @@ class Absence extends Model
{
return $this->belongsTo('App\User', 'requesterID', 'id');
}
/**
* Determines whether this model can be setApproved(), setDeclined() or setCancelled()
*
* @param bool $toCancel Switch the check to cancellability check
* @return bool
*/
public function isActionable(bool $toCancel = false): bool
{
if ($toCancel)
{
return in_array($this->getRawOriginal('status'), ['PENDING', 'APPROVED']);
}
return $this->getRawOriginal('status') == 'PENDING';
}
/**
* Sets the Absence's status as approved
*
* @return Absence
* @throws AbsenceNotActionableException
*/
public function setApproved(): Absence
{
if ($this->isActionable())
{
return tap($this)->update([
'status' => 'APPROVED'
]);
}
throw new AbsenceNotActionableException('This absence is not actionable!');
}
/**
* Sets the absence's status as declined
*
* @return Absence
* @throws AbsenceNotActionableException
*/
public function setDeclined(): Absence
{
if ($this->isActionable()) {
return tap($this)->update([
'status' => 'DECLINED'
]);
}
throw new AbsenceNotActionableException('This absence is not actionable!');
}
/**
* Sets the absence's status as cancelled
*
* @return Absence
* @throws AbsenceNotActionableException Thrown when the switch to this status would be invalid
*/
public function setCancelled(): Absence
{
if ($this->isActionable(true)) {
return tap($this)->update([
'status' => 'CANCELLED'
]);
}
throw new AbsenceNotActionableException('This absence is not actionable!');
}
/**
* Sets the absence's status as ended
*
* @return Absence
*/
public function setEnded(): Absence
{
return tap($this)->update([
'status' => 'ENDED'
]);
}
// Look out when retrieving this value;
//If you need the unaltered version of it, either adapt to its formatting or call getRawOriginal()
protected function status(): Attribute {
return Attribute::make(
get: fn($value) => ucfirst(strtolower($value))
);
}
}