haikal/inventory/management/commands/plans_maintenance.py

72 lines
2.5 KiB
Python

from django.core.management.base import BaseCommand
from django.utils import timezone
from django.conf import settings
from django.template.loader import render_to_string
from plans.models import UserPlan, Order
from datetime import timedelta
from django.utils.translation import activate, get_language
from django_q.tasks import async_task
import logging
from inventory.tasks import send_bilingual_reminder, handle_email_result
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = "Handles subscription plan maintenance tasks"
def handle(self, *args, **options):
self.stdout.write("Starting plans maintenance...")
# 1. Send expiration reminders
self.send_expiration_reminders()
# 2. Deactivate expired plans
self.deactivate_expired_plans()
# 3. Clean up old incomplete orders
self.cleanup_old_orders()
self.stdout.write("Maintenance completed!")
def send_expiration_reminders(self):
"""Queue email reminders for expiring plans"""
reminder_days = getattr(settings, 'PLANS_EXPIRATION_REMIND', [3, 7, 14])
today = timezone.now().date()
for days in reminder_days:
target_date = today + timedelta(days=days)
expiring_plans = UserPlan.objects.filter(
active=True,
expire=target_date
).select_related('user', 'plan')
self.stdout.write(f"Queuing {days}-day reminders for {expiring_plans.count()} plans")
for user_plan in expiring_plans:
# Queue email task
async_task(
send_bilingual_reminder,
user_plan.user_id,
user_plan.plan_id,
user_plan.expire,
days,
hook=handle_email_result
)
def deactivate_expired_plans(self):
"""Deactivate plans that have expired (synchronous)"""
expired_plans = UserPlan.objects.filter(
active=True,
expire__lt=timezone.now().date()
)
count = expired_plans.update(active=False)
self.stdout.write(f"Deactivated {count} expired plans")
def cleanup_old_orders(self):
"""Delete incomplete orders older than 30 days"""
cutoff = timezone.now() - timedelta(days=30)
count, _ = Order.objects.filter(
created__lt=cutoff,
status=Order.STATUS.NEW
).delete()
self.stdout.write(f"Cleaned up {count} old incomplete orders")