Skip to content

Commit

Permalink
#465 - notification for employees (#467)
Browse files Browse the repository at this point in the history
* #465 - feat: added employee notification about upcoming medical exam or ohs training

* #465 - fix: fixed channel

* #465 - fix: fixed slack messages

* #465 - feat: added some tests

* #465 - fix: code review fixes
  • Loading branch information
kamilpiech97 authored Jul 17, 2024
1 parent ace38c4 commit 54ad119
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Toby\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Toby\Enums\UserHistoryType;
use Toby\Models\User;
use Toby\Notifications\UpcomingMedicalExamForEmployeeNotification;

class SendNotificationAboutUpcomingMedicalExamsForEmployees extends Command
{
protected $signature = "toby:send-notification-about-medical-exams-for-employees";
protected $description = "Send notifications about upcoming medical exams.";

public function handle(): void
{
$usersUpcomingMedicalExams = User::query()
->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));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Toby\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Toby\Enums\UserHistoryType;
use Toby\Models\User;
use Toby\Notifications\UpcomingOhsTrainingForEmployeeNotification;

class SendNotificationAboutUpcomingOhsTrainingsForEmployees extends Command
{
protected $signature = "toby:send-notification-about-ohs-trainings-for-employees";
protected $description = "Send notifications about upcoming ohs trainings.";

public function handle(): void
{
$usersUpcomingOhsTrainings = User::query()
->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));
}
}
}
37 changes: 37 additions & 0 deletions app/Notifications/UpcomingMedicalExamForEmployeeNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Toby\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Support\Carbon;
use Toby\Models\User;
use Toby\Slack\Elements\SlackMessage;

class UpcomingMedicalExamForEmployeeNotification extends QueuedNotification
{
use Queueable;

public function __construct(
protected User $user,
) {
parent::__construct();
}

public function via(): array
{
return [Channels::SLACK];
}

public function toSlack(): SlackMessage
{
$lastMedicalExamDate = $this->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),
]));
}
}
37 changes: 37 additions & 0 deletions app/Notifications/UpcomingOhsTrainingForEmployeeNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Toby\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Support\Carbon;
use Toby\Models\User;
use Toby\Slack\Elements\SlackMessage;

class UpcomingOhsTrainingForEmployeeNotification extends QueuedNotification
{
use Queueable;

public function __construct(
protected User $user,
) {
parent::__construct();
}

public function via(): array
{
return [Channels::SLACK];
}

public function toSlack(): SlackMessage
{
$lastOhsTrainingDate = $this->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),
]));
}
}
2 changes: 2 additions & 0 deletions lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down
10 changes: 10 additions & 0 deletions routes/console.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Tests\Unit;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
use Tests\Traits\InteractsWithYearPeriods;
use Toby\Console\Commands\SendNotificationAboutUpcomingMedicalExamsForEmployees;
use Toby\Models\User;
use Toby\Notifications\UpcomingMedicalExamForEmployeeNotification;

class SendNotificationAboutUpcomingMedicalExamsToSlackTest extends TestCase
{
use RefreshDatabase;
use InteractsWithYearPeriods;

protected User $user;

protected function setUp(): void
{
parent::setUp();

Notification::fake();
$this->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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Tests\Unit;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use Tests\TestCase;
use Tests\Traits\InteractsWithYearPeriods;
use Toby\Console\Commands\SendNotificationAboutUpcomingOhsTrainingsForEmployees;
use Toby\Models\User;
use Toby\Notifications\UpcomingOhsTrainingForEmployeeNotification;

class SendNotificationAboutUpcomingOhsTrainingsToSlackTest extends TestCase
{
use RefreshDatabase;
use InteractsWithYearPeriods;

protected User $user;

protected function setUp(): void
{
parent::setUp();

Notification::fake();
$this->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();
}
}

0 comments on commit 54ad119

Please sign in to comment.