Commit 97de72c2 authored by Jacob Priddy's avatar Jacob Priddy 👌
Browse files

Override usecases and add reason for overrides

parent c9728c92
......@@ -53,14 +53,17 @@ use Source\UseCases\DoorGroup\AddDoorToGroup\AddDoorToGroupUseCaseServiceProvide
use Source\UseCases\GroupUser\AddUserToGroup\AddUserToGroupUseCaseServiceProvider;
use Source\UseCases\Schedules\ScheduleCreate\ScheduleCreateUseCaseServiceProvider;
use Source\UseCases\Schedules\ScheduleUpdate\ScheduleUpdateUseCaseServiceProvider;
use Source\UseCases\Overrides\OverrideCreate\OverrideCreateUseCaseServiceProvider;
use Source\UseCases\Doors\GenerateDoorToken\GenerateDoorTokenUseCaseServiceProvider;
use Source\UseCases\Entries\GetEntriesForDoor\GetEntriesForDoorUseCaseServiceProvider;
use Source\UseCases\Entries\GetEntriesForUser\GetEntriesForUserUseCaseServiceProvider;
use Source\UseCases\Overrides\OverridesForDoor\OverridesForDoorUseCaseServiceProvider;
use Source\UseCases\Attempts\GetAttemptsForDoor\GetAttemptsForDoorUseCaseServiceProvider;
use Source\UseCases\DoorGroup\RemoveDoorFromGroup\RemoveDoorFromGroupUseCaseServiceProvider;
use Source\UseCases\GroupSchedule\SchedulesForGroup\SchedulesForGroupUseCaseServiceProvider;
use Source\UseCases\GroupUser\RemoveUserFromGroup\RemoveUserFromGroupUseCaseServiceProvider;
use Source\UseCases\Entries\GetEntriesForDateRange\GetEntriesForDateRangeUseCaseServiceProvider;
use Source\UseCases\Overrides\OverridesForDateRange\OverridesForDateRangeUseCaseServiceProvider;
use Source\UseCases\Attempts\GetAttemptCountForDoor\GetAttemptCountForDoorUseCaseServiceProvider;
use Source\UseCases\Entries\GetEntriesForDoorAndUser\GetEntriesForDoorAndUserUseCaseServiceProvider;
use Source\UseCases\GroupSchedule\ActiveSchedulesForGroup\ActiveSchedulesForGroupUseCaseServiceProvider;
......@@ -165,6 +168,11 @@ class AppServiceProvider extends ServiceProvider
// DoorUser
DoorUserGroupMapUseCaseServiceProvider::class,
// Overrides
OverrideCreateUseCaseServiceProvider::class,
OverridesForDoorUseCaseServiceProvider::class,
OverridesForDateRangeUseCaseServiceProvider::class,
];
/**
......
......@@ -15,6 +15,7 @@ class CreateOverridesTable extends Migration
{
Schema::create('overrides', static function (Blueprint $table) {
$table->id();
$table->string('reason');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('door_id');
/*
......
......@@ -10,6 +10,7 @@ class Override
{
public const TYPE_OPEN = 0;
public const TYPE_LOCKED = 1;
public const TYPE_NORMAL = 2;
protected int $id;
......@@ -39,8 +40,11 @@ class Override
*/
protected ?Carbon $updatedAt;
protected string $reason;
public function __construct(
int $id,
string $reason,
int $userId,
int $doorId,
int $type,
......@@ -49,7 +53,7 @@ class Override
?Carbon $createdAt = null,
?Carbon $updatedAt = null
) {
if ($type > self::TYPE_LOCKED || $type < self::TYPE_OPEN) {
if ($type > self::TYPE_NORMAL || $type < self::TYPE_OPEN) {
throw new InvalidArgumentException('Type not valid override type.');
}
......@@ -61,6 +65,7 @@ class Override
$this->end = $end;
$this->createdAt = $createdAt;
$this->updatedAt = $updatedAt;
$this->reason = $reason;
}
/**
......@@ -71,6 +76,14 @@ class Override
return $this->id;
}
/**
* @return string
*/
public function getReason(): string
{
return $this->reason;
}
/**
* @return int
*/
......
......@@ -20,6 +20,7 @@ class DatabaseOverridesRepository implements OverridesRepository
{
return new Override(
$override->getAttribute('id'),
$override->getAttribute('reason'),
$override->getAttribute('user_id'),
$override->getAttribute('door_id'),
$override->getAttribute('type'),
......@@ -93,6 +94,7 @@ class DatabaseOverridesRepository implements OverridesRepository
$o->setAttribute('type', $override->getType());
$o->setAttribute('start', $override->getStart());
$o->setAttribute('end', $override->getEnd());
$o->setAttribute('reason', $override->getReason());
if ($override->getCreatedAt()) {
$o->setCreatedAt($override->getCreatedAt());
......
......@@ -15,6 +15,7 @@ class LocalOverridesRepository extends InMemoryOverridesRepository
$now = Carbon::now();
$this->addOverride(new Override(
1,
'Override amazon door cause idk why just for some reason.',
LocalUsersRepository::getAdminUser()->getId(),
LocalDoorsRepository::getAmazonDoor()->getId(),
Override::TYPE_OPEN,
......@@ -26,6 +27,7 @@ class LocalOverridesRepository extends InMemoryOverridesRepository
$this->addOverride(new Override(
1,
'No one is allowed in the bat cave!',
LocalUsersRepository::getAdminUser()->getId(),
LocalDoorsRepository::getTheBatCave()->getId(),
Override::TYPE_LOCKED,
......
......@@ -11,6 +11,8 @@ use Source\Entities\Group;
use Source\Entities\Token;
use Source\Entities\Attempt;
use Source\Entities\Schedule;
use Source\Entities\Override;
use Facade\Ignition\Support\Packagist\Package;
abstract class BasePresenter
{
......@@ -164,6 +166,10 @@ abstract class BasePresenter
];
}
/**
* @param \Source\Entities\Entry|null $entry
* @return array
*/
public function formatEntry(?Entry $entry): array
{
if (!$entry) {
......@@ -178,4 +184,27 @@ abstract class BasePresenter
'created_at' => $entry->getCreatedAt(),
];
}
/**
* @param \Source\Entities\Override|null $override
* @return array
*/
public function formatOverride(?Override $override): array
{
if (!$override) {
return [];
}
return [
'id' => $override->getId(),
'reason' => $override->getReason(),
'user_id' => $override->getUserId(),
'door_id' => $override->getDoorId(),
'type' => $override->getType(),
'start' => $this->formatDateTime($override->getStart()),
'end' => $this->formatDateTime($override->getEnd()),
'created_at' => $this->formatDateTime($override->getCreatedAt()),
'updated_at' => $this->formatDateTime($override->getUpdatedAt()),
];
}
}
<?php
namespace Source\UseCases\Overrides;
use Source\Entities\Override;
use Source\UseCases\BasePresenter;
class ApiPresenter extends BasePresenter implements Presenter
{
protected array $viewModel = [];
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->viewModel['overrides'] = array_map(function (Override $override) {
return $this->formatOverride($override);
}, $responseModel->getOverrides());
}
/** @inheritDoc */
public function getViewModel(): array
{
return $this->viewModel;
}
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
use Source\UseCases\BasePresenter;
class ApiPresenter extends BasePresenter implements Presenter
{
protected array $viewModel = [];
protected int $statusCode = 200;
/** @inheritDoc */
public function present(ResponseModel $responseModel): void
{
$this->viewModel['override'] = $this->formatOverride($responseModel->getOverride());
}
/** @inheritDoc */
public function getViewModel(): array
{
return $this->viewModel;
}
/**
* @inheritDoc
*/
public function presentError(ResponseModel $responseModel): void
{
$this->statusCode = 422;
$this->viewModel['errors'] = $responseModel->getErrors();
}
public function getStatusCode(): int
{
return $this->statusCode;
}
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
use Carbon\Carbon;
use Source\Sanitize\CastsTo;
use Source\Entities\Override;
use InvalidArgumentException;
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Doors\DoorsRepository;
use Source\Gateways\Overrides\OverridesRepository;
class OverrideCreate implements OverrideCreateUseCase
{
use CastsTo;
/**
* @var \Source\Gateways\Overrides\OverridesRepository
*/
protected OverridesRepository $overrides;
/**
* @var \Source\Gateways\Users\UsersRepository
*/
protected UsersRepository $users;
/**
* @var \Source\Gateways\Doors\DoorsRepository
*/
protected DoorsRepository $doors;
public function __construct(OverridesRepository $overrides, UsersRepository $users, DoorsRepository $doors)
{
$this->overrides = $overrides;
$this->users = $users;
$this->doors = $doors;
}
/**
* @inheritDoc
*/
public function create(array $attributes, Presenter $presenter): void
{
$response = new ResponseModel();
$userId = $this->castToInt($attributes['user_id']);
$doorId = $this->castToInt($attributes['door_id']);
if (!$this->users->get($userId)) {
$response->addError('User does not exist!');
}
if (!$this->doors->get($doorId)) {
$response->addError('Door does not exist!');
}
try {
$override = $this->overrides->addOverride(
new Override(
0,
$attributes['reason'],
$userId,
$doorId,
$attributes['type'],
new Carbon($attributes['start']),
new Carbon($attributes['end'])
)
);
if (!$override) {
$response->addError('Something went wrong when adding the override');
} else {
$response->setOverride($override);
}
} catch (InvalidArgumentException $e) {
$response->addError($e->getMessage());
}
if ($response->hasError()) {
$presenter->presentError($response);
} else {
$presenter->present($response);
}
}
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
interface OverrideCreateUseCase
{
/**
* Required Attributes
* - reason: string (reason for override)
* - user_id: string or int (user who initiated the action)
* - door_id: string or int (door to apply override to)
* - type: int (0=Open mode override, 1=Closed mode override, 2=business as usual override (no override, basically an override override))
* - start: string (start of override string must be parsable by DateTime)
* - end: string (end of override string must be parsable by DateTime)
* Throws an exception if the dates are not parsable
*
* @param array $attributes
* @param \Source\UseCases\Overrides\OverrideCreate\Presenter $presenter
* @throws \Exception
*/
public function create(array $attributes, Presenter $presenter): void;
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Doors\DoorsRepository;
use Illuminate\Contracts\Foundation\Application;
use Source\Gateways\Overrides\OverridesRepository;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
/**
* Service provider must be registered in AppServiceProvider
*/
class OverrideCreateUseCaseServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(OverrideCreateUseCase::class, static function (Application $app) {
return new OverrideCreate(
$app->make(OverridesRepository::class),
$app->make(UsersRepository::class),
$app->make(DoorsRepository::class)
);
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
}
/**
* @return array
*/
public function provides()
{
return [OverrideCreateUseCase::class];
}
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
interface Presenter
{
/**
* @param ResponseModel $responseModel
* @return void
*/
public function present(ResponseModel $responseModel): void;
/**
* @param \Source\UseCases\Overrides\OverrideCreate\ResponseModel $responseModel
*/
public function presentError(ResponseModel $responseModel): void;
/**
* @return array
*/
public function getViewModel(): array;
}
<?php
namespace Source\UseCases\Overrides\OverrideCreate;
use Source\Entities\Override;
class ResponseModel
{
/**
* @var string[]
*/
protected array $errors = [];
protected Override $override;
/**
* @param \Source\Entities\Override $override
*/
public function setOverride(Override $override): void
{
$this->override = $override;
}
/**
* @return \Source\Entities\Override
*/
public function getOverride(): Override
{
return $this->override;
}
/**
* @param string $error
*/
public function addError(string $error): void
{
$this->errors[] = $error;
}
/**
* @return bool
*/
public function hasError(): bool
{
return (bool)$this->errors;
}
/**
* @return string[]
*/
public function getErrors(): array
{
return $this->errors;
}
}
<?php
namespace Source\UseCases\Overrides\OverridesForDateRange;
use Carbon\Carbon;
use Source\UseCases\Overrides\Presenter;
use Source\UseCases\Overrides\ResponseModel;
use Source\Gateways\Overrides\OverridesRepository;
class OverridesForDateRange implements OverridesForDateRangeUseCase
{
/**
* @var \Source\Gateways\Overrides\OverridesRepository
*/
protected OverridesRepository $overrides;
public function __construct(OverridesRepository $overrides)
{
$this->overrides = $overrides;
}
/**
* @inheritDoc
*/
public function getOverridesForDateRange(string $start, string $end, Presenter $presenter): void
{
$overrides = $this->overrides->overrideHistoryBetween(new Carbon($start), new Carbon($end));
$response = new ResponseModel();
foreach ($overrides as $override) {
$response->addOverride($override);
}
$presenter->present($response);
}
}
<?php
namespace Source\UseCases\Overrides\OverridesForDateRange;
use Source\UseCases\Overrides\Presenter;
interface OverridesForDateRangeUseCase
{
/**
* Gets all overrides within a range
*
* @param string $start
* @param string $end
* @param \Source\UseCases\Overrides\Presenter $presenter
* @throws \Exception
*/
public function getOverridesForDateRange(string $start, string $end, Presenter $presenter): void;
}
<?php
namespace Source\UseCases\Overrides\OverridesForDateRange;
use Illuminate\Contracts\Foundation\Application;
use Source\Gateways\Overrides\OverridesRepository;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
/**
* Service provider must be registered in AppServiceProvider
*/
class OverridesForDateRangeUseCaseServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(OverridesForDateRangeUseCase::class, static function (Application $app) {
return new OverridesForDateRange($app->make(OverridesRepository::class));
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
}
/**
* @return array
*/
public function provides()
{
return [OverridesForDateRangeUseCase::class];
}
}
<?php
namespace Source\UseCases\Overrides\OverridesForDoor;
use Source\UseCases\Overrides\Presenter;
use Source\UseCases\Overrides\ResponseModel;