feat: Add notification services for Email, Telegram, and WhatsApp
- Implement EmailNotifier for sending batch and test notifications via email. - Implement TelegramNotifier for sending batch and test notifications via Telegram. - Implement WahaNotifier for sending batch and test notifications via WhatsApp using WAHA API. - Create migration for client_categories table and update clients table to include category_id. - Create migration for notification_settings table to manage notification configurations. - Add ClientCategorySeeder to populate default client categories. - Create manifest.json for PWA support. - Implement service worker (sw.js) for caching static assets and offline support. - Add edit event view for modifying scheduled events. - Create search results view for displaying search queries. - Develop notification settings view for configuring notification channels and triggers.
This commit is contained in:
113
app/Services/NotificationDispatcher.php
Normal file
113
app/Services/NotificationDispatcher.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ContentBrief;
|
||||
use App\Models\Event;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\NotificationSetting;
|
||||
use App\Services\Notifications\EmailNotifier;
|
||||
use App\Services\Notifications\TelegramNotifier;
|
||||
use App\Services\Notifications\WahaNotifier;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class NotificationDispatcher
|
||||
{
|
||||
/** Dispatch all due notifications for enabled channels */
|
||||
public function dispatchAll(): void
|
||||
{
|
||||
$settings = NotificationSetting::where('is_enabled', true)->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}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user