add dated assignment endpoint

This commit is contained in:
Yisroel Baum 2026-08-15 21:50:37 +03:00
parent 6afe7864be
commit 483ca6fc1d
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
9 changed files with 252 additions and 8 deletions

View file

@ -0,0 +1,27 @@
<?php
namespace App\Schedule;
final readonly class AssignmentForDate
{
public function __construct(
private int $scheduleId,
private string $setName,
private ScheduleAssignment $assignment,
) {}
public function getScheduleId(): int
{
return $this->scheduleId;
}
public function getSetName(): string
{
return $this->setName;
}
public function getAssignment(): ScheduleAssignment
{
return $this->assignment;
}
}

View file

@ -61,6 +61,40 @@ class EloquentScheduleRepository implements ScheduleRepository
return $schedules;
}
public function findAssignmentsForUserOnDate(
User $user,
DateTimeImmutable $date,
): array {
$assignmentModels = ScheduleAssignmentModel::query()
->select('schedule_assignments.*')
->join(
'schedules',
'schedules.id',
'=',
'schedule_assignments.schedule_id',
)
->where('schedules.user_id', $user->getId())
->where('schedule_assignments.scheduled_date', $date->format(
'Y-m-d',
))
->with('schedule')
->orderByDesc('schedules.id')
->orderBy('schedule_assignments.position')
->orderBy('schedule_assignments.id')
->get();
$assignments = [];
foreach ($assignmentModels as $assignmentModel) {
$assignments[] = new AssignmentForDate(
scheduleId: $assignmentModel->schedule->id,
setName: $assignmentModel->schedule->set_name,
assignment: $this->assignmentToDomain($assignmentModel),
);
}
return $assignments;
}
private function toDomain(ScheduleModel $model, User $user): Schedule
{
$assignmentModels = ScheduleAssignmentModel::query()
@ -71,14 +105,7 @@ class EloquentScheduleRepository implements ScheduleRepository
$assignments = [];
foreach ($assignmentModels as $assignmentModel) {
$assignments[] = new ScheduleAssignment(
id: $assignmentModel->id,
name: $assignmentModel->element_name,
kind: $assignmentModel->element_kind,
path: $assignmentModel->element_path,
scheduledDate: $this->date($assignmentModel->scheduled_date),
position: $assignmentModel->position,
);
$assignments[] = $this->assignmentToDomain($assignmentModel);
}
return new Schedule(
@ -92,6 +119,19 @@ class EloquentScheduleRepository implements ScheduleRepository
);
}
private function assignmentToDomain(
ScheduleAssignmentModel $model,
): ScheduleAssignment {
return new ScheduleAssignment(
id: $model->id,
name: $model->element_name,
kind: $model->element_kind,
path: $model->element_path,
scheduledDate: $this->date($model->scheduled_date),
position: $model->position,
);
}
private function date(string $value): DateTimeImmutable
{
return new DateTimeImmutable($value, new DateTimeZone('UTC'));

View file

@ -5,6 +5,7 @@ namespace App\Schedule;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int $id
@ -14,6 +15,7 @@ use Illuminate\Database\Eloquent\Model;
* @property list<string> $element_path
* @property string $scheduled_date
* @property int $position
* @property-read ScheduleModel $schedule
*
* @method static Builder<static>|ScheduleAssignmentModel newModelQuery()
* @method static Builder<static>|ScheduleAssignmentModel newQuery()
@ -46,4 +48,12 @@ class ScheduleAssignmentModel extends Model
'position' => 'integer',
];
}
/**
* @return BelongsTo<ScheduleModel, $this>
*/
public function schedule(): BelongsTo
{
return $this->belongsTo(ScheduleModel::class, 'schedule_id');
}
}

View file

@ -3,6 +3,7 @@
namespace App\Schedule;
use App\User\User;
use DateTimeImmutable;
interface ScheduleRepository
{
@ -14,4 +15,12 @@ interface ScheduleRepository
* @return list<Schedule>
*/
public function findAllForUser(User $user): array;
/**
* @return list<AssignmentForDate>
*/
public function findAssignmentsForUserOnDate(
User $user,
DateTimeImmutable $date,
): array;
}

View file

@ -0,0 +1,59 @@
<?php
namespace App\Schedule\UseCases\ListAssignmentsForDate;
use App\Exceptions\BadRequestException;
use App\Schedule\AssignmentForDate;
use App\Schedule\ScheduleRepository;
use DateTimeImmutable;
use DateTimeZone;
class ListAssignmentsForDate
{
public function __construct(
private ScheduleRepository $scheduleRepository,
) {}
/**
* @return list<AssignmentForDate>
* @throws BadRequestException
*/
public function execute(ListAssignmentsForDateRequest $request): array
{
$date = $this->parseDate($request->date);
return $this->scheduleRepository->findAssignmentsForUserOnDate(
$request->user,
$date,
);
}
/**
* @throws BadRequestException
*/
private function parseDate(?string $value): DateTimeImmutable
{
if ($value === null || $value === '') {
throw new BadRequestException('date is required');
}
$date = DateTimeImmutable::createFromFormat(
'!Y-m-d',
$value,
new DateTimeZone('UTC'),
);
$errors = DateTimeImmutable::getLastErrors();
if (
$date === false
|| $date->format('Y-m-d') !== $value
|| ($errors !== false
&& ($errors['warning_count'] > 0 || $errors['error_count'] > 0))
) {
throw new BadRequestException(
'date must be a valid date in YYYY-MM-DD format',
);
}
return $date;
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace App\Schedule\UseCases\ListAssignmentsForDate;
use App\User\User;
final readonly class ListAssignmentsForDateRequest
{
public function __construct(
public User $user,
public ?string $date,
) {}
}