Skip to content

Commit

Permalink
fixes and improvements in events and registration
Browse files Browse the repository at this point in the history
  • Loading branch information
Bhuvnesh Sharma authored and Bhuvnesh Sharma committed Sep 25, 2024
1 parent a66c009 commit 20213d1
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 74 deletions.
8 changes: 5 additions & 3 deletions backend/djangoindia/api/serializers/event.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework import serializers

from djangoindia.db.models.event import Event, EventRegistration,Sponsor,Sponsorship
from djangoindia.db.models.event import Event, EventRegistration



Expand Down Expand Up @@ -28,6 +28,8 @@ class EventSerializer(serializers.Serializer):
end_date= serializers.DateTimeField()
registration_end_date= serializers.DateTimeField()
event_mode = serializers.CharField()
max_seats = serializers.IntegerField()
seats_left = serializers.IntegerField()
sponsors = SponsorSerializer(many=True, read_only=True, source='event_sponsors')


Expand All @@ -36,8 +38,8 @@ class EventRegistrationSerializer(serializers.Serializer):
email = serializers.EmailField()
first_name = serializers.CharField(max_length=255)
last_name = serializers.CharField(max_length=255)
professional_status = serializers.ChoiceField(choices=EventRegistration.PROFESSIONAL_STATUS_CHOICES)
gender = serializers.ChoiceField(choices=EventRegistration.GENDER_CHOICES)
professional_status = serializers.ChoiceField(choices=EventRegistration.ProfessionalStatus)
gender = serializers.ChoiceField(choices=EventRegistration.Gender)
organization = serializers.CharField(max_length=100,required=False, allow_blank=True)
description = serializers.CharField(required=False, allow_blank=True)
linkedin = serializers.URLField()
Expand Down
36 changes: 36 additions & 0 deletions backend/djangoindia/db/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
from django.urls import path
from django.template.response import TemplateResponse
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import F, Count


# Register your models here.
Expand Down Expand Up @@ -43,6 +46,7 @@ class EventAdmin(admin.ModelAdmin):
class EventRegistrationAdmin(admin.ModelAdmin):
list_display = ('event', 'first_name', 'email', 'created_at')
readonly_fields = ('created_at', 'updated_at')
list_filter = ('event',)
search_fields=['email','event__name','first_name','last_name',]
actions = [send_email_to_selected_users]

Expand All @@ -53,6 +57,38 @@ def get_urls(self):
]
return custom_urls + urls

@transaction.atomic
def save_model(self, request, obj, form, change):
# This is a new registration
if not change:
if obj.event.seats_left > 0:
obj.event.seats_left -= 1
obj.event.save()
else:
raise ValidationError("No seats left for this event.")
super().save_model(request, obj, form, change)

@transaction.atomic
def delete_model(self, request, obj):
if obj.event.seats_left < obj.event.max_seats:
obj.event.seats_left += 1
obj.event.save()
super().delete_model(request, obj)

@transaction.atomic
def delete_queryset(self, request, queryset):
# Group registrations by event and count them
event_counts = queryset.values('event').annotate(count=Count('id'))

# Update seats_left for each affected event
for event_count in event_counts:
Event.objects.filter(id=event_count['event']).update(
seats_left=F('seats_left') + event_count['count']
)

# Perform the actual deletion
super().delete_queryset(request, queryset)

def send_email_view(self, request):
if request.method == 'POST':
form = EmailForm(request.POST)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Generated by Django 4.2.5 on 2024-09-25 16:28

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('db', '0007_sponsor_remove_event_event_end_date_and_more'),
]

operations = [
migrations.AddField(
model_name='event',
name='max_seats',
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='event',
name='seats_left',
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='sponsorship',
name='amount_inr',
field=models.IntegerField(blank=True, null=True),
),
migrations.AlterField(
model_name='event',
name='event_mode',
field=models.CharField(choices=[('in_person', 'In Person'), ('online', 'Online')], default='in_person', max_length=20),
),
migrations.AlterField(
model_name='eventregistration',
name='gender',
field=models.CharField(choices=[('male', 'Male'), ('female', 'Female'), ('other', 'Other')], max_length=15),
),
migrations.AlterField(
model_name='eventregistration',
name='professional_status',
field=models.CharField(choices=[('working_professional', 'Working Professional'), ('student', 'Student'), ('freelancer', 'Freelancer'), ('other', 'Other')], default='other', max_length=100),
),
migrations.AlterField(
model_name='sponsor',
name='type',
field=models.CharField(choices=[('individual', 'Individual'), ('organization', 'Organization')], max_length=20),
),
migrations.AlterField(
model_name='sponsorship',
name='tier',
field=models.CharField(choices=[('platinum', 'Platinum'), ('gold', 'Gold'), ('silver', 'Silver'), ('venue_sponsors', 'Venue Sponsors'), ('food_sponsors', 'Food Sponsors'), ('schwag_sponsors', 'Schwag Sponsors'), ('grant', 'Grant'), ('individual', 'Individual'), ('organization', 'Organization')], max_length=20),
),
migrations.AlterField(
model_name='sponsorship',
name='type',
field=models.CharField(choices=[('community_sponsorship', 'Community Sponsorship'), ('event_sponsorship', 'Event Sponsorship')], max_length=30),
),
]
123 changes: 54 additions & 69 deletions backend/djangoindia/db/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@
from .base import BaseModel
from django.utils import timezone
from django.core.exceptions import ValidationError
from datetime import timedelta

def validate_future_date(value):
if value <= timezone.now():
raise ValidationError("Date must be in the future.")


class Event(BaseModel):
IN_PERSON = "In-person"
ONLINE = "Online"

EVENT_MODE_CHOICES = [
(IN_PERSON, IN_PERSON),
(ONLINE, ONLINE)
]

class EventModes(models.TextChoices):
IN_PERSON = "in_person"
ONLINE = "online"

name = models.CharField(max_length=255, unique=True)
cover_image = models.ImageField(upload_to="event_images/", blank=True)
Expand All @@ -28,7 +24,9 @@ class Event(BaseModel):
start_date = models.DateTimeField(null=True, blank=True, validators=[validate_future_date])
end_date = models.DateTimeField(null=True, blank=True, validators=[validate_future_date])
registration_end_date = models.DateTimeField(null=True, blank=True, validators=[validate_future_date])
event_mode = models.CharField(max_length=20,choices=EVENT_MODE_CHOICES,default=IN_PERSON)
event_mode = models.CharField(max_length=20,choices=EventModes.choices,default=EventModes.IN_PERSON)
max_seats = models.IntegerField(null=True, blank=True)
seats_left = models.IntegerField(null=True, blank=True)

def clean(self):
super().clean()
Expand All @@ -41,26 +39,16 @@ def __str__(self) -> str:
return f"{self.name} @ {self.city} ({self.start_date.date()})"

class EventRegistration(BaseModel):
WORKING_PROFESSIONAL = "working_professional"
STUDENT = "student"
FREELANCER = "freelancer"
OTHER = "other"

MALE = "male"
FEMALE = "female"

PROFESSIONAL_STATUS_CHOICES = [
(WORKING_PROFESSIONAL, WORKING_PROFESSIONAL),
(STUDENT, STUDENT),
(FREELANCER, FREELANCER),
(OTHER, OTHER)
]

GENDER_CHOICES = [
(MALE, MALE),
(FEMALE, FEMALE),
(OTHER, OTHER)
]
class ProfessionalStatus(models.TextChoices):
WORKING_PROFESSIONAL = "working_professional"
STUDENT = "student"
FREELANCER = "freelancer"
OTHER = "other"

class Gender(models.TextChoices):
MALE = "male"
FEMALE = "female"
OTHER = "other"

event = models.ForeignKey(
"db.Event",
Expand All @@ -71,13 +59,13 @@ class EventRegistration(BaseModel):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
professional_status = models.CharField(
max_length=100, choices=PROFESSIONAL_STATUS_CHOICES, default=OTHER
max_length=100, choices=ProfessionalStatus.choices, default=ProfessionalStatus.OTHER
)
organization = models.CharField(max_length=100, null=True, blank=True)
description = models.TextField(null=True, blank=True)
gender = models.CharField(
max_length=15,
choices=GENDER_CHOICES
choices=Gender.choices
)
linkedin = models.URLField()
github = models.URLField(null=True, blank=True)
Expand All @@ -93,26 +81,30 @@ class Meta:
)
]

def save(self, *args, **kwargs):
# This is a new registration
if self._state.adding:
if self.event.seats_left > 0:
self.event.seats_left -= 1
self.event.save()
else:
raise ValueError("No seats left for this event.")
super().save(*args, **kwargs)

def __str__(self) -> str:
return (
f"{self.first_name} {self.last_name} ({self.email}) --- {self.event.name}"
)



class Sponsor(BaseModel):

INDIVIDUAL = "individual"
ORGANIZATION = "organization"

SPONSOR_TYPE_CHOICES = [
(INDIVIDUAL, INDIVIDUAL),
(ORGANIZATION, ORGANIZATION),
]

class SponsorType(models.TextChoices):
INDIVIDUAL = "individual"
ORGANIZATION = "organization"

name = models.CharField(max_length=255)
email = models.CharField(max_length=100)
type = models.CharField(max_length=20, choices=SPONSOR_TYPE_CHOICES)
type = models.CharField(max_length=20, choices=SponsorType.choices)
logo = models.ImageField(upload_to='sponsors/logos/')
url = models.URLField(max_length=500, blank=True, null=True)

Expand All @@ -121,40 +113,33 @@ def __str__(self):


class Sponsorship(BaseModel):
class SponsorshipTier(models.TextChoices):
PLATINUM = "platinum"
GOLD = "gold"
SILVER = "silver"
VENUE_SPONSORS = "venue_sponsors"
FOOD_SPONSORS = "food_sponsors"
SCHWAG_SPONSORS = "schwag_sponsors"
GRANT = "grant"
INDIVIDUAL = "individual"
ORGANIZATION = "organization"

PLATINUM = "platinum"
GOLD = "gold"
SILVER = "silver"
INDIVIDUAL = "individual"
ORGANIZATION = "organization"

COMMUNITY_SPONSORSHIP = "community_sponsorship"
EVENT_SPONSORSHIP = "event_sponsorship"
class SponsorshipType(models.TextChoices):
COMMUNITY_SPONSORSHIP = "community_sponsorship"
EVENT_SPONSORSHIP = "event_sponsorship"

SPONSORSHIP_TIER_CHOICES = [
(PLATINUM, PLATINUM),
(GOLD, GOLD),
(SILVER, SILVER),
(INDIVIDUAL, INDIVIDUAL),
(ORGANIZATION, ORGANIZATION),
]

SPONSORSHIP_TYPE_CHOICES = [
(COMMUNITY_SPONSORSHIP, COMMUNITY_SPONSORSHIP),
(EVENT_SPONSORSHIP, EVENT_SPONSORSHIP),
]

sponsor_details = models.ForeignKey(Sponsor, on_delete=models.CASCADE, related_name='sponsorships')
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='sponsors', null=True, blank=True)
tier = models.CharField(max_length=20, choices=SPONSORSHIP_TIER_CHOICES)
type = models.CharField(max_length=30, choices=SPONSORSHIP_TYPE_CHOICES)
tier = models.CharField(max_length=20, choices=SponsorshipTier.choices)
type = models.CharField(max_length=30, choices=SponsorshipType.choices)
amount_inr = models.IntegerField(null=True, blank=True)

def clean(self):
super().clean()
if self.type == self.COMMUNITY_SPONSORSHIP and self.tier not in [self.INDIVIDUAL, self.ORGANIZATION]:
raise ValidationError("For community sponsorship, tier must be either 'individual' or 'organization'.")
elif self.type == self.EVENT_SPONSORSHIP and self.tier not in [self.PLATINUM, self.GOLD, self.SILVER]:
raise ValidationError("For event sponsorship, tier must be either 'platinum', 'gold', or 'silver'.")
if self.type == self.SponsorshipType.COMMUNITY_SPONSORSHIP and self.tier not in [self.SponsorshipTier.INDIVIDUAL, self.SponsorshipTier.ORGANIZATION, self.SponsorshipTier.GRANT]:
raise ValidationError("For community sponsorship, tier must be 'individual', 'organization' or 'grant.")
elif self.type == self.SponsorshipType.EVENT_SPONSORSHIP and self.tier not in [self.SponsorshipTier.PLATINUM, self.SponsorshipTier.GOLD, self.SponsorshipTier.SILVER, self.SponsorshipTier.VENUE_SPONSORS, self.SponsorshipTier.FOOD_SPONSORS, self.SponsorshipTier.GRANT, self.SponsorshipTier.SCHWAG_SPONSORS]:
raise ValidationError("For event sponsorship, tier must be either 'platinum', 'gold', 'silver', 'venue_sponsors', 'food_sponsors', 'grant_sponsors' or 'schwag_sponsors'.")


def __str__(self):
Expand Down
4 changes: 2 additions & 2 deletions backend/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
psycopg2-binary==2.9.6
psycopg2-binary==2.9.9
celery==5.3.4
sqlalchemy==2.0.27
Pillow==9.5.0
Pillow==10.4.0

Django==4.2.5
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
Expand Down

0 comments on commit 20213d1

Please sign in to comment.