models.py 6.86 KB
Newer Older
1
2
3
4
5
6
7
8
# Future Imports
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

# Python stdlib Imports
import datetime

# Django Imports
9
from django.db import models
10
from django.contrib.auth.models import User
Ben Waters's avatar
Ben Waters committed
11
from model_utils.models import TimeStampedModel
12
from autoslug import AutoSlugField
Tyler Hallada's avatar
Tyler Hallada committed
13

Ben Waters's avatar
Ben Waters committed
14
class Category(TimeStampedModel):
15
16
    """
    """
17
18
19
20
21
22
23
24
    name = models.CharField(max_length=100)

    class Meta:
        verbose_name = "category"
        verbose_name_plural = "categories"
        # Sort by name in admin view
        ordering = ['name']

25
    def __str__(self):
26
        return '%s' % self.name
27

David Haynes's avatar
David Haynes committed
28
29
30
31
32
33
34
35
36
class Location(TimeStampedModel):
    """
    Represents a specific location (unique lat, lon) that a Facility can be
    found in real life.
    """
    # The building that the facility is located in (on campus)
    building = models.CharField(max_length=100, null=True, blank=True)
    # The physical address of the facility
    address = models.CharField(max_length=100, null=True, blank=True)
37
    # Boolean for whether or not the location is "on campus" or not
David Haynes's avatar
David Haynes committed
38
39
    on_campus = models.BooleanField(default=True)

Ben Waters's avatar
Ben Waters committed
40
class Facility(TimeStampedModel):
David Haynes's avatar
David Haynes committed
41
42
43
44
    """
    Represents a specific facility location.
    """
    # The name of the Facility
Tyler Hallada's avatar
Tyler Hallada committed
45
    name = models.CharField(max_length=100)
David Haynes's avatar
David Haynes committed
46
47
    # Instead of id
    slug = AutoSlugField(populate_from='name', unique=True)
48

David Haynes's avatar
David Haynes committed
49
    # The category that this facility falls under
50
51
    facility_category = models.ForeignKey('Category',
                                          related_name="facilities",
David Haynes's avatar
David Haynes committed
52
53
                                          null=True, blank=True)
    # The location object that relates to this facility
54
55
    facility_location = models.ForeignKey('Location',
                                          related_name="facilities")
56

David Haynes's avatar
David Haynes committed
57
    # The User(s) that claim ownership over this facility
58
    owners = models.ManyToManyField(User)
David Haynes's avatar
David Haynes committed
59
60

    # The schedule that is defaulted to if no special schedule is in effect
61
    main_schedule = models.ForeignKey('Schedule',
David Haynes's avatar
David Haynes committed
62
63
                                      related_name='facility_main')
    # A schedule that has a specific start and end date
64
    special_schedules = models.ManyToManyField('Schedule',
David Haynes's avatar
David Haynes committed
65
66
                                               related_name='facility_special',
                                               blank=True,
67
68
69
70
71
                                               help_text="""This schedule will
                                                            come into effect
                                                            only for its
                                                            specified duration.
                                                            """)
David Haynes's avatar
David Haynes committed
72

73
    class Meta:
74
75
        verbose_name = "facility"
        verbose_name_plural = "facilities"
76
77
        # Sort by name in admin view
        ordering = ['name']
78

79
80
    def isOpen(self):
        """
81
        Return true if this facility is currently open.
82
83
84
85

        First checks any valid special schedules and then checks the
        main default schedule.
        """
86
87
88
89
90
91
92
93
        today = datetime.datetime.today().date()
        # Check special schedules first
        for schedule in self.special_schedules.all():
            # Special schedules must have valid_start and valid_end set
            if schedule.valid_start and schedule.valid_end:
                if schedule.valid_start <= today <= schedule.valid_end:
                    if schedule.isOpenNow():
                        return True
94
95
                    else:
                        return False
96
        if self.main_schedule.isOpenNow():
97
98
99
            return True
        return False

100
    def __str__(self):
101
102
        return self.name

Ben Waters's avatar
Ben Waters committed
103
class Schedule(TimeStampedModel):
104
105
106
107
108
109
    """
    Contains opening and closing times for each day in a week.

    For special (temporary) schedules, start and end dates for
    when this schedule will be valid can also be set.
    """
Tyler Hallada's avatar
Tyler Hallada committed
110
    name = models.CharField(max_length=100)
111
    # (inclusive)
112
    valid_start = models.DateField('Start Date', null=True, blank=True,
113
114
                                   help_text="""Date that this schedule goes
                                                into effect""")
115
    valid_end = models.DateField('End Date', null=True, blank=True,
116
117
118
                                 help_text="""Last day that this schedule is
                                              in effect""")

119
120
    class Meta:
        ordering = ['name']
121

122
    def isOpenNow(self):
123
124
125
        """
        Return true if this schedule is open right now.
        """
126
127
128
129
130
        for time in OpenTime.objects.filter(schedule=self):
            if time.isOpenNow():
                return True
        return False

131
    def __str__(self):
132
133
134
        return self.name


Ben Waters's avatar
Ben Waters committed
135
class OpenTime(TimeStampedModel):
136
137
138
    """
    Represents a period time when a Facility is open.
    """
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    MONDAY = 0
    TUESDAY = 1
    WEDNESDAY = 2
    THURSDAY = 3
    FRIDAY = 4
    SATURDAY = 5
    SUNDAY = 6

    DAY_CHOICES = (
        (MONDAY, 'Monday'),
        (TUESDAY, 'Tuesday'),
        (WEDNESDAY, 'Wednesday'),
        (THURSDAY, 'Thursday'),
        (FRIDAY, 'Friday'),
        (SATURDAY, 'Saturday'),
        (SUNDAY, 'Sunday'),
    )

157
    schedule = models.ForeignKey('Schedule', related_name='open_times')
158
159
    # 0-6, Monday == 0
    start_day = models.IntegerField(default=0, choices=DAY_CHOICES)
160
    start_time = models.TimeField()
161
    end_day = models.IntegerField(default=0, choices=DAY_CHOICES)
162
163
164
    end_time = models.TimeField()

    def isOpenNow(self):
165
166
167
        """
        Return true if the current time is this OpenTime's range
        """
168
        today = datetime.datetime.today()
169
170
171
172
173
174
175
176
177
178
179
        if self.start_day <= self.end_day:
            if self.start_day == today.weekday():
                if self.start_time > today.time():
                    return False
            elif self.start_day > today.weekday():
                return False
            if self.end_day == today.weekday():
                if self.end_time < today.time():
                    return False
            elif self.end_day < today.weekday():
                return False
180
        else:
181
182
183
184
185
186
187
188
189
            if self.start_day == today.weekday():
                if self.start_time > today.time():
                    return False
            if self.end_day == today.weekday():
                if self.end_time < today.time():
                    return False
            if self.end_day < today.weekday() < self.start_day:
                return False
        return True
190

191
    def __str__(self):
192
        weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
193
                    'Saturday', 'Sunday']
194
        return '%s %s to %s %s' % (weekdays[self.start_day],
195
196
197
198
                                   self.start_time.strftime("%H:%M:%S"),
                                   # to
                                   weekdays[self.end_day],
                                   self.end_time.strftime("%H:%M:%S"))