"""
Notification service for Plutus payment processing application.
Handles email notifications for payment failures and success reports.
Integrates with existing emailclass.py for SMTP functionality.
"""
from datetime import datetime
from typing import List, Dict, Any, Optional
from emailclass import SendEmail
import json
import logging
logger = logging.getLogger(__name__)
class NotificationService:
def __init__(self):
self.email_client = SendEmail()
def send_payment_failure_notification(
self,
payment_data: Dict[str, Any],
recipient_email: str = "alan.woodman@interphone.com.au"
) -> bool:
"""
Send email notification for a failed payment.
Args:
payment_data: Dictionary containing payment information
recipient_email: Email address to send notification to
Returns:
bool: True if email sent successfully
"""
try:
# Extract payment information
splynx_id = payment_data.get('splynx_id', 'Unknown')
payment_id = payment_data.get('payment_id', 'Unknown')
amount = payment_data.get('amount', 0.0)
error = payment_data.get('error', 'Unknown error')
payment_method = payment_data.get('payment_method', 'Unknown')
customer_name = payment_data.get('customer_name', 'Unknown Customer')
# Configure email
self.email_client.receiver = recipient_email
self.email_client.subject = f"Payment Failure - Customer {splynx_id} - ${amount:.2f}"
self.email_client.message_type = "html"
# Create HTML email content
html_content = self._create_failure_email_html(
payment_data, splynx_id, payment_id, amount, error,
payment_method, customer_name
)
self.email_client.message_body_html = html_content
# Send email
result = self.email_client.send()
if result:
logger.info(f"Payment failure email sent successfully for payment {payment_id}")
else:
logger.error(f"Failed to send payment failure email for payment {payment_id}")
return result
except Exception as e:
logger.error(f"Error sending payment failure notification: {e}")
return False
def send_batch_summary_email(
self,
batch_summary: Dict[str, Any],
recipient_email: str = "alan.woodman@interphone.com.au"
) -> bool:
"""
Send email summary for batch payment processing.
Args:
batch_summary: Dictionary containing batch processing summary
recipient_email: Email address to send summary to
Returns:
bool: True if email sent successfully
"""
try:
batch_id = batch_summary.get('batch_id', 'Unknown')
total_processed = batch_summary.get('total_processed', 0)
successful_count = batch_summary.get('successful_count', 0)
failed_count = batch_summary.get('failed_count', 0)
total_amount = batch_summary.get('total_amount', 0.0)
# Configure email
self.email_client.receiver = recipient_email
self.email_client.subject = f"Batch Payment Summary - Batch #{batch_id} - {successful_count}/{total_processed} Successful"
self.email_client.message_type = "html"
# Create HTML email content
html_content = self._create_batch_summary_html(batch_summary)
self.email_client.message_body_html = html_content
# Send email
result = self.email_client.send()
if result:
logger.info(f"Batch summary email sent successfully for batch {batch_id}")
else:
logger.error(f"Failed to send batch summary email for batch {batch_id}")
return result
except Exception as e:
logger.error(f"Error sending batch summary email: {e}")
return False
def _create_failure_email_html(
self,
payment_data: Dict[str, Any],
splynx_id: str,
payment_id: str,
amount: float,
error: str,
payment_method: str,
customer_name: str
) -> str:
"""Create HTML content for payment failure email."""
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
return f"""
Payment Failed: A payment processing attempt has failed and requires attention.
Payment Details
| Payment ID | {payment_id} |
| Splynx Customer ID | {splynx_id} |
| Customer Name | {customer_name} |
| Payment Amount | ${amount:.2f} AUD |
| Payment Method | {payment_method} |
| Timestamp | {timestamp} |
Error Information
Recommended Actions
- Review customer payment method in Splynx
- Contact customer about payment failure
- Check if customer needs to update payment details
- Consider creating a support ticket
System Links:
"""
def _create_batch_summary_html(self, batch_summary: Dict[str, Any]) -> str:
"""Create HTML content for batch summary email."""
batch_id = batch_summary.get('batch_id', 'Unknown')
total_processed = batch_summary.get('total_processed', 0)
successful_count = batch_summary.get('successful_count', 0)
failed_count = batch_summary.get('failed_count', 0)
total_amount = batch_summary.get('total_amount', 0.0)
success_amount = batch_summary.get('success_amount', 0.0)
failed_payments = batch_summary.get('failed_payments', [])
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# Determine status color
if failed_count == 0:
status_color = "#28a745" # Green
status_text = "✅ All Successful"
elif successful_count == 0:
status_color = "#dc3545" # Red
status_text = "❌ All Failed"
else:
status_color = "#ffc107" # Yellow
status_text = "⚠️ Partial Success"
# Build failed payments table
failed_payments_html = ""
if failed_payments:
failed_payments_html = """
Failed Payments
| Payment ID | Customer ID | Amount | Error |
"""
for payment in failed_payments[:10]: # Limit to first 10 failures
failed_payments_html += f"""
| {payment.get('id', 'N/A')} |
{payment.get('splynx_id', 'N/A')} |
${payment.get('amount', 0.0):.2f} |
{payment.get('error', 'Unknown error')[:100]}... |
"""
failed_payments_html += "
"
if len(failed_payments) > 10:
failed_payments_html += f"... and {len(failed_payments) - 10} more failed payments
"
return f"""
Processing Summary
{total_processed}
Total Processed
{successful_count}
Successful
| Metric | Value |
| Batch ID | #{batch_id} |
| Total Amount Processed | ${total_amount:.2f} AUD |
| Successful Amount | ${success_amount:.2f} AUD |
| Success Rate | {(successful_count/total_processed*100):.1f}% |
| Processing Time | {timestamp} |
{failed_payments_html}
Actions Required
{"- ✅ No action required - all payments successful
" if failed_count == 0 else f"- ⚠️ Review {failed_count} failed payment(s)
"}
{"- 📧 Consider contacting customers with failed payments
" if failed_count > 0 else ""}
- 📊 View detailed batch report
"""