Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions appointment/email_sender/email_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
from django.template import loader
from django_q.tasks import async_task

from appointment.logger_config import get_logger
from appointment.settings import APP_DEFAULT_FROM_EMAIL, check_q_cluster

logger = get_logger(__name__)


def has_required_email_settings():
"""Check if all required email settings are configured and warn if any are missing."""
Expand All @@ -22,8 +25,8 @@ def has_required_email_settings():

if missing_settings:
missing_settings_str = ", ".join(missing_settings)
print(f"Warning: The following settings are missing in settings.py: {missing_settings_str}. "
"Email functionality will be disabled.")
logger.warning(f"Warning: The following settings are missing in settings.py: {missing_settings_str}. "
"Email functionality will be disabled.")
return False
return True

Expand Down Expand Up @@ -57,7 +60,7 @@ def send_email(recipient_list, subject: str, template_url: str = None, context:
recipient_list=recipient_list, fail_silently=False,
)
except Exception as e:
print(f"Error sending email: {e}")
logger.error(f"Error sending email: {e}")


def notify_admin(subject: str, template_url: str = None, context: dict = None, message: str = None):
Expand All @@ -77,7 +80,7 @@ def notify_admin(subject: str, template_url: str = None, context: dict = None, m
html_message=html_message if template_url else None
)
except Exception as e:
print(f"Error sending email to admin: {e}")
logger.error(f"Error sending email to admin: {e}")


def get_use_django_q_for_emails():
Expand All @@ -86,5 +89,5 @@ def get_use_django_q_for_emails():
from django.conf import settings
return getattr(settings, 'USE_DJANGO_Q_FOR_EMAILS', False)
except AttributeError:
print("Error accessing USE_DJANGO_Q_FOR_EMAILS. Defaulting to False.")
logger.error("Error accessing USE_DJANGO_Q_FOR_EMAILS. Defaulting to False.")
return False
52 changes: 46 additions & 6 deletions appointment/logger_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,51 @@

import logging
import sys
from datetime import datetime

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
import colorama

# TODO: change the logger format configuration later
# configure basicConfig with the formatter, log level, and handlers
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG,
handlers=[logging.StreamHandler(sys.stdout)])
# Initialize colorama for cross-platform color support
colorama.init()


class ColoredFormatter(logging.Formatter):
COLORS = {
'DEBUG': colorama.Fore.BLUE,
'INFO': colorama.Fore.GREEN,
'WARNING': colorama.Fore.YELLOW,
'ERROR': colorama.Fore.RED,
'CRITICAL': colorama.Fore.RED + colorama.Style.BRIGHT,
}

def format(self, record):
log_color = self.COLORS.get(record.levelname, colorama.Fore.WHITE)
log_time = datetime.fromtimestamp(record.created).strftime('%d/%b/%Y %H:%M:%S')

log_msg = (
f"{log_color}[{log_time}] {record.levelname:<4}{colorama.Style.RESET_ALL} "
f"{colorama.Fore.LIGHTBLUE_EX}{record.name}:{record.funcName}:{record.lineno}{colorama.Style.RESET_ALL} "
f"- {record.getMessage()}"
)

if record.exc_info:
log_msg += '\n' + self.formatException(record.exc_info)
return log_msg


def get_logger(name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)

# Create a colored formatter
formatter = ColoredFormatter()

# Create a stream handler
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)

# Add the handler to the logger
logger.addHandler(stream_handler)

return logger
8 changes: 5 additions & 3 deletions appointment/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from django.conf import settings
from django.conf.global_settings import DEFAULT_FROM_EMAIL

from appointment.logger_config import logger
from appointment.logger_config import get_logger

logger = get_logger(__name__)

APPOINTMENT_BASE_TEMPLATE = getattr(settings, 'APPOINTMENT_BASE_TEMPLATE', 'base_templates/base.html')
APPOINTMENT_ADMIN_BASE_TEMPLATE = getattr(settings, 'APPOINTMENT_ADMIN_BASE_TEMPLATE', 'base_templates/base.html')
Expand All @@ -32,7 +34,7 @@ def check_q_cluster():
Returns True if configurations are correct, otherwise False.
"""
missing_conf = []

logger.info("Checking missing configuration for django q cluster")
# Check if Django Q is installed
if 'django_q' not in settings.INSTALLED_APPS:
missing_conf.append("Django Q is not in settings.INSTALLED_APPS. Please add it to the list.\n"
Expand Down Expand Up @@ -64,6 +66,6 @@ def check_q_cluster():
for warning in missing_conf:
logger.warning(warning)
return False
print(f"Missing conf: {missing_conf}")
# Both 'django_q' is installed and 'Q_CLUSTER' is configured
logger.info("Django Q cluster is properly configured")
return True
11 changes: 8 additions & 3 deletions appointment/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
from django.utils.translation import gettext as _

from appointment.email_sender import notify_admin, send_email
from appointment.logger_config import logger
from appointment.logger_config import get_logger
from appointment.models import Appointment

logger = get_logger(__name__)


def send_email_reminder(to_email, first_name, reschedule_link, appointment_id):
"""
Expand All @@ -32,6 +34,7 @@ def send_email_reminder(to_email, first_name, reschedule_link, appointment_id):
template_url='email_sender/reminder_email.html', context=email_context
)
# Notify the admin
logger.info(f"Sending admin reminder also")
email_context['recipient_type'] = 'admin'
notify_admin(
subject=_("Admin Reminder: Upcoming Appointment"),
Expand All @@ -46,12 +49,13 @@ def send_email_task(recipient_list, subject, message, html_message, from_email):
"""
try:
from django.core.mail import send_mail
logger.info(f"Sending email to {recipient_list} with subject: {subject}")
send_mail(
subject=subject, message=message, html_message=html_message, from_email=from_email,
recipient_list=recipient_list, fail_silently=False,
)
except Exception as e:
print(f"Error sending email from task: {e}")
logger.error(f"Error sending email from task: {e}")


def notify_admin_task(subject, message, html_message):
Expand All @@ -60,6 +64,7 @@ def notify_admin_task(subject, message, html_message):
"""
try:
from django.core.mail import mail_admins
logger.info(f"Sending admin email with subject: {subject}")
mail_admins(subject=subject, message=message, html_message=html_message, fail_silently=False)
except Exception as e:
print(f"Error sending admin email from task: {e}")
logger.error(f"Error sending admin email from task: {e}")
5 changes: 4 additions & 1 deletion appointment/utils/db_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from django_q.models import Schedule
from django_q.tasks import schedule

from appointment.logger_config import logger
from appointment.logger_config import get_logger
from appointment.settings import (
APPOINTMENT_BUFFER_TIME, APPOINTMENT_FINISH_TIME, APPOINTMENT_LEAD_TIME, APPOINTMENT_PAYMENT_URL,
APPOINTMENT_SLOT_DURATION, APPOINTMENT_WEBSITE_NAME
Expand All @@ -37,6 +37,8 @@
EmailVerificationCode = apps.get_model('appointment', 'EmailVerificationCode')
AppointmentRescheduleHistory = apps.get_model('appointment', 'AppointmentRescheduleHistory')

logger = get_logger(__name__)


def calculate_slots(start_time, end_time, buffer_time, slot_duration):
"""Calculate the available slots between the given start and end times using the given buffer time and slot duration
Expand Down Expand Up @@ -109,6 +111,7 @@ def create_and_save_appointment(ar, client_data: dict, appointment_data: dict, r
appointment.save()
logger.info(f"New appointment created: {appointment.to_dict()}")
if appointment.want_reminder:
logger.info(f"User wants a reminder for appointment {appointment.id}, scheduling it...")
schedule_email_reminder(appointment, request)
return appointment

Expand Down
33 changes: 19 additions & 14 deletions appointment/utils/email_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

from appointment import messages_ as email_messages
from appointment.email_sender import notify_admin, send_email
from appointment.logger_config import get_logger
from appointment.models import AppointmentRequest, EmailVerificationCode, PasswordResetToken
from appointment.settings import APPOINTMENT_PAYMENT_URL
from appointment.utils.date_time import convert_24_hour_time_to_12_hour_time
from appointment.utils.db_helpers import get_absolute_url_, get_website_name

logger = get_logger(__name__)


def get_thank_you_message(ar: AppointmentRequest) -> str:
"""
Expand Down Expand Up @@ -83,8 +86,8 @@ def send_thank_you_email(ar: AppointmentRequest, user, request, email: str, appo
'reschedule_link': reschedule_link,
}
send_email(
recipient_list=[email], subject=_("Thank you for booking us."),
template_url='email_sender/thank_you_email.html', context=email_context
recipient_list=[email], subject=_("Thank you for booking us."),
template_url='email_sender/thank_you_email.html', context=email_context
)


Expand Down Expand Up @@ -121,34 +124,36 @@ def send_reset_link_to_staff_member(user, request, email: str, account_details=N
Regards,
{company}
""").format(
first_name=user.first_name,
current_year=datetime.datetime.now().year,
company=website_name,
activation_link=set_passwd_link,
account_details=account_details if account_details else _("No additional details provided."),
username=user.username
first_name=user.first_name,
current_year=datetime.datetime.now().year,
company=website_name,
activation_link=set_passwd_link,
account_details=account_details if account_details else _("No additional details provided."),
username=user.username
)

# Assuming send_email is a method you have that sends an email
send_email(
recipient_list=[email],
subject=_("Set Your Password for {company}").format(company=website_name),
message=message,
recipient_list=[email],
subject=_("Set Your Password for {company}").format(company=website_name),
message=message,
)


def notify_admin_about_appointment(appointment, client_name: str):
"""Notify the admin and the staff member about a new appointment request."""
logger.info(f"Sending admin notification for new appointment {appointment.id}")
email_context = {
'client_name': client_name,
'appointment': appointment
}

subject = _("New Appointment Request for ") + client_name
staff_member = appointment.get_staff_member()
# Assuming notify_admin and send_email are previously defined functions
notify_admin(subject=subject, template_url='email_sender/admin_new_appointment_email.html', context=email_context)
if staff_member.user.email not in settings.ADMINS:
logger.info(
f"Let's notify the staff member as well for new appointment {appointment.id} since they are not an admin.")
send_email(recipient_list=[staff_member.user.email], subject=subject,
template_url='email_sender/admin_new_appointment_email.html', context=email_context)

Expand Down Expand Up @@ -190,8 +195,8 @@ def send_reschedule_confirmation_email(request, reschedule_history, appointment_

subject = _("Confirm Your Appointment Rescheduling")
send_email(
recipient_list=[email], subject=subject,
template_url='email_sender/reschedule_email.html', context=email_context
recipient_list=[email], subject=subject,
template_url='email_sender/reschedule_email.html', context=email_context
)


Expand Down
4 changes: 3 additions & 1 deletion appointment/utils/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
from django.utils.translation import gettext as _
from phonenumber_field.phonenumber import PhoneNumber

from appointment.logger_config import logger
from appointment.logger_config import get_logger
from appointment.utils.db_helpers import get_user_by_email
from appointment.utils.email_ops import send_verification_email

logger = get_logger(__name__)


def handle_existing_email(request, client_data, appointment_data, appointment_request_id, id_request):
"""
Expand Down
3 changes: 1 addition & 2 deletions appointment/utils/view_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

import uuid

from django.conf import settings
from django.utils.translation import get_language, to_locale


def get_locale() -> str:
"""Get the current locale based on the user's language settings, without the country code.
Used in the javascript files.
Used in the JavaScript files.
Can't use the lang_country format because it is not supported.

:return: The current locale as a string (language code only)
Expand Down
Loading
Loading