You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

150 lines
5.4 KiB

import uuid
from django.db import models
from django.utils.text import slugify
from django.conf import settings
from apps.profiles.models import Institution
class EventCategory(models.TextChoices):
RELIGIOUS = 'religious', 'Religious'
EDUCATIONAL = 'educational', 'Educational'
CULTURAL = 'cultural', 'Cultural'
COUNSELING = 'counseling', 'Counseling'
CONFERENCE = 'conference', 'Conference'
WORKSHOP = 'workshop', 'Workshop'
class LocationType(models.TextChoices):
IN_PERSON = 'in_person', 'In Person'
ONLINE = 'online', 'Online'
HYBRID = 'hybrid', 'Hybrid'
class RegistrationStatus(models.TextChoices):
REGISTERED = 'registered', 'Registered'
ATTENDED = 'attended', 'Attended'
CANCELLED = 'cancelled', 'Cancelled'
class Event(models.Model):
LANGUAGE_CHOICES = [
('fa', 'Persian'),
('ar', 'Arabic'),
('en', 'English'),
('ur', 'Urdu'),
('fr', 'French'),
]
title = models.CharField(max_length=255, verbose_name="Event Title")
slug = models.SlugField(max_length=280, unique=True, blank=True, verbose_name="Slug")
description = models.TextField(verbose_name="Event Description")
organizer = models.ForeignKey(
Institution,
on_delete=models.CASCADE,
related_name='events',
verbose_name="Organizer Institution"
)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='created_events',
verbose_name="Created By"
)
category = models.CharField(
max_length=30,
choices=EventCategory.choices,
default=EventCategory.CULTURAL,
verbose_name="Category"
)
event_date = models.DateField(verbose_name="Event Date")
start_time = models.TimeField(verbose_name="Start Time")
end_time = models.TimeField(null=True, blank=True, verbose_name="End Time")
speaker_name = models.CharField(max_length=255, blank=True, verbose_name="Speaker Name")
speaker_title = models.CharField(max_length=255, blank=True, verbose_name="Speaker Title / Affiliation")
speaker_avatar = models.ImageField(upload_to='events/speakers/', blank=True, null=True, verbose_name="Speaker Avatar")
location_type = models.CharField(
max_length=20,
choices=LocationType.choices,
default=LocationType.IN_PERSON,
verbose_name="Location Type"
)
venue_address = models.CharField(max_length=500, blank=True, verbose_name="Venue Address")
online_meeting_url = models.URLField(blank=True, verbose_name="Online Meeting Link")
cover_image = models.ImageField(upload_to='events/covers/', blank=True, null=True, verbose_name="Cover Image")
capacity = models.PositiveIntegerField(default=100, verbose_name="Capacity Limit")
registration_count = models.PositiveIntegerField(default=0, verbose_name="Current Registrations")
is_active = models.BooleanField(default=True, verbose_name="Is Active")
is_featured = models.BooleanField(default=False, verbose_name="Is Featured")
tags = models.JSONField(default=list, blank=True, verbose_name="Tags")
language = models.CharField(max_length=10, choices=LANGUAGE_CHOICES, default='fa', verbose_name="Language")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['event_date', 'start_time']
verbose_name = "Event"
verbose_name_plural = "Events"
indexes = [
models.Index(fields=['event_date', 'is_active']),
models.Index(fields=['category', 'is_active']),
models.Index(fields=['organizer', 'is_active']),
]
def __str__(self):
return f"{self.title} ({self.event_date})"
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(self.title, allow_unicode=True) or "event"
unique_slug = base_slug
counter = 1
while Event.objects.filter(slug=unique_slug).exclude(pk=self.pk).exists():
unique_slug = f"{base_slug}-{counter}"
counter += 1
self.slug = unique_slug
super().save(*args, **kwargs)
def update_registration_count(self):
count = self.registrations.filter(status=RegistrationStatus.REGISTERED).count()
if self.registration_count != count:
self.registration_count = count
self.save(update_fields=['registration_count', 'updated_at'])
class EventRegistration(models.Model):
event = models.ForeignKey(
Event,
on_delete=models.CASCADE,
related_name='registrations',
verbose_name="Event"
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='event_registrations',
verbose_name="Participant"
)
status = models.CharField(
max_length=20,
choices=RegistrationStatus.choices,
default=RegistrationStatus.REGISTERED,
verbose_name="Status"
)
notes = models.TextField(blank=True, verbose_name="Participant Notes")
registered_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ('event', 'user')
ordering = ['-registered_at']
verbose_name = "Event Registration"
verbose_name_plural = "Event Registrations"
def __str__(self):
return f"{self.user} -> {self.event.title} ({self.status})"