- Enable meetings app in INSTALLED_APPS and add URL routing - Switch from PostgreSQL to SQLite for default database configuration - Remove meetings directory from .gitignore - Move API root endpoint from users app to main URL configuration - Remove HIPAA-specific email and compliance settings (EMAIL_ENCRYPTION_KEY, HIPAA_EMAIL_CONFIG, BAA_VERIFICATION) - Add SITE_NAME and ENCRYPTION_KEY environment variables - Regenerate initial user migrations These changes simplify the development setup by using SQLite as the default database and removing complex compliance configurations while enabling the core meetings functionality.
273 lines
9.9 KiB
Python
273 lines
9.9 KiB
Python
from django.core.mail import send_mail
|
|
from django.conf import settings
|
|
from django.template.loader import render_to_string
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def send_booking_notification_email(booking_id):
|
|
"""
|
|
Send email to admin when a new therapy booking is submitted
|
|
"""
|
|
try:
|
|
from .models import TherapyBooking
|
|
booking = TherapyBooking.objects.get(id=booking_id)
|
|
|
|
subject = f"New Therapy Booking Request - {booking.full_name}"
|
|
|
|
html_message = render_to_string('emails/booking_notification.html', {
|
|
'booking': booking,
|
|
})
|
|
|
|
plain_message = f"""
|
|
New Therapy Booking Request Received!
|
|
|
|
Client: {booking.full_name}
|
|
Email: {booking.email}
|
|
Phone: {booking.phone}
|
|
Appointment Type: {booking.get_appointment_type_display()}
|
|
Preferred Date: {booking.preferred_date}
|
|
Preferred Time: {booking.preferred_time}
|
|
|
|
Additional Message:
|
|
{booking.additional_message or 'No additional message provided.'}
|
|
|
|
Please review this booking in the admin dashboard.
|
|
"""
|
|
|
|
# Send to admin email
|
|
admin_email = settings.ADMIN_EMAIL or settings.DEFAULT_FROM_EMAIL
|
|
|
|
send_mail(
|
|
subject=subject,
|
|
message=plain_message,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
recipient_list=[admin_email],
|
|
html_message=html_message,
|
|
fail_silently=True, # Don't crash if email fails
|
|
)
|
|
|
|
logger.info(f"Booking notification email sent for booking {booking_id}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to send booking notification email: {str(e)}")
|
|
|
|
def send_booking_confirmation_email(booking_id):
|
|
"""
|
|
Send beautiful confirmation email when booking is confirmed
|
|
"""
|
|
try:
|
|
from .models import TherapyBooking
|
|
booking = TherapyBooking.objects.get(id=booking_id)
|
|
|
|
logger.info(f"Attempting to send confirmation email for booking {booking_id} to {booking.email}")
|
|
|
|
subject = f"✅ Appointment Confirmed - {booking.get_appointment_type_display()} - {booking.confirmed_datetime.strftime('%b %d')}"
|
|
|
|
# Render professional HTML template
|
|
html_message = render_to_string('emails/booking_confirmed.html', {
|
|
'booking': booking,
|
|
'payment_url': f"https://attunehearttherapy.com/payment/{booking.id}",
|
|
})
|
|
|
|
# Get appointment duration
|
|
duration = get_appointment_duration(booking.appointment_type)
|
|
|
|
# Format datetime for plain text
|
|
formatted_datetime = booking.confirmed_datetime.strftime('%A, %B %d, %Y at %I:%M %p')
|
|
|
|
# Build plain text message dynamically
|
|
plain_message_parts = [
|
|
f"APPOINTMENT CONFIRMED - Attune Heart Therapy",
|
|
f"",
|
|
f"Dear {booking.full_name},",
|
|
f"",
|
|
f"We're delighted to confirm your {booking.get_appointment_type_display()} appointment.",
|
|
f"",
|
|
f"APPOINTMENT DETAILS:",
|
|
f"- Type: {booking.get_appointment_type_display()}",
|
|
f"- Date & Time: {formatted_datetime}",
|
|
f"- Duration: {duration}",
|
|
f"- Therapist: {booking.assigned_therapist.get_full_name() if booking.assigned_therapist else 'To be assigned'}",
|
|
f"- Payment Status: {booking.get_payment_status_display()}",
|
|
f"",
|
|
f"JOIN YOUR SESSION:",
|
|
f"Video Meeting Link: {booking.jitsi_meet_url}",
|
|
f"",
|
|
f"Please join 5-10 minutes before your scheduled time to test your audio and video.",
|
|
f"",
|
|
f"PREPARATION TIPS:",
|
|
f"• Test your camera, microphone, and internet connection",
|
|
f"• Find a quiet, private space",
|
|
f"• Use Chrome, Firefox, or Safari for best experience",
|
|
f"• Have a glass of water nearby",
|
|
f""
|
|
]
|
|
|
|
# Add payment information if not paid
|
|
if booking.payment_status != 'paid':
|
|
plain_message_parts.extend([
|
|
f"PAYMENT INFORMATION:",
|
|
f"Your session fee of ${booking.amount} is pending. Please complete your payment before the session.",
|
|
f""
|
|
])
|
|
|
|
plain_message_parts.extend([
|
|
f"NEED TO RESCHEDULE?",
|
|
f"Please contact us at least 24 hours in advance at (954) 807-3027.",
|
|
f"",
|
|
f"We look forward to supporting you on your healing journey!",
|
|
f"",
|
|
f"Warm regards,",
|
|
f"The Attune Heart Therapy Team",
|
|
f"",
|
|
f"Contact Information:",
|
|
f"📞 (954) 807-3027",
|
|
f"✉️ hello@attunehearttherapy.com",
|
|
f"🌐 attunehearttherapy.com",
|
|
f"",
|
|
f"Confirmation ID: {booking.id}"
|
|
])
|
|
|
|
plain_message = "\n".join(plain_message_parts)
|
|
|
|
result = send_mail(
|
|
subject=subject,
|
|
message=plain_message,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
recipient_list=[booking.email],
|
|
html_message=html_message,
|
|
fail_silently=False,
|
|
)
|
|
|
|
logger.info(f"✅ Booking confirmation email sent successfully to {booking.email}. Sendmail result: {result}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"❌ Failed to send booking confirmation email: {str(e)}", exc_info=True)
|
|
return False
|
|
def get_appointment_duration(appointment_type):
|
|
"""Helper function to get appointment duration"""
|
|
durations = {
|
|
'initial-consultation': '90 minutes',
|
|
'individual-therapy': '60 minutes',
|
|
'family-therapy': '90 minutes',
|
|
'couples-therapy': '75 minutes',
|
|
'group-therapy': '90 minutes',
|
|
'follow-up': '45 minutes',
|
|
}
|
|
return durations.get(appointment_type, '60 minutes')
|
|
def get_appointment_duration(appointment_type):
|
|
"""Helper function to get appointment duration"""
|
|
durations = {
|
|
'initial-consultation': '90 minutes',
|
|
'individual-therapy': '60 minutes',
|
|
'family-therapy': '90 minutes',
|
|
'couples-therapy': '75 minutes',
|
|
'group-therapy': '90 minutes',
|
|
'follow-up': '45 minutes',
|
|
}
|
|
return durations.get(appointment_type, '60 minutes')
|
|
|
|
def send_payment_confirmation_email(booking_id):
|
|
try:
|
|
from .models import TherapyBooking
|
|
booking = TherapyBooking.objects.get(id=booking_id)
|
|
|
|
subject = f"💳 Payment Confirmed - {booking.get_appointment_type_display()}"
|
|
|
|
html_message = render_to_string('emails/payment_confirmed.html', {
|
|
'booking': booking,
|
|
})
|
|
|
|
duration = get_appointment_duration(booking.appointment_type)
|
|
payment_id = booking.stripe_payment_intent_id or str(booking.id)
|
|
|
|
plain_message = f"""
|
|
PAYMENT CONFIRMED - Attune Heart Therapy
|
|
|
|
Dear {booking.full_name},
|
|
|
|
Thank you for your payment! Your {booking.get_appointment_type_display()} appointment is now fully confirmed.
|
|
|
|
PAYMENT DETAILS:
|
|
- Amount Paid: ${booking.amount}
|
|
- Payment Date: {booking.paid_at.strftime('%B %d, %Y at %I:%M %p')}
|
|
- Payment ID: {payment_id}
|
|
- Appointment: {booking.get_appointment_type_display()}
|
|
|
|
SESSION DETAILS:
|
|
- Date & Time: {booking.confirmed_datetime.strftime('%A, %B %d, %Y at %I:%M %p')}
|
|
- Duration: {duration}
|
|
- Therapist: {booking.assigned_therapist.get_full_name() if booking.assigned_therapist else 'To be assigned'}
|
|
- Video Meeting: {booking.jitsi_meet_url}
|
|
|
|
Please join 5-10 minutes before your scheduled time to test your audio and video.
|
|
|
|
This email serves as your receipt for tax purposes.
|
|
|
|
If you have any questions about your payment or appointment, please contact us at (954) 807-3027.
|
|
|
|
Thank you for trusting us with your care!
|
|
|
|
Warm regards,
|
|
The Attune Heart Therapy Team
|
|
|
|
Contact Information:
|
|
📞 (954) 807-3027
|
|
✉️ hello@attunehearttherapy.com
|
|
🌐 attunehearttherapy.com
|
|
|
|
Payment ID: {payment_id}
|
|
Processed: {booking.paid_at.strftime('%Y-%m-%d %H:%M')}
|
|
"""
|
|
|
|
send_mail(
|
|
subject=subject,
|
|
message=plain_message,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
recipient_list=[booking.email],
|
|
html_message=html_message,
|
|
fail_silently=False,
|
|
)
|
|
|
|
logger.info(f"✅ Payment confirmation email sent to {booking.email}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"❌ Failed to send payment confirmation email: {str(e)}")
|
|
return False
|
|
|
|
def send_payment_failure_email(booking_id):
|
|
"""
|
|
Send payment failure email
|
|
"""
|
|
try:
|
|
from .models import TherapyBooking
|
|
booking = TherapyBooking.objects.get(id=booking_id)
|
|
|
|
subject = f"Payment Issue - {booking.get_appointment_type_display()}"
|
|
|
|
plain_message = f"""
|
|
Payment Issue
|
|
|
|
Dear {booking.full_name},
|
|
|
|
We encountered an issue processing your payment for the {booking.get_appointment_type_display()} appointment.
|
|
|
|
Please try again or contact us at (954) 807-3027 to complete your payment.
|
|
|
|
Best regards,
|
|
Attune Heart Therapy Team
|
|
"""
|
|
|
|
send_mail(
|
|
subject=subject,
|
|
message=plain_message,
|
|
from_email=settings.DEFAULT_FROM_EMAIL,
|
|
recipient_list=[booking.email],
|
|
fail_silently=True,
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to send payment failure email: {str(e)}") |