2013-06-02 21:26:10 +02:00
|
|
|
from django.db import models
|
|
|
|
from django.utils.translation import ugettext as _
|
2013-10-14 19:46:53 +02:00
|
|
|
from django.contrib.auth.models import User, Permission
|
2019-01-05 11:27:15 +01:00
|
|
|
from django.db.models import Q
|
2013-09-26 21:56:32 +02:00
|
|
|
|
2014-04-18 13:43:02 +02:00
|
|
|
from datetime import datetime
|
|
|
|
from location_field.models import PlainLocationField
|
2013-06-02 21:26:10 +02:00
|
|
|
|
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
class NoNextEventException(Exception):
|
|
|
|
def __str__(self):
|
|
|
|
return "No event scheduled for the future"
|
2013-09-22 11:11:48 +02:00
|
|
|
|
2013-06-02 21:26:10 +02:00
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
class Event(models.Model):
|
2013-06-02 21:26:10 +02:00
|
|
|
EVENT_TYPES = (
|
2019-01-05 11:27:15 +01:00
|
|
|
('Reh', _('Rehearsal')),
|
|
|
|
('Conc', _('Concert')),
|
|
|
|
('Party', _('Party')),
|
|
|
|
('Travel', _('Travel')),
|
|
|
|
('Option', _('Option')),
|
2013-06-02 21:26:10 +02:00
|
|
|
)
|
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
type = models.CharField(max_length=6, choices=EVENT_TYPES, default='Reh', verbose_name=_("type"))
|
|
|
|
short_desc = models.CharField(null=True, max_length=100, blank=True, verbose_name=_("Short Description"))
|
|
|
|
location = models.TextField(blank=True, verbose_name=_("location"))
|
|
|
|
map_location = PlainLocationField(blank=True, based_field=location, zoom=7, verbose_name=_("Location on map"))
|
|
|
|
desc = models.TextField(blank=True, verbose_name=_("description"))
|
|
|
|
|
|
|
|
date = models.DateField(verbose_name=_("date"))
|
|
|
|
time = models.TimeField(null=True, blank=True, verbose_name=_("time"))
|
|
|
|
meeting_time = models.TimeField(null=True, blank=True, verbose_name=_("meeting_time"))
|
|
|
|
|
|
|
|
end_date = models.DateField(null=True, blank=True, verbose_name=_("End Date"))
|
|
|
|
|
|
|
|
participants = models.ManyToManyField(User, through='EventParticipation', verbose_name=_("participants"))
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.title
|
2013-06-02 21:26:10 +02:00
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
# Call the "real" save() method
|
|
|
|
super(Event, self).save(*args, **kwargs)
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-06-02 21:26:10 +02:00
|
|
|
# Create a "Don't Know" participation for each Musician
|
2019-01-05 11:27:15 +01:00
|
|
|
for u in User.objects.all():
|
2013-09-26 21:56:32 +02:00
|
|
|
if not u in self.participants.all():
|
2019-01-05 11:27:15 +01:00
|
|
|
EventParticipation.objects.create(event=self, user=u, status='-', comment='')
|
|
|
|
|
2013-09-28 18:57:19 +02:00
|
|
|
@property
|
|
|
|
def title(self):
|
|
|
|
res = self.get_type_display()
|
2014-06-22 11:52:26 +02:00
|
|
|
if self.short_desc:
|
2013-11-01 12:42:57 +01:00
|
|
|
res += " (" + self.short_desc + ") "
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-09-28 18:57:19 +02:00
|
|
|
return res
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-09-15 14:48:40 +02:00
|
|
|
@property
|
|
|
|
def displaytime(self):
|
|
|
|
if self.meeting_time is None or self.meeting_time == "":
|
|
|
|
return self.time
|
|
|
|
else:
|
2019-01-05 11:27:15 +01:00
|
|
|
return self.meeting_time
|
|
|
|
|
2014-01-11 11:46:53 +01:00
|
|
|
@property
|
|
|
|
def displaydatetime(self):
|
|
|
|
if not self.displaytime == None:
|
2019-01-05 11:27:15 +01:00
|
|
|
return datetime.combine(self.date, self.displaytime)
|
2014-01-11 11:46:53 +01:00
|
|
|
else:
|
2019-01-05 11:27:15 +01:00
|
|
|
return datetime.combine(self.date, datetime.min.time())
|
2013-06-02 21:26:10 +02:00
|
|
|
|
2014-01-11 15:01:40 +01:00
|
|
|
@staticmethod
|
2019-01-05 11:27:15 +01:00
|
|
|
def getNextEvent(eventType="", includePreviousFromToday=True):
|
2014-01-11 15:01:40 +01:00
|
|
|
"""Return the next event, of the given type. If type is the empty string the next event is returned
|
|
|
|
regardless of its type.
|
|
|
|
if includePreviousFromToday the nextEvent returned could also have been today with a startime < now """
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2014-01-11 15:01:40 +01:00
|
|
|
if includePreviousFromToday:
|
|
|
|
if eventType == "":
|
2019-01-05 11:27:15 +01:00
|
|
|
nextEvents = Event.objects.filter(date__gte=datetime.now()).order_by('date')[:1]
|
2014-01-11 15:01:40 +01:00
|
|
|
else:
|
2019-01-05 11:27:15 +01:00
|
|
|
nextEvents = Event.objects.filter(date__gte=datetime.now(), type=eventType).order_by('date')[:1]
|
|
|
|
|
|
|
|
if len(nextEvents) == 0:
|
2014-01-11 15:01:40 +01:00
|
|
|
raise NoNextEventException()
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2014-01-11 15:01:40 +01:00
|
|
|
return nextEvents[0]
|
|
|
|
else:
|
|
|
|
maximalNumberOfEventsOnSameDay = 4
|
|
|
|
nextEvents = []
|
2019-01-05 11:27:15 +01:00
|
|
|
if eventType == "":
|
|
|
|
nextEvents = Event.objects.filter(date__gte=datetime.now()).order_by('date')[
|
|
|
|
:maximalNumberOfEventsOnSameDay]
|
2014-01-11 15:01:40 +01:00
|
|
|
else:
|
2019-01-05 11:27:15 +01:00
|
|
|
nextEvents = Event.objects.filter(date__gte=datetime.now(), type=eventType).order_by('date')[
|
|
|
|
:maximalNumberOfEventsOnSameDay]
|
|
|
|
|
2014-01-11 15:01:40 +01:00
|
|
|
if len(nextEvents) == 0:
|
|
|
|
raise NoNextEventException()
|
|
|
|
|
|
|
|
i = 0
|
|
|
|
nextEvent = nextEvents[0]
|
|
|
|
# nextEvent is not necessarily events[0] since events[0] may have been previously today
|
|
|
|
while nextEvent.displaydatetime < datetime.now():
|
2019-01-05 11:27:15 +01:00
|
|
|
if len(nextEvents) <= i:
|
2014-01-11 15:01:40 +01:00
|
|
|
raise NoNextEventException()
|
|
|
|
else:
|
|
|
|
i += 1
|
|
|
|
nextEvent = nextEvents[i]
|
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
return nextEvent
|
2014-04-18 13:43:02 +02:00
|
|
|
|
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
class EventParticipation(models.Model):
|
|
|
|
OPTIONS = (('?', _('?')),
|
|
|
|
('Yes', _('Yes')),
|
|
|
|
('No', _('No')),
|
|
|
|
('-', _('-'))
|
|
|
|
)
|
2014-04-18 13:43:02 +02:00
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
event = models.ForeignKey(Event, verbose_name=_("event"), on_delete=models.PROTECT)
|
|
|
|
user = models.ForeignKey(User, verbose_name=_("user"), on_delete=models.PROTECT)
|
|
|
|
status = models.CharField(max_length=3, choices=OPTIONS, default='?', verbose_name=_("status"))
|
|
|
|
comment = models.CharField(max_length=64, blank=True, verbose_name=_("comment"))
|
2014-04-18 13:43:02 +02:00
|
|
|
|
2013-09-26 21:56:32 +02:00
|
|
|
def get_username(self):
|
|
|
|
return self.user.username
|
2019-01-05 11:27:15 +01:00
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
prev = EventParticipation.objects.filter(event=self.event, user=self.user)
|
2014-06-20 08:57:33 +02:00
|
|
|
if len(prev) == 0:
|
2019-01-05 11:27:15 +01:00
|
|
|
super(EventParticipation, self).save(*args, **kwargs)
|
2014-06-20 08:57:33 +02:00
|
|
|
else:
|
|
|
|
prev = prev[0]
|
|
|
|
if prev.status != self.status or prev.comment != self.comment:
|
2019-01-05 11:27:15 +01:00
|
|
|
super(EventParticipation, self).save(*args, **kwargs)
|
2014-04-21 09:21:59 +02:00
|
|
|
|
2013-09-15 14:48:40 +02:00
|
|
|
@staticmethod
|
2019-01-05 11:27:15 +01:00
|
|
|
def hasUserSetParticipationForAllEvents(user):
|
2013-10-14 19:46:53 +02:00
|
|
|
if not EventParticipation.isMember(user):
|
|
|
|
return True
|
2013-09-26 21:56:32 +02:00
|
|
|
|
2019-01-05 11:27:15 +01:00
|
|
|
futurePart = EventParticipation.objects.filter(event__date__gte=datetime.now())
|
|
|
|
|
|
|
|
notYetEntered = futurePart.filter(user=user).filter(status='-')
|
|
|
|
if len(notYetEntered) > 0:
|
2013-09-15 14:48:40 +02:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
2014-04-18 13:43:02 +02:00
|
|
|
|
2013-10-14 19:46:53 +02:00
|
|
|
@staticmethod
|
2019-01-05 11:27:15 +01:00
|
|
|
def isMember(user):
|
2013-10-14 19:46:53 +02:00
|
|
|
return user.has_perm('eventplanner.member')
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-10-14 19:46:53 +02:00
|
|
|
@staticmethod
|
2019-01-05 11:27:15 +01:00
|
|
|
def isAdmin(user):
|
2013-10-14 19:46:53 +02:00
|
|
|
return user.has_perm('eventplanner.admin')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def members():
|
2019-01-05 11:27:15 +01:00
|
|
|
perm = Permission.objects.get(codename='member')
|
|
|
|
f = User.objects.filter(Q(groups__permissions=perm) | Q(user_permissions=perm)).distinct()
|
2013-10-15 21:51:05 +02:00
|
|
|
return f.order_by('musician__position')
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-06-30 16:55:00 +02:00
|
|
|
@staticmethod
|
2019-01-05 11:27:15 +01:00
|
|
|
def get_or_create(user, event):
|
2013-06-30 16:55:00 +02:00
|
|
|
try:
|
2019-01-05 11:27:15 +01:00
|
|
|
result = EventParticipation.objects.get(event=event, user=user)
|
2013-06-30 16:55:00 +02:00
|
|
|
except EventParticipation.DoesNotExist:
|
2019-01-05 11:27:15 +01:00
|
|
|
result = EventParticipation.objects.create(event=event, user=user, status='-', comment='')
|
|
|
|
|
2013-06-30 16:55:00 +02:00
|
|
|
return result
|
2019-01-05 11:27:15 +01:00
|
|
|
|
2013-06-02 21:26:10 +02:00
|
|
|
class Meta:
|
2013-09-26 21:56:32 +02:00
|
|
|
unique_together = ("event", "user")
|
2013-06-30 16:55:00 +02:00
|
|
|
permissions = (
|
2019-01-05 11:27:15 +01:00
|
|
|
("admin", _("Admin")),
|
|
|
|
("member", _("Member")),
|
2013-06-30 16:55:00 +02:00
|
|
|
)
|