*/ public $backoff = [2, 5, 10, 30]; public function __construct( public User $user, public Budget $budget, public BudgetPeriod $period, public BudgetNotificationType $type, public ?Transaction $transaction = null, ) { $this->onQueue('emails'); } public function envelope(): Envelope { $subject = match ($this->type) { BudgetNotificationType::NewTransaction => __('New transaction in ":budget"', ['budget' => $this->budget->name]), BudgetNotificationType::CloseToLimit => __('":budget" is close to its limit', ['budget' => $this->budget->name]), BudgetNotificationType::OverLimit => __('":budget" is over its limit', ['budget' => $this->budget->name]), }; return new Envelope( from: new Address( config('mail.from.address', 'no-reply@whisper.money'), config('mail.from.name', 'Whisper Money'), ), subject: $subject, ); } public function content(): Content { $currency = $this->user->currency_code ?? 'USD'; $allocated = $this->period->allocated_amount; $spent = $this->period->spentAmount(); $remaining = $allocated - $spent; $hasLimit = $allocated > 0; return new Content( markdown: 'mail.budget-notification', with: [ 'userName' => $this->user->name, 'budgetName' => $this->budget->name, 'type' => $this->type, 'transaction' => $this->transaction, 'periodStart' => $this->period->start_date, 'periodEnd' => $this->period->end_date, 'hasLimit' => $hasLimit, 'allocatedFormatted' => Money::format($allocated, $currency), 'spentFormatted' => Money::format($spent, $currency), 'remainingFormatted' => Money::format(abs($remaining), $currency), 'transactionAmountFormatted' => $this->transaction ? Money::format(abs((int) $this->transaction->amount), $currency) : null, // Aligns with the service: at exactly the limit we are "over". 'isOverLimit' => $hasLimit && $spent >= $allocated, ], ); } /** * Get the middleware the job should pass through. * * @return array */ public function middleware(): array { return [(new RateLimited('emails'))->releaseAfter(1)]; } }