Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion events/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib import admin
from django.db.models import Q

from events.enums import EventStatus
from events.enums.status import EventStatus
from events.filters.category import ActiveCategoryFilter
from events.models.banner import Banner
from events.models.category import Category
Expand Down
6 changes: 5 additions & 1 deletion events/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ class EventsConfig(AppConfig):
name = "events"

def ready(self): # noqa: PLR6301
import events.signals # type: ignore # noqa: F401
import events.signals.banner # type: ignore # noqa: F401
import events.signals.category
import events.signals.events
import events.signals.signup
import events.signals.triggers
import events.validators # type: ignore # noqa: F401
File renamed without changes.
2 changes: 1 addition & 1 deletion events/management/commands/fake_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from faker import Faker
from PIL import Image

from events.enums import EventStatus
from events.enums.status import EventStatus
from events.models.banner import Banner
from events.models.category import Category
from events.models.event import Event
Expand Down
2 changes: 1 addition & 1 deletion events/managers/banners.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.db import models
from django.db.models import QuerySet

from events.enums import EventStatus
from events.enums.status import EventStatus


class BannerQuerySet(QuerySet):
Expand Down
2 changes: 1 addition & 1 deletion events/models/event.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib.auth.models import User
from django.db import models

from events.enums import EventStatus
from events.enums.status import EventStatus
from events.validators import (
validate_event_attributes,
validate_total_participants,
Expand Down
2 changes: 1 addition & 1 deletion events/models/signup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib.auth.models import User
from django.db import models

from events.enums import EventStatus
from events.enums.status import EventStatus
from events.models.event import Event
from events.validators import (
validate_event_attributes,
Expand Down
2 changes: 1 addition & 1 deletion events/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework import serializers

from events.enums import EventStatus
from events.enums.status import EventStatus
from events.models.event import Event
from events.models.signup import EventSignup

Expand Down
146 changes: 0 additions & 146 deletions events/signals.py

This file was deleted.

Empty file added events/signals/__init__.py
Empty file.
32 changes: 32 additions & 0 deletions events/signals/banner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from django.core.exceptions import PermissionDenied
from django.db.models.signals import pre_delete, pre_save
from django.dispatch import receiver

from events.enums.status import EventStatus
from events.models.banner import Banner


@receiver(pre_delete, sender=Banner)
def restrict_banner_deletion(instance, **kwargs):
"""
Restrict the deletion of a banner if it is for a active/completed event.
"""

if instance.event.status not in [
EventStatus.DRAFT,
]:
raise PermissionDenied("You can only delete the banner of a draft event.")


@receiver(pre_save, sender=Banner)
def validate_banner(instance, **kwargs):
"""
Validate the banner instance before saving it to the database.
Restrict the addition of a banner for a active/completed/cancelled event.
"""

if instance.event.status not in [
EventStatus.DRAFT,
]:
raise PermissionDenied("You can only add banners to draft events.")
instance.full_clean()
16 changes: 16 additions & 0 deletions events/signals/category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.core.exceptions import PermissionDenied
from django.db.models.signals import pre_save
from django.dispatch import receiver

from events.enums.status import EventStatus
from events.models.category import Category


@receiver(pre_save, sender=Category)
def restrict_category_update(instance, **kwargs):
"""
Restrict the update of a category if it is associated with a active/completed event.
"""
if instance.pk and instance.event_set.exclude(status__in=[EventStatus.DRAFT]).exists():
raise PermissionDenied("You can only update a category linked to a draft event.")
instance.full_clean()
27 changes: 27 additions & 0 deletions events/signals/events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.core.exceptions import PermissionDenied
from django.db.models.signals import pre_delete, pre_save
from django.dispatch import receiver

from events.models.event import Event


@receiver(pre_delete, sender=Event)
def restrict_event_deletion(instance, **kwargs):
"""
Restrict the deletion of an event if the user is not the creator or a superuser.
"""

request = kwargs.get("request")
if request:
user = request.user
if not (user == instance.created_by or user.is_superuser):
raise PermissionDenied("You do not have permission to delete this event.")


@receiver(pre_save, sender=Event)
def validate_event(instance, **kwargs):
"""
Validate the event instance before saving it to the database.
"""

instance.full_clean()
52 changes: 52 additions & 0 deletions events/signals/signup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver

from events.models.signup import EventSignup
from preferences.enums import EmailTemplateType
from preferences.models import EmailTemplate
from root.tasks import send_email_task


@receiver(post_save, sender=EventSignup)
def send_event_registration_email(instance, created, **kwargs):
"""
Send an email to the user after successfully signing up for an event.
"""

if created:
event_signup_template = EmailTemplate.get_email_template_by_type(
EmailTemplateType.EVENT_SIGNUP
)

if not event_signup_template:
raise ValueError("Event signup email template not found")

email_template = {
"html": event_signup_template.body_html,
"plaintext": event_signup_template.body_plaintext,
}
email_title = event_signup_template.subject

context = {
"user": instance.user.username,
"event": {
"title": instance.event.title,
"start_date": instance.event.schedule.start_date,
"end_date": instance.event.schedule.end_date,
"start_time": instance.event.schedule.start_time,
"end_time": instance.event.schedule.end_time,
"address": instance.event.location.address,
"map_link": instance.event.location.google_map_link,
},
"current_year": instance.signup_date.year,
}
send_email_task.delay(email_template, instance.user.email, email_title, context)


@receiver(pre_save, sender=EventSignup)
def validate_eventSignup(instance, **kwargs):
"""
Validate the eventsignup instance before saving it to the database.
"""

instance.full_clean()
52 changes: 52 additions & 0 deletions events/signals/triggers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from django.core.exceptions import PermissionDenied
from django.db.models.signals import post_delete, pre_delete, pre_save
from django.dispatch import receiver

from events.enums.status import EventStatus
from events.models.banner import Banner
from events.models.location import Location
from events.models.schedule import Schedule


@receiver(pre_save, sender=Schedule)
@receiver(pre_save, sender=Location)
def validate_location(instance, **kwargs):
"""
Validate the instance before saving it to the database.
Dont allow changes to a related model if the event is verified.
"""

if instance.event.status not in [EventStatus.DRAFT]:
raise PermissionDenied("You can only add objects to draft events.")
instance.full_clean()


@receiver(pre_delete, sender=Schedule)
@receiver(pre_delete, sender=Location)
def restrict_deletion(instance, **kwargs):
"""
Restrict the deletion of a related model if the event is verified.
"""

if instance.event.status not in [EventStatus.DRAFT]:
raise PermissionDenied("You can only delete objects of a draft event.")


@receiver(post_delete, sender=Banner)
@receiver(post_delete, sender=Location)
@receiver(post_delete, sender=Schedule)
def check_verified_event_requirements(instance, **kwargs):
"""
Check if the event requirements are met after deleting a related model.
If the requirements are not met, change the event status to draft.
"""

event = instance.event
if event and event.status in [EventStatus.ACTIVE]:
has_banner = Banner.objects.filter(event=event).exists()
has_location = Location.objects.filter(event=event).exists()
has_schedule = Schedule.objects.filter(event=event).exists()

if not all([has_banner, has_location, has_schedule]):
event.status = EventStatus.DRAFT
event.save()
1 change: 0 additions & 1 deletion events/tests.py

This file was deleted.

Loading
Loading