diff --git a/app/Console/Commands/SendNotificationAboutUpcomingMedicalExamsForEmployees.php b/app/Console/Commands/SendNotificationAboutUpcomingMedicalExamsForEmployees.php new file mode 100644 index 00000000..b71134cf --- /dev/null +++ b/app/Console/Commands/SendNotificationAboutUpcomingMedicalExamsForEmployees.php @@ -0,0 +1,35 @@ +whereRelation("histories", function ($query): void { + $query->where("type", UserHistoryType::MedicalExam) + ->where("to", ">", Carbon::now()) + ->where("to", "<=", Carbon::now()->addMonth()); + })->get(); + + if ($usersUpcomingMedicalExams->isEmpty()) { + return; + } + + foreach ($usersUpcomingMedicalExams as $user) { + $user->notify(new UpcomingMedicalExamForEmployeeNotification($user)); + } + } +} diff --git a/app/Console/Commands/SendNotificationAboutUpcomingOhsTrainingsForEmployees.php b/app/Console/Commands/SendNotificationAboutUpcomingOhsTrainingsForEmployees.php new file mode 100644 index 00000000..65c2259b --- /dev/null +++ b/app/Console/Commands/SendNotificationAboutUpcomingOhsTrainingsForEmployees.php @@ -0,0 +1,35 @@ +whereRelation("histories", function ($query): void { + $query->where("type", UserHistoryType::OhsTraining) + ->where("to", ">", Carbon::now()) + ->where("to", "<=", Carbon::now()->addMonth()); + })->get(); + + if ($usersUpcomingOhsTrainings->isEmpty()) { + return; + } + + foreach ($usersUpcomingOhsTrainings as $user) { + $user->notify(new UpcomingOhsTrainingForEmployeeNotification($user)); + } + } +} diff --git a/app/Notifications/UpcomingMedicalExamForEmployeeNotification.php b/app/Notifications/UpcomingMedicalExamForEmployeeNotification.php new file mode 100644 index 00000000..69481ad4 --- /dev/null +++ b/app/Notifications/UpcomingMedicalExamForEmployeeNotification.php @@ -0,0 +1,37 @@ +user->lastMedicalExam(); + + return (new SlackMessage()) + ->text(__("The deadline for occupational medical examinations for you is about to expire - :date (:difference days)", [ + "date" => $lastMedicalExamDate->to->toDisplayString(), + "difference" => (int)$lastMedicalExamDate->to->diffInDays(Carbon::today(), true), + ])); + } +} diff --git a/app/Notifications/UpcomingOhsTrainingForEmployeeNotification.php b/app/Notifications/UpcomingOhsTrainingForEmployeeNotification.php new file mode 100644 index 00000000..990f0c4c --- /dev/null +++ b/app/Notifications/UpcomingOhsTrainingForEmployeeNotification.php @@ -0,0 +1,37 @@ +user->lastOhsTraining(); + + return (new SlackMessage()) + ->text(__("The deadline for occupational ohs training for you is about to expire - :date (:difference days)", [ + "date" => $lastOhsTrainingDate->to->toDisplayString(), + "difference" => (int)$lastOhsTrainingDate->to->diffInDays(Carbon::today(), true), + ])); + } +} diff --git a/lang/pl.json b/lang/pl.json index 5e28ac3d..52045847 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -75,6 +75,8 @@ "The request :title is waiting for your administrative approval.\nUser: :requester\nDate: :date (number of days: :days)": "Wniosek :title czeka na Twoją akceptację administracyjną.\nPracownik: :requester\nData: :date (liczba dni: :days)", "The request :title has been approved by you as a technical approver.\nUser: :requester\nDate: :date (number of days: :days)": "Wniosek :title został zaakceptowany przez Ciebie jako przełożonego technicznego.\nPracownik: :requester\nData: :date (liczba dni: :days)", "The request :title has been approved by you as an administrative approver.\nUser: :requester\nDate: :date (number of days: :days)": "Wniosek :title został zaakceptowany przez Ciebie jako przełożonego administracyjnego.\nPracownik: :requester\nData: :date (liczba dni: :days)", + "The deadline for occupational ohs training for you is about to expire - :date (:difference days)": "Niedługo mija termin Twojego szkolenia BHP - :date (:difference dni)", + "The deadline for occupational medical examinations for you is about to expire - :date (:difference days)": "Niedługo mija termin Twojego badania lekarskiego z medycyny pracy - :date (:difference dni)", "Request :title has been :status": "Wniosek :title został :status", "Request :title in :application": "Wniosek :title w aplikacji :application", "The request :title from user :requester has been :status.": "Wniosek :title użytkownika :requester został :status.", diff --git a/routes/console.php b/routes/console.php index c659305b..ccfa9a82 100644 --- a/routes/console.php +++ b/routes/console.php @@ -9,6 +9,8 @@ use Toby\Console\Commands\SendNotificationAboutBenefitsReportCreation; use Toby\Console\Commands\SendNotificationAboutUpcomingAndOverdueMedicalExams; use Toby\Console\Commands\SendNotificationAboutUpcomingAndOverdueOhsTraining; +use Toby\Console\Commands\SendNotificationAboutUpcomingMedicalExamsForEmployees; +use Toby\Console\Commands\SendNotificationAboutUpcomingOhsTrainingsForEmployees; use Toby\Console\Commands\SendOvertimeRequestSummariesToApprovers; use Toby\Console\Commands\SendVacationRequestSummariesToApprovers; use Toby\Jobs\CheckYearPeriod; @@ -49,6 +51,14 @@ ->hourly() ->onOneServer(); +Schedule::command(SendNotificationAboutUpcomingMedicalExamsForEmployees::class) + ->weeklyOn(1, "08:30") + ->onOneServer(); + +Schedule::command(SendNotificationAboutUpcomingOhsTrainingsForEmployees::class) + ->weeklyOn(1, "08:30") + ->onOneServer(); + $scheduledTask = Schedule::command(BackupPostgresDatabase::class) ->dailyAt(time: "05:00") ->withoutOverlapping() diff --git a/tests/Unit/SendNotificationAboutUpcomingMedicalExamsToSlackTest.php b/tests/Unit/SendNotificationAboutUpcomingMedicalExamsToSlackTest.php new file mode 100644 index 00000000..b6655d80 --- /dev/null +++ b/tests/Unit/SendNotificationAboutUpcomingMedicalExamsToSlackTest.php @@ -0,0 +1,59 @@ +createCurrentYearPeriod(); + $this->user = User::factory()->employee()->create(); + } + + public function testNotificationIsSentToUserWithUpcomingMedicalExams(): void + { + $this->user->histories()->create([ + "from" => Carbon::createFromDate(2022, 1, 1), + "to" => Carbon::now()->addDays(14), + "type" => "medical_exam", + ]); + + $this->artisan(SendNotificationAboutUpcomingMedicalExamsForEmployees::class) + ->execute(); + + Notification::assertSentTo($this->user, UpcomingMedicalExamForEmployeeNotification::class); + } + + public function testNotificationIsNotSentToUserWithoutUpcomingMedicalExams(): void + { + $this->user->histories()->create([ + "from" => Carbon::createFromDate(2022, 1, 1), + "to" => Carbon::now()->addYear(), + "type" => "medical_exam", + ]); + + $this->artisan(SendNotificationAboutUpcomingMedicalExamsForEmployees::class) + ->execute(); + + Notification::assertNothingSent(); + } +} diff --git a/tests/Unit/SendNotificationAboutUpcomingOhsTrainingsToSlackTest.php b/tests/Unit/SendNotificationAboutUpcomingOhsTrainingsToSlackTest.php new file mode 100644 index 00000000..0c6442c1 --- /dev/null +++ b/tests/Unit/SendNotificationAboutUpcomingOhsTrainingsToSlackTest.php @@ -0,0 +1,66 @@ +createCurrentYearPeriod(); + Http::fake(fn(): array => [ + "channel" => Str::random(8), + "message" => ["ts" => Carbon::now()->toDateTimeString()], + ]); + + $this->user = User::factory()->employee()->create(); + } + + public function testNotificationIsSentToUserWithUpcomingMedicalExams(): void + { + $this->user->histories()->create([ + "from" => Carbon::createFromDate(2022, 1, 1), + "to" => Carbon::now()->addDays(14), + "type" => "ohs_training", + ]); + + $this->artisan(SendNotificationAboutUpcomingOhsTrainingsForEmployees::class) + ->execute(); + + Notification::assertSentTo($this->user, UpcomingOhsTrainingForEmployeeNotification::class); + } + + public function testNotificationIsNotSentToUserWithoutUpcomingMedicalExams(): void + { + $this->user->histories()->create([ + "from" => Carbon::createFromDate(2022, 1, 1), + "to" => Carbon::now()->addYear(), + "type" => "ohs_training", + ]); + + $this->artisan(SendNotificationAboutUpcomingOhsTrainingsForEmployees::class) + ->execute(); + + Notification::assertNothingSent(); + } +}