Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import asyncio | |
| from datetime import timedelta | |
| from sqlalchemy import select | |
| from sqlalchemy.ext.asyncio import async_sessionmaker | |
| from ..config import settings | |
| from ..models import ReminderDelivery | |
| from .datetime_utils import now_in_config_timezone | |
| from .inventory import get_expiring_products, list_active_users | |
| from .telegram import send_message | |
| def seconds_until_next_run() -> float: | |
| now = now_in_config_timezone() | |
| target = now.replace(hour=settings.reminder_hour, minute=settings.reminder_minute, second=0, microsecond=0) | |
| if target <= now: | |
| target = target + timedelta(days=1) | |
| return (target - now).total_seconds() | |
| def render_reminder(records: list[dict]) -> str: | |
| if not records: | |
| return f"Recordatorio diario: no hay productos por vencer en los proximos {settings.expiry_warning_days} dias." | |
| lines = [ | |
| f"- {item['producto']}: vence {item['fechaCaducidad']}, stock {item['stockActual']} {item['unidad']}" | |
| for item in records | |
| ] | |
| return "Recordatorio diario de vencimientos:\n" + "\n".join(lines) | |
| async def run_daily_reminders(session_factory: async_sessionmaker) -> None: | |
| async with session_factory() as session: | |
| users = await list_active_users(session) | |
| if not users: | |
| return | |
| records = await get_expiring_products(session, settings.expiry_warning_days) | |
| message = render_reminder(records) | |
| reminder_date = now_in_config_timezone().date().isoformat() | |
| for user in users: | |
| try: | |
| delivery_id = f"{user.chat_id}:{reminder_date}" | |
| exists = await session.get(ReminderDelivery, delivery_id) | |
| if exists is not None: | |
| continue | |
| await send_message(user.chat_id, message) | |
| session.add( | |
| ReminderDelivery( | |
| delivery_id=delivery_id, | |
| chat_id=str(user.chat_id), | |
| reminder_date=reminder_date, | |
| created_at=now_in_config_timezone().replace(microsecond=0).isoformat(), | |
| ) | |
| ) | |
| await session.commit() | |
| except Exception as exc: | |
| print(f"No se pudo enviar recordatorio a {user.chat_id}: {exc}") | |
| async def reminder_loop(session_factory: async_sessionmaker) -> None: | |
| while True: | |
| await asyncio.sleep(seconds_until_next_run()) | |
| await run_daily_reminders(session_factory) | |