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

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

23
    def __str__(self):
24
        return '%s' % self.name
25

David Haynes's avatar
David Haynes committed
26
27
28
29
30
31
32
33
34
35
36
37
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)
    on_campus = models.BooleanField(default=True)

Ben Waters's avatar
Ben Waters committed
38
class Facility(TimeStampedModel):
David Haynes's avatar
David Haynes committed
39
40
41
42
43
    """
    Represents a specific facility location.

    """
    # The name of the Facility
Tyler Hallada's avatar
Tyler Hallada committed
44
    name = models.CharField(max_length=100)
David Haynes's avatar
David Haynes committed
45
46
    # Instead of id
    slug = AutoSlugField(populate_from='name', unique=True)
47

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

David Haynes's avatar
David Haynes committed
54
    # The User(s) that claim ownership over this facility
55
    owners = models.ManyToManyField(User)
David Haynes's avatar
David Haynes committed
56
57

    # The schedule that is defaulted to if no special schedule is in effect
58
    main_schedule = models.ForeignKey('Schedule',
David Haynes's avatar
David Haynes committed
59
60
61
                                      related_name='facility_main')

    # A schedule that has a specific start and end date
62
    special_schedules = models.ManyToManyField('Schedule',
David Haynes's avatar
David Haynes committed
63
64
65
66
                                               related_name='facility_special',
                                               blank=True,
                                               help_text='This schedule will come into effect only for its specified duration.')

67
    class Meta:
68
69
        verbose_name = "facility"
        verbose_name_plural = "facilities"
70
71
        # Sort by name in admin view
        ordering = ['name']
72

73
74
    def isOpen(self):
        """
75
        Return true if this facility is currently open.
76
77
78
79
80

        First checks any valid special schedules and then checks the
        main default schedule.

        """
81
82
83
84
85
86
87
88
        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
89
90
                    else:
                        return False
91
        if self.main_schedule.isOpenNow():
92
93
94
            return True
        return False

95
    def __str__(self):
96
97
        return self.name

Ben Waters's avatar
Ben Waters committed
98
class Schedule(TimeStampedModel):
99
100
101
102
103
104
105
    """
    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
106
    name = models.CharField(max_length=100)
107
    # inclusive:
108
109
110
111
    valid_start = models.DateField('Start Date', null=True, blank=True,
            help_text='Date that this schedule goes into effect')
    valid_end = models.DateField('End Date', null=True, blank=True,
            help_text='Last day that this schedule is in effect')
112
113
114
115
    
    class Meta:
        ordering = ['name']
        
116
117
    def isOpenNow(self):
        """Return true if this schedule is open right now."""
118
119
120
121
122
        for time in OpenTime.objects.filter(schedule=self):
            if time.isOpenNow():
                return True
        return False

123
    def __str__(self):
124
125
126
        return self.name


Ben Waters's avatar
Ben Waters committed
127
class OpenTime(TimeStampedModel):
128
    """Represents a period time when a Facility is open"""
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

    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'),
    )

148
    schedule = models.ForeignKey('Schedule', related_name='open_times')
149
    start_day = models.IntegerField(default=0, choices=DAY_CHOICES)  # 0-6, Monday == 0
150
    start_time = models.TimeField()
151
    end_day = models.IntegerField(default=0, choices=DAY_CHOICES)
152
153
154
155
    end_time = models.TimeField()

    def isOpenNow(self):
        """Return true if the current time is this OpenTime's range"""
156
        today = datetime.datetime.today()
157
158
159
160
161
162
163
164
165
166
167
        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
168
        else:
169
170
171
172
173
174
175
176
177
            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
178

179
    def __str__(self):
180
181
182
183
184
        weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
                'Saturday', 'Sunday']
        return '%s %s to %s %s' % (weekdays[self.start_day],
                self.start_time.strftime("%H:%M:%S"), weekdays[self.end_day],
                self.end_time.strftime("%H:%M:%S"))