from itertools import groupby from django.core.mail import send_mail from django.core.management.base import BaseCommand, CommandError from django.template import loader from tasks.models import Tool, Task, Event, GroupToolSubscription, GroupTaskSubscription class Command(BaseCommand): help = "Sends any notifications for upcoming and overdue tasks" def _active_task_subscriptions(self): for subscription in GroupTaskSubscription.objects.all(): if subscription.should_remind: yield subscription for tool_subscription in GroupToolSubscription.objects.all(): for subscription in tool_subscription.get_task_subscriptions(): if subscription.should_remind: yield subscription def _expand_group_subscriptions_to_users(self, subscriptions): out = {} for subscription in subscriptions: for user in subscription.group.user_set.all(): if user not in out: out[user] = [] out[user].append(subscription) return { user: sorted(subscriptions, key=lambda r: r.task.next_recurrence) for user, subscriptions in out.items() } def handle(self, *args, **options): template = loader.get_template("tasks/notificationEmail.txt.dtl") group_subscriptions = self._active_task_subscriptions() subscriptions_per_user = self._expand_group_subscriptions_to_users( group_subscriptions ) for user, subscriptions in subscriptions_per_user.items(): if not user.email: self.stdout.write( self.style.ERROR( f"Can't send email, user '{user}' is missing an email address" ) ) continue self.stdout.write( self.style.SUCCESS( f"Sending notification for {len(subscriptions)} task(s) to {user}" ) ) try: send_mail( subject=f"[CMS Tool Maintenance] {len(subscriptions)} tasks are upcoming or overdue!", message=template.render({"subscriptions": subscriptions}).strip(), from_email="adam@adamgoldsmith.name", recipient_list=[user.email], fail_silently=False, ) except Exception as e: self.stdout.write( self.style.ERROR( f"Failed to send mail for user '{user}': {type(e).__name__}: {e}" ) )