Skip to content

Commit

Permalink
feat: reminder backend (monicahq/chandler#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
djaiss authored Mar 14, 2022
1 parent 02e2078 commit 896da02
Show file tree
Hide file tree
Showing 38 changed files with 1,509 additions and 364 deletions.
53 changes: 53 additions & 0 deletions app/Console/Commands/TestReminders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use App\Models\UserNotificationChannel;
use App\Models\ScheduledContactReminder;
use App\Jobs\Notifications\SendEmailNotification;
use App\Services\Contact\ManageReminder\RescheduleContactReminder;

class TestReminders extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test:send-reminders';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Send all the scheduled contact reminders regardless of the time they should be send.';

/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
if (App::environment('production')) {
exit;
}

$scheduledReminders = ScheduledContactReminder::where('triggered_at', null)
->with('userNotificationChannel')
->get();

foreach ($scheduledReminders as $scheduledReminder) {
if ($scheduledReminder->userNotificationChannel->type == UserNotificationChannel::TYPE_EMAIL) {
SendEmailNotification::dispatch($scheduledReminder)->onQueue('low');
}

(new RescheduleContactReminder)->execute([
'scheduled_contact_reminder_id' => $scheduledReminder->id,
]);
}
}
}
3 changes: 2 additions & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use App\Jobs\ProcessScheduledContactReminders;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
Expand All @@ -15,7 +16,7 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
$schedule->job(new ProcessScheduledContactReminders)->everyMinute();
}

/**
Expand Down
57 changes: 57 additions & 0 deletions app/Jobs/Notifications/SendEmailNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace App\Jobs\Notifications;

use Carbon\Carbon;
use App\Mail\SendReminder;
use Illuminate\Bus\Queueable;
use App\Models\UserNotificationSent;
use Illuminate\Support\Facades\Mail;
use Illuminate\Queue\SerializesModels;
use App\Models\ScheduledContactReminder;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendEmailNotification implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public ScheduledContactReminder $scheduledReminder;

/**
* Create a new job instance.
*
* @param ScheduledContactReminder $scheduledReminder
* @return void
*/
public function __construct(ScheduledContactReminder $scheduledReminder)
{
$this->scheduledReminder = $scheduledReminder;
}

/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$emailAddress = $this->scheduledReminder->userNotificationChannel->content;
$user = $this->scheduledReminder->userNotificationChannel->user;

Mail::to($emailAddress)
->queue((new SendReminder($this->scheduledReminder, $user))
->onQueue('low')
);

$this->scheduledReminder->triggered_at = Carbon::now();
$this->scheduledReminder->save();

UserNotificationSent::create([
'user_notification_channel_id' => $this->scheduledReminder->userNotificationChannel->id,
'sent_at' => Carbon::now(),
'subject_line' => $this->scheduledReminder->reminder->label,
]);
}
}
57 changes: 57 additions & 0 deletions app/Jobs/ProcessScheduledContactReminders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace App\Jobs;

use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use App\Models\UserNotificationChannel;
use App\Models\ScheduledContactReminder;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Jobs\Notifications\SendEmailNotification;
use App\Services\Contact\ManageReminder\RescheduleContactReminder;

class ProcessScheduledContactReminders implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
}

/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// this cron job runs every five minutes, so we must make sure that
// the date we run this cron against, has no seconds, otherwise getting
// the scheduled reminders will not return any results
$currentDate = Carbon::now();
$currentDate->second = 0;

$scheduledReminders = ScheduledContactReminder::where('scheduled_at', '<=', $currentDate)
->where('triggered_at', null)
->with('userNotificationChannel')
->get();

foreach ($scheduledReminders as $scheduledReminder) {
if ($scheduledReminder->userNotificationChannel->type == UserNotificationChannel::TYPE_EMAIL) {
SendEmailNotification::dispatch($scheduledReminder)->onQueue('low');
}

(new RescheduleContactReminder)->execute([
'scheduled_contact_reminder_id' => $scheduledReminder->id,
]);
}
}
}
49 changes: 49 additions & 0 deletions app/Mail/SendReminder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace App\Mail;

use App\Models\User;
use App\Helpers\NameHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Models\ScheduledContactReminder;

class SendReminder extends Mailable
{
use Queueable, SerializesModels;

public ScheduledContactReminder $scheduledContactReminder;
public User $user;

/**
* Create a new message instance.
*
* @return void
*/
public function __construct(ScheduledContactReminder $contactReminder, User $user)
{
$this->scheduledContactReminder = $contactReminder;
$this->user = $user;
}

/**
* Build the message.
*
* @return $this
*/
public function build()
{
$contact = $this->scheduledContactReminder->reminder->contact;
$contactName = NameHelper::formatContactName($this->user, $contact);

$reason = $this->scheduledContactReminder->reminder->label;

return $this->subject(trans('email.notification_reminder_email', ['name' => $contactName]))
->markdown('emails.notifications.reminder', [
'name' => $this->user->name,
'reason' => $reason,
'contactName' => $contactName,
]);
}
}
19 changes: 6 additions & 13 deletions app/Models/ScheduledContactReminder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ class ScheduledContactReminder extends Model
*/
protected $fillable = [
'contact_reminder_id',
'user_notification_channel_id',
'scheduled_at',
'triggered_at',
'triggered',
];

/**
Expand All @@ -29,18 +30,10 @@ class ScheduledContactReminder extends Model
* @var array
*/
protected $dates = [
'scheduled_at',
'triggered_at',
];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'triggered' => 'boolean',
];

/**
* Get the contact reminder associated with the scheduled contact reminder.
*
Expand All @@ -52,12 +45,12 @@ public function reminder()
}

/**
* Get the user associated with the scheduled contact reminder.
* Get the user notification channel associated with the scheduled contact reminder.
*
* @return BelongsTo
*/
public function user()
public function userNotificationChannel()
{
return $this->belongsTo(User::class);
return $this->belongsTo(UserNotificationChannel::class);
}
}
21 changes: 21 additions & 0 deletions app/Services/Account/ManageUsers/AcceptInvitation.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use App\Services\BaseService;
use App\Interfaces\ServiceInterface;
use Illuminate\Support\Facades\Hash;
use App\Models\UserNotificationChannel;
use App\Services\User\NotificationChannels\CreateUserNotificationChannel;

class AcceptInvitation extends BaseService implements ServiceInterface
{
Expand Down Expand Up @@ -41,6 +43,7 @@ public function execute(array $data): User
$this->validateRules($data);
$this->findUserByInvitationCode();
$this->updateUser();
$this->createNotificationChannel();

return $this->user;
}
Expand All @@ -60,6 +63,24 @@ private function updateUser(): void
$this->user->invitation_accepted_at = Carbon::now();
$this->user->email_verified_at = Carbon::now();
$this->user->password = Hash::make($this->data['password']);
$this->user->timezone = 'UTC';
$this->user->save();
}

private function createNotificationChannel(): void
{
$channel = (new CreateUserNotificationChannel)->execute([
'account_id' => $this->user->account_id,
'author_id' => $this->user->id,
'label' => trans('app.notification_channel_email'),
'type' => UserNotificationChannel::TYPE_EMAIL,
'content' => $this->user->email,
'verify_email' => false,
'preferred_time' => '09:00',
]);

$channel->verified_at = Carbon::now();
$channel->active = true;
$channel->save();
}
}
4 changes: 4 additions & 0 deletions app/Services/Contact/ManageReminder/CreateReminder.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public function execute(array $data): ContactReminder
$this->contact->last_updated_at = Carbon::now();
$this->contact->save();

(new ScheduleContactReminder)->execute([
'contact_reminder_id' => $this->reminder->id,
]);

$this->log();

return $this->reminder;
Expand Down
Loading

0 comments on commit 896da02

Please sign in to comment.