diff --git a/backend/gsr_booking/admin.py b/backend/gsr_booking/admin.py index 93deb3b2..61f6b372 100644 --- a/backend/gsr_booking/admin.py +++ b/backend/gsr_booking/admin.py @@ -34,7 +34,7 @@ class GSRAdmin(admin.ModelAdmin): def get_queryset(self, request): return GSR.all_objects.all() - list_display = ["name", "kind", "lid", "gid", "in_use"] + list_display = ["name", "kind", "lid", "gid", "in_use", "bookable_days"] search_fields = ["name", "lid", "gid"] ordering = ["-in_use"] diff --git a/backend/gsr_booking/data/gsr_data.csv b/backend/gsr_booking/data/gsr_data.csv index 4cc81374..a22da039 100644 --- a/backend/gsr_booking/data/gsr_data.csv +++ b/backend/gsr_booking/data/gsr_data.csv @@ -1,15 +1,15 @@ -LID,GID,NAME,SERVICE -JMHH,1,Huntsman,wharton -20157,42437,Amy Gutmann Hall,penngroups -ARB,6,Academic Research,wharton -3620,6102,Albrecht Music Library,libcal -2634,1914,Penn Museum Library,libcal -1086,1889,Weigle,libcal -2495,1886,Education Commons,libcal -2587,4368,Lippincott,libcal -4370,7426,Perelman Center,libcal -1086,4660,VP Ground Floor,libcal -1090,1909,Levin Building,libcal -2683,1885,Biotech Commons,libcal -1086,4659,VP 3rd Floor,libcal -1086,1891,VP 4th Floor,libcal \ No newline at end of file +LID,GID,NAME,SERVICE,BOOKABLE_DAYS +JMHH,1,Huntsman,wharton,7 +20157,42437,Amy Gutmann Hall,penngroups,4 +ARB,6,Academic Research,wharton,7 +3620,6102,Albrecht Music Library,libcal,7 +2634,1914,Penn Museum Library,libcal,7 +1086,1889,Weigle,libcal,7 +2495,1886,Education Commons,libcal,7 +2587,4368,Lippincott,libcal,7 +4370,7426,Perelman Center,libcal,7 +1086,4660,VP Ground Floor,libcal,7 +1090,1909,Levin Building,libcal,7 +2683,1885,Biotech Commons,libcal,7 +1086,4659,VP 3rd Floor,libcal,7 +1086,1891,VP 4th Floor,libcal,7 \ No newline at end of file diff --git a/backend/gsr_booking/management/commands/load_gsrs.py b/backend/gsr_booking/management/commands/load_gsrs.py index 0f17b297..966b71eb 100644 --- a/backend/gsr_booking/management/commands/load_gsrs.py +++ b/backend/gsr_booking/management/commands/load_gsrs.py @@ -11,7 +11,7 @@ def handle(self, *args, **kwargs): with open("gsr_booking/data/gsr_data.csv") as data: reader = csv.reader(data) next(reader) - for lid, gid, name, service in reader: + for lid, gid, name, service, bookable_days in reader: # gets image from s3 given the lid and gid # TODO: fix image url! image_url = ( @@ -23,7 +23,14 @@ def handle(self, *args, **kwargs): else GSR.KIND_WHARTON if service == "wharton" else GSR.KIND_LIBCAL ) GSR.objects.update_or_create( - lid=lid, gid=gid, defaults={"name": name, "kind": kind, "image_url": image_url} + lid=lid, + gid=gid, + defaults={ + "name": name, + "kind": kind, + "image_url": image_url, + "bookable_days": int(bookable_days), + }, ) # Note: Caches are automatically cleared by post_save signals on GSR model diff --git a/backend/gsr_booking/migrations/0015_gsr_bookable_days.py b/backend/gsr_booking/migrations/0015_gsr_bookable_days.py new file mode 100644 index 00000000..a6eacfcd --- /dev/null +++ b/backend/gsr_booking/migrations/0015_gsr_bookable_days.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2026-02-21 23:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("gsr_booking", "0014_merge_20251207_1429"), + ] + + operations = [ + migrations.AddField( + model_name="gsr", + name="bookable_days", + field=models.IntegerField(default=7), + ), + ] diff --git a/backend/gsr_booking/models.py b/backend/gsr_booking/models.py index d9e0e485..f7ace778 100644 --- a/backend/gsr_booking/models.py +++ b/backend/gsr_booking/models.py @@ -117,6 +117,7 @@ class GSR(models.Model): lid = models.CharField(max_length=255) gid = models.IntegerField(null=True) name = models.CharField(max_length=255) + bookable_days = models.IntegerField(default=7) image_url = models.URLField() in_use = models.BooleanField(default=True) diff --git a/backend/tests/gsr_booking/test_gsr_views.py b/backend/tests/gsr_booking/test_gsr_views.py index b68fbe6e..90a0aa32 100644 --- a/backend/tests/gsr_booking/test_gsr_views.py +++ b/backend/tests/gsr_booking/test_gsr_views.py @@ -23,6 +23,7 @@ def create_test_gsrs(cls): "kind": GSR.KIND_WHARTON, "image_url": "https://s3.us-east-2.amazonaws.com/labs.api/gsr/lid-JMHH-gid-1.jpg", "in_use": True, + "bookable_days": 7, }, ) cls.agh_gsr, _ = GSR.objects.get_or_create( @@ -33,6 +34,7 @@ def create_test_gsrs(cls): "kind": GSR.KIND_PENNGROUPS, "image_url": "https://s3.us-east-2.amazonaws.com/labs.api/gsr/lid-20157-gid-42437.jpg", "in_use": True, + "bookable_days": 4, }, ) cls.weigle_gsr, _ = GSR.objects.get_or_create( @@ -43,6 +45,7 @@ def create_test_gsrs(cls): "kind": GSR.KIND_LIBCAL, "image_url": "https://s3.us-east-2.amazonaws.com/labs.api/gsr/lid-1086-gid-1889.jpg", "in_use": True, + "bookable_days": 7, }, ) @@ -104,11 +107,26 @@ def test_get_location(self): """Test that the locations endpoint returns all GSRs without auth checks""" response = self.client.get(reverse("locations")) res_json = json.loads(response.content) + # TODO: add AGH back to availability route for entry in res_json: if entry["id"] == 1: self.assertEquals(entry["name"], "Huntsman") + self.assertEquals(entry["kind"], GSR.KIND_WHARTON) + self.assertEquals(entry["lid"], "JMHH") + self.assertEquals(entry["gid"], 1) + self.assertEquals(entry["bookable_days"], 7) if entry["id"] == 2: + self.assertEquals(entry["name"], "Amy Gutmann Hall") + self.assertEquals(entry["kind"], GSR.KIND_PENNGROUPS) + self.assertEquals(entry["lid"], "20157") + self.assertEquals(entry["gid"], 42437) + self.assertEquals(entry["bookable_days"], 4) + if entry["id"] == 3: self.assertEquals(entry["name"], "Weigle") + self.assertEquals(entry["kind"], GSR.KIND_LIBCAL) + self.assertEquals(entry["lid"], "1086") + self.assertEquals(entry["gid"], 1889) + self.assertEquals(entry["bookable_days"], 7) @mock.patch("gsr_booking.views.WhartonGSRBooker.is_wharton", return_value=False) @mock.patch("gsr_booking.views.PennGroupsGSRBooker.is_seas", return_value=False) @@ -234,14 +252,15 @@ def test_recent(self): response = self.client.get(reverse("recent-gsrs")) res_json = json.loads(response.content) self.assertEqual(2, len(res_json)) - self.assertEqual(6, len(res_json[0])) - self.assertEqual(6, len(res_json[1])) + self.assertEqual(7, len(res_json[0])) + self.assertEqual(7, len(res_json[1])) self.assertIn("id", res_json[0]) self.assertIn("kind", res_json[0]) self.assertIn("lid", res_json[0]) self.assertIn("gid", res_json[0]) self.assertIn("name", res_json[0]) self.assertIn("image_url", res_json[0]) + self.assertIn("bookable_days", res_json[0]) self.assertNotEqual(res_json[0]["id"], res_json[1]["id"]) @mock.patch("gsr_booking.api_wrapper.WhartonBookingWrapper.is_wharton", is_wharton_false) diff --git a/backend/tests/gsr_booking/test_share_codes.py b/backend/tests/gsr_booking/test_share_codes.py index e96dc524..19eab6ba 100644 --- a/backend/tests/gsr_booking/test_share_codes.py +++ b/backend/tests/gsr_booking/test_share_codes.py @@ -124,7 +124,6 @@ def test_view_shared_booking_public_access(self): payload = json.loads(response.content) # Should only contain booking info and not owner info - print("Payload: ", payload) self.assertIn("booking_id", payload) self.assertIn("gsr", payload) self.assertIn("lid", payload["gsr"])