import streamlit as st import pandas as pd from datetime import date, datetime from zoneinfo import ZoneInfo from app_core.services.mailer_service import MailerService def render_page(): if st.session_state.get("auth_user") is None: st.warning("Please login to continue.") st.stop() st.markdown("## Mailer") st.caption("Automated daily email sending logs and status.") service = MailerService() ist = ZoneInfo("Asia/Kolkata") st.markdown("### Scheduler Status") # Check if scheduler container is running by checking if daily report was sent today today_logs = [log for log in service.recent_logs(limit=1000) if log.get('date_for') == str(date.today())] daily_report_sent_today = any('Daily Report' in str(log.get('subject', '')) for log in today_logs) if daily_report_sent_today: st.success("Scheduler is running - Daily report already sent today") else: # Check if it's past 8 PM IST today now_ist = datetime.now(ist) eight_pm_today = now_ist.replace(hour=20, minute=0, second=0, microsecond=0) if now_ist >= eight_pm_today: st.warning("Scheduler is running - Waiting for next scheduled run (8:00 PM IST daily)") else: next_run_ist = eight_pm_today st.success(f"Scheduler is running - Next report will be sent at {next_run_ist.strftime('%B %d, %Y at %I:%M %p IST')}") st.markdown("---") # Show system status st.markdown("### System Status") col1, col2, col3 = st.columns(3) with col1: st.metric("Total Emails Sent", len([log for log in service.recent_logs(limit=1000) if log.get('status') == 'sent'])) with col2: failed_count = len([log for log in service.recent_logs(limit=1000) if log.get('status') == 'failed']) st.metric("Failed Sends", failed_count, delta=f"-{failed_count}" if failed_count > 0 else None) with col3: today_logs = [log for log in service.recent_logs(limit=1000) if log.get('date_for') == str(date.today())] st.metric("Today's Sends", len(today_logs)) st.markdown("---") # Manual trigger section st.markdown("### Manual Controls") mcol1, mcol2, mcol3 = st.columns([2, 2, 3]) with mcol1: target_date = st.date_input("Report Date", value=date.today()) with mcol2: st.write("") # Spacer force_resend = st.checkbox("Force Resend", value=True, help="Send the report even if it was already sent for this date.") with mcol3: st.write("") # Spacer if st.button("Send Report Now", type="primary", use_container_width=True): with st.spinner(f"Sending report for {target_date}..."): try: from app_core.services.daily_report import main as run_daily_report # Pass the selected date and force flag result = run_daily_report(for_date=str(target_date), force=force_resend) if result == 0: st.success(f"Report for {target_date} sent successfully!") st.rerun() else: st.error(f"Failed to send report (exit code: {result})") except Exception as e: st.error(f"Error: {str(e)}") st.caption("Select a date to manually trigger or re-trigger the daily report email. This is useful for reconciliations.") st.markdown("---") # Show email logs table st.markdown("### Email Logs") logs = service.recent_logs(limit=100) if not logs: st.info("No email logs yet. Automated emails will appear here once sent.") else: df_logs = pd.DataFrame(logs) col_map = { "id": "ID", "sent_at": "Sent At", "recipients": "Recipients", "subject": "Subject", "status": "Status", "error": "Error", "date_for": "Report Date", } df_logs = df_logs[["id", "sent_at", "date_for", "recipients", "subject", "status", "error"]] df_logs = df_logs.rename(columns=col_map) # Add status styling def style_status(val): if val == 'sent': return 'background-color: #D1FAE5; color: #065F46; font-weight: 600;' elif val == 'failed': return 'background-color: #FEE2E2; color: #991B1B; font-weight: 600;' return '' styled_logs = df_logs.style.map(style_status, subset=['Status']) st.dataframe(styled_logs, use_container_width=True, height=400) # trigger reload