File: /home/xedaptot/ai.naniguide.com/app/Notifications/Admin/CustomerSubscriptionOverdue.php
<?php
namespace App\Notifications\Admin;
use App\Model\Subscription;
use App\Notifications\AppNotification;
use Illuminate\Database\Eloquent\Model;
/**
* Shared admin bell row when the cron detects a customer's subscription has
* passed its period end. Two states mirror the customer-facing event:
*
* - 'grace' : within Setting('grace_period') days of period_end, still ACTIVE
* - 'expired' : suspended this cron tick (status set to ENDED)
*
* Audience is `admins` so the row is shared (1 INSERT, every admin sees it).
* The group_key is keyed by subscription uid + state so repeat ticks dedupe and
* a state transition produces a fresh row.
*/
class CustomerSubscriptionOverdue extends AppNotification
{
public const STATE_GRACE = 'grace';
public const STATE_EXPIRED = 'expired';
public function __construct(public Subscription $subscription, public string $state) {}
public function audience(): string { return self::AUDIENCE_ADMINS; }
public function category(): string { return self::CATEGORY_INFO; }
public function severity(): string
{
return match ($this->state) {
self::STATE_GRACE => self::SEVERITY_WARNING,
self::STATE_EXPIRED => self::SEVERITY_INFO,
};
}
public function groupKey(): string
{
return 'customer-subscription-overdue:' . $this->subscription->uid . ':' . $this->state;
}
public function subject(): ?Model
{
return $this->subscription;
}
public function toArray(object $notifiable = null): array
{
$customer = $this->subscription->customer;
$planName = $this->subscription->plan->name ?? '—';
$periodEnd = optional($this->subscription->current_period_ends_at)->toDateString() ?? '—';
return [
'title' => trans('refactor/notifications.subscription_overdue.admin.' . $this->state . '.title'),
'body' => trans('refactor/notifications.subscription_overdue.admin.' . $this->state . '.body', [
'customer' => $customer?->displayName() ?? '—',
'email' => $customer?->email ?? '—',
'plan' => $planName,
'date' => $periodEnd,
]),
];
}
}