279 lines
9.5 KiB
PHP
Executable File
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
|
|
}
|
|
}
|
|
|