physiotherapy-clinic/app/Services/ReminderService.php

138 lines
3.8 KiB
PHP

<?php
namespace App\Services;
use App\Models\Reminder;
use App\Models\ReminderTemplate;
use App\Models\Appointment;
use Carbon\Carbon;
class ReminderService
{
/**
* Generate reminders for an appointment
*/
public function generateReminders(Appointment $appointment): void
{
$templates = ReminderTemplate::where('is_active', true)->get();
foreach ($templates as $template) {
$sendAt = $appointment->appointment_date->copy()->subHours($template->hours_before);
// Don't create if send time is in the past
if ($sendAt->isPast()) {
continue;
}
$placeholders = [
'patient_name' => $appointment->patient->fullName(),
'date' => $appointment->appointment_date->format('Y-m-d'),
'time' => $appointment->appointment_date->format('H:i'),
'therapist_name' => $appointment->user->name,
];
Reminder::create([
'appointment_id' => $appointment->id,
'template_id' => $template->id,
'channel' => $template->channel,
'content' => $template->parseContent($placeholders),
'send_at' => $sendAt,
'status' => 'queued',
]);
}
}
/**
* Get due reminders
*/
public function getDueReminders(int $limit = 50): array
{
return Reminder::with('appointment.patient')
->where('status', 'queued')
->where('send_at', '<=', now())
->limit($limit)
->get()
->toArray();
}
/**
* Process and send reminders
*/
public function processReminders(): array
{
$reminders = Reminder::with('appointment.patient')
->where('status', 'queued')
->where('send_at', '<=', now())
->get();
$results = [
'sent' => 0,
'failed' => 0,
];
foreach ($reminders as $reminder) {
try {
$this->sendReminder($reminder);
$reminder->markAsSent();
$results['sent']++;
} catch (\Exception $e) {
$reminder->markAsFailed($e->getMessage());
$results['failed']++;
}
}
return $results;
}
/**
* Send a single reminder (stub - implement with actual SMS/WhatsApp provider)
*/
public function sendReminder(Reminder $reminder): void
{
// Stub implementation - integrate with SMS/WhatsApp provider
$channel = $reminder->channel;
$content = $reminder->content;
switch ($channel) {
case 'sms':
// TODO: Integrate with SMS provider
break;
case 'whatsapp':
// TODO: Integrate with WhatsApp Business API
break;
case 'email':
// TODO: Send email
break;
case 'internal':
// Internal notification - logged only
break;
}
}
/**
* Get reminder configuration
*/
public function getConfiguration(): array
{
return ReminderTemplate::where('is_active', true)
->get()
->map(fn($t) => [
'id' => $t->id,
'name' => $t->name,
'channel' => $t->channel,
'hours_before' => $t->hours_before,
])
->toArray();
}
/**
* Update reminder configuration
*/
public function updateConfiguration(int $templateId, array $data): ReminderTemplate
{
$template = ReminderTemplate::findOrFail($templateId);
$template->update($data);
return $template;
}
}