svthalia/concrexit

View on GitHub
website/pushnotifications/signals/pizzas.py

Summary

Maintainability
A
2 hrs
Test Coverage
from django.db.models.signals import post_save, pre_delete, pre_save
from django.utils import timezone

from events.models import EventRegistration
from members.models import Member
from utils.models.signals import suspendingreceiver

from ..models import Category, FoodOrderReminderMessage


@suspendingreceiver(
    post_save,
    sender="pizzas.FoodEvent",
    dispatch_uid="schedule_food_order_reminder_pushnotification",
)
def schedule_food_order_reminder_pushnotification(sender, instance, **kwargs):
    """Create, update or delete a scheduled message for the food event if necessary."""
    message = getattr(instance, "end_reminder", None)

    if not instance.send_notification:
        # Remove existing not-sent notification if there is one.
        if message is not None and not message.sent:
            instance.end_reminder = None
            message.delete()
    else:
        reminder_time = instance.end - timezone.timedelta(minutes=10)

        # Delete reminder if the event is changed so that the reminder time has now passed.
        if (
            message is not None
            and message.time != reminder_time
            and reminder_time < timezone.now()
        ):
            instance.end_reminder = None
            message.delete()
            return

        # Don't update if the message has already been sent or the reminder time has passed.
        if (message is not None and message.sent) or reminder_time < timezone.now():
            return

        # Update existing notification or create new one.
        if message is None:
            message = FoodOrderReminderMessage(food_event=instance)

        message.title = f"{instance.event.title}: Order food"
        message.body = "You can order food for 10 more minutes"
        message.category = Category.objects.get(key=Category.PIZZA)
        message.time = reminder_time
        message.save()

        if instance.event.registration_required:
            message.users.set(
                instance.event.registrations.filter(member__isnull=False)
                .select_related("member")
                .values_list("member", flat=True)
            )
        else:
            message.users.set(Member.current_members.all())


@suspendingreceiver(
    post_save,
    sender=EventRegistration,
    dispatch_uid="add_registered_member_to_food_order_reminder",
)
def add_registered_member_to_food_order_reminder(sender, instance, **kwargs):
    """Update members on food order reminder notification."""
    if not instance.event.has_food_event:
        return

    message = getattr(instance.event.food_event, "end_reminder", None)
    if message is not None and not message.sent and instance.member is not None:
        if instance.date_cancelled:
            message.users.remove(instance.member)
        else:
            message.users.add(instance.member)


@suspendingreceiver(
    pre_save,
    sender="pizzas.FoodOrder",
    dispatch_uid="remove_ordered_members_from_food_order_reminder",
)
def remove_ordered_members_from_food_order_reminder(sender, instance, **kwargs):
    """Remove members from the food order reminder when they create an order."""
    message = getattr(instance.food_event, "end_reminder", None)
    if not instance.pk and message is not None and not message.sent:
        message.users.remove(instance.member)


@suspendingreceiver(
    pre_delete,
    sender="pizzas.FoodOrder",
    dispatch_uid="add_member_to_food_order_reminder_on_order_deletion",
)
def add_member_to_food_order_reminder_on_order_deletion(sender, instance, **kwargs):
    """Re-add user to food order reminder on order deletion."""
    message = getattr(instance.food_event, "end_reminder", None)
    if message is not None and not message.sent:
        message.users.add(instance.member)