Files
healthy-fit/backend/app/scheduler.py
Carlos Escalante f279907ae3 Add supplements, kettlebell, calendar, push notifications, and PWA support
- Supplement tracking: CRUD endpoints, /today, /logs, Supplements page
- Kettlebell workouts: session tracking, analytics endpoint, ActiveSession page
- Calendar module: events CRUD, calendar components
- Push notifications: VAPID keys, PushSubscription model, APScheduler reminders,
  service worker with push/notificationclick handlers, Profile notifications UI
- PWA: vite-plugin-pwa, manifest, icons, service worker generation
- Frontend: TypeScript types, API modules, ConfirmModal, toast notifications
- Auth fixes: password hashing, nutrition endpoint auth
- CLAUDE.md: project documentation and development guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:57:03 -06:00

48 lines
1.4 KiB
Python

from datetime import datetime, timezone
import pytz
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from sqlmodel import Session, select
from app.db import engine
from app.models.push_subscription import PushSubscription
scheduler = BackgroundScheduler(timezone="UTC")
def send_supplement_reminders() -> None:
from app.api.v1.endpoints.push import send_push
now_utc = datetime.now(timezone.utc)
with Session(engine) as session:
subs = session.exec(
select(PushSubscription).where(PushSubscription.is_active == True) # noqa: E712
).all()
due = []
for sub in subs:
try:
tz = pytz.timezone(sub.timezone)
local_now = now_utc.astimezone(tz)
if local_now.hour == sub.reminder_hour and local_now.minute == sub.reminder_minute:
due.append(sub)
except Exception:
pass
if due:
send_push(due, title="Supplement Reminder", body="Time to log your supplements for today!", session=session)
session.commit()
def start_scheduler() -> None:
scheduler.add_job(
send_supplement_reminders,
CronTrigger(minute="*"),
id="supplement_reminders",
replace_existing=True,
)
scheduler.start()
def stop_scheduler() -> None:
scheduler.shutdown(wait=False)