138 lines
3.8 KiB
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;
|
|
}
|
|
}
|