This commit is contained in:
Iliyan Angelov
2025-11-21 08:55:55 +02:00
parent 6f85b8cf17
commit 4488e3a795
76 changed files with 364 additions and 36 deletions

View File

@@ -295,7 +295,7 @@ async def create_service_stripe_payment_intent(
intent = StripeService.create_payment_intent( intent = StripeService.create_payment_intent(
amount=amount, amount=amount,
currency=currency, currency=currency,
description=f"Service Booking description=f"Service Booking #{booking.id}",
db=db db=db
) )

View File

@@ -712,11 +712,77 @@ async def test_smtp_email(
timestamp_str = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") timestamp_str = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
test_html = f test_html = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SMTP Test Email</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f3f4f6;">
<table role="presentation" style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 40px 20px;">
<table role="presentation" style="max-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
<tr>
<td style="padding: 40px; text-align: center; background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%); border-radius: 10px 10px 0 0;">
<h1 style="color: #d4af37; margin: 0; font-size: 28px;">SMTP Configuration Test</h1>
</td>
</tr>
<tr>
<td style="padding: 40px;">
<h2 style="color: #1a1a1a; font-size: 24px; margin-bottom: 20px;">✅ Success!</h2>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Hello {admin_name},
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
This is a test email to verify that your SMTP configuration is working correctly.
</p>
<div style="background: #d1fae5; border-left: 4px solid #10b981; padding: 15px; margin: 20px 0; border-radius: 4px;">
<p style="margin: 0; color: #065f46; font-size: 14px;">
<strong>Test Details:</strong><br>
Sent by: {admin_name}<br>
Timestamp: {timestamp_str}<br>
Status: SMTP Configuration Active
</p>
</div>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-top: 30px;">
If you received this email, your SMTP settings are configured correctly and emails will be sent successfully.
</p>
</td>
</tr>
<tr>
<td style="padding: 40px; background-color: #f9fafb; border-radius: 0 0 10px 10px; text-align: center;">
<p style="color: #6b7280; font-size: 12px; margin: 0;">Hotel Booking System - SMTP Test</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
"""
test_text = f test_text = f"""
.strip() SMTP Configuration Test
Hello {admin_name},
This is a test email to verify that your SMTP configuration is working correctly.
Test Details:
- Sent by: {admin_name}
- Timestamp: {timestamp_str}
- Status: SMTP Configuration Active
If you received this email, your SMTP settings are configured correctly and emails will be sent successfully.
---
Hotel Booking System - SMTP Test
""".strip()
await send_email( await send_email(

View File

@@ -338,9 +338,7 @@ class AuthService:
logger.info(f"Reset URL: {reset_url}") logger.info(f"Reset URL: {reset_url}")
email_html = password_reset_email_template(reset_url) email_html = password_reset_email_template(reset_url)
plain_text = f"Please click the following link to reset your password: {reset_url}\n\nIf you did not request this, please ignore this email."
plain_text = f
.strip()
await send_email( await send_email(
to=user.email, to=user.email,

View File

@@ -61,41 +61,136 @@ def get_base_template(content: str, title: str = "Hotel Booking", client_url: st
else: else:
full_logo_url = company_logo_url full_logo_url = company_logo_url
logo_html = f logo_html = f'<img src="{full_logo_url}" alt="{company_name}" style="max-width: 200px; height: auto; margin-bottom: 20px;" />'
else: else:
logo_html = f logo_html = f'<div style="font-size: 32px; font-weight: bold; color: #d4af37; margin-bottom: 20px;">{company_name}</div>'
footer_contact = "" footer_contact = ""
if company_phone or company_email or company_address: if company_phone or company_email or company_address:
footer_contact = footer_contact = '<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #e5e7eb; color: #6b7280; font-size: 14px;">'
if company_phone: if company_phone:
footer_contact += f footer_contact += f'<p style="margin: 5px 0;">Phone: {company_phone}</p>'
if company_email: if company_email:
footer_contact += f footer_contact += f'<p style="margin: 5px 0;">Email: <a href="mailto:{company_email}" style="color: #d4af37; text-decoration: none;">{company_email}</a></p>'
if company_address: if company_address:
formatted_address = company_address.replace('\n', '<br>') formatted_address = company_address.replace('\n', '<br>')
footer_contact += f footer_contact += f'<p style="margin: 5px 0;">Address: {formatted_address}</p>'
footer_contact += footer_contact += '</div>'
return f return f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f3f4f6;">
<table role="presentation" style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 40px 20px;">
<table role="presentation" style="max-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
<tr>
<td style="padding: 40px; text-align: center; background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%); border-radius: 10px 10px 0 0;">
{logo_html}
<p style="color: #d4af37; font-size: 12px; letter-spacing: 2px; margin: 10px 0 0 0; text-transform: uppercase;">{company_tagline}</p>
</td>
</tr>
<tr>
<td style="padding: 40px;">
{content}
</td>
</tr>
<tr>
<td style="padding: 40px; background-color: #f9fafb; border-radius: 0 0 10px 10px; text-align: center;">
<p style="color: #6b7280; font-size: 12px; margin: 0 0 10px 0;"{datetime.now().year} {company_name}. All rights reserved.</p>
{footer_contact}
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
"""
def welcome_email_template(name: str, email: str, client_url: str) -> str: def welcome_email_template(name: str, email: str, client_url: str) -> str:
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
content = f content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<h1 style="color: #1a1a1a; font-size: 28px; margin-bottom: 20px;">Welcome to {company_name}!</h1>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Dear {name},
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Thank you for registering with {company_name}. We're excited to have you as part of our community!
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 30px;">
You can now explore our luxurious rooms and make bookings. If you have any questions, feel free to contact us.
</p>
<div style="text-align: center; margin-top: 30px;">
<a href="{client_url}/rooms" style="display: inline-block; background: #d4af37; color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: bold;">
Explore Our Rooms
</a>
</div>
</div>
"""
return get_base_template(content, f"Welcome to {company_name}", client_url) return get_base_template(content, f"Welcome to {company_name}", client_url)
def password_reset_email_template(reset_url: str) -> str: def password_reset_email_template(reset_url: str) -> str:
content = f content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<h1 style="color: #1a1a1a; font-size: 28px; margin-bottom: 20px;">Password Reset Request</h1>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
You have requested to reset your password. Click the button below to create a new password.
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
If you did not request this, please ignore this email and your password will remain unchanged.
</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{reset_url}" style="display: inline-block; background: #d4af37; color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: bold;">
Reset Password
</a>
</div>
<p style="font-size: 14px; color: #6b7280; line-height: 1.6; margin-top: 30px;">
If the button doesn't work, copy and paste this link into your browser:<br>
<a href="{reset_url}" style="color: #d4af37; word-break: break-all;">{reset_url}</a>
</p>
<p style="font-size: 14px; color: #6b7280; line-height: 1.6; margin-top: 20px;">
This link will expire in 1 hour for security reasons.
</p>
</div>
"""
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
return get_base_template(content, f"Password Reset - {company_name}", reset_url.split('/reset-password')[0] if '/reset-password' in reset_url else "http://localhost:5173") return get_base_template(content, f"Password Reset - {company_name}", reset_url.split('/reset-password')[0] if '/reset-password' in reset_url else "http://localhost:5173")
def password_changed_email_template(email: str) -> str: def password_changed_email_template(email: str) -> str:
content = f content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<h1 style="color: #1a1a1a; font-size: 28px; margin-bottom: 20px;">Password Changed Successfully</h1>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Your password has been successfully changed.
</p>
<div style="background: #d1fae5; border-left: 4px solid #10b981; padding: 15px; margin: 20px 0; border-radius: 4px;">
<p style="margin: 0; color: #065f46; font-size: 14px;">
<strong>Security Notice:</strong> If you did not make this change, please contact us immediately to secure your account.
</p>
</div>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-top: 30px;">
For your security, we recommend:
</p>
<ul style="font-size: 16px; color: #374151; line-height: 1.8; margin: 20px 0;">
<li>Using a strong, unique password</li>
<li>Not sharing your password with anyone</li>
<li>Logging out when using shared devices</li>
</ul>
</div>
"""
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
return get_base_template(content, f"Password Changed - {company_name}", "http://localhost:5173") return get_base_template(content, f"Password Changed - {company_name}", "http://localhost:5173")
@@ -121,21 +216,95 @@ def booking_confirmation_email_template(
) -> str: ) -> str:
deposit_info = "" deposit_info = ""
if requires_deposit and deposit_amount and amount_paid is None: if requires_deposit and deposit_amount and amount_paid is None:
deposit_info = f deposit_info = f"""
<div style="background: #fef3c7; border-left: 4px solid #f59e0b; padding: 15px; margin: 20px 0; border-radius: 4px;">
<p style="margin: 0; color: #92400e; font-size: 14px;">
<strong>Deposit Required:</strong> A deposit of {currency_symbol}{deposit_amount:.2f} is required to confirm your booking.
</p>
</div>
"""
payment_breakdown = "" payment_breakdown = ""
if amount_paid is not None: if amount_paid is not None:
remaining_due = total_price - amount_paid remaining_due = total_price - amount_paid
payment_type_label = "Deposit Payment" if payment_type == "deposit" else "Full Payment" payment_type_label = "Deposit Payment" if payment_type == "deposit" else "Full Payment"
payment_breakdown = f payment_breakdown = f"""
<div style="background: #f9fafb; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #1a1a1a; font-size: 18px; margin-bottom: 15px;">Payment Summary</h3>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<span style="color: #374151;">{payment_type_label}:</span>
<span style="color: #1a1a1a; font-weight: bold;">{currency_symbol}{amount_paid:.2f}</span>
</div>
"""
if remaining_due > 0: if remaining_due > 0:
payment_breakdown += f payment_breakdown += f"""
<div style="display: flex; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1px solid #e5e7eb;">
<span style="color: #374151;">Remaining Due:</span>
<span style="color: #dc2626; font-weight: bold;">{currency_symbol}{remaining_due:.2f}</span>
</div>
"""
else: else:
payment_breakdown += f payment_breakdown += f"""
payment_breakdown += <div style="display: flex; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1px solid #e5e7eb;">
<span style="color: #059669; font-weight: bold;">Payment Complete</span>
</div>
"""
payment_breakdown += "</div>"
content = f discount_info = ""
if original_price and discount_amount and discount_amount > 0:
discount_info = f"""
<div style="background: #d1fae5; border-left: 4px solid #10b981; padding: 15px; margin: 20px 0; border-radius: 4px;">
<p style="margin: 0; color: #065f46; font-size: 14px;">
<strong>Discount Applied:</strong> {currency_symbol}{discount_amount:.2f} off
{f'(Promo Code: {promotion_code})' if promotion_code else ''}
</p>
</div>
"""
content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<div style="background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%); padding: 30px; border-radius: 10px; text-align: center; margin-bottom: 30px;">
<div style="font-size: 48px; color: #10b981; margin-bottom: 10px;">✓</div>
<h1 style="color: #10b981; margin: 0; font-size: 28px;">Booking Confirmed!</h1>
</div>
<div style="background: #ffffff; padding: 30px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Dear {guest_name},
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Your booking has been confirmed! We're excited to welcome you to our hotel.
</p>
<div style="background: #f9fafb; padding: 20px; border-radius: 8px; margin: 30px 0; border-left: 4px solid #d4af37;">
<h3 style="color: #1a1a1a; font-size: 18px; margin-bottom: 15px;">Booking Details</h3>
<p style="margin: 8px 0; color: #374151;"><strong>Booking Number:</strong> {booking_number}</p>
<p style="margin: 8px 0; color: #374151;"><strong>Room:</strong> {room_type} (Room {room_number})</p>
<p style="margin: 8px 0; color: #374151;"><strong>Check-in:</strong> {check_in}</p>
<p style="margin: 8px 0; color: #374151;"><strong>Check-out:</strong> {check_out}</p>
<p style="margin: 8px 0; color: #374151;"><strong>Guests:</strong> {num_guests}</p>
<p style="margin: 8px 0; color: #374151;"><strong>Total Price:</strong> {currency_symbol}{total_price:.2f}</p>
</div>
{discount_info}
{deposit_info}
{payment_breakdown}
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-top: 30px;">
If you have any questions or need to make changes to your booking, please don't hesitate to contact us.
</p>
<div style="text-align: center; margin-top: 30px;">
<a href="{client_url}/bookings/{booking_number}" style="display: inline-block; background: #d4af37; color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: bold;">
View Booking Details
</a>
</div>
</div>
</div>
"""
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
return get_base_template(content, f"Booking Confirmation - {company_name}", client_url) return get_base_template(content, f"Booking Confirmation - {company_name}", client_url)
@@ -153,22 +322,83 @@ def payment_confirmation_email_template(
) -> str: ) -> str:
transaction_info = "" transaction_info = ""
if transaction_id: if transaction_id:
transaction_info = f transaction_info = f"""
<div style="background: #f9fafb; padding: 15px; border-radius: 8px; margin: 15px 0;">
<p style="margin: 0; color: #374151; font-size: 14px;">
<strong>Transaction ID:</strong> {transaction_id}
</p>
</div>
"""
payment_type_info = "" payment_type_info = ""
if payment_type: if payment_type:
payment_type_label = "Deposit Payment (20%)" if payment_type == "deposit" else "Full Payment" payment_type_label = "Deposit Payment (20%)" if payment_type == "deposit" else "Full Payment"
payment_type_info = f payment_type_info = f"""
<div style="background: #eff6ff; border-left: 4px solid #3b82f6; padding: 15px; margin: 15px 0; border-radius: 4px;">
<p style="margin: 0; color: #1e40af; font-size: 14px;">
<strong>Payment Type:</strong> {payment_type_label}
</p>
</div>
"""
total_price_info = "" total_price_info = ""
remaining_due_info = "" remaining_due_info = ""
if total_price is not None: if total_price is not None:
total_price_info = f total_price_info = f"""
<div style="display: flex; justify-content: space-between; margin: 15px 0; padding: 10px 0; border-top: 1px solid #e5e7eb;">
<span style="color: #374151; font-weight: bold;">Total Booking Amount:</span>
<span style="color: #1a1a1a; font-weight: bold; font-size: 18px;">{currency_symbol}{total_price:.2f}</span>
</div>
"""
if payment_type == "deposit" and total_price > amount: if payment_type == "deposit" and total_price > amount:
remaining_due = total_price - amount remaining_due = total_price - amount
remaining_due_info = f remaining_due_info = f"""
<div style="background: #fef3c7; border-left: 4px solid #f59e0b; padding: 15px; margin: 15px 0; border-radius: 4px;">
<p style="margin: 0; color: #92400e; font-size: 14px;">
<strong>Remaining Balance:</strong> {currency_symbol}{remaining_due:.2f} (due at check-in)
</p>
</div>
"""
content = f content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<div style="background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); padding: 30px; border-radius: 10px; text-align: center; margin-bottom: 30px;">
<div style="font-size: 48px; color: #3b82f6; margin-bottom: 10px;">💳</div>
<h1 style="color: #3b82f6; margin: 0; font-size: 28px;">Payment Confirmed!</h1>
</div>
<div style="background: #ffffff; padding: 30px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Dear {guest_name},
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
We have successfully received your payment. Thank you!
</p>
<div style="background: #f9fafb; padding: 20px; border-radius: 8px; margin: 30px 0; border-left: 4px solid #3b82f6;">
<h3 style="color: #1a1a1a; font-size: 18px; margin-bottom: 15px;">Payment Details</h3>
<p style="margin: 8px 0; color: #374151;"><strong>Booking Number:</strong> {booking_number}</p>
<p style="margin: 8px 0; color: #374151;"><strong>Amount Paid:</strong> <span style="color: #10b981; font-weight: bold; font-size: 18px;">{currency_symbol}{amount:.2f}</span></p>
<p style="margin: 8px 0; color: #374151;"><strong>Payment Method:</strong> {payment_method.title()}</p>
{transaction_info}
{payment_type_info}
{total_price_info}
{remaining_due_info}
</div>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-top: 30px;">
Your payment has been processed successfully. You will receive a separate booking confirmation email with all the details of your reservation.
</p>
<div style="text-align: center; margin-top: 30px;">
<a href="{client_url}/bookings/{booking_number}" style="display: inline-block; background: #d4af37; color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: bold;">
View Booking Details
</a>
</div>
</div>
</div>
"""
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
return get_base_template(content, f"Payment Confirmation - {company_name}", client_url) return get_base_template(content, f"Payment Confirmation - {company_name}", client_url)
@@ -180,15 +410,49 @@ def booking_status_changed_email_template(
client_url: str = "http://localhost:5173" client_url: str = "http://localhost:5173"
) -> str: ) -> str:
status_colors = { status_colors = {
"confirmed": (" "confirmed": ("#10b981", "Confirmed", "", "#d1fae5", "#a7f3d0"),
"cancelled": (" "cancelled": ("#ef4444", "Cancelled", "", "#fee2e2", "#fecaca"),
"checked_in": (" "checked_in": ("#3b82f6", "Checked In", "", "#dbeafe", "#bfdbfe"),
"checked_out": (" "checked_out": ("#8b5cf6", "Checked Out", "", "#ede9fe", "#ddd6fe"),
} }
color, status_text, icon, bg_start, bg_end = status_colors.get(status.lower(), (" color, status_text, icon, bg_start, bg_end = status_colors.get(status.lower(), ("#6b7280", "Updated", "", "#f3f4f6", "#e5e7eb"))
content = f content = f"""
<div style="max-width: 600px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;">
<div style="background: linear-gradient(135deg, {bg_start} 0%, {bg_end} 100%); padding: 30px; border-radius: 10px; text-align: center; margin-bottom: 30px;">
<div style="font-size: 48px; color: {color}; margin-bottom: 10px;">{icon}</div>
<h1 style="color: {color}; margin: 0; font-size: 28px;">Booking {status_text}</h1>
</div>
<div style="background: #ffffff; padding: 30px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Dear {guest_name},
</p>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 20px;">
Your booking <strong style="color: {color};">{booking_number}</strong> has been <strong>{status_text.lower()}</strong>.
</p>
<div style="background: #f9fafb; padding: 20px; border-radius: 8px; margin: 30px 0; border-left: 4px solid {color};">
<p style="margin: 0; font-size: 14px; color: #6b7280;">
<strong>Booking Number:</strong> {booking_number}<br>
<strong>Status:</strong> <span style="color: {color}; font-weight: bold;">{status_text}</span>
</p>
</div>
<p style="font-size: 16px; color: #374151; line-height: 1.6; margin-bottom: 30px;">
If you have any questions or need assistance, please don't hesitate to contact us.
</p>
<div style="text-align: center; margin-top: 30px;">
<a href="{client_url}/bookings" style="display: inline-block; background: {color}; color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: bold;">
View Booking Details
</a>
</div>
</div>
</div>
"""
company_settings = _get_company_settings() company_settings = _get_company_settings()
company_name = company_settings.get("company_name") or "Hotel Booking" company_name = company_settings.get("company_name") or "Hotel Booking"
return get_base_template(content, f"Booking {status_text} - {company_name}", client_url) return get_base_template(content, f"Booking {status_text} - {company_name}", client_url)