Vital / core /weekly_startup.py
eddyejembi's picture
Upload folder using huggingface_hub
4e88df3 verified
Raw
History Blame Contribute Delete
3.64 kB
"""Weekly report scheduling — Sunday cron + startup catch-up."""
import logging
from datetime import date, datetime, time, timedelta
from db import queries
from llm.weekly_report import generate_weekly_report
logger = logging.getLogger(__name__)
_DEFAULT_REPORT_DAY = "Sunday"
_DEFAULT_REPORT_TIME = "20:00"
_WEEKDAY_BY_NAME = {
"monday": 0,
"tuesday": 1,
"wednesday": 2,
"thursday": 3,
"friday": 4,
"saturday": 5,
"sunday": 6,
}
def _parse_report_time(raw_time: str) -> time:
"""Parse HH:MM report time from weekly_check_structure."""
try:
hours_text, minutes_text = raw_time.strip().split(":", 1)
return time(hour=int(hours_text), minute=int(minutes_text))
except (AttributeError, TypeError, ValueError):
return time(hour=20, minute=0)
def _report_date_in_week(week_start: date, report_day: str) -> date:
"""Return the calendar date of report_day within the Monday-based week."""
target_weekday = _WEEKDAY_BY_NAME.get(report_day.strip().lower(), 6)
for offset in range(7):
candidate = week_start + timedelta(days=offset)
if candidate.weekday() == target_weekday:
return candidate
return week_start + timedelta(days=6)
def _report_deadline_for_week(week_start: date) -> datetime:
"""Return the local datetime when a week's report becomes due."""
structure = queries.get_weekly_check_structure() or {}
report_day = str(structure.get("report_day", _DEFAULT_REPORT_DAY))
report_time = str(structure.get("report_time", _DEFAULT_REPORT_TIME))
report_date = _report_date_in_week(week_start, report_day)
parsed_time = _parse_report_time(report_time)
return datetime.combine(report_date, parsed_time)
def is_weekly_report_due(week_start: date, now: datetime | None = None) -> bool:
"""Return true when the report deadline for week_start has passed."""
current = now or datetime.now()
return current >= _report_deadline_for_week(week_start)
def pending_weekly_report_start(now: datetime | None = None) -> date | None:
"""Return the Monday week_start that needs a report, or None."""
if not queries.check_onboarding_status():
return None
current = now or datetime.now()
today = current.date()
this_week = queries.monday_of_week(today)
last_week = this_week - timedelta(days=7)
for week_start in (last_week, this_week):
if not is_weekly_report_due(week_start, current):
continue
if queries.get_weekly_report(week_start) is not None:
continue
return week_start
return None
def ensure_weekly_report(force: bool = False, now: datetime | None = None) -> bool:
"""Generate the pending weekly report when due; return True if one exists."""
current = now or datetime.now()
week_start = queries.monday_of_week(current.date()) if force else pending_weekly_report_start(current)
if week_start is None and not force:
return queries.get_weekly_report(queries.monday_of_week(current.date())) is not None
if week_start is None:
week_start = queries.monday_of_week(current.date())
report = generate_weekly_report(week_start, force=force)
if report is None:
return False
logger.info(
"[weekly_report] Ready for week %s (%s chars).",
week_start.isoformat(),
len(report.report_text),
)
return True
def run_weekly_startup(force: bool = False) -> None:
"""Run idempotent weekly startup tasks for onboarded users."""
if not queries.check_onboarding_status():
return
ensure_weekly_report(force=force)