haikal/inventory/management/commands/invoices_due_date_reminder.py
2025-08-27 13:04:41 +03:00

146 lines
5.3 KiB
Python

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
<a href="{url}" target="_blank">View</a>.
"""
).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")