119 lines
4.6 KiB
Python
119 lines
4.6 KiB
Python
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
|