304 lines
11 KiB
Python
304 lines
11 KiB
Python
"""
|
|
Email and notification utilities for appointments app.
|
|
"""
|
|
from django.core.mail import send_mail, EmailMultiAlternatives
|
|
from django.template.loader import render_to_string
|
|
from django.conf import settings
|
|
from django.utils import timezone
|
|
from core.utils import AuditLogger
|
|
|
|
|
|
class AppointmentNotifications:
|
|
"""
|
|
Handle email notifications for appointment-related events.
|
|
"""
|
|
|
|
@staticmethod
|
|
def send_appointment_confirmation(appointment):
|
|
"""
|
|
Send confirmation email when appointment request is created.
|
|
"""
|
|
try:
|
|
subject = f'Appointment Request Confirmation - {appointment.request_id}'
|
|
|
|
# Render HTML email
|
|
html_content = render_to_string('appointments/emails/appointment_confirmation.html', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
# Render plain text email
|
|
text_content = render_to_string('appointments/emails/appointment_confirmation.txt', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
# Send email
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[appointment.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
# Log notification
|
|
AuditLogger.log_event(
|
|
tenant=appointment.tenant,
|
|
event_type='NOTIFICATION',
|
|
event_category='APPOINTMENT_MANAGEMENT',
|
|
action='Send Appointment Confirmation Email',
|
|
description=f'Sent confirmation email to {appointment.patient.user.email}',
|
|
user=None,
|
|
content_object=appointment,
|
|
request=None
|
|
)
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending appointment confirmation email: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def send_appointment_reminder(appointment, hours_before=24):
|
|
"""
|
|
Send reminder email before appointment.
|
|
"""
|
|
try:
|
|
subject = f'Appointment Reminder - {appointment.scheduled_datetime.strftime("%B %d, %Y")}'
|
|
|
|
html_content = render_to_string('appointments/emails/appointment_reminder.html', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
'hours_before': hours_before,
|
|
})
|
|
|
|
text_content = render_to_string('appointments/emails/appointment_reminder.txt', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
'hours_before': hours_before,
|
|
})
|
|
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[appointment.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
# Log notification
|
|
AuditLogger.log_event(
|
|
tenant=appointment.tenant,
|
|
event_type='NOTIFICATION',
|
|
event_category='APPOINTMENT_MANAGEMENT',
|
|
action='Send Appointment Reminder Email',
|
|
description=f'Sent {hours_before}h reminder to {appointment.patient.user.email}',
|
|
user=None,
|
|
content_object=appointment,
|
|
request=None
|
|
)
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending appointment reminder email: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def send_appointment_cancelled(appointment):
|
|
"""
|
|
Send notification when appointment is cancelled.
|
|
"""
|
|
try:
|
|
subject = f'Appointment Cancelled - {appointment.request_id}'
|
|
|
|
html_content = render_to_string('appointments/emails/appointment_cancelled.html', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
text_content = render_to_string('appointments/emails/appointment_cancelled.txt', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[appointment.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
# Log notification
|
|
AuditLogger.log_event(
|
|
tenant=appointment.tenant,
|
|
event_type='NOTIFICATION',
|
|
event_category='APPOINTMENT_MANAGEMENT',
|
|
action='Send Appointment Cancellation Email',
|
|
description=f'Sent cancellation email to {appointment.patient.user.email}',
|
|
user=None,
|
|
content_object=appointment,
|
|
request=None
|
|
)
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending appointment cancellation email: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def send_appointment_rescheduled(appointment):
|
|
"""
|
|
Send notification when appointment is rescheduled.
|
|
"""
|
|
try:
|
|
subject = f'Appointment Rescheduled - {appointment.request_id}'
|
|
|
|
html_content = render_to_string('appointments/emails/appointment_rescheduled.html', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
text_content = render_to_string('appointments/emails/appointment_rescheduled.txt', {
|
|
'appointment': appointment,
|
|
'patient': appointment.patient,
|
|
'provider': appointment.provider,
|
|
})
|
|
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[appointment.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
# Log notification
|
|
AuditLogger.log_event(
|
|
tenant=appointment.tenant,
|
|
event_type='NOTIFICATION',
|
|
event_category='APPOINTMENT_MANAGEMENT',
|
|
action='Send Appointment Rescheduled Email',
|
|
description=f'Sent rescheduled email to {appointment.patient.user.email}',
|
|
user=None,
|
|
content_object=appointment,
|
|
request=None
|
|
)
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending appointment rescheduled email: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def send_queue_position_update(queue_entry):
|
|
"""
|
|
Send notification when patient's queue position changes significantly.
|
|
"""
|
|
try:
|
|
subject = f'Queue Update - You are #{queue_entry.queue_position}'
|
|
|
|
html_content = render_to_string('appointments/emails/queue_position_update.html', {
|
|
'queue_entry': queue_entry,
|
|
'patient': queue_entry.patient,
|
|
'queue': queue_entry.queue,
|
|
})
|
|
|
|
text_content = render_to_string('appointments/emails/queue_position_update.txt', {
|
|
'queue_entry': queue_entry,
|
|
'patient': queue_entry.patient,
|
|
'queue': queue_entry.queue,
|
|
})
|
|
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[queue_entry.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending queue position update email: {e}")
|
|
return False
|
|
|
|
@staticmethod
|
|
def send_patient_called(queue_entry):
|
|
"""
|
|
Send notification when patient is called from queue.
|
|
"""
|
|
try:
|
|
subject = f'You are being called - {queue_entry.queue.name}'
|
|
|
|
html_content = render_to_string('appointments/emails/patient_called.html', {
|
|
'queue_entry': queue_entry,
|
|
'patient': queue_entry.patient,
|
|
'queue': queue_entry.queue,
|
|
})
|
|
|
|
text_content = render_to_string('appointments/emails/patient_called.txt', {
|
|
'queue_entry': queue_entry,
|
|
'patient': queue_entry.patient,
|
|
'queue': queue_entry.queue,
|
|
})
|
|
|
|
email = EmailMultiAlternatives(
|
|
subject=subject,
|
|
body=text_content,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
to=[queue_entry.patient.user.email],
|
|
)
|
|
email.attach_alternative(html_content, "text/html")
|
|
email.send()
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error sending patient called email: {e}")
|
|
return False
|
|
|
|
|
|
class QueueAudioNotifications:
|
|
"""
|
|
Handle audio notifications for queue management.
|
|
"""
|
|
|
|
@staticmethod
|
|
def get_notification_sound(notification_type='default'):
|
|
"""
|
|
Get the appropriate notification sound file.
|
|
"""
|
|
sounds = {
|
|
'default': 'sounds/notification.mp3',
|
|
'patient_called': 'sounds/patient_called.mp3',
|
|
'urgent': 'sounds/urgent.mp3',
|
|
'emergency': 'sounds/emergency.mp3',
|
|
}
|
|
return sounds.get(notification_type, sounds['default'])
|
|
|
|
@staticmethod
|
|
def should_play_sound(queue_entry):
|
|
"""
|
|
Determine if sound should be played based on priority.
|
|
"""
|
|
priority_sounds = {
|
|
'EMERGENCY': 'emergency',
|
|
'STAT': 'emergency',
|
|
'URGENT': 'urgent',
|
|
'ROUTINE': 'patient_called',
|
|
}
|
|
return priority_sounds.get(queue_entry.priority, 'default')
|