updates
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -295,7 +295,7 @@ async def create_service_stripe_payment_intent(
|
||||
intent = StripeService.create_payment_intent(
|
||||
amount=amount,
|
||||
currency=currency,
|
||||
description=f"Service Booking
|
||||
description=f"Service Booking #{booking.id}",
|
||||
db=db
|
||||
)
|
||||
|
||||
|
||||
@@ -712,11 +712,77 @@ async def test_smtp_email(
|
||||
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
|
||||
.strip()
|
||||
test_text = f"""
|
||||
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(
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -338,9 +338,7 @@ class AuthService:
|
||||
logger.info(f"Reset URL: {reset_url}")
|
||||
email_html = password_reset_email_template(reset_url)
|
||||
|
||||
|
||||
plain_text = f
|
||||
.strip()
|
||||
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."
|
||||
|
||||
await send_email(
|
||||
to=user.email,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -61,41 +61,136 @@ def get_base_template(content: str, title: str = "Hotel Booking", client_url: st
|
||||
else:
|
||||
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:
|
||||
logo_html = f
|
||||
logo_html = f'<div style="font-size: 32px; font-weight: bold; color: #d4af37; margin-bottom: 20px;">{company_name}</div>'
|
||||
|
||||
|
||||
footer_contact = ""
|
||||
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:
|
||||
footer_contact += f
|
||||
footer_contact += f'<p style="margin: 5px 0;">Phone: {company_phone}</p>'
|
||||
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:
|
||||
|
||||
formatted_address = company_address.replace('\n', '<br>')
|
||||
footer_contact += f
|
||||
footer_contact +=
|
||||
footer_contact += f'<p style="margin: 5px 0;">Address: {formatted_address}</p>'
|
||||
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:
|
||||
company_settings = _get_company_settings()
|
||||
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)
|
||||
|
||||
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_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")
|
||||
|
||||
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_name = company_settings.get("company_name") or "Hotel Booking"
|
||||
return get_base_template(content, f"Password Changed - {company_name}", "http://localhost:5173")
|
||||
@@ -121,21 +216,95 @@ def booking_confirmation_email_template(
|
||||
) -> str:
|
||||
deposit_info = ""
|
||||
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 = ""
|
||||
if amount_paid is not None:
|
||||
remaining_due = total_price - amount_paid
|
||||
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:
|
||||
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:
|
||||
payment_breakdown += f
|
||||
payment_breakdown +=
|
||||
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: #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_name = company_settings.get("company_name") or "Hotel Booking"
|
||||
return get_base_template(content, f"Booking Confirmation - {company_name}", client_url)
|
||||
@@ -153,22 +322,83 @@ def payment_confirmation_email_template(
|
||||
) -> str:
|
||||
transaction_info = ""
|
||||
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 = ""
|
||||
if payment_type:
|
||||
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 = ""
|
||||
remaining_due_info = ""
|
||||
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:
|
||||
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_name = company_settings.get("company_name") or "Hotel Booking"
|
||||
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"
|
||||
) -> str:
|
||||
status_colors = {
|
||||
"confirmed": ("
|
||||
"cancelled": ("
|
||||
"checked_in": ("
|
||||
"checked_out": ("
|
||||
"confirmed": ("#10b981", "Confirmed", "✓", "#d1fae5", "#a7f3d0"),
|
||||
"cancelled": ("#ef4444", "Cancelled", "✕", "#fee2e2", "#fecaca"),
|
||||
"checked_in": ("#3b82f6", "Checked In", "→", "#dbeafe", "#bfdbfe"),
|
||||
"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_name = company_settings.get("company_name") or "Hotel Booking"
|
||||
return get_base_template(content, f"Booking {status_text} - {company_name}", client_url)
|
||||
|
||||
Reference in New Issue
Block a user