85 lines
3.3 KiB
PHP
85 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Notifications;
|
|
|
|
use App\Models\Notification;
|
|
use App\Models\UserNotification;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class NotificationSendService
|
|
{
|
|
public function __construct(
|
|
private NotificationRecipientService $recipients,
|
|
private NotificationDispatchService $dispatcher
|
|
) {
|
|
}
|
|
|
|
public function send(array $payload, int $actorId): array
|
|
{
|
|
$channels = $payload['channels'] ?? ['in_app'];
|
|
$channels = array_values(array_unique(array_map('strtolower', (array) $channels)));
|
|
if (empty($channels)) {
|
|
$channels = ['in_app'];
|
|
}
|
|
|
|
return DB::transaction(function () use ($payload, $channels, $actorId) {
|
|
$notification = Notification::query()->create([
|
|
'title' => $payload['title'],
|
|
'message' => $payload['message'],
|
|
'target_group' => $payload['target_group'],
|
|
'delivery_channels' => $channels,
|
|
'priority' => $payload['priority'] ?? null,
|
|
'status' => $payload['status'] ?? null,
|
|
'action_url' => $payload['action_url'] ?? null,
|
|
'attachment_path' => $payload['attachment_path'] ?? null,
|
|
'scheduled_at' => $payload['scheduled_at'] ?? now(),
|
|
'sent_at' => in_array('in_app', $channels, true) ? now() : null,
|
|
'expires_at' => $payload['expires_at'] ?? null,
|
|
'school_year' => $payload['school_year'] ?? null,
|
|
'semester' => $payload['semester'] ?? null,
|
|
'created_at' => utc_now(),
|
|
'updated_at' => utc_now(),
|
|
]);
|
|
|
|
$users = $this->recipients->getRecipients((string) $payload['target_group']);
|
|
$created = 0;
|
|
|
|
foreach ($users as $user) {
|
|
UserNotification::query()->create([
|
|
'notification_id' => (int) $notification->id,
|
|
'user_id' => (int) ($user['id'] ?? 0),
|
|
'is_read' => false,
|
|
'delivered' => in_array('in_app', $channels, true),
|
|
'delivered_at' => in_array('in_app', $channels, true) ? now() : null,
|
|
'school_year' => $payload['school_year'] ?? null,
|
|
'semester' => $payload['semester'] ?? null,
|
|
]);
|
|
$created++;
|
|
|
|
if (in_array('email', $channels, true) && !empty($user['email'])) {
|
|
$this->dispatcher->sendEmail((string) $user['email'], (string) $payload['title'], (string) $payload['message']);
|
|
}
|
|
|
|
if (in_array('sms', $channels, true) && !empty($user['phone'])) {
|
|
$this->dispatcher->sendSms((string) $user['phone'], (string) $payload['message']);
|
|
}
|
|
}
|
|
|
|
Log::info('Notification dispatched.', [
|
|
'notification_id' => (int) $notification->id,
|
|
'target_group' => $payload['target_group'],
|
|
'channels' => $channels,
|
|
'recipients' => $created,
|
|
'actor_id' => $actorId,
|
|
]);
|
|
|
|
return [
|
|
'ok' => true,
|
|
'notification' => $notification,
|
|
'recipient_count' => $created,
|
|
];
|
|
});
|
|
}
|
|
}
|