- actions and notifications refactor (#88)

* wip

* fix

* fix

* fix

* add test

* fix

* wip

* fix

* fix translations

Co-authored-by: EwelinaLasowy <ewelina.lasowy@blumilk.pl>
This commit is contained in:
Adrian Hopek
2022-03-21 15:29:20 +01:00
committed by GitHub
parent d8ac2bd61f
commit 95f5ed44d6
47 changed files with 537 additions and 1014 deletions

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\VacationRequestStateManager;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class AcceptAsAdministrativeAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
protected ApproveAction $approveAction,
) {}
public function execute(VacationRequest $vacationRequest, User $user): void
{
$this->stateManager->acceptAsAdministrative($vacationRequest, $user);
$this->approveAction->execute($vacationRequest);
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class AcceptAsTechnicalAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
protected VacationTypeConfigRetriever $configRetriever,
protected WaitForAdminApprovalAction $waitForAdminApprovalAction,
protected ApproveAction $approveAction,
) {}
public function execute(VacationRequest $vacationRequest, User $user): void
{
$this->stateManager->acceptAsTechnical($vacationRequest, $user);
if ($this->configRetriever->needsAdministrativeApproval($vacationRequest->type)) {
$this->waitForAdminApprovalAction->execute($vacationRequest);
return;
}
$this->approveAction->execute($vacationRequest);
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Infrastructure\Jobs\SendVacationRequestDaysToGoogleCalendar;
class ApproveAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
) {}
public function execute(VacationRequest $vacationRequest, ?User $user = null): void
{
$this->stateManager->approve($vacationRequest, $user);
SendVacationRequestDaysToGoogleCalendar::dispatch($vacationRequest);
$this->notify($vacationRequest);
}
protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();
foreach ($users as $user) {
$user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $user));
}
$vacationRequest->user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $vacationRequest->user));
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Infrastructure\Jobs\ClearVacationRequestDaysInGoogleCalendar;
class CancelAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
) {}
public function execute(VacationRequest $vacationRequest, User $user): void
{
$this->stateManager->cancel($vacationRequest, $user);
ClearVacationRequestDaysInGoogleCalendar::dispatch($vacationRequest);
$this->notify($vacationRequest);
}
protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();
foreach ($users as $user) {
$user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $user));
}
$vacationRequest->user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $vacationRequest->user));
}
}

View File

@@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Illuminate\Validation\ValidationException;
use Toby\Domain\Notifications\VacationRequestCreatedNotification;
use Toby\Domain\VacationDaysCalculator;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Domain\Validation\VacationRequestValidator;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class CreateAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
protected VacationRequestValidator $vacationRequestValidator,
protected VacationTypeConfigRetriever $configRetriever,
protected VacationDaysCalculator $vacationDaysCalculator,
protected WaitForTechApprovalAction $waitForTechApprovalAction,
protected WaitForAdminApprovalAction $waitForAdminApprovalAction,
protected ApproveAction $approveAction,
) {}
/**
* @throws ValidationException
*/
public function execute(array $data, User $creator): VacationRequest
{
$vacationRequest = $this->createVacationRequest($data, $creator);
$this->handleCreatedVacationRequest($vacationRequest);
$this->notify($vacationRequest);
return $vacationRequest;
}
/**
* @throws ValidationException
*/
protected function createVacationRequest(array $data, User $creator): VacationRequest
{
/** @var VacationRequest $vacationRequest */
$vacationRequest = $creator->createdVacationRequests()->make($data);
$this->vacationRequestValidator->validate($vacationRequest);
$vacationRequest->save();
$days = $this->vacationDaysCalculator->calculateDays(
$vacationRequest->yearPeriod,
$vacationRequest->from,
$vacationRequest->to,
);
foreach ($days as $day) {
$vacationRequest->vacations()->create([
"date" => $day,
"user_id" => $vacationRequest->user->id,
"year_period_id" => $vacationRequest->yearPeriod->id,
]);
}
$this->stateManager->markAsCreated($vacationRequest);
return $vacationRequest;
}
protected function handleCreatedVacationRequest(VacationRequest $vacationRequest): void
{
if ($vacationRequest->hasFlowSkipped()) {
$this->approveAction->execute($vacationRequest);
return;
}
if ($this->configRetriever->needsTechnicalApproval($vacationRequest->type)) {
$this->waitForTechApprovalAction->execute($vacationRequest);
return;
}
if ($this->configRetriever->needsAdministrativeApproval($vacationRequest->type)) {
$this->waitForAdminApprovalAction->execute($vacationRequest);
return;
}
$this->stateManager->approve($vacationRequest);
}
protected function notify(VacationRequest $vacationRequest): void
{
$vacationRequest->user->notify(new VacationRequestCreatedNotification($vacationRequest));
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\VacationRequestStatusChangedNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class RejectAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
) {}
public function execute(VacationRequest $vacationRequest, User $user): void
{
$this->stateManager->reject($vacationRequest, $user);
$this->notify($vacationRequest);
}
protected function notify(VacationRequest $vacationRequest): void
{
$users = User::query()
->where("id", "!=", $vacationRequest->user->id)
->whereIn("role", [Role::TechnicalApprover, Role::AdministrativeApprover, Role::Administrator])
->get();
foreach ($users as $user) {
$user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $user));
}
$vacationRequest->user->notify(new VacationRequestStatusChangedNotification($vacationRequest, $vacationRequest->user));
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\VacationRequestWaitsForApprovalNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class WaitForAdminApprovalAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
protected VacationTypeConfigRetriever $configRetriever,
protected ApproveAction $approveAction,
) {}
public function execute(VacationRequest $vacationRequest): void
{
$this->stateManager->waitForAdministrative($vacationRequest);
$this->waitForAdminApprovers($vacationRequest);
}
protected function waitForAdminApprovers(VacationRequest $vacationRequest): void
{
$users = User::query()
->whereIn("role", [Role::AdministrativeApprover, Role::Administrator])
->get();
foreach ($users as $user) {
$user->notify(new VacationRequestWaitsForApprovalNotification($vacationRequest, $user));
}
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Toby\Domain\Actions\VacationRequest;
use Toby\Domain\Enums\Role;
use Toby\Domain\Notifications\VacationRequestWaitsForApprovalNotification;
use Toby\Domain\VacationRequestStateManager;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
class WaitForTechApprovalAction
{
public function __construct(
protected VacationRequestStateManager $stateManager,
protected VacationTypeConfigRetriever $configRetriever,
protected ApproveAction $approveAction,
) {}
public function execute(VacationRequest $vacationRequest): void
{
$this->stateManager->waitForTechnical($vacationRequest);
$this->notifyTechApprovers($vacationRequest);
}
protected function notifyTechApprovers(VacationRequest $vacationRequest): void
{
$users = User::query()
->whereIn("role", [Role::TechnicalApprover, Role::Administrator])
->get();
foreach ($users as $user) {
$user->notify(new VacationRequestWaitsForApprovalNotification($vacationRequest, $user));
}
}
}