2025-06-27 16:41:30 +00:00

129 lines
4.3 KiB
Python

import logging
from datetime import datetime, timedelta
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from sqlalchemy.orm import Session
from app.db.session import SessionLocal
from app.models.task import Task, TaskStatus
from app.models.user import User
from app.services.whatsapp_service import send_task_reminder, send_task_overdue
logger = logging.getLogger(__name__)
class SchedulerService:
def __init__(self):
self.scheduler = BackgroundScheduler()
self.scheduler.start()
self._setup_jobs()
def _setup_jobs(self):
self.scheduler.add_job(
func=self.send_reminders,
trigger=CronTrigger(hour=9, minute=0), # Daily at 9 AM
id='daily_reminders',
name='Send daily task reminders',
replace_existing=True
)
self.scheduler.add_job(
func=self.check_overdue_tasks,
trigger=CronTrigger(hour=18, minute=0), # Daily at 6 PM
id='overdue_check',
name='Check for overdue tasks',
replace_existing=True
)
def send_reminders(self):
logger.info("Starting daily reminder job")
db: Session = SessionLocal()
try:
# Get tasks scheduled for today that haven't been reminded
today = datetime.utcnow().date()
tomorrow = today + timedelta(days=1)
tasks = db.query(Task).join(User).filter(
Task.status.in_([TaskStatus.PENDING, TaskStatus.IN_PROGRESS]),
Task.scheduled_at >= datetime.combine(today, datetime.min.time()),
Task.scheduled_at < datetime.combine(tomorrow, datetime.min.time()),
Task.whatsapp_reminder_sent == False,
User.whatsapp_number.isnot(None)
).all()
sent_count = 0
for task in tasks:
if send_task_reminder(task.owner.whatsapp_number, task):
task.whatsapp_reminder_sent = True
sent_count += 1
db.commit()
logger.info(f"Sent {sent_count} reminders")
except Exception as e:
logger.error(f"Error in reminder job: {str(e)}")
db.rollback()
finally:
db.close()
def check_overdue_tasks(self):
logger.info("Starting overdue task check")
db: Session = SessionLocal()
try:
now = datetime.utcnow()
overdue_tasks = db.query(Task).join(User).filter(
Task.status.in_([TaskStatus.PENDING, TaskStatus.IN_PROGRESS]),
Task.due_date < now,
User.whatsapp_number.isnot(None)
).all()
sent_count = 0
for task in overdue_tasks:
if send_task_overdue(task.owner.whatsapp_number, task):
sent_count += 1
logger.info(f"Sent {sent_count} overdue notifications")
except Exception as e:
logger.error(f"Error in overdue check job: {str(e)}")
finally:
db.close()
def schedule_task_reminder(self, task_id: int, remind_at: datetime):
job_id = f"task_reminder_{task_id}"
self.scheduler.add_job(
func=self._send_individual_reminder,
trigger='date',
run_date=remind_at,
args=[task_id],
id=job_id,
name=f'Reminder for task {task_id}',
replace_existing=True
)
def _send_individual_reminder(self, task_id: int):
db: Session = SessionLocal()
try:
task = db.query(Task).join(User).filter(
Task.id == task_id,
User.whatsapp_number.isnot(None)
).first()
if task and task.status in [TaskStatus.PENDING, TaskStatus.IN_PROGRESS]:
send_task_reminder(task.owner.whatsapp_number, task)
task.whatsapp_reminder_sent = True
db.commit()
except Exception as e:
logger.error(f"Error sending individual reminder for task {task_id}: {str(e)}")
finally:
db.close()
def shutdown(self):
self.scheduler.shutdown()
scheduler_service = SchedulerService()