| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- <?php
- namespace App\Services;
- use App\Models\PushNotificationLog;
- use App\Notifications\Push\BasePushNotification;
- use App\Notifications\Push\Cliente\Marketing\AbandonoFunilPush;
- use App\Notifications\Push\Cliente\Marketing\ClienteInativoPush;
- use App\Notifications\Push\Cliente\Marketing\RecorrenciaQuebradaPush;
- use Illuminate\Support\Collection;
- class PushNotificationDispatcher
- {
- public function __construct(private PushNotificationService $pushService) {}
- /**
- * @return BasePushNotification[]
- */
- public function all(): array
- {
- return [
- // Cliente — Marketing
- new AbandonoFunilPush,
- new RecorrenciaQuebradaPush,
- new ClienteInativoPush,
- ];
- }
- /**
- * Processa todas as notificações: aplica cooldowns e envia para elegíveis.
- */
- public function dispatch(): void
- {
- foreach ($this->all() as $notification) {
- $users = $notification->eligibleUsers();
- if ($users->isEmpty()) {
- continue;
- }
- $filtered = $this->applyCooldowns($users, $notification);
- if ($filtered->isEmpty()) {
- continue;
- }
- $this->pushService->sendToUsers($filtered, $notification);
- }
- }
- /**
- * Remove da coleção os usuários que ainda estão em cooldown
- * (tanto de categoria quanto de notificação específica).
- */
- private function applyCooldowns(Collection $users, BasePushNotification $notification): Collection
- {
- $userIds = $users->pluck('id');
- $blockedByCategory = collect();
- if ($notification->categoryCooldownDays() > 0) {
- $blockedByCategory = PushNotificationLog::whereIn('user_id', $userIds)
- ->where('target', $notification->target()->value)
- ->where('category', $notification->category()->value)
- ->where('sent_at', '>=', now()->subDays($notification->categoryCooldownDays()))
- ->pluck('user_id')
- ->unique();
- }
- $blockedByNotification = PushNotificationLog::whereIn('user_id', $userIds)
- ->where('label', $notification->label())
- ->where('sent_at', '>=', now()->subDays($notification->notificationCooldownDays()))
- ->pluck('user_id')
- ->unique();
- $blocked = $blockedByCategory->merge($blockedByNotification)->unique();
- return $users->whereNotIn('id', $blocked)->values();
- }
- }
|