|
12 | 12 |
|
13 | 13 | from django.apps import apps
|
14 | 14 | from django.conf import settings
|
15 |
| -from django.contrib.auth.hashers import make_password |
16 | 15 | from django.core.cache import cache
|
17 | 16 | from django.core.exceptions import FieldDoesNotExist
|
18 | 17 | from django.urls import reverse
|
| 18 | +from django.utils import timezone |
| 19 | +from django_q.models import Schedule |
| 20 | +from django_q.tasks import schedule |
19 | 21 |
|
20 | 22 | from appointment.logger_config import logger
|
21 |
| -from appointment.settings import APPOINTMENT_SLOT_DURATION, APPOINTMENT_LEAD_TIME, APPOINTMENT_FINISH_TIME, \ |
22 |
| - APPOINTMENT_BUFFER_TIME, APPOINTMENT_WEBSITE_NAME, APPOINTMENT_PAYMENT_URL |
23 |
| -from appointment.utils.date_time import get_weekday_num, get_current_year |
| 23 | +from appointment.settings import (APPOINTMENT_BUFFER_TIME, APPOINTMENT_FINISH_TIME, APPOINTMENT_LEAD_TIME, |
| 24 | + APPOINTMENT_PAYMENT_URL, APPOINTMENT_SLOT_DURATION, APPOINTMENT_WEBSITE_NAME) |
| 25 | +from appointment.utils.date_time import combine_date_and_time, get_current_year, get_weekday_num |
24 | 26 |
|
25 | 27 | Appointment = apps.get_model('appointment', 'Appointment')
|
26 | 28 | AppointmentRequest = apps.get_model('appointment', 'AppointmentRequest')
|
@@ -100,10 +102,96 @@ def create_and_save_appointment(ar, client_data: dict, appointment_data: dict):
|
100 | 102 | **appointment_data
|
101 | 103 | )
|
102 | 104 | appointment.save()
|
103 |
| - logger.info(f"New appointment created: {appointment}") |
| 105 | + logger.info(f"New appointment created: {appointment.to_dict()}") |
| 106 | + schedule_email_reminder(appointment) |
104 | 107 | return appointment
|
105 | 108 |
|
106 | 109 |
|
| 110 | +def schedule_email_reminder(appointment, appointment_datetime=None): |
| 111 | + """Schedule an email reminder for the given appointment.""" |
| 112 | + # Check if the Django-Q cluster is running |
| 113 | + from appointment.settings import check_q_cluster |
| 114 | + if not check_q_cluster(): |
| 115 | + logger.warning("Django-Q cluster is not running. Email reminder will not be scheduled.") |
| 116 | + return |
| 117 | + |
| 118 | + # Calculate reminder datetime if not provided |
| 119 | + if appointment_datetime is None: |
| 120 | + appointment_datetime = combine_date_and_time(appointment.appointment_request.date, |
| 121 | + appointment.appointment_request.start_time) |
| 122 | + if timezone.is_naive(appointment_datetime): |
| 123 | + appointment_datetime = timezone.make_aware(appointment_datetime) |
| 124 | + |
| 125 | + reminder_datetime = appointment_datetime - datetime.timedelta(days=1) |
| 126 | + |
| 127 | + logger.info(f"Scheduling email reminder for appointment {appointment.id} at {reminder_datetime}") |
| 128 | + |
| 129 | + # Schedule the email reminder task with Django-Q |
| 130 | + schedule('appointment.tasks.send_email_reminder', |
| 131 | + to_email=appointment.client.email, |
| 132 | + name=f"reminder_{appointment.id_request}", |
| 133 | + first_name=appointment.client.first_name, |
| 134 | + appointment_id=appointment.id, |
| 135 | + schedule_type=Schedule.ONCE, # Use Schedule.ONCE for a one-time task |
| 136 | + next_run=reminder_datetime) |
| 137 | + |
| 138 | + |
| 139 | +def update_appointment_reminder(appointment, new_date, new_start_time, want_reminder=None): |
| 140 | + """ |
| 141 | + Updates or cancels the appointment reminder based on changes to the start time or date, |
| 142 | + and the user's preference for receiving a reminder. |
| 143 | +
|
| 144 | + :param appointment: The Appointment instance being updated. |
| 145 | + :param new_date: The new date as a string (format: "YYYY-MM-DD"). |
| 146 | + :param new_start_time: The new start time as a string (format: "HH:MM"). |
| 147 | + :param want_reminder: Boolean indicating if a reminder is desired. |
| 148 | + """ |
| 149 | + # Convert new date and time strings to datetime objects for comparison |
| 150 | + new_datetime = combine_date_and_time(new_date, new_start_time) |
| 151 | + |
| 152 | + existing_datetime = combine_date_and_time(appointment.appointment_request.date, |
| 153 | + appointment.appointment_request.start_time) |
| 154 | + |
| 155 | + # Ensure new_datetime is timezone-aware |
| 156 | + if timezone.is_naive(new_datetime): |
| 157 | + new_datetime = timezone.make_aware(new_datetime) |
| 158 | + |
| 159 | + # Ensure existing_datetime is timezone-aware |
| 160 | + if timezone.is_naive(existing_datetime): |
| 161 | + existing_datetime = timezone.make_aware(existing_datetime) |
| 162 | + |
| 163 | + # Determine if there's been a change in the datetime or the reminder preference |
| 164 | + want_reminder = want_reminder if want_reminder is not None else appointment.want_reminder |
| 165 | + datetime_changed = new_datetime != existing_datetime |
| 166 | + reminder_preference_changed = appointment.want_reminder != want_reminder |
| 167 | + |
| 168 | + if datetime_changed or reminder_preference_changed: |
| 169 | + # Cancel any existing reminder |
| 170 | + cancel_existing_reminder(appointment.id_request) |
| 171 | + |
| 172 | + # If a reminder is still desired and the appointment is in the future, schedule a new one |
| 173 | + if want_reminder and new_datetime > timezone.now(): |
| 174 | + schedule_email_reminder(appointment, new_datetime) |
| 175 | + else: |
| 176 | + logger.info( |
| 177 | + f"Reminder for appointment {appointment.id} is not scheduled per user's preference or past datetime.") |
| 178 | + |
| 179 | + # Update the appointment's reminder preference |
| 180 | + appointment.want_reminder = want_reminder |
| 181 | + appointment.save() |
| 182 | + |
| 183 | + |
| 184 | +def cancel_existing_reminder(appointment_id_request): |
| 185 | + """ |
| 186 | + Cancels any existing reminder for the appointment. |
| 187 | + Placeholder function - implement based on your scheduling mechanism. |
| 188 | + """ |
| 189 | + # Example: Delete existing scheduled tasks for this appointment |
| 190 | + # This is highly dependent on how reminders are implemented and stored |
| 191 | + task_name = f"reminder_{appointment_id_request}" |
| 192 | + Schedule.objects.filter(name=task_name).delete() |
| 193 | + |
| 194 | + |
107 | 195 | def generate_unique_username_from_email(email: str) -> str:
|
108 | 196 | username_base = email.split('@')[0]
|
109 | 197 | username = username_base
|
|
0 commit comments