snapshot schedule source data

This commit is contained in:
Yisroel Baum 2026-08-10 22:36:14 +03:00
parent 14fe2fcb46
commit f500bd6095
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
14 changed files with 84 additions and 87 deletions

View file

@ -2,7 +2,6 @@
namespace App\Http\Controllers;
use App\Element\Element;
use App\Exceptions\BadRequestException;
use App\Exceptions\NotFoundException;
use App\Schedule\Schedule;
@ -96,13 +95,10 @@ class ScheduleController extends Controller
*/
private function summaryPayload(Schedule $schedule): array
{
$set = $schedule->getSet();
return [
'id' => $schedule->getId(),
'set' => [
'id' => $set->getId(),
'name' => $set->getName(),
'name' => $schedule->getSetName(),
],
'elementKind' => $schedule->getElementKind(),
'startDate' => $schedule->getStartDate()->format('Y-m-d'),
@ -150,8 +146,7 @@ class ScheduleController extends Controller
}
/**
* @return array{element: array{
* id: int,
* @return array{id: int, element: array{
* name: string,
* kind: string,
* path: list<string>
@ -160,34 +155,16 @@ class ScheduleController extends Controller
private function assignmentPayload(
ScheduleAssignment $assignment,
): array {
$element = $assignment->getElement();
return [
'id' => $assignment->getId(),
'element' => [
'id' => $element->getId(),
'name' => $element->getName(),
'kind' => $element->getKind(),
'path' => $this->elementPath($element),
'name' => $assignment->getName(),
'kind' => $assignment->getKind(),
'path' => $assignment->getPath(),
],
];
}
/**
* @return list<string>
*/
private function elementPath(Element $element): array
{
$path = [];
$currentElement = $element;
while ($currentElement !== null) {
array_unshift($path, $currentElement->getName());
$currentElement = $currentElement->getParentElement();
}
return $path;
}
private function user(Request $request): User
{
/** @var User $user */

View file

@ -2,13 +2,17 @@
namespace App\Schedule;
use App\Element\Element;
use DateTimeImmutable;
final readonly class CreateScheduleAssignmentDto
{
/**
* @param list<string> $path
*/
public function __construct(
public Element $element,
public string $name,
public string $kind,
public array $path,
public DateTimeImmutable $scheduledDate,
public int $position,
) {}

View file

@ -2,7 +2,6 @@
namespace App\Schedule;
use App\Set\Set;
use App\User\User;
use DateTimeImmutable;
@ -13,7 +12,7 @@ final readonly class CreateScheduleDto
*/
public function __construct(
public User $user,
public Set $set,
public string $setName,
public string $elementKind,
public DateTimeImmutable $startDate,
public DateTimeImmutable $targetDate,

View file

@ -2,27 +2,19 @@
namespace App\Schedule;
use App\Element\ElementRepository;
use App\Set\SetRepository;
use App\User\User;
use DateTimeImmutable;
use DateTimeZone;
use Illuminate\Support\Facades\DB;
use RuntimeException;
class EloquentScheduleRepository implements ScheduleRepository
{
public function __construct(
private SetRepository $setRepository,
private ElementRepository $elementRepository,
) {}
public function create(CreateScheduleDto $dto): Schedule
{
return DB::transaction(function () use ($dto): Schedule {
$model = ScheduleModel::create([
'user_id' => $dto->user->getId(),
'set_id' => $dto->set->getId(),
'set_name' => $dto->setName,
'element_kind' => $dto->elementKind,
'start_date' => $dto->startDate->format('Y-m-d'),
'target_date' => $dto->targetDate->format('Y-m-d'),
@ -31,7 +23,9 @@ class EloquentScheduleRepository implements ScheduleRepository
foreach ($dto->assignments as $assignmentDto) {
ScheduleAssignmentModel::create([
'schedule_id' => $model->id,
'element_id' => $assignmentDto->element->getId(),
'element_name' => $assignmentDto->name,
'element_kind' => $assignmentDto->kind,
'element_path' => $assignmentDto->path,
'scheduled_date' => $assignmentDto->scheduledDate
->format('Y-m-d'),
'position' => $assignmentDto->position,
@ -69,11 +63,6 @@ class EloquentScheduleRepository implements ScheduleRepository
private function toDomain(ScheduleModel $model, User $user): Schedule
{
$set = $this->setRepository->find($model->set_id);
if ($set === null) {
throw new RuntimeException('schedule set not found');
}
$assignmentModels = ScheduleAssignmentModel::query()
->where('schedule_id', $model->id)
->orderBy('position')
@ -82,16 +71,11 @@ class EloquentScheduleRepository implements ScheduleRepository
$assignments = [];
foreach ($assignmentModels as $assignmentModel) {
$element = $this->elementRepository->find(
$assignmentModel->element_id,
);
if ($element === null) {
throw new RuntimeException('schedule element not found');
}
$assignments[] = new ScheduleAssignment(
id: $assignmentModel->id,
element: $element,
name: $assignmentModel->element_name,
kind: $assignmentModel->element_kind,
path: $assignmentModel->element_path,
scheduledDate: $this->date($assignmentModel->scheduled_date),
position: $assignmentModel->position,
);
@ -100,7 +84,7 @@ class EloquentScheduleRepository implements ScheduleRepository
return new Schedule(
id: $model->id,
user: $user,
set: $set,
setName: $model->set_name,
elementKind: $model->element_kind,
startDate: $this->date($model->start_date),
targetDate: $this->date($model->target_date),

View file

@ -2,7 +2,6 @@
namespace App\Schedule;
use App\Set\Set;
use App\User\User;
use DateTimeImmutable;
@ -14,7 +13,7 @@ final readonly class Schedule
public function __construct(
private int $id,
private User $user,
private Set $set,
private string $setName,
private string $elementKind,
private DateTimeImmutable $startDate,
private DateTimeImmutable $targetDate,
@ -31,9 +30,9 @@ final readonly class Schedule
return $this->user;
}
public function getSet(): Set
public function getSetName(): string
{
return $this->set;
return $this->setName;
}
public function getElementKind(): string

View file

@ -2,14 +2,18 @@
namespace App\Schedule;
use App\Element\Element;
use DateTimeImmutable;
final readonly class ScheduleAssignment
{
/**
* @param list<string> $path
*/
public function __construct(
private int $id,
private Element $element,
private string $name,
private string $kind,
private array $path,
private DateTimeImmutable $scheduledDate,
private int $position,
) {}
@ -19,9 +23,22 @@ final readonly class ScheduleAssignment
return $this->id;
}
public function getElement(): Element
public function getName(): string
{
return $this->element;
return $this->name;
}
public function getKind(): string
{
return $this->kind;
}
/**
* @return list<string>
*/
public function getPath(): array
{
return $this->path;
}
public function getScheduledDate(): DateTimeImmutable

View file

@ -9,7 +9,9 @@ use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property int $schedule_id
* @property int $element_id
* @property string $element_name
* @property string $element_kind
* @property list<string> $element_path
* @property string $scheduled_date
* @property int $position
*
@ -21,7 +23,9 @@ use Illuminate\Database\Eloquent\Model;
*/
#[Fillable([
'schedule_id',
'element_id',
'element_name',
'element_kind',
'element_path',
'scheduled_date',
'position',
])]
@ -38,7 +42,7 @@ class ScheduleAssignmentModel extends Model
{
return [
'schedule_id' => 'integer',
'element_id' => 'integer',
'element_path' => 'array',
'position' => 'integer',
];
}

View file

@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property int $user_id
* @property int $set_id
* @property string $set_name
* @property string $element_kind
* @property string $start_date
* @property string $target_date
@ -22,7 +22,7 @@ use Illuminate\Database\Eloquent\Model;
*/
#[Fillable([
'user_id',
'set_id',
'set_name',
'element_kind',
'start_date',
'target_date',
@ -40,7 +40,6 @@ class ScheduleModel extends Model
{
return [
'user_id' => 'integer',
'set_id' => 'integer',
];
}
}

View file

@ -70,7 +70,7 @@ class CreateSchedule
return $this->scheduleRepository->create(new CreateScheduleDto(
user: $request->user,
set: $set,
setName: $set->getName(),
elementKind: $request->elementKind,
startDate: $startDate,
targetDate: $targetDate,
@ -153,7 +153,9 @@ class CreateSchedule
dayCount: $dayCount,
);
$assignments[] = new CreateScheduleAssignmentDto(
element: $element,
name: $element->getName(),
kind: $element->getKind(),
path: $this->elementPath($element),
scheduledDate: $startDate->modify("+{$dayIndex} days"),
position: $index + 1,
);
@ -162,6 +164,22 @@ class CreateSchedule
return $assignments;
}
/**
* @return list<string>
*/
private function elementPath(Element $element): array
{
$path = [];
$currentElement = $element;
while ($currentElement !== null) {
array_unshift($path, $currentElement->getName());
$currentElement = $currentElement->getParentElement();
}
return $path;
}
private function dayIndex(
int $elementIndex,
int $elementCount,

View file

@ -13,9 +13,7 @@ return new class extends Migration
$table->foreignId('user_id')
->constrained('users')
->restrictOnDelete();
$table->foreignId('set_id')
->constrained('sets')
->restrictOnDelete();
$table->string('set_name');
$table->string('element_kind');
$table->date('start_date');
$table->date('target_date');

View file

@ -15,12 +15,11 @@ return new class extends Migration
$table->foreignId('schedule_id')
->constrained('schedules')
->cascadeOnDelete();
$table->foreignId('element_id')
->constrained('elements')
->restrictOnDelete();
$table->string('element_name');
$table->string('element_kind');
$table->json('element_path');
$table->date('scheduled_date');
$table->unsignedInteger('position');
$table->unique(['schedule_id', 'element_id']);
$table->unique(['schedule_id', 'position']);
$table->index([
'schedule_id',