"""Celery task: license expiry checks and alerts.""" import logging from datetime import date, timedelta from app.worker import celery_app logger = logging.getLogger(__name__) @celery_app.task(name="license.check_expiry") def check_expiry(): """Send expiry warning emails for licenses expiring in 30, 14, or 7 days.""" import os from sqlalchemy import create_engine, select, and_ from sqlalchemy.orm import sessionmaker from app.models.license import License, LicenseStatus from app.models.school import School from app.services.email import send_email db_url = os.getenv("DATABASE_URL", "postgresql://postgres:postgres@db:5432/taptrack_hub") engine = create_engine(db_url.replace("postgresql+asyncpg://", "postgresql://"), pool_pre_ping=True) db = sessionmaker(bind=engine)() try: today = date.today() for days_ahead in [30, 14, 7]: target = today + timedelta(days=days_ahead) expiring = db.execute( select(License).where( and_(License.expires_at == target, License.status == LicenseStatus.active) ) ).scalars().all() for lic in expiring: school = db.get(School, lic.school_id) if school and school.billing_email: send_email( to=school.billing_email, subject=f"[TapTrack Hub] License expires in {days_ahead} days — {school.name}", body=( f"Your TapTrack license for {school.name} expires on {lic.expires_at} " f"({days_ahead} days remaining). Please contact us to renew." ), template_name="email/license_expiry.html", context={ "contact_name": school.contact_name or school.name, "school_name": school.name, "license_key": lic.key, "expires_at": str(lic.expires_at), "days_left": days_ahead, }, email_type="license_expiry", school_id=school.id, ) db.commit() finally: db.close()