From eb5dcf39c6f9e64594647512e14ec2ca42658d57 Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Mon, 25 Apr 2022 15:49:33 +0200 Subject: [PATCH] #126 - fix workdays --- .../Actions/VacationRequest/CreateAction.php | 10 +++---- .../Rules/DoesNotExceedLimitRule.php | 8 +++--- .../Rules/MinimumOneVacationDayRule.php | 6 ++--- ...sCalculator.php => WorkDaysCalculator.php} | 5 ++-- ...endVacationRequestRemindersToApprovers.php | 14 +++++----- .../Api/CalculateVacationDaysController.php | 6 ++--- database/seeders/DatabaseSeeder.php | 4 +-- database/seeders/DemoSeeder.php | 8 +++--- .../Unit/SendVacationRequestRemindersTest.php | 26 ++++++++----------- 9 files changed, 42 insertions(+), 45 deletions(-) rename app/Domain/{VacationDaysCalculator.php => WorkDaysCalculator.php} (81%) diff --git a/app/Domain/Actions/VacationRequest/CreateAction.php b/app/Domain/Actions/VacationRequest/CreateAction.php index 8a823e3..43d9736 100644 --- a/app/Domain/Actions/VacationRequest/CreateAction.php +++ b/app/Domain/Actions/VacationRequest/CreateAction.php @@ -6,10 +6,10 @@ namespace Toby\Domain\Actions\VacationRequest; use Illuminate\Validation\ValidationException; use Toby\Domain\Notifications\VacationRequestCreatedNotification; -use Toby\Domain\VacationDaysCalculator; use Toby\Domain\VacationRequestStateManager; use Toby\Domain\VacationTypeConfigRetriever; use Toby\Domain\Validation\VacationRequestValidator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; @@ -19,7 +19,7 @@ class CreateAction protected VacationRequestStateManager $stateManager, protected VacationRequestValidator $vacationRequestValidator, protected VacationTypeConfigRetriever $configRetriever, - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $vacationDaysCalculator, protected WaitForTechApprovalAction $waitForTechApprovalAction, protected WaitForAdminApprovalAction $waitForAdminApprovalAction, protected ApproveAction $approveAction, @@ -52,11 +52,7 @@ class CreateAction $vacationRequest->save(); - $days = $this->vacationDaysCalculator->calculateDays( - $vacationRequest->yearPeriod, - $vacationRequest->from, - $vacationRequest->to, - ); + $days = $this->vacationDaysCalculator->calculateDays($vacationRequest->from, $vacationRequest->to); foreach ($days as $day) { $vacationRequest->vacations()->create([ diff --git a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php index 3fd5429..e563ab6 100644 --- a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php +++ b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php @@ -7,9 +7,9 @@ namespace Toby\Domain\Validation\Rules; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; use Toby\Domain\Enums\VacationType; -use Toby\Domain\VacationDaysCalculator; use Toby\Domain\VacationRequestStatesRetriever; use Toby\Domain\VacationTypeConfigRetriever; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; use Toby\Eloquent\Models\YearPeriod; @@ -18,7 +18,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule { public function __construct( protected VacationTypeConfigRetriever $configRetriever, - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $vacationDaysCalculator, ) {} public function check(VacationRequest $vacationRequest): bool @@ -29,7 +29,9 @@ class DoesNotExceedLimitRule implements VacationRequestRule $limit = $this->getUserVacationLimit($vacationRequest->user, $vacationRequest->yearPeriod); $vacationDays = $this->getVacationDaysWithLimit($vacationRequest->user, $vacationRequest->yearPeriod); - $estimatedDays = $this->vacationDaysCalculator->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to)->count(); + $estimatedDays = $this->vacationDaysCalculator + ->calculateDays($vacationRequest->from, $vacationRequest->to) + ->count(); return $limit >= ($vacationDays + $estimatedDays); } diff --git a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php index ae9f58b..f32a6a3 100644 --- a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php +++ b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php @@ -4,19 +4,19 @@ declare(strict_types=1); namespace Toby\Domain\Validation\Rules; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\VacationRequest; class MinimumOneVacationDayRule implements VacationRequestRule { public function __construct( - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $vacationDaysCalculator, ) {} public function check(VacationRequest $vacationRequest): bool { return $this->vacationDaysCalculator - ->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to) + ->calculateDays($vacationRequest->from, $vacationRequest->to) ->isNotEmpty(); } diff --git a/app/Domain/VacationDaysCalculator.php b/app/Domain/WorkDaysCalculator.php similarity index 81% rename from app/Domain/VacationDaysCalculator.php rename to app/Domain/WorkDaysCalculator.php index 0e41a4a..3dd3c5f 100644 --- a/app/Domain/VacationDaysCalculator.php +++ b/app/Domain/WorkDaysCalculator.php @@ -9,11 +9,12 @@ use Carbon\CarbonPeriod; use Illuminate\Support\Collection; use Toby\Eloquent\Models\YearPeriod; -class VacationDaysCalculator +class WorkDaysCalculator { - public function calculateDays(YearPeriod $yearPeriod, CarbonInterface $from, CarbonInterface $to): Collection + public function calculateDays(CarbonInterface $from, CarbonInterface $to): Collection { $period = CarbonPeriod::create($from, $to); + $yearPeriod = YearPeriod::findByYear($from->year); $holidays = $yearPeriod->holidays()->pluck("date"); $validDays = new Collection(); diff --git a/app/Infrastructure/Console/Commands/SendVacationRequestRemindersToApprovers.php b/app/Infrastructure/Console/Commands/SendVacationRequestRemindersToApprovers.php index 3d0fb36..99c0805 100644 --- a/app/Infrastructure/Console/Commands/SendVacationRequestRemindersToApprovers.php +++ b/app/Infrastructure/Console/Commands/SendVacationRequestRemindersToApprovers.php @@ -12,6 +12,7 @@ use Toby\Domain\Notifications\VacationRequestWaitsForApprovalNotification; use Toby\Domain\States\VacationRequest\WaitingForAdministrative; use Toby\Domain\States\VacationRequest\WaitingForTechnical; use Toby\Domain\VacationTypeConfigRetriever; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; @@ -22,7 +23,7 @@ class SendVacationRequestRemindersToApprovers extends Command protected $signature = "toby:send-vacation-request-reminders"; protected $description = "Sends vacation request reminders to approvers if they didn't approve"; - public function handle(VacationTypeConfigRetriever $configRetriever): void + public function handle(VacationTypeConfigRetriever $configRetriever, WorkDaysCalculator $daysCalculator): void { $vacationRequests = VacationRequest::query() ->type(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type))->all()) @@ -30,7 +31,7 @@ class SendVacationRequestRemindersToApprovers extends Command /** @var VacationRequest $vacationRequest */ foreach ($vacationRequests as $vacationRequest) { - if (!$this->shouldNotify($vacationRequest)) { + if (!$this->shouldNotify($vacationRequest, $daysCalculator)) { continue; } @@ -44,12 +45,13 @@ class SendVacationRequestRemindersToApprovers extends Command } } - protected function shouldNotify(VacationRequest $vacationRequest): bool + protected function shouldNotify(VacationRequest $vacationRequest, WorkDaysCalculator $daysCalculator): bool { - $today = Carbon::today(); - $diff = $vacationRequest->updated_at->diffInDays($today); + $days = $daysCalculator + ->calculateDays($vacationRequest->updated_at->addDay(), Carbon::today()) + ->count(); - return $diff >= static::REMINDER_INTERVAL && ($diff % static::REMINDER_INTERVAL === 0); + return $days >= static::REMINDER_INTERVAL && ($days % static::REMINDER_INTERVAL === 0); } protected function notifyAdminApprovers(VacationRequest $vacationRequest): void diff --git a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php index c204be1..1c3f91b 100644 --- a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php +++ b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php @@ -6,15 +6,15 @@ namespace Toby\Infrastructure\Http\Controllers\Api; use Illuminate\Http\JsonResponse; use Illuminate\Support\Carbon; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Infrastructure\Http\Controllers\Controller; use Toby\Infrastructure\Http\Requests\Api\CalculateVacationDaysRequest; class CalculateVacationDaysController extends Controller { - public function __invoke(CalculateVacationDaysRequest $request, VacationDaysCalculator $calculator): JsonResponse + public function __invoke(CalculateVacationDaysRequest $request, WorkDaysCalculator $calculator): JsonResponse { - $days = $calculator->calculateDays($request->yearPeriod(), $request->from(), $request->to()); + $days = $calculator->calculateDays($request->from(), $request->to()); return new JsonResponse($days->map(fn(Carbon $day) => $day->toDateString())->all()); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index f5e0e51..74e8b6a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -7,7 +7,7 @@ namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Carbon; use Toby\Domain\PolishHolidaysRetriever; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\Key; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationLimit; @@ -70,7 +70,7 @@ class DatabaseSeeder extends Seeder "year_period_id" => $yearPeriods->random()->id, ]) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to, diff --git a/database/seeders/DemoSeeder.php b/database/seeders/DemoSeeder.php index 41470ba..d879612 100644 --- a/database/seeders/DemoSeeder.php +++ b/database/seeders/DemoSeeder.php @@ -18,7 +18,7 @@ use Toby\Domain\States\VacationRequest\Created; use Toby\Domain\States\VacationRequest\Rejected; use Toby\Domain\States\VacationRequest\WaitingForAdministrative; use Toby\Domain\States\VacationRequest\WaitingForTechnical; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\Key; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationLimit; @@ -164,7 +164,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to, @@ -234,7 +234,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to, @@ -291,7 +291,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to, diff --git a/tests/Unit/SendVacationRequestRemindersTest.php b/tests/Unit/SendVacationRequestRemindersTest.php index a7ebc57..6255744 100644 --- a/tests/Unit/SendVacationRequestRemindersTest.php +++ b/tests/Unit/SendVacationRequestRemindersTest.php @@ -32,11 +32,10 @@ class SendVacationRequestRemindersTest extends TestCase Notification::fake(); } - public function testReminderIsSentIfItsBeenThreeDaysSinceTheUpdate(): void + public function testReminderIsSentIfItsBeenThreeWorkDaysSinceTheUpdate(): void { $currentYearPeriod = YearPeriod::current(); - $now = Carbon::today(); - $this->travelTo($now); + $this->travelTo(Carbon::create(2022, 4, 20)); $user = User::factory()->create(); $technicalApprover = User::factory() @@ -51,18 +50,17 @@ class SendVacationRequestRemindersTest extends TestCase ->for($currentYearPeriod) ->create(); - $this->travelTo($now->addDays(3)); + $this->travelTo(Carbon::create(2022, 4, 25)); $this->artisan(SendVacationRequestRemindersToApprovers::class); Notification::assertSentTo([$technicalApprover], VacationRequestWaitsForApprovalNotification::class); } - public function testReminderIsSentIfItsBeenAnotherThreeDaysSinceTheUpdate(): void + public function testReminderIsSentIfItsBeenAnotherThreeWorkDaysSinceTheUpdate(): void { $currentYearPeriod = YearPeriod::current(); - $now = Carbon::today(); - $this->travelTo($now); + $this->travelTo(Carbon::create(2022, 4, 20)); $user = User::factory()->create(); $technicalApprover = User::factory() @@ -77,18 +75,17 @@ class SendVacationRequestRemindersTest extends TestCase ->for($currentYearPeriod) ->create(); - $this->travelTo($now->addDays(6)); + $this->travelTo(Carbon::create(2022, 4, 28)); $this->artisan(SendVacationRequestRemindersToApprovers::class); Notification::assertSentTo([$technicalApprover], VacationRequestWaitsForApprovalNotification::class); } - public function testReminderIsNotSentIfItHasntBeenThreeDays(): void + public function testReminderIsNotSentIfItHasntBeenThreeWorkDays(): void { $currentYearPeriod = YearPeriod::current(); - $now = Carbon::today(); - $this->travelTo($now); + $this->travelTo(Carbon::create(2022, 4, 20)); $user = User::factory()->create(); $technicalApprover = User::factory() @@ -103,7 +100,7 @@ class SendVacationRequestRemindersTest extends TestCase ->for($currentYearPeriod) ->create(); - $this->travelTo($now->addDays(2)); + $this->travelTo(Carbon::create(2022, 4, 24)); $this->artisan(SendVacationRequestRemindersToApprovers::class); @@ -113,8 +110,7 @@ class SendVacationRequestRemindersTest extends TestCase public function testReminderIsSentToProperApprover(): void { $currentYearPeriod = YearPeriod::current(); - $now = Carbon::today(); - $this->travelTo($now); + $this->travelTo(Carbon::create(2022, 4, 20)); $user = User::factory()->create(); $adminApprover = User::factory() @@ -132,7 +128,7 @@ class SendVacationRequestRemindersTest extends TestCase ->for($currentYearPeriod) ->create(); - $this->travelTo($now->addDays(3)); + $this->travelTo(Carbon::create(2022, 4, 25)); $this->artisan(SendVacationRequestRemindersToApprovers::class);