get(); foreach ($settings as $setting) { try { $this->dispatchForSetting($setting); } catch (\Throwable $e) { Log::error("Notification dispatch failed for [{$setting->name}]: " . $e->getMessage()); } } } public function dispatchForSetting(NotificationSetting $setting): void { $triggers = $setting->triggers ?? []; $hours = $setting->notify_before_hours; $messages = collect(); if (in_array('upcoming_event', $triggers)) { $events = Event::with('client') ->where('start_time', '>=', now()) ->where('start_time', '<=', now()->addHours($hours)) ->whereNotIn('status', ['completed', 'cancelled']) ->get(); foreach ($events as $event) { $messages->push( "๐Ÿ“… *Upcoming Event*\n" . "*{$event->title}*\n" . "โฐ " . $event->start_time->format('d M Y, H:i') . "\n" . ($event->client ? "๐Ÿ‘ค {$event->client->name}\n" : '') . ($event->location ? "๐Ÿ“ {$event->location}" : '') ); } } if (in_array('invoice_due', $triggers)) { $invoices = Invoice::with('client') ->whereBetween('due_date', [now(), now()->addHours($hours)]) ->whereNotIn('status', ['paid', 'cancelled']) ->get(); foreach ($invoices as $inv) { $messages->push( "๐Ÿงพ *Invoice Due Soon*\n" . "*{$inv->invoice_number}*" . ($inv->title ? " โ€” {$inv->title}" : '') . "\n" . "๐Ÿ“… Due: " . $inv->due_date->format('d M Y') . "\n" . ($inv->client ? "๐Ÿ‘ค {$inv->client->name}\n" : '') . ($inv->formatted_total ?? '') ); } } if (in_array('content_due', $triggers)) { $content = ContentBrief::with('client') ->whereBetween('target_date', [now(), now()->addHours($hours)]) ->whereNotIn('status', ['posted', 'archived']) ->get(); foreach ($content as $c) { $messages->push( "๐ŸŽฌ *Content Target*\n" . "*{$c->title}*\n" . "๐Ÿ“… " . $c->target_date->format('d M Y') . "\n" . ucfirst($c->platform) . ($c->client ? " ยท {$c->client->name}" : '') ); } } if ($messages->isEmpty()) return; $notifier = $this->resolveNotifier($setting); $notifier->sendBatch($setting, $messages->all()); } /** Send a simple test message */ public function sendTest(NotificationSetting $setting): void { $this->resolveNotifier($setting)->sendTest($setting); } private function resolveNotifier(NotificationSetting $setting): EmailNotifier|TelegramNotifier|WahaNotifier { return match ($setting->channel) { 'email' => new EmailNotifier, 'telegram' => new TelegramNotifier, 'whatsapp' => new WahaNotifier, default => throw new \InvalidArgumentException("Unknown channel: {$setting->channel}"), }; } }