Files
alrahma_sunday_school_api/app/Http/Controllers/Api/NotificationManagementController.php
T
2026-03-05 12:29:37 -05:00

279 lines
9.5 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\Api;
use App\Models\Notification;
use App\Models\UserNotification;
use App\Models\User;
use App\Services\EmailService;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;
class NotificationManagementController extends BaseApiController
{
protected Notification $notification;
protected UserNotification $userNotification;
protected User $user;
protected EmailService $emailService;
public function __construct()
{
parent::__construct();
$this->notification = model(Notification::class);
$this->userNotification = model(UserNotification::class);
$this->user = model(User::class);
$this->emailService = app(EmailService::class);
}
/**
* GET /api/v1/notifications/active
* Get active (non-deleted, non-expired) notifications
*/
public function activeNotificationsData()
{
try {
$targetGroup = $this->request->getGet('target_group');
$payload = $this->buildActiveNotificationsPayload($targetGroup);
return $this->success($payload, 'Active notifications retrieved successfully');
} catch (\Throwable $e) {
log_message('error', 'Active notifications data error: ' . $e->getMessage());
return $this->respondError('Failed to retrieve active notifications', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* GET /api/v1/notifications/deleted
* Get soft-deleted notifications
*/
public function deletedNotificationsData()
{
try {
$payload = $this->buildDeletedNotificationsPayload();
return $this->success($payload, 'Deleted notifications retrieved successfully');
} catch (\Throwable $e) {
log_message('error', 'Deleted notifications data error: ' . $e->getMessage());
return $this->respondError('Failed to retrieve deleted notifications', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* POST /api/v1/notifications/send
* Create and send notifications to a target group
*/
public function send()
{
$user = $this->getCurrentUser();
if (!$user) {
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
}
$payload = $this->payloadData();
$title = trim((string) ($payload['title'] ?? ''));
$message = trim((string) ($payload['message'] ?? ''));
$group = trim((string) ($payload['target_group'] ?? ''));
$channels = (array) ($payload['channels'] ?? []);
if (empty($title) || empty($message) || empty($group) || empty($channels)) {
return $this->respondError('Title, message, target_group, and channels are required', Response::HTTP_BAD_REQUEST);
}
try {
// Create notification
$notifId = $this->notification->insert([
'title' => $title,
'message' => $message,
'target_group' => $group,
'delivery_channels' => implode(',', $channels),
'created_at' => utc_now(),
], true);
if (!$notifId) {
return $this->respondError('Failed to create notification', Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Get users by role (target_group)
$users = $this->user->getUsersByRole($group);
$sentCount = 0;
$emailCount = 0;
$smsCount = 0;
foreach ($users as $user) {
// Create user notification record
$this->userNotification->insert([
'notification_id' => $notifId,
'user_id' => (int) $user['id'],
'is_read' => 0,
]);
// Send via email if requested
if (in_array('email', $channels) && !empty($user['email'])) {
try {
$this->sendEmail($user['email'], $title, $message);
$emailCount++;
} catch (\Throwable $e) {
log_message('error', 'Failed to send email to ' . $user['email'] . ': ' . $e->getMessage());
}
}
// Send via SMS if requested
if (in_array('sms', $channels) && !empty($user['cellphone'])) {
try {
$this->sendSMS($user['cellphone'], $message);
$smsCount++;
} catch (\Throwable $e) {
log_message('error', 'Failed to send SMS to ' . $user['cellphone'] . ': ' . $e->getMessage());
}
}
$sentCount++;
}
return $this->success([
'notification_id' => $notifId,
'users_notified' => $sentCount,
'emails_sent' => $emailCount,
'sms_sent' => $smsCount,
], 'Notification sent successfully');
} catch (\Throwable $e) {
log_message('error', 'Notification send error: ' . $e->getMessage());
return $this->respondError('Failed to send notification: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* POST /api/v1/notifications/{id}/restore
* Restore a soft-deleted notification
*/
public function restore($id)
{
try {
$id = (int) $id;
// Check if notification exists and is deleted
$notification = $this->notification->withDeleted()->find($id);
if (!$notification) {
return $this->respondError('Notification not found', Response::HTTP_NOT_FOUND);
}
$restored = $this->notification->restoreNotification($id);
// Check if update was successful (update returns affected rows or false)
if ($restored !== false) {
return $this->success([
'id' => $id,
], 'Notification restored successfully');
}
return $this->respondError('Failed to restore notification', Response::HTTP_BAD_REQUEST);
} catch (\Throwable $e) {
log_message('error', 'Notification restore error: ' . $e->getMessage());
return $this->respondError('Failed to restore notification: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Build active notifications payload
*/
private function buildActiveNotificationsPayload(?string $targetGroup): array
{
$targetGroup = $targetGroup !== null ? trim($targetGroup) : null;
if ($targetGroup === '') {
$targetGroup = null;
}
$rows = $this->notification->getActiveNotifications($targetGroup);
if (!is_array($rows)) {
$rows = [];
}
$now = time();
$notifications = array_map(static function ($row) use ($now) {
if (!is_array($row)) {
return [];
}
$expiresAt = $row['expires_at'] ?? null;
$expiryTs = $expiresAt ? strtotime((string) $expiresAt) : false;
$isExpired = $expiryTs !== false && $expiryTs <= $now;
return [
'id' => $row['id'] ?? null,
'title' => $row['title'] ?? null,
'message' => $row['message'] ?? null,
'priority' => $row['priority'] ?? null,
'scheduled_at' => $row['scheduled_at'] ?? null,
'expires_at' => $expiresAt,
'created_at' => $row['created_at'] ?? null,
'target_group' => $row['target_group'] ?? null,
'isExpired' => $isExpired,
];
}, $rows);
return [
'notifications' => $notifications,
];
}
/**
* Build deleted notifications payload
*/
private function buildDeletedNotificationsPayload(): array
{
$rows = $this->notification->getDeletedNotifications();
if (!is_array($rows)) {
$rows = [];
}
$notifications = array_map(static function ($row) {
if (!is_array($row)) {
return [];
}
return [
'id' => $row['id'] ?? null,
'title' => $row['title'] ?? null,
'message' => $row['message'] ?? null,
'priority' => $row['priority'] ?? null,
'scheduled_at' => $row['scheduled_at'] ?? null,
'expires_at' => $row['expires_at'] ?? null,
'deleted_at' => $row['deleted_at'] ?? null,
];
}, $rows);
return [
'notifications' => $notifications,
];
}
/**
* Send email notification
*/
protected function sendEmail(string $to, string $subject, string $message): void
{
try {
$this->emailService->setTo($to);
$this->emailService->setSubject($subject);
$this->emailService->setMessage($message);
$this->emailService->send();
} catch (\Throwable $e) {
log_message('error', 'Email send error: ' . $e->getMessage());
throw $e;
}
}
/**
* Send SMS notification (placeholder - logs for now)
*/
protected function sendSMS(string $phone, string $message): void
{
log_message('info', "SMS to {$phone}: {$message}");
// TODO: Implement actual SMS sending via SendSMSController or SMS service
}
}