Skip to content

Commit 685c705

Browse files
authored
Revert "Add backend for bookable office hours"
1 parent f578ecb commit 685c705

File tree

11 files changed

+25
-478
lines changed

11 files changed

+25
-478
lines changed

backend/Pipfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ channels = "==3.0.5"
4141
channels-redis = "*"
4242
uvicorn = {extras = ["standard"],version = "*"}
4343
gunicorn = "*"
44+
django-schedules-ohq = "*"
4445
typing-extensions = "*"
4546
drf-excel = "*"
4647
pytz = "*"
4748
inflection = "*"
48-
django-scheduler = {git = "https://github.com/llazzaro/django-scheduler.git", ref = "8aa6f877f17e5b05f17d7c39e93d8e73625b0a65"}
4949

5050
[requires]
5151
python_version = "3.11"

backend/Pipfile.lock

+7-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/ohq/admin.py

-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
Semester,
1414
Tag,
1515
UserStatistic,
16-
Booking,
1716
)
1817

1918

@@ -29,4 +28,3 @@
2928
admin.site.register(Announcement)
3029
admin.site.register(Tag)
3130
admin.site.register(UserStatistic)
32-
admin.site.register(Booking)

backend/ohq/migrations/0022_booking.py

-56
This file was deleted.

backend/ohq/models.py

+1-70
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
from django.conf import settings
22
from django.core.validators import MaxValueValidator, MinValueValidator
3-
from django.core.exceptions import ValidationError
43
from django.db import models
54
from django.dispatch import receiver
65
from email_tools.emails import send_email
76
from phonenumber_field.modelfields import PhoneNumberField
8-
from schedule.models import Event, Occurrence
7+
98

109
User = settings.AUTH_USER_MODEL
1110

@@ -448,71 +447,3 @@ class Meta:
448447

449448
def __str__(self):
450449
return f"{self.user}: {self.metric}"
451-
452-
class Booking(models.Model):
453-
"""
454-
Booking within an occurrence.
455-
Bookings can only be created with start times of 5-minute intervals.
456-
"""
457-
458-
occurrence = models.ForeignKey(Occurrence, on_delete=models.CASCADE, related_name="bookings")
459-
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
460-
start = models.DateTimeField("start", db_index=True)
461-
end = models.DateTimeField("end", db_index=True)
462-
463-
class Meta:
464-
verbose_name = ("booking")
465-
verbose_name_plural = ("bookings")
466-
ordering = ["start"]
467-
index_together = (("start", "end"),)
468-
469-
def clean(self):
470-
if self.start >= self.end:
471-
raise ValidationError('Start time must be before end time.')
472-
473-
if self.start.minute % 5 != 0:
474-
raise ValidationError('Start time must be on a 5-minute interval (e.g., :00, :05, :10, :15, etc).')
475-
476-
if self.start < self.occurrence.start or self.end > self.occurrence.end:
477-
raise ValidationError('Booking times must be within the occurrence\'s start and end times.')
478-
479-
duration = self.end - self.start
480-
duration_minutes = duration.total_seconds() / 60
481-
482-
if duration_minutes != self.occurrence.interval:
483-
raise ValidationError(f'Booking duration must be {self.occurrence.interval} minutes.')
484-
485-
overlapping_bookings = Booking.objects.filter(
486-
occurrence=self.occurrence,
487-
start__lt=self.end,
488-
end__gt=self.start
489-
).exclude(id=self.id)
490-
if overlapping_bookings.exists():
491-
raise ValidationError('Booking times cannot overlap with existing bookings.')
492-
493-
super().clean()
494-
495-
def save(self, *args, **kwargs):
496-
self.clean()
497-
super().save(*args, **kwargs)
498-
499-
def __str__(self):
500-
start_str = self.start.strftime("%Y-%m-%d %H:%M:%S")
501-
end_str = self.end.strftime("%Y-%m-%d %H:%M:%S")
502-
return f"{start_str} to {end_str}"
503-
504-
Event.add_to_class('location', models.CharField(max_length=255, blank=True))
505-
Occurrence.add_to_class('location', models.CharField(max_length=255, blank=True))
506-
Occurrence.add_to_class('interval', models.IntegerField(blank=True, null=True))
507-
508-
def new_occurrence_init(self, *args, **kwargs):
509-
super(Occurrence, self).__init__(*args, **kwargs)
510-
event = kwargs.get("event", None)
511-
if not self.title and event:
512-
self.title = event.title
513-
if not self.description and event:
514-
self.description = event.description
515-
if not self.location and event:
516-
self.location = event.location
517-
518-
Occurrence.__init__ = new_occurrence_init

backend/ohq/permissions.py

+3-47
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
from django.db.models import Q
22
from rest_framework import permissions
33
from schedule.models import Event, EventRelation, Occurrence
4-
from ohq.models import (
5-
Course,
6-
Membership,
7-
Question,
8-
Booking,
9-
)
4+
5+
from ohq.models import Course, Membership, Question
6+
107

118
# Hierarchy of permissions is usually:
129
# Professor > Head TA > TA > Student > User
@@ -507,44 +504,3 @@ def has_permission(self, request, view):
507504
return True
508505

509506
return True
510-
511-
class BookingPermission(permissions.BasePermission):
512-
@staticmethod
513-
def get_membership_from_occurrence(request, occurrence):
514-
event_course_relation = EventRelation.objects.filter(event=occurrence.event).first()
515-
membership = Membership.objects.filter(
516-
course_id=event_course_relation.object_id, user=request.user
517-
).first()
518-
return membership
519-
520-
def has_object_permission(self, request, view, obj):
521-
if view.action in ["retrieve"]:
522-
booking = Booking.objects.filter(pk=view.kwargs["pk"]).first()
523-
membership = self.get_membership_from_occurrence(request=request, occurrence=booking.occurrence)
524-
return membership is not None
525-
526-
if view.action in ["update", "partial_update", "destroy"]:
527-
booking = Booking.objects.filter(pk=view.kwargs["pk"]).first()
528-
membership = self.get_membership_from_occurrence(request=request, occurrence=booking.occurrence)
529-
530-
if membership is None:
531-
return False
532-
533-
if membership.is_ta:
534-
return True
535-
536-
return booking.user == request.user
537-
538-
return False
539-
540-
def has_permission(self, request, view):
541-
if not request.user.is_authenticated:
542-
return False
543-
544-
if view.action in ["list", "create"]:
545-
occurrence_id = view.kwargs.get("occurrence_pk")
546-
occurrence = Occurrence.objects.filter(id=occurrence_id).first()
547-
membership = self.get_membership_from_occurrence(request=request, occurrence=occurrence)
548-
return membership is not None
549-
550-
return True

backend/ohq/serializers.py

+5-17
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from phonenumber_field.serializerfields import PhoneNumberField
88
from rest_framework import serializers
99
from rest_live.signals import save_handler
10-
from schedule.models import Calendar, Event, Occurrence, EventRelation, EventRelationManager, Rule
10+
from schedule.models import Calendar, Event, EventRelation, EventRelationManager, Rule
11+
from schedule.models.events import Occurrence
1112

1213
from ohq.models import (
1314
Announcement,
@@ -21,7 +22,6 @@
2122
QueueStatistic,
2223
Semester,
2324
Tag,
24-
Booking,
2525
)
2626
from ohq.sms import sendSMSVerification
2727
from ohq.tasks import sendUpNextNotificationTask
@@ -542,7 +542,7 @@ def update(self, instance, validated_data):
542542
else:
543543
rule, _ = Rule.objects.get_or_create(
544544
frequency=validated_data["rule"]["frequency"],
545-
params=validated_data["rule"].get("params", ""),
545+
params=validated_data["rule"]["params"],
546546
)
547547
validated_data.pop("rule")
548548

@@ -564,7 +564,7 @@ def create(self, validated_data):
564564
course = Course.objects.get(pk=validated_data["course_id"])
565565
rule = None
566566
if "rule" in validated_data and validated_data["rule"] is not None:
567-
rule, _ = Rule.objects.get_or_create(frequency=validated_data["rule"]["frequency"], params = validated_data["rule"].get("params", ""))
567+
rule, _ = Rule.objects.get_or_create(frequency=validated_data["rule"]["frequency"], params = validated_data["rule"]["params"])
568568
validated_data.pop("rule")
569569

570570
validated_data.pop("course_id")
@@ -592,16 +592,4 @@ class OccurrenceSerializer(serializers.ModelSerializer):
592592

593593
class Meta:
594594
model = Occurrence
595-
fields = ("id", "title", "description", "location", "start", "end", "cancelled", "event", "interval")
596-
597-
class BookingSerializer(serializers.ModelSerializer):
598-
"""
599-
Serializer for booking
600-
"""
601-
602-
occurrence = OccurrenceSerializer(read_only=True)
603-
604-
class Meta:
605-
model = Booking
606-
fields = ("id", "occurrence", "user", "start", "end")
607-
595+
fields = ("id", "title", "description", "location", "start", "end", "cancelled", "event")

backend/ohq/urls.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
SemesterViewSet,
2020
TagViewSet,
2121
UserView,
22-
BookingDetailViewSet,
23-
BookingListCreateViewSet,
2422
HealthView,
2523
)
2624

@@ -32,10 +30,6 @@
3230
router.register("courses", CourseViewSet, basename="course")
3331
router.register("events", EventViewSet, basename="event")
3432
router.register("occurrences", OccurrenceViewSet, basename="occurrence")
35-
router.register("bookings", BookingDetailViewSet, basename="booking")
36-
37-
occurrence_router = routers.NestedSimpleRouter(router, "occurrences", lookup="occurrence")
38-
occurrence_router.register("bookings", BookingListCreateViewSet, basename="booking-create")
3933

4034
course_router = routers.NestedSimpleRouter(router, "courses", lookup="course")
4135
course_router.register("queues", QueueViewSet, basename="queue")
@@ -71,4 +65,4 @@
7165
),
7266
]
7367

74-
urlpatterns = router.urls + occurrence_router.urls + course_router.urls + queue_router.urls + additional_urls
68+
urlpatterns = router.urls + course_router.urls + queue_router.urls + additional_urls

0 commit comments

Comments
 (0)