PushNotificationDispatcher.php 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <?php
  2. namespace App\Services;
  3. use App\Models\PushNotificationLog;
  4. use App\Notifications\Push\BasePushNotification;
  5. use App\Notifications\Push\Cliente\Marketing\AbandonoFunilPush;
  6. use App\Notifications\Push\Cliente\Marketing\ClienteInativoPush;
  7. use App\Notifications\Push\Cliente\Marketing\RecorrenciaQuebradaPush;
  8. use Illuminate\Support\Collection;
  9. class PushNotificationDispatcher
  10. {
  11. public function __construct(private PushNotificationService $pushService) {}
  12. /**
  13. * @return BasePushNotification[]
  14. */
  15. public function all(): array
  16. {
  17. return [
  18. // Cliente — Marketing
  19. new AbandonoFunilPush,
  20. new RecorrenciaQuebradaPush,
  21. new ClienteInativoPush,
  22. ];
  23. }
  24. /**
  25. * Processa todas as notificações: aplica cooldowns e envia para elegíveis.
  26. */
  27. public function dispatch(): void
  28. {
  29. foreach ($this->all() as $notification) {
  30. $users = $notification->eligibleUsers();
  31. if ($users->isEmpty()) {
  32. continue;
  33. }
  34. $filtered = $this->applyCooldowns($users, $notification);
  35. if ($filtered->isEmpty()) {
  36. continue;
  37. }
  38. $this->pushService->sendToUsers($filtered, $notification);
  39. }
  40. }
  41. /**
  42. * Remove da coleção os usuários que ainda estão em cooldown
  43. * (tanto de categoria quanto de notificação específica).
  44. */
  45. private function applyCooldowns(Collection $users, BasePushNotification $notification): Collection
  46. {
  47. $userIds = $users->pluck('id');
  48. $blockedByCategory = collect();
  49. if ($notification->categoryCooldownDays() > 0) {
  50. $blockedByCategory = PushNotificationLog::whereIn('user_id', $userIds)
  51. ->where('target', $notification->target()->value)
  52. ->where('category', $notification->category()->value)
  53. ->where('sent_at', '>=', now()->subDays($notification->categoryCooldownDays()))
  54. ->pluck('user_id')
  55. ->unique();
  56. }
  57. $blockedByNotification = PushNotificationLog::whereIn('user_id', $userIds)
  58. ->where('label', $notification->label())
  59. ->where('sent_at', '>=', now()->subDays($notification->notificationCooldownDays()))
  60. ->pluck('user_id')
  61. ->unique();
  62. $blocked = $blockedByCategory->merge($blockedByNotification)->unique();
  63. return $users->whereNotIn('id', $blocked)->values();
  64. }
  65. }