NotifyProvidersOfNewOpportunityJob.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <?php
  2. namespace App\Jobs;
  3. use App\Enums\PushNotificationTargetEnum;
  4. use App\Models\Provider;
  5. use App\Models\Schedule;
  6. use App\Models\User;
  7. use App\Services\CustomScheduleService;
  8. use Carbon\Carbon;
  9. use Illuminate\Bus\Queueable;
  10. use Illuminate\Contracts\Queue\ShouldQueue;
  11. use Illuminate\Foundation\Bus\Dispatchable;
  12. use Illuminate\Queue\InteractsWithQueue;
  13. use Illuminate\Queue\SerializesModels;
  14. use Illuminate\Support\Facades\Log;
  15. class NotifyProvidersOfNewOpportunityJob implements ShouldQueue
  16. {
  17. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  18. public int $tries = 3;
  19. public int $timeout = 60;
  20. public array $backoff = [10, 60, 300];
  21. /**
  22. * @param int[] $scheduleIds
  23. */
  24. public function __construct(public readonly array $scheduleIds) {}
  25. public function handle(CustomScheduleService $customScheduleService): void
  26. {
  27. $scheduleId = $this->scheduleIds[0] ?? null;
  28. if (! $scheduleId) {
  29. return;
  30. }
  31. $schedule = Schedule::with(['customSchedule', 'address'])->find($scheduleId);
  32. if (! $this->shouldNotify($schedule)) {
  33. return;
  34. }
  35. $providerIds = $customScheduleService->getAvailableProvidersForOpportunity($schedule);
  36. if ($providerIds->isEmpty()) {
  37. Log::info('Nenhum prestador disponivel para a nova oportunidade', [
  38. 'schedule_id' => $schedule->id,
  39. ]);
  40. return;
  41. }
  42. $userIds = User::query()
  43. ->whereIn('id', Provider::whereIn('id', $providerIds)->pluck('user_id'))
  44. ->where('push_notifications_enabled', true)
  45. ->whereHas('deviceTokens', function ($query) {
  46. $query->where('app_type', PushNotificationTargetEnum::PRESTADOR->value)
  47. ->where('active', true);
  48. })
  49. ->pluck('id');
  50. if ($userIds->isEmpty()) {
  51. return;
  52. }
  53. $district = $schedule->address?->district;
  54. $dateLabel = Carbon::parse($schedule->date)->format('d/m');
  55. $quantity = count($this->scheduleIds);
  56. $userIds->chunk(50)->each(function ($chunk) use ($schedule, $district, $dateLabel, $quantity) {
  57. foreach ($chunk as $userId) {
  58. SendOpportunityPushJob::dispatch(
  59. $userId,
  60. $schedule->id,
  61. $district,
  62. $dateLabel,
  63. $quantity,
  64. );
  65. }
  66. });
  67. }
  68. public function failed(\Throwable $exception): void
  69. {
  70. Log::error('Falha ao notificar prestadores de nova oportunidade', [
  71. 'schedule_ids' => $this->scheduleIds,
  72. 'error' => $exception->getMessage(),
  73. ]);
  74. }
  75. private function shouldNotify(?Schedule $schedule): bool
  76. {
  77. if (! $schedule || ! $schedule->customSchedule) {
  78. return false;
  79. }
  80. if ($schedule->schedule_type !== 'custom' || $schedule->status !== 'pending') {
  81. return false;
  82. }
  83. if ($schedule->provider_id !== null) {
  84. return false;
  85. }
  86. return ! Carbon::parse($schedule->date)->lt(today());
  87. }
  88. }