Skip to content

Commit

Permalink
feat: #81 send e-mail notifications regarding ending trial
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdan-shulha committed Jul 26, 2024
1 parent ad0586b commit 00ec406
Show file tree
Hide file tree
Showing 9 changed files with 973 additions and 7 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ If you discover a security vulnerability within Ptah.sh services, please send an
## License

The Ptah.sh service suite is open-sourced software licensed under the [Functional Source License, Version 1.1, Apache 2.0 Future License](https://github.com/ptah-sh/ptah-server/blob/main/LICENSE.md).

## Star History ★

[![Star History Chart](https://api.star-history.com/svg?repos=ptah-sh/ptah-server&type=Date)](https://star-history.com/#ptah-sh/ptah-server&Date)
50 changes: 50 additions & 0 deletions app/Listeners/ScheduleTrialEndNotifications.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Listeners;

use App\Models\Team;
use App\Notifications\TrialEndsSoonNotification;
use Carbon\CarbonInterval;
use Illuminate\Events\Dispatcher;
use Laravel\Paddle\Events\SubscriptionCreated;
use Laravel\Paddle\Events\SubscriptionUpdated;

class ScheduleTrialEndNotifications
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}

/**
* Handle the event.
*/
public function subscribe(Dispatcher $dispatcher): array
{
return [
SubscriptionCreated::class => 'scheduleNotifications',
SubscriptionUpdated::class => 'scheduleNotifications',
];
}

public function scheduleNotifications(SubscriptionCreated|SubscriptionUpdated $event): void
{
if (! $event->subscription->trial_ends_at) {
return;
}

$subscription = $event->subscription;

/* @var Team $team */
$team = $subscription->billable;

$days3 = $subscription->trial_ends_at->sub(CarbonInterval::days(3))->diffAsDateInterval(now(), absolute: true);
$team->notify((new TrialEndsSoonNotification($team))->delay($days3));

$days1 = $subscription->trial_ends_at->sub(CarbonInterval::day())->diffAsDateInterval(now(), absolute: true);
$team->notify((new TrialEndsSoonNotification($team))->delay($days1));
}
}
14 changes: 13 additions & 1 deletion app/Models/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
use Laravel\Jetstream\Events\TeamCreated;
use Laravel\Jetstream\Events\TeamDeleted;
use Laravel\Jetstream\Events\TeamUpdated;
Expand All @@ -14,6 +16,7 @@ class Team extends JetstreamTeam
{
use HasFactory;
use Billable;
use Notifiable;

/**
* The attributes that are mass assignable.
Expand Down Expand Up @@ -79,12 +82,21 @@ protected function paddleEmail(): string
return $this->owner->email;
}

protected function getBillingAttribute(): array
protected function getBillingAttribute(): array | null
{
if ($this->subscription() === null) {
return null;
}

return collect($this->subscription()->toArray())->only([
'status',
'trial_ends_at',
'ends_at',
])->toArray();
}

public function routeNotificationForMail(Notification $notification): array | string
{
return [$this->customer->email => $this->customer->name];
}
}
65 changes: 65 additions & 0 deletions app/Notifications/TrialEndsSoonNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\Notifications;

use App\Models\Team;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class TrialEndsSoonNotification extends Notification implements ShouldQueue
{
use Queueable;

/**
* Create a new notification instance.
*/
public function __construct(
protected Team $team,
)
{
$this->afterCommit();
}

public function shouldSend(object $notifiable, string $channel): bool
{
return $this->team->onTrial();
}

/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['mail'];
}

/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
$nextPayment = $this->team->subscription()->nextPayment();

return (new MailMessage)
->line('Your trial ends soon.')
->line("You will be charged {$nextPayment->amount()} on {$nextPayment->date->toDateTimeString()} ({$nextPayment->date->longRelativeToNowDiffForHumans()}).")
->action('Manage Subscription', url(route('teams.billing.show', $this->team)))
->line('Any other questions? Contact us at '.config('app.email'));
}

/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
//
];
}
}
4 changes: 3 additions & 1 deletion app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Providers;

use App\Listeners\ScheduleTrialEndNotifications;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
Expand All @@ -19,6 +21,6 @@ public function register(): void
*/
public function boot(): void
{
//
Event::subscribe(ScheduleTrialEndNotifications::class);
}
}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"spatie/laravel-data": "^4.7",
"spatie/laravel-ray": "^1.37",
"tightenco/ziggy": "^2.0"
},
"require-dev": {
Expand Down
Loading

0 comments on commit 00ec406

Please sign in to comment.