import sys import os import pandas as pd import boto3 import traceback import time from datetime import datetime from dotenv import load_dotenv import shutil from core_utilities.mail_service import send_mail_with_attachment from core_utilities import cf_encrypt_decrypt from utils import execute_query, get_cloudwatch_logger from scripts.mysql_queries import merchant_collection_report_query load_dotenv() stream_name = 'merchant_collection_report' logger = get_cloudwatch_logger(stream_name=stream_name) def generate_merchant_collection_report(): try: logger.send_log_event(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] INFO: Starting Merchant Collection Report Script") df = execute_query(merchant_collection_report_query) if df.empty: logger.send_log_event(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] INFO: No cases found matching the criteria.") return # Decrypt contact fields for all rows secret_key = os.environ.get('CF_ENCRYPT_DECRYPT_KEY') cols_to_decrypt = [ 'merchant_email', 'contact_number', 'rcp_mobile', 'sales_head_mobile', 'finance_head_mobile', 'mobile_number' ] def safe_decrypt(val): if pd.isna(val) or not str(val).strip() or str(val).strip() == 'None': return val return cf_encrypt_decrypt.wall_decrypt(str(val), key=secret_key) for col in cols_to_decrypt: if col in df.columns: df[col] = df[col].apply(safe_decrypt) emails_sent = 0 total_merchants = 0 summary_data = [] # Create output directory for excel files output_dir = "/tmp/collection_reports" if not os.path.exists(output_dir): os.makedirs(output_dir) for merchant_id, group_df in df.groupby('merchant_id'): total_merchants += 1 merchant_name = str(group_df['merchant_name'].iloc[0]) merchant_email = str(group_df['merchant_email'].iloc[0]) # Log the decrypted fields for this merchant logger.send_log_event(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] INFO: Merchant {merchant_name} Decrypted Info - Email: {merchant_email}, Contact: {group_df['contact_number'].iloc[0] if 'contact_number' in group_df else ''}, RCP: {group_df['rcp_mobile'].iloc[0] if 'rcp_mobile' in group_df else ''}") # If email is null or missing, skip if pd.isna(merchant_email) or not merchant_email.strip() or merchant_email.strip() == 'None': logger.send_log_event(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] WARNING: Skipping merchant {merchant_name} (ID: {merchant_id}) due to missing email.") continue # Drop internal and contact columns for the Excel report columns_to_drop = [ 'merchant_email', 'contact_number', 'rcp_mobile', 'sales_head_mobile', 'finance_head_mobile', 'merchant_id', 'lender_id', 'application_id', 'total_delay_days', 'merchant_name', 'lender_name' ] report_df = group_df.drop(columns=[col for col in columns_to_drop if col in group_df.columns]) # Rename columns to user-friendly names rename_mapping = { 'loan_application_no': 'Loan Application No', 'customer_name': 'Customer Name', 'mobile_number': 'Contact', 'overdue_amount': 'Overdue Amount', 'emi': 'Installment Amount', 'last_payment_date': 'Last Payment Date' } report_df = report_df.rename(columns=rename_mapping) # Reorder columns exactly as requested desired_order = [ 'Loan Application No', 'Customer Name', 'Contact', 'Overdue Amount', 'Installment Amount', 'Last Payment Date' ] # Ensure we only include columns that exist to prevent KeyErrors final_columns = [col for col in desired_order if col in report_df.columns] report_df = report_df[final_columns] # Generate Excel File securely naming it safe_name = "".join([c for c in merchant_name if c.isalpha() or c.isdigit() or c==' ']).rstrip() file_name = f"{output_dir}/Collection_Report_{safe_name.replace(' ', '_')}_{datetime.now().strftime('%d_%b_%Y')}.xlsx" report_df.to_excel(file_name, index=False) # Send Email case_count = len(report_df) # --- TEST LOGIC OVERRIDE --- if os.environ.get('TEST_MERCHANT_REPORT') == '1': merchant_email = "ashish.gupta@creditfair.in" cc_list = [] else: cc_list = ['imran@creditfair.in', 'ketan@creditfair.in', 'amol@creditfair.in'] # If the database contains multiple comma-separated emails, extract the first # as the 'To' address, and append the rest to the 'CC' list. if isinstance(merchant_email, str) and ',' in merchant_email: emails = [e.strip() for e in merchant_email.split(',') if e.strip()] if emails: merchant_email = emails[0] cc_list.extend(emails[1:]) html_body = f"""
Dear {merchant_name},
Please find your pending collection cases attached. We need your support to clear these cases as soon as possible.
For discussing please call us on 8850077108 / 8928769161.
""" if case_count < 6: html_body += "Dear Team,
Please find the summary of the Merchant Collection Report execution below.
Please find the detailed summary attached.
Regards,
Creditfair Tech