import time import arrow from typing import List, Any from Schemas import AccountRecords from jinja2 import Environment, FileSystemLoader from Controllers.Email.send_email import EmailSendModel, EmailService def render_email_template( headers: List[str], rows: List[List[Any]], balance_error: bool, bank_balance: str ) -> str: """ Render the HTML email template with the provided data. Args: headers: List of column headers for the table rows: List of data rows for the table balance_error: Flag indicating if there's a balance discrepancy bank_balance: Current bank balance formatted as string Returns: Rendered HTML template as string """ try: # Look for template in ServiceDepends directory env = Environment(loader=FileSystemLoader("/")) template = env.get_template("template_accounts.html") return template.render( headers=headers, rows=rows, bank_balance=bank_balance, balance_error=balance_error, today=str(arrow.now().date()), ) except Exception as e: print(f'Template rendering failed: {e}') raise def send_email_to_given_address(send_to: str, html_template: str, count_of_records: int) -> bool: """ Send email with the rendered HTML template to the specified address. Args: send_to: Email address of the recipient html_template: Rendered HTML template content Returns: Boolean indicating if the email was sent successfully """ today = arrow.now() subject = f"{str(today.date())} Gunes Apt. Cari Durum Kayıt Giriş Raporu" # Create email parameters using EmailSendModel email_params = EmailSendModel( subject=subject + f" ({count_of_records} kayıt)", html=html_template, receivers=[send_to], text=f"Gunes Apt. Cari Durum Kayıt Giriş Raporu - {today.date()}" ) try: # Use the context manager to handle connection errors with EmailService.new_session() as email_session: # Send email through the service EmailService.send_email(email_session, email_params) print(f"Email successfully sent to: {send_to}") return True except Exception as e: print(f'Failed to send email: {e}') return False def process_unsent_email_records() -> bool: """ Process account records that haven't been emailed yet. Finds records with is_email_send=False, formats them into an email, sends the email, and updates the records as sent if successful. Returns: bool: True if email was sent successfully, False otherwise """ try: # Use the context manager to handle database connections with AccountRecords.new_session() as db_session: # Query un-sent mail rows - with limit for display only account_records_query = AccountRecords.filter_all( AccountRecords.is_email_send == False, db=db_session, ).query.order_by(AccountRecords.bank_date.asc()).limit(20) account_records: List[AccountRecords] = account_records_query.all() if not account_records: print("No unsent email records found") return False # Get the IDs of the records we're processing record_ids = [record.id for record in account_records] print(f"Found {len(account_records)} unsent email records") # Format rows for the email template list_of_rows = [] for record in account_records: list_of_rows.append([ record.bank_date.strftime("%d/%m/%Y %H:%M"), record.process_comment, f"{record.currency_value:,.2f}", f"{record.bank_balance:,.2f}" ]) # Reverse list by date list_of_rows = list_of_rows[::-1] # Get the most recent bank balance last_bank_balance = sorted(account_records, key=lambda x: x.bank_date, reverse=True)[0].bank_balance # Define headers for the table headers = ["Ulaştığı Tarih", "Banka Transaksiyonu Ek Bilgi", "Aktarım Değeri", "Banka Bakiyesi"] # Recipient email address send_to = "karatay@mehmetkaratay.com.tr" # Render email template html_template = render_email_template( headers=headers, rows=list_of_rows, balance_error=False, bank_balance=f"{last_bank_balance:,.2f}", ) # Send the email if send_email_to_given_address(send_to=send_to, html_template=html_template, count_of_records=len(list_of_rows)): # Create a new query without limit for updating update_query = AccountRecords.filter_all( AccountRecords.id.in_(record_ids), db=db_session ).query # Update records as sent update_query.update({"is_email_send": True}, synchronize_session=False) AccountRecords.save(db_session) print(f"Successfully marked {len(account_records)} records as sent") return True print("Email sending failed, records not updated") return False except Exception as e: print(f'Error processing unsent email records: {e}') return False if __name__ == "__main__": print("Starting Email Sender Service") while True: try: result = process_unsent_email_records() if result: print("Email processing completed successfully") else: print("No emails sent in this iteration") except Exception as e: print(f"Unexpected error in main loop: {e}") # Sleep for 60 seconds before next check print("Sleeping for 60 seconds") time.sleep(60)