Files
pagasis/backend/events/models.py
T
2025-10-20 16:14:08 -06:00

139 lines
4.7 KiB
Python

from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone
from authentication.models import UserProfile
class Event(models.Model):
EVENT_TYPES = (
('conference', 'Conferencia'),
('workshop', 'Taller'),
('panel', 'Mesa Redonda'),
('seminar', 'Seminario'),
)
MODALITY_CHOICES = (
('presencial', 'Presencial'),
('online', 'En línea'),
('hybrid', 'Híbrido'),
)
title = models.CharField(
max_length=200,
verbose_name="Título de la ponencia"
)
description = models.TextField(
verbose_name="Descripción"
)
event_type = models.CharField(
max_length=20,
choices=EVENT_TYPES,
default='conference',
verbose_name="Tipo de evento"
)
modality = models.CharField(
max_length=15,
choices=MODALITY_CHOICES,
default='presencial',
verbose_name="Modalidad"
)
speaker = models.CharField(
max_length=200,
verbose_name="Ponente"
)
date = models.DateField(verbose_name="Fecha")
start_time = models.TimeField(verbose_name="Hora de inicio")
end_time = models.TimeField(verbose_name="Hora de fin")
location = models.CharField(
max_length=200,
verbose_name="Ubicación/Plataforma",
help_text="Para eventos presenciales: aula/salón. Para eventos en línea: enlace o plataforma"
)
max_capacity = models.IntegerField(
default=100,
verbose_name="Capacidad máxima"
)
is_active = models.BooleanField(
default=True,
verbose_name="Evento activo"
)
requires_registration = models.BooleanField(
default=False,
verbose_name="Requiere registro previo"
)
meeting_link = models.URLField(
blank=True,
null=True,
verbose_name="Enlace de reunión",
help_text="Para eventos en línea o híbridos"
)
meeting_id = models.CharField(
max_length=50,
blank=True,
null=True,
verbose_name="ID de reunión",
help_text="Código de sala/reunión"
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['date', 'start_time']
verbose_name = "Evento/Ponencia"
verbose_name_plural = "Eventos/Ponencias"
def clean(self):
# Validar que la hora de fin sea después de la hora de inicio
if self.start_time and self.end_time:
if self.start_time >= self.end_time:
raise ValidationError("La hora de fin debe ser posterior a la hora de inicio.")
# Validar que la fecha/hora del evento no haya terminado
if self.date and self.end_time:
from datetime import datetime
event_end = datetime.combine(self.date, self.end_time)
# Hacer timezone-aware si es necesario
if timezone.is_naive(event_end):
event_end = timezone.make_aware(event_end)
# Solo validar si el evento ya terminó completamente
if event_end < timezone.now():
raise ValidationError("No se puede crear un evento que ya finalizó.")
# Validar que eventos en línea tengan enlace
if self.modality in ['online', 'hybrid'] and not self.meeting_link:
raise ValidationError("Los eventos en línea o híbridos requieren un enlace de reunión.")
def save(self, *args, **kwargs):
# Permitir omitir validación para importaciones históricas
skip_validation = kwargs.pop('skip_validation', False)
if not skip_validation:
self.clean()
super().save(*args, **kwargs)
@property
def duration_minutes(self):
"""Duración del evento en minutos"""
if self.start_time and self.end_time:
start_datetime = timezone.datetime.combine(self.date, self.start_time)
end_datetime = timezone.datetime.combine(self.date, self.end_time)
duration = end_datetime - start_datetime
return duration.total_seconds() / 60
return 0
@property
def is_happening_now(self):
"""Verifica si el evento está ocurriendo ahora"""
now = timezone.now()
if self.date == now.date():
current_time = now.time()
return self.start_time <= current_time <= self.end_time
return False
@property
def is_online(self):
"""Verifica si el evento es en línea"""
return self.modality in ['online', 'hybrid']
def __str__(self):
modality_icon = "🖥️" if self.is_online else "🏢"
return f"{modality_icon} {self.title} - {self.date} {self.start_time}"