diff --git a/app/Plan/UseCases/CreatePlan.php b/app/Plan/UseCases/CreatePlan.php index 0d0124c..9841b33 100644 --- a/app/Plan/UseCases/CreatePlan.php +++ b/app/Plan/UseCases/CreatePlan.php @@ -42,6 +42,21 @@ class CreatePlan throw new BadRequestException('name is required'); } + if ($request->dateStart === null) { + throw new BadRequestException('date start is required'); + } + + if ($request->dateEnd === null) { + throw new BadRequestException('date end is required'); + } + + $startDate = new DateTimeImmutable($request->dateStart); + $endDate = new DateTimeImmutable($request->dateEnd); + + if ($endDate < $startDate) { + throw new BadRequestException('date end cannot be before date start'); + } + $userId = $request->userId; $user = $this->userRepo->find($userId); if ($user === null) { @@ -59,10 +74,22 @@ class CreatePlan name: $request->name, user: $user, )); - foreach ($nodesOfText as $node) { + + $dates = []; + $currentDate = $startDate; + while ($currentDate <= $endDate) { + $dates[] = $currentDate; + $currentDate = $currentDate->modify('+1 day'); + } + + $nodesPerDay = (int) ceil(count($nodesOfText) / count($dates)); + foreach ($nodesOfText as $index => $node) { + $dateIndex = (int) floor($index / $nodesPerDay); + $scheduledDate = $dates[$dateIndex]; + $this->createScheduledNode->execute( new CreateScheduledNodeRequest( - date: '2025-01-01', // TODO: this should be cycling over some list of dates + date: $scheduledDate->format('Y-m-d'), planId: $plan->getId(), ) ); diff --git a/app/Plan/UseCases/CreatePlanRequest.php b/app/Plan/UseCases/CreatePlanRequest.php index d9e0669..300a7a9 100644 --- a/app/Plan/UseCases/CreatePlanRequest.php +++ b/app/Plan/UseCases/CreatePlanRequest.php @@ -8,5 +8,7 @@ class CreatePlanRequest public ?int $userId, public ?int $textId, public ?string $name, + public ?string $dateStart, + public ?string $dateEnd, ) {} } diff --git a/app/ScheduledNode/ScheduledNode.php b/app/ScheduledNode/ScheduledNode.php index ce6ed05..7d479db 100644 --- a/app/ScheduledNode/ScheduledNode.php +++ b/app/ScheduledNode/ScheduledNode.php @@ -22,4 +22,9 @@ class ScheduledNode { return $this->plan; } + + public function getDate(): DateTimeImmutable + { + return $this->date; + } } diff --git a/tests/Unit/Plan/UseCases/CreatePlanTest.php b/tests/Unit/Plan/UseCases/CreatePlanTest.php index cccc4ea..667e72c 100644 --- a/tests/Unit/Plan/UseCases/CreatePlanTest.php +++ b/tests/Unit/Plan/UseCases/CreatePlanTest.php @@ -11,6 +11,7 @@ use App\Text\CreateTextDto; use App\User\UseCases\CreateUserDto; use App\User\User; use App\ValueObjects\EmailAddress; +use DateTimeImmutable; use DomainException; use Tests\Fakes\FakeNodeRepository; use Tests\Fakes\FakePlanRepository; @@ -59,6 +60,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); $this->assertEquals('testPlan', $plan->getName()); } @@ -69,6 +72,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); $this->assertInstanceOf(User::class, $plan->getUser()); } @@ -81,6 +86,8 @@ class CreatePlanTest extends TestCase userId: 1, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); } @@ -92,6 +99,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: 1, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); } @@ -107,6 +116,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); $this->assertNotNull($this->scheduledNodeRepo->find(0)); } @@ -128,6 +139,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); $this->assertEquals( 1, @@ -144,6 +157,8 @@ class CreatePlanTest extends TestCase userId: null, name: 'testPlan', textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); } @@ -156,6 +171,8 @@ class CreatePlanTest extends TestCase userId: 0, name: 'testPlan', textId: null, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); } @@ -168,6 +185,139 @@ class CreatePlanTest extends TestCase userId: 0, name: null, textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-01', )); } + + public function test_throws_if_date_start_is_null(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('date start is required'); + + $this->useCase->execute(new CreatePlanRequest( + userId: 0, + name: 'test', + textId: 0, + dateStart: null, + dateEnd: '2025-01-01', + )); + } + + public function test_throws_if_date_end_is_null(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('date end is required'); + + $this->useCase->execute(new CreatePlanRequest( + userId: 0, + name: 'test', + textId: 0, + dateStart: '2025-01-01', + dateEnd: null, + )); + } + + public function test_throws_if_date_end_is_before_date_start(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('date end cannot be before date start'); + + $this->useCase->execute(new CreatePlanRequest( + userId: 0, + name: 'test', + textId: 0, + dateStart: '2025-01-02', + dateEnd: '2025-01-01', + )); + } + + public function test_scheduled_nodes_are_scheduled_on_different_days(): void + { + $text = $this->textRepo->find(0); + $rootNode = $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'root node', + parentNode: null, + )); + $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'child 1', + parentNode: $rootNode, + )); + $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'child 2', + parentNode: $rootNode, + )); + $plan = $this->useCase->execute(new CreatePlanRequest( + userId: 0, + name: 'testPlan', + textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-02', + )); + $childOne = $this->scheduledNodeRepo->find(0); + $childTwo = $this->scheduledNodeRepo->find(1); + $this->assertNotNull($childOne); + $this->assertNotNull($childTwo); + $this->assertEquals( + new DateTimeImmutable('2025-01-01'), + $childOne->getDate() + ); + $this->assertEquals( + new DateTimeImmutable('2025-01-02'), + $childTwo->getDate() + ); + } + + public function test_more_scheduled_nodes_than_days(): void + { + $text = $this->textRepo->find(0); + $rootNode = $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'root node', + parentNode: null, + )); + $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'child 1', + parentNode: $rootNode, + )); + $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'child 2', + parentNode: $rootNode, + )); + $this->nodeRepo->create(new CreateNodeDto( + text: $text, + title: 'child 3', + parentNode: $rootNode, + )); + $plan = $this->useCase->execute(new CreatePlanRequest( + userId: 0, + name: 'testPlan', + textId: 0, + dateStart: '2025-01-01', + dateEnd: '2025-01-02', + )); + $childOne = $this->scheduledNodeRepo->find(0); + $childTwo = $this->scheduledNodeRepo->find(1); + $childThree = $this->scheduledNodeRepo->find(2); + $this->assertNotNull($childOne); + $this->assertNotNull($childTwo); + $this->assertNotNull($childThree); + $this->assertEquals( + new DateTimeImmutable('2025-01-01'), + $childOne->getDate() + ); + $this->assertEquals( + new DateTimeImmutable('2025-01-01'), + $childTwo->getDate() + ); + $this->assertEquals( + new DateTimeImmutable('2025-01-02'), + $childThree->getDate() + ); + } }