Files
thrillwiki_django_no_react/backend/apps/rides/tasks.py
pacnpal 7ba0004c93 chore: fix pghistory migration deps and improve htmx utilities
- Update pghistory dependency from 0007 to 0006 in account migrations
- Add docstrings and remove unused imports in htmx_forms.py
- Add DJANGO_SETTINGS_MODULE bash commands to Claude settings
- Add state transition definitions for ride statuses
2025-12-21 17:33:24 -05:00

124 lines
3.5 KiB
Python

"""
Celery tasks for rides app.
This module contains background tasks for ride management including:
- Automatic status transitions for closing rides
"""
import logging
from celery import shared_task
from django.contrib.auth import get_user_model
from django.db import transaction
from django.utils import timezone
logger = logging.getLogger(__name__)
User = get_user_model()
@shared_task(name="rides.check_overdue_closings")
def check_overdue_closings() -> dict:
"""
Check for rides in CLOSING status that have reached their closing_date
and automatically transition them to their post_closing_status.
This task should be run daily via Celery Beat.
Returns:
dict: Summary with counts of processed, succeeded, and failed rides
"""
from apps.rides.models import Ride
logger.info("Starting overdue closings check")
# Get or create system user for automated transitions
system_user = _get_system_user()
# Query rides that need transition
today = timezone.now().date()
overdue_rides = Ride.objects.filter(
status="CLOSING", closing_date__lte=today
).select_for_update()
processed = 0
succeeded = 0
failed = 0
failures = []
for ride in overdue_rides:
processed += 1
try:
with transaction.atomic():
ride.apply_post_closing_status(user=system_user)
succeeded += 1
logger.info(
"Successfully transitioned ride %s (%s) from CLOSING to %s",
ride.id,
ride.name,
ride.status,
)
except Exception as e:
failed += 1
error_msg = f"Ride {ride.id} ({ride.name}): {str(e)}"
failures.append(error_msg)
logger.error(
"Failed to transition ride %s (%s): %s",
ride.id,
ride.name,
str(e),
exc_info=True,
)
result = {
"processed": processed,
"succeeded": succeeded,
"failed": failed,
"failures": failures,
"date": today.isoformat(),
}
logger.info(
"Completed overdue closings check: %s processed, %s succeeded, %s failed",
processed,
succeeded,
failed,
)
return result
def _get_system_user():
"""
Get or create a system user for automated transitions.
Returns:
User: System user instance
"""
try:
# Try to get existing system user
system_user = User.objects.get(username="system")
except User.DoesNotExist:
# Create system user if it doesn't exist
try:
system_user = User.objects.create_user(
username="system",
email="system@thrillwiki.com",
is_active=False,
is_staff=False,
)
logger.info("Created system user for automated tasks")
except Exception as e:
# If creation fails, try to get moderator or admin user
logger.warning(
"Failed to create system user, falling back to moderator: %s", str(e)
)
try:
system_user = User.objects.filter(is_staff=True).first()
if not system_user:
# Last resort: use any user
system_user = User.objects.first()
except Exception:
system_user = None
return system_user