refactor(api): update Employee request handling and remove toInput method

Refactor EmployeeShowRequest and EmployeesIndexRequest to improve clarity and maintainability.
This commit is contained in:
Jérémy Munsch 2026-08-13 09:55:27 +02:00
parent 6c7c782a1d
commit 554e4002df
Signed by: forge-joniko
GPG key ID: D7EFE2F5CB6CC0E4
6 changed files with 58 additions and 33 deletions

View file

@ -4,12 +4,20 @@ declare(strict_types=1);
namespace Domain\Models\ValueObjects\Employees;
enum EmployeeSortColumn
use Shared\Enums\BaseEnum;
/**
* @use BaseEnum<string>
*/
enum EmployeeSortColumn: string
{
case arcadiaId;
case startDate;
case endDate;
case plannedEndDate;
case createdAt;
case updatedAt;
/** @use BaseEnum<string> */
use BaseEnum;
case arcadiaId = 'arcadiaId';
case startDate = 'startDate';
case endDate = 'endDate';
case plannedEndDate = 'plannedEndDate';
case createdAt = 'createdAt';
case updatedAt = 'updatedAt';
}

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Presentation\Api\V1\Http\Controllers\Employees;
use Application\Usecase\Employees\Find\FindEmployee;
use Application\Usecase\Employees\Find\Input;
use Illuminate\Http\JsonResponse;
use Presentation\Api\V1\Http\Requests\Employees\EmployeeShowRequest;
use Presentation\Api\V1\Http\Responses\Employees\EmployeeShowResponse;
@ -24,13 +25,21 @@ final readonly class EmployeeShowController
public function __invoke(EmployeeShowRequest $request): JsonResponse
{
/** @var \Presentation\Api\V1\Presenters\Employees\EmployeeShowView $response */
$response = UsecaseBuilder::using($this->executor)
->do($this->usecase)
->from($request->toInput())
->from($this->toInput($request))
->with($this->presenter)
->run();
return (new EmployeeShowResponse($response))->present();
}
private function toInput(EmployeeShowRequest $request): Input
{
return new Input(
id: $request->employeeId(),
);
}
}

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Presentation\Api\V1\Http\Controllers\Employees;
use Application\Usecase\Employees\FindAll\FindAllEmployees;
use Application\Usecase\Employees\FindAll\Input;
use Illuminate\Http\JsonResponse;
use Presentation\Api\V1\Http\Requests\Employees\EmployeesIndexRequest;
use Presentation\Api\V1\Http\Responses\Employees\EmployeesIndexResponse;
@ -24,10 +25,15 @@ final readonly class EmployeesIndexController
public function __invoke(EmployeesIndexRequest $request): JsonResponse
{
$input = new Input(
pagination: $request->pagination(),
sorter: $request->sorter(),
);
/** @var \Presentation\Api\V1\Presenters\Employees\EmployeesIndexView $response */
$response = UsecaseBuilder::using($this->executor)
->do($this->usecase)
->from($request->toInput())
->from($input)
->with($this->presenter)
->run();

View file

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Presentation\Api\V1\Http\Requests\Employees;
use Application\Usecase\Employees\Find\Input;
use Domain\Models\ValueObjects\Entities\ArcadiaEmployeeId;
use Illuminate\Foundation\Http\FormRequest;
@ -30,10 +29,8 @@ final class EmployeeShowRequest extends FormRequest
]);
}
public function toInput(): Input
public function employeeId(): ArcadiaEmployeeId
{
return new Input(
id: new ArcadiaEmployeeId($this->string('employeeId')->value()),
);
return new ArcadiaEmployeeId($this->string('employeeId')->value());
}
}

View file

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Presentation\Api\V1\Http\Requests\Employees;
use Application\Usecase\Employees\FindAll\Input;
use Domain\Models\ValueObjects\Employees\EmployeeSortColumn;
use Domain\Models\ValueObjects\Employees\EmployeeSorter;
use Illuminate\Foundation\Http\FormRequest;
@ -21,17 +20,11 @@ final class EmployeesIndexRequest extends FormRequest
'limit' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
'page' => ['sometimes', 'integer', 'min:1'],
'pageSize' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
'per_page' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
'sortBy' => ['sometimes', Rule::in(array_map(
static fn (EmployeeSortColumn $case): string => $case->name,
EmployeeSortColumn::cases()
))],
'sort_by' => ['sometimes', Rule::in(array_map(
static fn (EmployeeSortColumn $case): string => $case->name,
EmployeeSortColumn::cases()
))],
'sortDirection' => ['sometimes', Rule::in(['Ascending', 'Descending'])],
'direction' => ['sometimes', Rule::in(['Ascending', 'Descending'])],
'since' => ['sometimes', 'date'],
'establishment' => ['sometimes', 'string'],
'siteId' => ['sometimes', 'string'],
@ -44,19 +37,29 @@ final class EmployeesIndexRequest extends FormRequest
return true;
}
public function toInput(): Input
public function pagination(): Pagination
{
return new Input(
pagination: $this->pagination(),
sorter: new EmployeeSorter($this->sortBy(), $this->direction()),
if ($this->has('offset') || $this->has('limit')) {
return Pagination::ofOffsetAndLimit(
offset: $this->integer('offset', 0),
limit: $this->integer('limit', 25),
);
}
return Pagination::ofPage(
pageNumber: $this->integer('page', 1),
pageSize: $this->integer('pageSize', 25),
);
}
private function sortBy(): EmployeeSortColumn
public function sorter(): EmployeeSorter
{
$value = $this->string('sortBy')->isEmpty()
? $this->string('sort_by', EmployeeSortColumn::arcadiaId->name)->value()
: $this->string('sortBy')->value();
return new EmployeeSorter($this->sortBy(), $this->direction());
}
public function sortBy(): EmployeeSortColumn
{
$value = $this->string('sortBy', EmployeeSortColumn::arcadiaId->name)->value();
return match ($value) {
'startDate' => EmployeeSortColumn::startDate,
@ -68,11 +71,9 @@ final class EmployeesIndexRequest extends FormRequest
};
}
private function direction(): \SortDirection
public function direction(): \SortDirection
{
$value = $this->string('sortDirection')->isEmpty()
? $this->string('direction', \SortDirection::Ascending->name)->value()
: $this->string('sortDirection')->value();
$value = $this->string('sortDirection', \SortDirection::Ascending->name)->value();
return match ($value) {
'Descending' => \SortDirection::Descending,

View file

@ -25,6 +25,10 @@ describe('Presentation Architecture Rules', function (): void {
->expect('Presentation\Api\V1\Http\Requests')
->toExtend('Illuminate\Foundation\Http\FormRequest');
arch('Presentation FormRequests do not contain toInput method')
->expect('Presentation\Api\V1\Http\Requests')
->not->toHaveMethod('toInput');
arch('Presentation layer uses strict types')
->expect('Presentation')
->toUseStrictTypes();