68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
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())
|