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")