Marwan Alwali 263292f6be update
2025-11-04 00:50:06 +03:00

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')