symposion_app/vendor/symposion/schedule/models.py
Joel Addison 252697b842 Update to Django 2.2
Upgrade site and modules to Django 2.2. Remove and replace obsolete
functionality with current equivalents. Update requirements to latest
versions where possible. Remove unused dependencies.
2020-11-22 23:58:14 +10:00

404 lines
11 KiB
Python

import datetime
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import ugettext_lazy as _
from symposion.managers import DefaultSelectRelatedManager
from symposion.text_parser import parse
from symposion.proposals.models import ProposalBase
from symposion.conference.models import Section
from symposion.speakers.models import Speaker
User = get_user_model()
class Schedule(models.Model):
objects = DefaultSelectRelatedManager()
section = models.OneToOneField(
Section,
verbose_name=_("Section"),
on_delete=models.CASCADE,
)
published = models.BooleanField(default=True, verbose_name=_("Published"))
hidden = models.BooleanField(_("Hide schedule from overall conference view"), default=False)
def __str__(self):
return "%s Schedule" % self.section
class SymposionMeta:
select_related = ('section', )
class Meta:
ordering = ["section"]
verbose_name = _('Schedule')
verbose_name_plural = _('Schedules')
class Day(models.Model):
objects = DefaultSelectRelatedManager()
schedule = models.ForeignKey(
Schedule,
verbose_name=_("Schedule"),
on_delete=models.CASCADE,
)
date = models.DateField(verbose_name=_("Date"))
def __str__(self):
return "%s: %s" % (self.schedule.section.name, self.date)
class SymposionMeta:
select_related = ('schedule__section', )
class Meta:
unique_together = [("schedule", "date")]
ordering = ["date"]
verbose_name = _("date")
verbose_name_plural = _("dates")
class Room(models.Model):
schedule = models.ForeignKey(
Schedule,
verbose_name=_("Schedule"),
on_delete=models.CASCADE,
)
name = models.CharField(max_length=65, verbose_name=_("Name"))
order = models.PositiveIntegerField(verbose_name=_("Order"))
def __unicode__(self):
return self.name
def __str__(self):
return self.name
class Meta:
verbose_name = _("Room")
verbose_name_plural = _("Rooms")
class Track(models.Model):
name = models.CharField(max_length=80, verbose_name=_("Track"))
room = models.ForeignKey(Room, on_delete=models.CASCADE)
day = models.ForeignKey(Day, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Meta:
unique_together = [('room', 'day')]
verbose_name = _("Track")
verbose_name_plural = _("Tracks")
class SlotKind(models.Model):
"""
A slot kind represents what kind a slot is. For example, a slot can be a
break, lunch, or X-minute talk.
"""
schedule = models.ForeignKey(
Schedule,
verbose_name=_("schedule"),
on_delete=models.CASCADE,
)
label = models.CharField(max_length=50, verbose_name=_("Label"))
def __str__(self):
return ": ".join((self.schedule.section.name, self.label))
class Meta:
verbose_name = _("Slot kind")
verbose_name_plural = _("Slot kinds")
class Slot(models.Model):
objects = DefaultSelectRelatedManager()
name = models.CharField(max_length=512, editable=False)
day = models.ForeignKey(
Day,
verbose_name=_("Day"),
on_delete=models.CASCADE,
)
kind = models.ForeignKey(
SlotKind,
verbose_name=_("Kind"),
on_delete=models.CASCADE,
)
start = models.TimeField(verbose_name=_("Start"))
end = models.TimeField(verbose_name=_("End"))
exclusive = models.BooleanField(
default=False,
help_text=_("Set to true if this is the only event during this "
"timeslot"),
)
content_override = models.TextField(blank=True, verbose_name=_("Content override"))
content_override_html = models.TextField(blank=True)
def assign(self, content):
"""
Assign the given content to this slot and if a previous slot content
was given we need to unlink it to avoid integrity errors.
"""
self.unassign()
content.slot = self
content.save()
def unassign(self):
"""
Unassign the associated content with this slot.
"""
content = self.content
if content and content.slot_id:
content.slot = None
content.save()
@property
def content(self):
"""
Return the content this slot represents.
@@@ hard-coded for presentation for now
"""
try:
return self.content_ptr
except ObjectDoesNotExist:
return None
@property
def start_datetime(self):
return datetime.datetime(
self.day.date.year,
self.day.date.month,
self.day.date.day,
self.start.hour,
self.start.minute)
@property
def end_datetime(self):
return datetime.datetime(
self.day.date.year,
self.day.date.month,
self.day.date.day,
self.end.hour,
self.end.minute)
@property
def length_in_minutes(self):
return int(
(self.end_datetime - self.start_datetime).total_seconds() / 60)
@property
def rooms(self):
return Room.objects.filter(pk__in=self.slotroom_set.values("room"))
def save(self, *args, **kwargs):
roomlist = ' '.join(map(str, self.rooms))
self.name = "%s %s (%s - %s) %s" % (self.day.date, self.kind.label, self.start, self.end, roomlist)
self.content_override_html = parse(self.content_override)
super(Slot, self).save(*args, **kwargs)
def __str__(self):
return "%s: %s" % (self.day.schedule.section.name, self.name)
class SymposionMeta:
select_related = ('kind__schedule__section', 'day')
class Meta:
ordering = ["day__schedule__section__name", "day", "start" ]
verbose_name = _("slot")
verbose_name_plural = _("slots")
class SlotRoom(models.Model):
"""
Links a slot with a room.
"""
slot = models.ForeignKey(
Slot,
verbose_name=_("Slot"),
on_delete=models.CASCADE,
)
room = models.ForeignKey(
Room,
verbose_name=_("Room"),
on_delete=models.CASCADE,
)
def __str__(self):
return "%s %s" % (self.room, self.slot)
class Meta:
unique_together = [("slot", "room")]
ordering = ["slot", "room__order"]
verbose_name = _("Slot room")
verbose_name_plural = _("Slot rooms")
class Presentation(models.Model):
objects = DefaultSelectRelatedManager()
slot = models.OneToOneField(
Slot,
null=True,
blank=True,
related_name="content_ptr",
verbose_name=_("Slot"),
on_delete=models.CASCADE,
)
title = models.CharField(max_length=100, verbose_name=_("Title"))
abstract = models.TextField(verbose_name=_("Abstract"))
abstract_html = models.TextField(blank=True)
speaker = models.ForeignKey(
Speaker,
related_name="presentations",
verbose_name=_("Speaker"),
on_delete=models.CASCADE,
)
additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
blank=True, verbose_name=_("Additional speakers"))
unpublish = models.BooleanField(
default=False,
verbose_name=_("Do not publish"),
)
cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
proposal_base = models.OneToOneField(
ProposalBase,
related_name="presentation",
verbose_name=_("Proposal base"),
on_delete=models.CASCADE,
)
section = models.ForeignKey(
Section,
related_name="presentations",
verbose_name=_("Section"),
on_delete=models.CASCADE,
)
def save(self, *args, **kwargs):
self.abstract_html = parse(self.abstract)
return super(Presentation, self).save(*args, **kwargs)
@property
def number(self):
return self.proposal.number
@property
def proposal(self):
if self.proposal_base_id is None:
return None
return ProposalBase.objects.get_subclass(pk=self.proposal_base_id)
def speakers(self):
yield self.speaker
for speaker in self.additional_speakers.all():
if speaker.user:
yield speaker
def __str__(self):
return "#%s %s (%s)" % (self.number, self.title, self.speaker)
class Meta:
ordering = ["slot"]
verbose_name = _("presentation")
verbose_name_plural = _("presentations")
class Session(models.Model):
day = models.ForeignKey(
Day,
related_name="sessions",
verbose_name=_("Day"),
on_delete=models.CASCADE,
)
slots = models.ManyToManyField(Slot, related_name="sessions", verbose_name=_("Slots"))
def sorted_slots(self):
return self.slots.order_by("start")
def start(self):
slots = self.sorted_slots()
if slots:
return list(slots)[0].start
else:
return None
def end(self):
slots = self.sorted_slots()
if slots:
return list(slots)[-1].end
else:
return None
def chair(self):
for role in self.sessionrole_set.all():
if role.role == SessionRole.SESSION_ROLE_CHAIR:
return role
return None
@property
def rooms(self):
return Room.objects.filter(slotroom__slot__in=self.slots.all()).distinct()
@property
def room_names(self):
return ', '.join(room.name for room in self.rooms)
def __str__(self):
start = self.start()
end = self.end()
rooms = ', '.join(room.name for room in self.rooms)
if start and end:
return "%s: %s - %s in %s" % (
self.day.date.strftime("%a"),
start.strftime("%X"),
end.strftime("%X"),
rooms
)
return ""
class Meta:
verbose_name = _("Session")
verbose_name_plural = _("Sessions")
class SessionRole(models.Model):
SESSION_ROLE_CHAIR = 1
SESSION_ROLE_RUNNER = 2
SESSION_ROLE_TYPES = [
(SESSION_ROLE_CHAIR, _("Session Chair")),
(SESSION_ROLE_RUNNER, _("Session Runner")),
]
session = models.ForeignKey(
Session,
verbose_name=_("Session"),
on_delete=models.CASCADE,
)
user = models.ForeignKey(
User,
verbose_name=_("User"),
on_delete=models.CASCADE,
)
role = models.IntegerField(choices=SESSION_ROLE_TYPES, verbose_name=_("Role"))
status = models.NullBooleanField(verbose_name=_("Status"))
submitted = models.DateTimeField(default=datetime.datetime.now)
class Meta:
unique_together = [("session", "user", "role")]
verbose_name = _("Session role")
verbose_name_plural = _("Session roles")
def __str__(self):
return "%s %s: %s" % (self.user, self.session,
self.SESSION_ROLE_TYPES[self.role - 1][1])