Coverage for app/models/event.py: 88%
81 statements
« prev ^ index » next coverage.py v7.10.2, created at 2026-08-24 19:35 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2026-08-24 19:35 +0000
1from app.models import *
2from app.models.term import Term
3from app.models.program import Program
4from datetime import datetime
6class Event(baseModel):
7 name = CharField()
8 term = ForeignKeyField(Term)
9 description = TextField()
10 timeStart = TimeField()
11 timeEnd = TimeField()
12 location = CharField()
13 isFoodProvided = BooleanField(default=False)
14 allowsLabor = BooleanField(default=False) # Event has some labor students working in addition to volunteers
15 isLaborOnly = BooleanField(default=False) # Event is a labor meeting, specifically for labor students only
16 isTraining = BooleanField(default=False) # Event is a training for a Program (required by volunteers to earn service hours in that program)
17 isAllVolunteerTraining = BooleanField(default=False) # Event is an All Volunteers Training (required to earn any service hours)
18 isCeltsTraining = BooleanField(default=False) # Event is a CELTS labor training (required by all CELTS labor students)
19 isRsvpRequired = BooleanField(default=False)
20 isService = BooleanField(default=False)
21 isEngagement = BooleanField(default=False)
22 rsvpLimit = IntegerField(null=True)
23 startDate = DateField()
24 seriesId = IntegerField(null=True)
25 isRepeating = BooleanField(default=False)
26 contactEmail = CharField(null=True)
27 contactName = CharField(null=True)
28 program = ForeignKeyField(Program)
29 isCanceled = BooleanField(default=False)
30 deletionDate = DateTimeField(null=True)
31 deletedBy = TextField(null=True)
32 eventFlagsMatrix = {'isAllVolunteerTraining': {'isAllVolunteerTraining',
33 'isTraining'},
34 'isCeltsTraining': {'isCeltsTraining',
35 'isLaborOnly',
36 'isTraining'},
37 'isLaborOnly': {'isLaborOnly',
38 'isCeltsTraining',
39 'isTraining'},
40 'allowsLabor': {'allowsLabor',
41 'isTraining',
42 'isService',
43 'isEngagement'},
44 'isTraining': {'isTraining',
45 'isAllVolunteerTraining',
46 'isCeltsTraining',
47 'isLaborOnly',
48 'allowsLabor'},
49 'isService': {'isService',
50 'allowsLabor'},
51 'isEngagement': {'isEngagement',
52 'allowsLabor'}
53 }
55 _spCache = "Empty"
57 def save(self, *args, **kwargs):
58 """
59 Overrides the default Peewee save method.
60 NOTE: This method is not called when using Model.update()
61 """
62 if self.checkFlags():
63 return super().save(*args, **kwargs)
64 else:
65 raise IntegrityError("This combination of options is not allowed")
67 def __str__(self):
68 return f"{self.id}: {self.description}"
70 def checkFlags(self):
71 """
72 Checks the eventFlagsMatrix to ensure the user is only picking a combination of flags that are allowed.
73 """
74 setFlags = []
75 for attribute in self._meta.fields.keys():
76 if self.eventFlagsMatrix.get(attribute):
77 if getattr(self, attribute):
78 setFlags.append(attribute)
79 for setFlag in setFlags:
80 allowedFlags = self.eventFlagsMatrix[setFlag]
81 if not all(flag in allowedFlags for flag in setFlags):
82 return False
83 return True
85 @property
86 def isDeleted(self):
87 return self.deletionDate is not None
89 @property
90 def noProgram(self):
91 return not self.program_id
93 @property
94 def isPastStart(self):
95 return datetime.now() >= datetime.combine(self.startDate, self.timeStart)
97 @property
98 def isPastEnd(self):
99 return datetime.now() >= datetime.combine(self.startDate, self.timeEnd)
101 @property
102 def isFirstRepeatingEvent(self):
103 firstRepeatingEvent = Event.select().where(Event.seriesId==self.seriesId).order_by(Event.id).get()
104 return firstRepeatingEvent.id == self.id
106 @property
107 def relativeTime(self):
108 relativeTime = datetime.combine(self.startDate, self.timeStart) - datetime.now()
110 secondsFromNow = relativeTime.seconds
111 minutesFromNow = secondsFromNow // 60
112 hoursFromNow = minutesFromNow // 60
113 daysFromNow = relativeTime.days
114 if self.isPastStart:
115 return ""
116 elif (daysFromNow):
117 return f"{daysFromNow} day" + ("s" if daysFromNow > 1 else "")
118 elif hoursFromNow:
119 return f"{hoursFromNow} hour" + ("s" if hoursFromNow > 1 else "")
120 elif minutesFromNow:
121 return f"{minutesFromNow} minute" + ("s" if minutesFromNow > 1 else "")
122 else:
123 return f"happening now"