from __future__ import annotations import asyncio from datetime import UTC, datetime, timedelta from sqlalchemy import delete, select from app.db.session import async_session_factory from app.models.car import ServiceEmployee, ServiceNotification, ServiceVisit async def main() -> None: now = datetime.now(UTC) async with async_session_factory() as session: expired = ( await session.execute( select(ServiceEmployee).where( ServiceEmployee.status == "invited", ServiceEmployee.invite_expires_at.is_not(None), ServiceEmployee.invite_expires_at <= now, ) ) ).scalars() expired_count = 0 for employee in expired: employee.status = "expired" employee.invite_token = None expired_count += 1 abandoned_count = 0 abandoned = ( await session.execute( select(ServiceNotification).where( ServiceNotification.status.in_(["failed", "retrying"]), ServiceNotification.retry_count >= 5, ServiceNotification.created_at < now - timedelta(days=1), ) ) ).scalars() for notification in abandoned: notification.status = "abandoned" abandoned_count += 1 old_notifications = await session.execute( delete(ServiceNotification).where( ServiceNotification.status == "abandoned", ServiceNotification.created_at < now - timedelta(days=30), ) ) orphan_drafts = await session.execute( delete(ServiceVisit).where( ServiceVisit.status == "draft", ServiceVisit.created_at < now - timedelta(days=90), ) ) await session.commit() print( "Cleanup done: " f"expired_invites={expired_count}, " f"abandoned_notifications={abandoned_count}, " f"deleted_old_notifications={old_notifications.rowcount or 0}, " f"orphan_drafts={orphan_drafts.rowcount or 0}" ) if __name__ == "__main__": asyncio.run(main())