Coverage for app/models/event.py: 88%
84 statements
« prev ^ index » next coverage.py v7.10.2, created at 2026-09-22 13:52 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2026-09-22 13:52 +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 campusGroupsId = IntegerField(null=True)
33 campusGroupsURL = CharField(null=True)
34 isCampusGroupsSynced = BooleanField(default=False)
35 eventFlagsMatrix = {'isAllVolunteerTraining': {'isAllVolunteerTraining',
36 'isTraining'},
37 'isCeltsTraining': {'isCeltsTraining',
38 'isLaborOnly',
39 'isTraining'},
40 'isLaborOnly': {'isLaborOnly',
41 'isCeltsTraining',
42 'isTraining'},
43 'allowsLabor': {'allowsLabor',
44 'isTraining',
45 'isService',
46 'isEngagement'},
47 'isTraining': {'isTraining',
48 'isAllVolunteerTraining',
49 'isCeltsTraining',
50 'isLaborOnly',
51 'allowsLabor'},
52 'isService': {'isService',
53 'allowsLabor'},
54 'isEngagement': {'isEngagement',
55 'allowsLabor'}
56 }
58 _spCache = "Empty"
60 def save(self, *args, **kwargs):
61 """
62 Overrides the default Peewee save method.
63 NOTE: This method is not called when using Model.update()
64 """
65 if self.checkFlags():
66 return super().save(*args, **kwargs)
67 else:
68 raise IntegrityError("This combination of options is not allowed")
70 def __str__(self):
71 return f"{self.id}: {self.description}"
73 def checkFlags(self):
74 """
75 Checks the eventFlagsMatrix to ensure the user is only picking a combination of flags that are allowed.
76 """
77 setFlags = []
78 for attribute in self._meta.fields.keys():
79 if self.eventFlagsMatrix.get(attribute):
80 if getattr(self, attribute):
81 setFlags.append(attribute)
82 for setFlag in setFlags:
83 allowedFlags = self.eventFlagsMatrix[setFlag]
84 if not all(flag in allowedFlags for flag in setFlags):
85 return False
86 return True
88 @property
89 def isDeleted(self):
90 return self.deletionDate is not None
92 @property
93 def noProgram(self):
94 return not self.program_id
96 @property
97 def isPastStart(self):
98 return datetime.now() >= datetime.combine(self.startDate, self.timeStart)
100 @property
101 def isPastEnd(self):
102 return datetime.now() >= datetime.combine(self.startDate, self.timeEnd)
104 @property
105 def isFirstRepeatingEvent(self):
106 firstRepeatingEvent = Event.select().where(Event.seriesId==self.seriesId).order_by(Event.id).get()
107 return firstRepeatingEvent.id == self.id
109 @property
110 def relativeTime(self):
111 relativeTime = datetime.combine(self.startDate, self.timeStart) - datetime.now()
113 secondsFromNow = relativeTime.seconds
114 minutesFromNow = secondsFromNow // 60
115 hoursFromNow = minutesFromNow // 60
116 daysFromNow = relativeTime.days
117 if self.isPastStart:
118 return ""
119 elif (daysFromNow):
120 return f"{daysFromNow} day" + ("s" if daysFromNow > 1 else "")
121 elif hoursFromNow:
122 return f"{hoursFromNow} hour" + ("s" if hoursFromNow > 1 else "")
123 elif minutesFromNow:
124 return f"{minutesFromNow} minute" + ("s" if minutesFromNow > 1 else "")
125 else:
126 return f"happening now"