models.py 7.17 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
    name = models.CharField(max_length=100)

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

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

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

39
40
41
42
43
44
45
46
47
48
49
50
    class Meta:
        verbose_name = "location"
        verbose_name_plural = "locations"

    def __str__(self):
        """
        String representation of a Location object.
        """
        return 'Found in %s at %s | On Campus: %s' % (self.building,
                                                      self.address,
                                                      self.on_campus)

Ben Waters's avatar
Ben Waters committed
51
class Facility(TimeStampedModel):
David Haynes's avatar
David Haynes committed
52
53
54
55
    """
    Represents a specific facility location.
    """
    # The name of the Facility
Tyler Hallada's avatar
Tyler Hallada committed
56
    name = models.CharField(max_length=100)
David Haynes's avatar
David Haynes committed
57
58
    # Instead of id
    slug = AutoSlugField(populate_from='name', unique=True)
59

David Haynes's avatar
David Haynes committed
60
    # The category that this facility falls under
61
62
    facility_category = models.ForeignKey('Category',
                                          related_name="facilities",
David Haynes's avatar
David Haynes committed
63
64
                                          null=True, blank=True)
    # The location object that relates to this facility
65
66
    facility_location = models.ForeignKey('Location',
                                          related_name="facilities")
67

David Haynes's avatar
David Haynes committed
68
    # The User(s) that claim ownership over this facility
69
    owners = models.ManyToManyField(User)
David Haynes's avatar
David Haynes committed
70
71

    # The schedule that is defaulted to if no special schedule is in effect
72
    main_schedule = models.ForeignKey('Schedule',
David Haynes's avatar
David Haynes committed
73
74
                                      related_name='facility_main')
    # A schedule that has a specific start and end date
75
    special_schedules = models.ManyToManyField('Schedule',
David Haynes's avatar
David Haynes committed
76
77
                                               related_name='facility_special',
                                               blank=True,
78
79
80
81
82
                                               help_text="""This schedule will
                                                            come into effect
                                                            only for its
                                                            specified duration.
                                                            """)
David Haynes's avatar
David Haynes committed
83

84
    class Meta:
85
86
        verbose_name = "facility"
        verbose_name_plural = "facilities"
87
88
        # Sort by name in admin view
        ordering = ['name']
89

90
91
    def isOpen(self):
        """
92
        Return true if this facility is currently open.
93
94
95
96

        First checks any valid special schedules and then checks the
        main default schedule.
        """
97
98
99
100
101
102
103
104
        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
105
106
                    else:
                        return False
107
        if self.main_schedule.isOpenNow():
108
109
110
            return True
        return False

111
    def __str__(self):
112
113
        return self.name

Ben Waters's avatar
Ben Waters committed
114
class Schedule(TimeStampedModel):
115
116
117
118
119
120
    """
    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
121
    name = models.CharField(max_length=100)
122
    # (inclusive)
123
    valid_start = models.DateField('Start Date', null=True, blank=True,
124
125
                                   help_text="""Date that this schedule goes
                                                into effect""")
126
    valid_end = models.DateField('End Date', null=True, blank=True,
127
128
129
                                 help_text="""Last day that this schedule is
                                              in effect""")

130
131
    class Meta:
        ordering = ['name']
132

133
    def isOpenNow(self):
134
135
136
        """
        Return true if this schedule is open right now.
        """
137
138
139
140
141
        for time in OpenTime.objects.filter(schedule=self):
            if time.isOpenNow():
                return True
        return False

142
    def __str__(self):
143
144
145
        return self.name


Ben Waters's avatar
Ben Waters committed
146
class OpenTime(TimeStampedModel):
147
148
149
    """
    Represents a period time when a Facility is open.
    """
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    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'),
    )

168
    schedule = models.ForeignKey('Schedule', related_name='open_times')
169
170
    # 0-6, Monday == 0
    start_day = models.IntegerField(default=0, choices=DAY_CHOICES)
171
    start_time = models.TimeField()
172
    end_day = models.IntegerField(default=0, choices=DAY_CHOICES)
173
174
175
    end_time = models.TimeField()

    def isOpenNow(self):
176
177
178
        """
        Return true if the current time is this OpenTime's range
        """
179
        today = datetime.datetime.today()
180
181
182
183
184
185
186
187
188
189
190
        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
191
        else:
192
193
194
195
196
197
198
199
200
            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
201

202
    def __str__(self):
203
        weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
204
                    'Saturday', 'Sunday']
205
        return '%s %s to %s %s' % (weekdays[self.start_day],
206
207
208
209
                                   self.start_time.strftime("%H:%M:%S"),
                                   # to
                                   weekdays[self.end_day],
                                   self.end_time.strftime("%H:%M:%S"))