import logging from datetime import timedelta from django.urls import reverse from django.conf import settings from django.utils import timezone from inventory.tasks import send_email from django.core.management.base import BaseCommand from django.template.loader import render_to_string from django.utils.translation import gettext_lazy as _ from django.contrib.contenttypes.models import ContentType from django_ledger.models import InvoiceModel, EstimateModel from inventory.models import ExtraInfo, Notification, CustomGroup logger = logging.getLogger(__name__) class Command(BaseCommand): help = "Handles invoices due date reminders" def handle(self, *args, **options): self.stdout.write("Starting invoices due date reminders..") # 1. Send expiration reminders self.invocie_expiration_reminders() # self.invoice_past_due() # # 2. Deactivate expired plans # self.deactivate_expired_plans() # # 3. Clean up old incomplete orders # self.cleanup_old_orders() # self.stdout.write("Reminders completed!") def invocie_expiration_reminders(self): """Queue email reminders for expiring plans""" reminder_days = getattr(settings, "INVOICE_PAST_DUE_REMIND", [3, 7, 14]) today = timezone.now().date() for days in reminder_days: target_date = today + timedelta(days=days) expiring_plans = InvoiceModel.objects.filter( date_due=target_date ).select_related("customer", "ce_model") for inv in expiring_plans: # dealer = inv.customer.customer_set.first().dealer subject = f"Your invoice is due in {days} days" message = render_to_string( "emails/invoice_past_due_reminder.txt", { "customer_name": inv.customer.customer_name, "invoice_number": inv.invoice_number, "amount_due": inv.amount_due, "days_past_due": inv.due_in_days(), "SITE_NAME": settings.SITE_NAME, }, ) send_email( "noreply@yourdomain.com", inv.customer.email, subject, message, ) self.stdout.write(f"Queuing {expiring_plans} reminders for {target_date}") def invoice_past_due(self): """Queue email reminders for expiring plans""" today = timezone.now().date() expiring_plans = InvoiceModel.objects.filter( date_due__lte=today ).select_related("customer", "ce_model") # Send email for inv in expiring_plans: dealer = inv.customer.customer_set.first().dealer subject = f"Your invoice is past due" message = render_to_string( "emails/invoice_past_due.txt", { "customer_name": inv.customer.customer_name, "invoice_number": inv.invoice_number, "amount_due": inv.amount_due, "days_past_due": (today - inv.date_due).days, "SITE_NAME": settings.SITE_NAME, }, ) # send notification to accountatnt recipients = ( CustomGroup.objects.filter(dealer=dealer, name="Accountant") .first() .group.user_set.exclude(email=dealer.user.email) .distinct() ) for rec in recipients: Notification.objects.create( user=rec, message=_( """ Invoice {invoice_number} is past due,please your View. """ ).format( invoice_number=inv.invoice_number, url=reverse( "invoice_detail", kwargs={ "dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "pk": inv.pk, }, ), ), ) # send email to customer send_email( "noreply@yourdomain.com", inv.customer.email, subject, message, ) self.stdout.write(f"Queuing {expiring_plans} reminders for {today}") # 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")