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
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})"
|