diff --git a/app/Domain/EmployeesMilestoneRetriever.php b/app/Domain/EmployeesMilestoneRetriever.php new file mode 100644 index 00000000..9145722d --- /dev/null +++ b/app/Domain/EmployeesMilestoneRetriever.php @@ -0,0 +1,50 @@ + $this->getUpcomingBirthdays($searchText), + "birthday-desc" => $this->getUpcomingBirthdays($searchText, "desc"), + "seniority-asc" => $this->getSeniority($searchText), + "seniority-desc" => $this->getSeniority($searchText, "desc"), + default => User::query() + ->search($searchText) + ->orderByProfileField("last_name") + ->orderByProfileField("first_name") + ->get(), + }; + } + + public function getUpcomingBirthdays(?string $searchText, string $direction = "asc"): Collection + { + $users = User::query() + ->whereRelation("profile", fn(Builder $query): Builder => $query->whereNotNull("birthday")) + ->search($searchText) + ->get(); + + return $users->sortBy(fn(User $user): int => $user->upcomingBirthday()->diffInDays(Carbon::today()), descending: $direction !== "asc"); + } + + public function getSeniority(?string $searchText, string $direction = "asc"): Collection + { + return User::query() + ->search($searchText) + ->orderByProfileField("employment_date", $direction) + ->get(); + } +} diff --git a/app/Eloquent/Models/User.php b/app/Eloquent/Models/User.php index 28ec2147..eb41f646 100644 --- a/app/Eloquent/Models/User.php +++ b/app/Eloquent/Models/User.php @@ -150,9 +150,15 @@ public function upcomingBirthday(): ?Carbon return $birthday; } - public function seniority(): string + public function seniority(): ?string { - return $this->profile->employment_date->longAbsoluteDiffForHumans(Carbon::today(), 2); + $employmentDate = $this->profile->employment_date; + + if ($employmentDate->isFuture() || $employmentDate->isToday()) { + return null; + } + + return $employmentDate->longAbsoluteDiffForHumans(Carbon::today(), 2); } public function routeNotificationForSlack() @@ -160,24 +166,17 @@ public function routeNotificationForSlack() return $this->profile->slack_id; } - public function scopeSortForEmployeesMilestones(Builder $query, ?string $sort): Builder - { - return match ($sort) { - // "birthday-asc" TO DO - // "birthday-desc" TO DO - "seniority-asc" => $query->orderByProfileField("employment_date", "asc"), - "seniority-desc" => $query->orderByProfileField("employment_date", "desc"), - default => $query - ->orderByProfileField("last_name") - ->orderByProfileField("first_name"), - }; - } - public function isWorkAnniversaryToday(): bool { $today = Carbon::now(); - $workAnniversary = $this->profile->employment_date->setYear($today->year); + $employmentDate = $this->profile->employment_date; + + if ($employmentDate->isToday()) { + return false; + } + + $workAnniversary = $employmentDate->setYear($today->year); return $workAnniversary->isToday(); } diff --git a/app/Infrastructure/Http/Controllers/EmployeesMilestonesController.php b/app/Infrastructure/Http/Controllers/EmployeesMilestonesController.php index 25dd5b45..ace7b3e9 100644 --- a/app/Infrastructure/Http/Controllers/EmployeesMilestonesController.php +++ b/app/Infrastructure/Http/Controllers/EmployeesMilestonesController.php @@ -6,28 +6,23 @@ use Illuminate\Http\Request; use Inertia\Response; -use Toby\Eloquent\Models\User; +use Toby\Domain\EmployeesMilestoneRetriever; use Toby\Infrastructure\Http\Resources\EmployeeMilestoneResource; class EmployeesMilestonesController extends Controller { - public function index(Request $request): Response + public function index(Request $request, EmployeesMilestoneRetriever $employeesMilestoneRetriever): Response { $searchText = $request->query("search"); $sort = $request->query("sort"); - $users = User::query() - ->sortForEmployeesMilestones($sort) - ->search($searchText) - ->orderByProfileField("last_name") - ->orderByProfileField("first_name") - ->paginate() - ->withQueryString(); + $users = $employeesMilestoneRetriever->getResults($searchText, $sort); return inertia("EmployeesMilestones", [ "users" => EmployeeMilestoneResource::collection($users), "filters" => [ "search" => $searchText, + "sort" => $sort, ], ]); } diff --git a/app/Infrastructure/Http/Requests/UserRequest.php b/app/Infrastructure/Http/Requests/UserRequest.php index c0a4e165..76b6ca9f 100644 --- a/app/Infrastructure/Http/Requests/UserRequest.php +++ b/app/Infrastructure/Http/Requests/UserRequest.php @@ -22,7 +22,7 @@ public function rules(): array "position" => ["required"], "employmentForm" => ["required", new Enum(EmploymentForm::class)], "employmentDate" => ["required", "date_format:Y-m-d"], - "birthday" => ["nullable", "date_format:Y-m-d"], + "birthday" => ["nullable", "date_format:Y-m-d", "before:today"], "slackId" => [], "nextMedicalExamDate" => ["nullable", "after:lastMedicalExamDate"], "nextOhsTrainingDate" => ["nullable", "after:lastOhsTrainingDate"], diff --git a/lang/pl/validation.php b/lang/pl/validation.php index e52bfc17..863e9dab 100644 --- a/lang/pl/validation.php +++ b/lang/pl/validation.php @@ -170,6 +170,9 @@ "nextMedicalExamDate" => [ "after" => "Data następnego badania lekarskiego musi być późniejsza od daty ostatniego badania lekarskiego.", ], + "birthday" => [ + "before" => "Data urodzenia musi być datą wcześniejszą od dzisiaj.", + ], ], "attributes" => [ "to" => "do", @@ -182,5 +185,6 @@ "date" => "data", "name" => "nazwa", "password" => "hasło", + "birthday" => "data urodzenia", ], ]; diff --git a/resources/js/Pages/EmployeesMilestones.vue b/resources/js/Pages/EmployeesMilestones.vue index 07dc9785..03515927 100644 --- a/resources/js/Pages/EmployeesMilestones.vue +++ b/resources/js/Pages/EmployeesMilestones.vue @@ -179,7 +179,7 @@ watch(form, debounce(() => {
- {{ user.seniorityDisplayDate }} + {{ user.seniorityDisplayDate ? user.seniorityDisplayDate : '-'}} {
- \ No newline at end of file diff --git a/tests/Feature/EmployeesMilestonesTest.php b/tests/Feature/EmployeesMilestonesTest.php new file mode 100644 index 00000000..3495d2b6 --- /dev/null +++ b/tests/Feature/EmployeesMilestonesTest.php @@ -0,0 +1,102 @@ +employeesMilestoneRetriever = $this->app->make(EmployeesMilestoneRetriever::class); + } + + public function testUserCanSeeEmployeesMilestonesList(): void + { + $user = User::factory()->create(); + + User::factory()->count(9)->create(); + + $this->actingAs($user) + ->get("/employees-milestones") + ->assertOk() + ->assertInertia( + fn(Assert $page) => $page + ->component("EmployeesMilestones") + ->has("users.data", 10), + ); + } + + public function testSortingByBirthdays(): void + { + $user1 = User::factory() + ->hasProfile(["birthday" => Carbon::createFromDate(1998, 1, 1)]) + ->employee() + ->create(); + + $user2 = User::factory() + ->hasProfile(["birthday" => Carbon::createFromDate(2000, 12, 30)]) + ->employee() + ->create(); + + $user3 = User::factory() + ->hasProfile(["birthday" => Carbon::createFromDate(1997, 5, 22)]) + ->employee() + ->create(); + + $sortedUsersByUpcomingBirthday = $this->employeesMilestoneRetriever->getResults(null, "birthday-asc")->values(); + + $this->assertEquals($user1->id, $sortedUsersByUpcomingBirthday[0]->id); + $this->assertEquals($user3->id, $sortedUsersByUpcomingBirthday[1]->id); + $this->assertEquals($user2->id, $sortedUsersByUpcomingBirthday[2]->id); + + $sortedUsersByFurthestBirthday = $this->employeesMilestoneRetriever->getResults(null, "birthday-desc")->values(); + + $this->assertEquals($user2->id, $sortedUsersByFurthestBirthday[0]->id); + $this->assertEquals($user3->id, $sortedUsersByFurthestBirthday[1]->id); + $this->assertEquals($user1->id, $sortedUsersByFurthestBirthday[2]->id); + } + + public function testSortingBySeniority(): void + { + $user1 = User::factory() + ->hasProfile(["employment_date" => Carbon::createFromDate(2023, 1, 31)]) + ->employee() + ->create(); + + $user2 = User::factory() + ->hasProfile(["employment_date" => Carbon::createFromDate(2022, 1, 1)]) + ->employee() + ->create(); + + $user3 = User::factory() + ->hasProfile(["employment_date" => Carbon::createFromDate(2021, 10, 4)]) + ->employee() + ->create(); + + $sortedUsersByLongestSeniority = $this->employeesMilestoneRetriever->getResults(null, "seniority-asc")->values(); + + $this->assertEquals($user3->id, $sortedUsersByLongestSeniority[0]->id); + $this->assertEquals($user2->id, $sortedUsersByLongestSeniority[1]->id); + $this->assertEquals($user1->id, $sortedUsersByLongestSeniority[2]->id); + + $sortedUsersByShortestSeniority = $this->employeesMilestoneRetriever->getResults(null, "seniority-desc")->values(); + + $this->assertEquals($user1->id, $sortedUsersByShortestSeniority[0]->id); + $this->assertEquals($user2->id, $sortedUsersByShortestSeniority[1]->id); + $this->assertEquals($user3->id, $sortedUsersByShortestSeniority[2]->id); + } +}