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