diff --git a/backend/laundry/api_wrapper.py b/backend/laundry/api_wrapper.py index 53a99a95..fe12928f 100644 --- a/backend/laundry/api_wrapper.py +++ b/backend/laundry/api_wrapper.py @@ -1,46 +1,50 @@ import requests -from bs4 import BeautifulSoup from django.conf import settings from django.utils import timezone -from requests.exceptions import ConnectTimeout, HTTPError, ReadTimeout +from requests.exceptions import HTTPError from laundry.models import LaundryRoom, LaundrySnapshot -HALL_URL = f"{settings.LAUNDRY_URL}/?location=" +def get_room_url(room_id: int): + return f"{settings.LAUNDRY_URL}/rooms/{room_id}/machines?raw=true" -def update_machine_object(cols, machine_object): +def update_machine_object(machine, machine_type_data): """ Updates Machine status and time remaining """ - if cols[2].getText() in ["In use", "Almost done"]: - time_remaining = cols[3].getText().split(" ")[0] - machine_object["running"] += 1 + # TODO: Early stage in update 9/29/2024, known status codes are + # TODO: "IN_USE", "AVAILABLE", "COMPLETE"; + # TODO: need to update if we identify other codes, especially error + status = machine["currentStatus"]["statusId"] + if status == "IN_USE": + time_remaining = machine[3].getText().split(" ")[0] + machine_type_data["running"] += 1 try: - machine_object["time_remaining"].append(int(time_remaining)) + machine_type_data["time_remaining"].append(int(time_remaining)) except ValueError: pass - elif cols[2].getText() == "Out of order": - machine_object["out_of_order"] += 1 - elif cols[2].getText() == "Not online": - machine_object["offline"] += 1 + elif status in ["AVAILABLE", "COMPLETE"]: + machine_type_data["open"] += 1 + # TODO: Verify there are no other statuses else: - machine_object["open"] += 1 + machine_type_data["offline"] += 1 # edge case that handles machine not sending time data - diff = int(machine_object["running"]) - len(machine_object["time_remaining"]) + # TODO: I don't think we need this? + diff = int(machine_type_data["running"]) - len(machine_type_data["time_remaining"]) while diff > 0: - machine_object["time_remaining"].append(-1) + machine_type_data["time_remaining"].append(-1) diff = diff - 1 - return machine_object + return machine_type_data -def parse_a_hall(hall_link): +def parse_a_room(room_request_link): """ - Return names, hall numbers, and the washers/dryers available for a certain hall_id + Return names, hall numbers, and the washers/dryers available for a certain room_id """ washers = {"open": 0, "running": 0, "out_of_order": 0, "offline": 0, "time_remaining": []} @@ -49,40 +53,33 @@ def parse_a_hall(hall_link): detailed = [] try: - page = requests.get( - hall_link, - timeout=60, - headers={"Authorization": "Basic Sure-Nothing-Could-Go-Wrong-With-This-HaHa-Not"}, - ) - # page = requests.get(hall_link, timeout=60) - except (ConnectTimeout, ReadTimeout): + request = requests.get(room_request_link, timeout=60, headers=settings.LAUNDRY_HEADERS) + request.raise_for_status() + except HTTPError: return {"washers": washers, "dryers": dryers, "details": detailed} - soup = BeautifulSoup(page.content, "html.parser") - soup.prettify() - - rows = soup.find_all("tr") - for row in rows: - cols = row.find_all("td") - if len(cols) > 1: - machine_type = cols[1].getText() - if machine_type == "Washer": - washers = update_machine_object(cols, washers) - elif machine_type == "Dryer": - dryers = update_machine_object(cols, dryers) - if machine_type in ["Washer", "Dryer"]: - try: - time = int(cols[3].getText().split(" ")[0]) - except ValueError: - time = 0 - detailed.append( - { - "id": int(cols[0].getText().split(" ")[1][1:]), - "type": cols[1].getText().lower(), - "status": cols[2].getText(), - "time_remaining": time, - } - ) + request_json = request.json() + + [ + update_machine_object(machine, washers) if machine["isWasher"] else None + for machine in request_json + ] + [ + update_machine_object(machine, dryers) if machine["isDryer"] else None + for machine in request_json + ] + [ + detailed.append( + { + "id": machine["id"], + "type": "washer" if machine["isWasher"] else "dryer", + "status": machine["currentStatus"]["statusId"], + "time_remaining": machine["currentStatus"]["remainingSeconds"], + } + ) + for machine in request_json + if machine["isWasher"] or machine["isDryer"] + ] return {"washers": washers, "dryers": dryers, "details": detailed} @@ -93,25 +90,16 @@ def check_is_working(): """ try: - r = requests.post( - "{}/".format(settings.LAUNDRY_URL), + all_rooms_request = requests.get( + f"{settings.LAUNDRY_URL}/geoBoundaries/5610?raw=true", timeout=60, - headers={"Authorization": "Basic Sure-Nothing-Could-Go-Wrong-With-This-HaHa-Not"}, - data={ - "locationid": "5faec7e9-a4aa-47c2-a514-950c03fac460", - "email": "pennappslabs@gmail.com", - "washers": 0, - "dryers": 0, - "locationalert": "OK", - }, - ) - r.raise_for_status() - return ( - "The transaction log for database 'QuantumCoin' is full due to 'LOG_BACKUP'." - not in r.text + headers=settings.LAUNDRY_HEADERS, ) + all_rooms_request.raise_for_status() + except HTTPError: return False + return True def all_status(): @@ -120,16 +108,16 @@ def all_status(): """ return { - room.name: parse_a_hall(HALL_URL + str(room.uuid)) for room in LaundryRoom.objects.all() + room.name: parse_a_room(get_room_url(room.room_id)) for room in LaundryRoom.objects.all() } -def hall_status(room): +def room_status(room): """ Return the status of each specific washer/dryer in a particular hall_id """ - machines = parse_a_hall(HALL_URL + str(room.uuid)) + machines = parse_a_room(get_room_url(room.room_id)) return {"machines": machines, "hall_name": room.name, "location": room.location} @@ -145,7 +133,6 @@ def save_data(): data = all_status() for name, room in data.items(): - laundry_room = LaundryRoom.objects.get(name=name) LaundrySnapshot.objects.create( diff --git a/backend/laundry/data/laundry_data.csv b/backend/laundry/data/laundry_data.csv index d6708b13..46ec4951 100644 --- a/backend/laundry/data/laundry_data.csv +++ b/backend/laundry/data/laundry_data.csv @@ -1,53 +1,53 @@ -0,Bishop White,Quad,5faec7e9-a4aa-47c2-a514-950c03fac460,9,9 -1,Chestnut Butcher,Quad,7dfa4b34-f44a-4a38-a6b9-44cdb968a915,11,11 -2,Class of 1928 Fisher,Quad,e6697dca-d164-4980-8843-ea0a29b1cf49,8,8 -3,Craig,Quad,37d661ce-3e50-4746-ab68-a5c61cd0bd0a,3,3 -4,DuBois,DuBois,3ffa8978-e742-4076-9bcb-4a3e5c0eca92,6,6 -5,English House,KCEH,b655a5be-1287-4ce2-b693-e9c1ae526f38,3,3 -6,Harnwell Floor 02,Harnwell,1c7a9fb3-a938-4756-83c6-42d601d46036,3,3 -7,Harnwell Floor 04,Harnwell,fba67cc0-336e-42f7-9603-c0b8a0e5030c,3,3 -8,Harnwell Floor 06,Harnwell,87195ec7-eb3d-42fd-84aa-d63f4e45e285,3,3 -9,Harnwell Floor 08,Harnwell,1bbb2ff6-d5e6-406d-a3a2-96c7972cceeb,3,3 -10,Harnwell Floor 10,Harnwell,987bf30b-e8e1-4a9e-b842-c9cd8aeafddc,3,3 -11,Harnwell Floor 12,Harnwell,dcb76f10-0137-4783-8604-bece4111b6dd,3,3 -12,Harnwell Floor 14,Harnwell,941b2fcb-2b1b-4afd-8e8e-c100fbcbe0f2,3,3 -13,Harnwell Floor 16,Harnwell,c74b2798-2d09-42a6-b65c-a5834219be59,3,3 -14,Harnwell Floor 18,Harnwell,f30af904-72ad-49f6-aecf-f44c8301fb6b,3,3 -15,Harnwell Floor 20,Harnwell,80a413fd-e0fa-456d-b922-f1576ded1f98,3,3 -16,Harnwell Floor 22,Harnwell,35119e5e-92c0-45fb-bfeb-f2059196f644,3,3 -17,Harnwell Floor 24,Harnwell,5880b051-8216-4cf4-92d6-5c7475f43eea,3,3 -18,Harrison Floor 04,Harrison,447b5682-4c3c-441d-ab49-5f45aee6991f,3,3 -19,Harrison Floor 06,Harrison,f77f7c68-f719-4843-8987-d64dabc0abff,3,3 -20,Harrison Floor 08,Harrison,6561bb14-634f-437d-84fd-a0837ef991e7,3,3 -21,Harrison Floor 10,Harrison,2dd7a63d-7d13-48e5-b038-98054b4f039f,3,3 -22,Harrison Floor 12,Harrison,fdb607c7-63eb-4d55-a312-0c16b682cbe7,3,3 -23,Harrison Floor 14,Harrison,53fdd440-e887-49e1-9ca9-7bb3cb4ab541,3,3 -24,Harrison Floor 16,Harrison,8cedf60a-8f87-4128-89dd-4c75343ca64a,3,3 -25,Harrison Floor 18,Harrison,116a8d6f-045b-47a5-b3f7-af31f4e661eb,3,3 -26,Harrison Floor 20,Harrison,f6a8b303-1302-49e6-be53-c8e345316ed8,3,3 -27,Harrison Floor 22,Harrison,b21c78af-1ebf-418c-a73b-85dc5ff49763,3,3 -28,Harrison Floor 24,Harrison,9b95c471-053c-46ea-bc3b-d23bcad7a3a1,3,3 -29,Hill House,Hill,82a00eb7-f70d-4a4c-9f0a-c2dafa4b67ea,16,16 -30,Magee Amhurst,Quad,f6825dac-5a5a-4e4b-b66f-ea8226cbe78e,12,12 -31,Mayer,Stouffer,6e3531d1-eebd-48b4-ad04-cf5983d42b02,8,8 -32,Morgan,Quad,f249ca9f-ef84-4a35-9477-449b14612057,2,2 -33,Rodin Floor 02,Rodin,7f25802d-31ad-4f80-ba26-d68a3f403aa8,3,3 -34,Rodin Floor 04,Rodin,49e560fb-c1aa-4c98-a88a-cc9564481ec0,3,3 -35,Rodin Floor 06,Rodin,701ce966-aa3c-4063-b3db-548ad89cb643,3,3 -36,Rodin Floor 08,Rodin,4998a8a2-fb86-4900-bcb7-9d7cc6d9b938,3,3 -37,Rodin Floor 10,Rodin,030c81c4-2300-4e8e-ae3a-303397a2e216,3,3 -38,Rodin Floor 12,Rodin,c561f889-5898-41ba-99f5-2e6d4243e4d3,3,3 -39,Rodin Floor 14,Rodin,2d211700-5b59-4c61-8922-991c0f7d7c15,3,3 -40,Rodin Floor 16,Rodin,a10ede1d-044d-4852-87c7-eba7588c2497,3,3 -41,Rodin Floor 18,Rodin,c3d3f9ae-792c-401c-8bd5-8c61fffe2ab1,3,3 -42,Rodin Floor 20,Rodin,e88d3561-dce7-4188-89e7-b72cff7d69d6,3,3 -43,Rodin Floor 22,Rodin,6b7dcd18-fe4e-4dc2-893f-35f0d7939c3c,3,3 -44,Rodin Floor 24,Rodin,18397cd6-202e-4680-b82e-33ccd9ded1a7,3,3 -45,Sansom East,Sansom,ad980c78-bf6d-429a-9a08-1b0899f83d62,16,16 -46,Sansom West,Sansom,d1637690-098b-4eca-b48b-6d137207a38e,16,16 -47,Stouffer Commons,Stouffer,d4848e7d-fdd0-4faa-b6bd-dc152842cf84,6,6 -48,New College House,New College House,14b91b75-563b-4a7f-8b80-4efed338c29b,10,10 -49,Harrison Floor 02,Harrison,78568718-85eb-420b-bc10-77154a685699,3,3 -50,Van Pelt,Gregory,5d9b0588-c987-4d2c-9842-2ce3e9101577,6,6 -51,Class of 1925,Gregory,78f20171-ab32-4650-a1ce-28ace7095790,4,4 -52,Kings Court,KCEH,fdbd6c5f-cb26-486f-86cc-f0b95a7f2a8a,5,6 +14089,English House,English House,14146,3,3 +14082,"Gregory College House: Class of 1925""",Gregory College House: Class of 1925,14138,4,4 +14085,Gregory College House: Van Pelt,Gregory College House: Van Pelt,14141,6,6 +5249,Gutmann College House,Gutmann College House,5611,18,18 +14099,Harnwell 10th Floor,Harnwell College House,14150,3,3 +14100,Harnwell 12th Floor,Harnwell College House,14150,3,3 +14101,Harnwell 14th Floor,Harnwell College House,14150,3,3 +14102,Harnwell 16th Floor,Harnwell College House,14150,3,3 +14103,Harnwell 18th Floor,Harnwell College House,14150,3,3 +14104,Harnwell 20th Floor,Harnwell College House,14150,3,3 +14105,Harnwell 22nd Floor,Harnwell College House,14150,3,3 +14106,Harnwell 24th Floor,Harnwell College House,14150,3,3 +14094,Harnwell 2nd Floor,Harnwell College House,14150,3,3 +14095,Harnwell 4th Floor,Harnwell College House,14150,3,3 +14096,Harnwell 6th Floor,Harnwell College House,14150,3,3 +14098,Harnwell 8th Floor,Harnwell College House,14150,3,3 +14111,Harrison 10th Floor,Harrison College House,14153,3,3 +14112,Harrison 12th Floor ,Harrison College House,14153,3,3 +14113,Harrison 14th Floor,Harrison College House,14153,3,3 +14114,Harrison 16th Floor,Harrison College House,14153,3,3 +14115,Harrison 18th Floor ,Harrison College House,14153,3,3 +14116,Harrison 20th Floor,Harrison College House,14153,3,3 +14117,Harrison 22nd Floor,Harrison College House,14153,3,3 +14118,Harrison 24th Floor,Harrison College House,14153,3,3 +14107,Harrison 2nd Floor,Harrison College House,14153,3,3 +14108,Harrison 4th Floor,Harrison College House,14153,3,3 +14109,Harrison 6th Floor,Harrison College House,14153,3,3 +14110,Harrison 8th Floor,Harrison College House,14153,3,3 +14090,Hill College House,Hill College House,14147,16,16 +14091,King's Court,King's Court,14148,5,6 +14092,Lauder,Lauder,14149,10,10 +14078,Class of 28,Quad: Fisher College House,14655,0,0 +14079,Craig,Quad: Fisher College House,14655,0,0 +14080,Ashhurst - Magee,Quad: Riepe College House,14137,12,12 +14076,Birthday - Bishop White,Quad: Riepe College House,14137,9,9 +14077,Butcher - Chestnut,Quad: Ware College House,14656,0,0 +14081,Morgan,Quad: Ware College House,14656,0,0 +14123,Rodin 10th Floor,Rodin College House,14154,3,3 +14124,Rodin 12th Floor,Rodin College House,14154,3,3 +14125,Rodin 14th Floor,Rodin College House,14154,3,3 +14126,Rodin 16th Floor,Rodin College House,14154,3,3 +14127,Rodin 18th Floor,Rodin College House,14154,3,3 +14128,Rodin 20th Floor,Rodin College House,14154,3,3 +14129,Rodin 22nd Floor,Rodin College House,14154,3,3 +14130,Rodin 24th Floor,Rodin College House,14154,3,3 +14119,Rodin 2nd Floor,Rodin College House,14154,3,3 +14120,Rodin 4th Floor,Rodin College House,14154,3,3 +14121,Rodin 6th Floor,Rodin College House,14154,3,3 +14122,Rodin 8th Floor,Rodin College House,14154,3,3 +14084,Samson West,Samson West,14140,16,16 +11373,Stouffer Commons,Stouffer College House,11693,4,4 +14093,Stouffer Mayer,Stouffer College House,11693,8,8 +14083,W.E.B. Du Bois College House,W.E.B. Du Bois College House,14139,6,6 diff --git a/backend/laundry/management/commands/load_laundry_rooms.py b/backend/laundry/management/commands/load_laundry_rooms.py index 6b26cc8b..1bbbe668 100644 --- a/backend/laundry/management/commands/load_laundry_rooms.py +++ b/backend/laundry/management/commands/load_laundry_rooms.py @@ -12,15 +12,16 @@ def handle(self, *args, **kwargs): reader = csv.reader(data) for i, row in enumerate(reader): - hall_id, hall_name, location, uuid, total_washers, total_dryers = row + room_id, name, location, location_id, total_washers, total_dryers = row - LaundryRoom.objects.get_or_create( - hall_id=int(hall_id), - name=hall_name, + LaundryRoom.objects.create( + room_id=room_id, + name=name, location=location, - uuid=uuid, + location_id=location_id, total_washers=total_washers, total_dryers=total_dryers, + new=True, ) self.stdout.write("Uploaded Laundry Rooms!") diff --git a/backend/laundry/management/commands/update_laundry_rooms.py b/backend/laundry/management/commands/update_laundry_rooms.py new file mode 100644 index 00000000..677cea4f --- /dev/null +++ b/backend/laundry/management/commands/update_laundry_rooms.py @@ -0,0 +1,79 @@ +import csv + +import requests +from django.conf import settings +from django.core.management.base import BaseCommand +from requests.exceptions import HTTPError + + +class Command(BaseCommand): + help = "Update laundry rooms csv from server" + + def handle(self, *args, **kwargs): + # Pull initial request with everything + try: + headers = { + "x-api-key": settings.LAUNDRY_X_API_KEY, + "alliancels-auth-token": settings.LAUNDRY_ALLIANCELS_API_KEY, + } + all_rooms_request = requests.get( + f"{settings.LAUNDRY_URL}/geoBoundaries/5610?raw=true", timeout=60, headers=headers + ) + all_rooms_request.raise_for_status() + + except HTTPError as e: + self.stdout.write(f"Error: {e}") + return + + all_rooms_request_json = all_rooms_request.json() + locations = all_rooms_request_json["geoBoundaries"][0]["geoBoundaries"] + + laundry_rooms = [ + { + "room_id": room["id"], + "room_name": room["roomName"], + "room_description": location["description"], + "room_location": location["id"], + } + for location in locations + for room in location["rooms"] + ] + + # for each room, send a request to find number of washers and dryers + # TODO: This is really inefficient, but may require change in frontend code to update + for room in laundry_rooms: + try: + room_request = requests.get( + f"{settings.LAUNDRY_URL}/rooms/{room['room_id']}/machines?raw=true", + timeout=60, + headers=headers, + ) + room_request.raise_for_status() + except HTTPError as e: + self.stdout.write(f"Error: {e}") + return + + room_request_json = room_request.json() + # count washers and dryers + count_washers = 0 + count_dryers = 0 + for machine in room_request_json: + if machine["isWasher"]: + count_washers += 1 + if machine["isDryer"]: + count_dryers += 1 + room["count_washers"] = count_washers + room["count_dryers"] = count_dryers + + # write to csv + keys = [ + "room_id", + "room_name", + "room_description", + "room_location", + "count_washers", + "count_dryers", + ] + with open("laundry/data/laundry_data.csv", "w") as f: + writer = csv.DictWriter(f, keys) + writer.writerows(laundry_rooms) diff --git a/backend/laundry/migrations/0003_rename_hall_id_laundryroom_room_id_and_more.py b/backend/laundry/migrations/0003_rename_hall_id_laundryroom_room_id_and_more.py new file mode 100644 index 00000000..de0baf42 --- /dev/null +++ b/backend/laundry/migrations/0003_rename_hall_id_laundryroom_room_id_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.2 on 2024-09-29 06:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("laundry", "0002_auto_20210321_1105"), + ] + + operations = [ + migrations.RenameField( + model_name="laundryroom", + old_name="hall_id", + new_name="room_id", + ), + migrations.RemoveField( + model_name="laundryroom", + name="uuid", + ), + migrations.AddField( + model_name="laundryroom", + name="location_id", + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name="laundryroom", + name="new", + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/laundry/models.py b/backend/laundry/models.py index 4af9bd2a..ab39e26c 100644 --- a/backend/laundry/models.py +++ b/backend/laundry/models.py @@ -1,22 +1,20 @@ -import uuid - from django.db import models from django.utils import timezone class LaundryRoom(models.Model): - hall_id = models.IntegerField(default=0) + room_id = models.IntegerField(default=0) name = models.CharField(max_length=255) location = models.CharField(max_length=255) + location_id = models.IntegerField(default=0) total_washers = models.IntegerField(default=0) total_dryers = models.IntegerField(default=0) - # Each Laundry Room has a UUID that we need to - # access Penn API laundry data - uuid = models.UUIDField(default=uuid.uuid4) + # laundry api update 9/29/2024; new indicates it is new, added to avoid nuking old info + new = models.BooleanField(default=False) def __str__(self): - return f"Hall No. {self.hall_id} | {self.name}" + return f"Hall {self.name} | {self.location}" class LaundrySnapshot(models.Model): @@ -26,4 +24,4 @@ class LaundrySnapshot(models.Model): available_dryers = models.IntegerField() def __str__(self): - return f"Hall No. {self.room.hall_id} | {self.date.date()}" + return f"Hall {self.room.name} | {self.date.date()}" diff --git a/backend/laundry/serializers.py b/backend/laundry/serializers.py index fb35d9e9..5c4513c3 100644 --- a/backend/laundry/serializers.py +++ b/backend/laundry/serializers.py @@ -6,4 +6,4 @@ class LaundryRoomSerializer(serializers.ModelSerializer): class Meta: model = LaundryRoom - fields = ("name", "hall_id", "location") + fields = ("name", "room_id", "location") diff --git a/backend/laundry/views.py b/backend/laundry/views.py index fa9a008f..a4893971 100644 --- a/backend/laundry/views.py +++ b/backend/laundry/views.py @@ -10,7 +10,7 @@ from rest_framework.response import Response from rest_framework.views import APIView -from laundry.api_wrapper import check_is_working, hall_status +from laundry.api_wrapper import check_is_working, room_status from laundry.models import LaundryRoom, LaundrySnapshot from laundry.serializers import LaundryRoomSerializer from pennmobile.analytics import Metric, record_analytics @@ -31,9 +31,9 @@ class HallInfo(APIView): GET: returns list of a particular hall, its respective machines and machine details """ - def get(self, request, hall_id): + def get(self, request, room_id): try: - return Response(hall_status(get_object_or_404(LaundryRoom, hall_id=hall_id))) + return Response(room_status(get_object_or_404(LaundryRoom, room_id=room_id))) except HTTPError: return Response({"error": "The laundry api is currently unavailable."}, status=503) @@ -43,15 +43,15 @@ class MultipleHallInfo(APIView): GET: returns list of hall information as well as hall usage """ - def get(self, request, hall_ids): - halls = [int(x) for x in hall_ids.split(",")] + def get(self, request, room_ids): + rooms = [int(x) for x in room_ids.split(",")] output = {"rooms": []} - for hall_id in halls: - hall_data = hall_status(get_object_or_404(LaundryRoom, hall_id=hall_id)) - hall_data["id"] = hall_id - hall_data["usage_data"] = HallUsage.compute_usage(hall_id) - output["rooms"].append(hall_data) + for room_id in rooms: + room_data = room_status(get_object_or_404(LaundryRoom, room_id=room_id)) + room_data["id"] = room_id + room_data["usage_data"] = HallUsage.compute_usage(room_id) + output["rooms"].append(room_id) record_analytics(Metric.LAUNDRY_VIEWED, request.user.username) @@ -66,9 +66,9 @@ class HallUsage(APIView): def safe_division(a, b): return round(a / float(b), 3) if b > 0 else 0 - def get_snapshot_info(hall_id): + def get_snapshot_info(room_id): # filters for LaundrySnapshots within timeframe - room = get_object_or_404(LaundryRoom, hall_id=hall_id) + room = get_object_or_404(LaundryRoom, room_id=room_id) # get start time, which is now without the times start = timezone.localtime().replace(hour=0, minute=0, second=0, microsecond=0) @@ -83,9 +83,9 @@ def get_snapshot_info(hall_id): snapshots = LaundrySnapshot.objects.filter(filter).order_by("-date") return (room, snapshots) - def compute_usage(hall_id): + def compute_usage(room_id): try: - (room, snapshots) = HallUsage.get_snapshot_info(hall_id) + (room, snapshots) = HallUsage.get_snapshot_info(room_id) except ValueError: return Response({"error": "Invalid hall id passed to server."}, status=404) @@ -156,6 +156,9 @@ def get(self, request): if cached_preferences is None: preferences = request.user.profile.laundry_preferences.all() cached_preferences = preferences.values_list("hall_id", flat=True) + # get all laundries with one of thse + valid_rooms = LaundryRoom.objects.filter(room_id__in=cached_preferences, new=True) + cached_preferences = valid_rooms.values_list("room_id", flat=True) cache.set(key, cached_preferences, Cache.MONTH) return Response({"rooms": cached_preferences}) @@ -168,7 +171,7 @@ def post(self, request): return Response({"success": False, "error": "No rooms provided"}, status=400) halls = [ - get_object_or_404(LaundryRoom, hall_id=int(hall_id)) + get_object_or_404(LaundryRoom, room_id=int(hall_id)) for hall_id in request.data["rooms"] ] diff --git a/backend/pennmobile/settings/base.py b/backend/pennmobile/settings/base.py index c54b3e21..fbdd07ef 100644 --- a/backend/pennmobile/settings/base.py +++ b/backend/pennmobile/settings/base.py @@ -160,7 +160,13 @@ # Laundry API URL # LAUNDRY_URL = os.environ.get("LAUNDRY_URL", "http://suds.kite.upenn.edu") -LAUNDRY_URL = "http://laundry.sketchy.dev/" +LAUNDRY_URL = "https://api.alliancelslabs.com" +LAUNDRY_X_API_KEY = os.environ.get("LAUNDRY_X_API_KEY", None) +LAUNDRY_ALLIANCELS_API_KEY = os.environ.get("LAUNDRY_ALLIANCE_LS_KEY", None) +LAUNDRY_HEADERS = { + "x-api-key": LAUNDRY_X_API_KEY, + "alliancels-auth-token": LAUNDRY_ALLIANCELS_API_KEY, +} # Dining API Credentials DINING_USERNAME = os.environ.get("DINING_USERNAME", None) diff --git a/backend/tests/laundry/test_api_wrapper.py b/backend/tests/laundry/test_api_wrapper.py index dccca9ea..faf26462 100644 --- a/backend/tests/laundry/test_api_wrapper.py +++ b/backend/tests/laundry/test_api_wrapper.py @@ -3,7 +3,7 @@ from django.conf import settings from django.test import TestCase -from laundry.api_wrapper import all_status, hall_status, save_data +from laundry.api_wrapper import all_status, room_status, save_data from laundry.models import LaundryRoom, LaundrySnapshot from tests.laundry.test_commands import fakeLaundryGet @@ -75,7 +75,7 @@ def test_all_status(self): for room in LaundryRoom.objects.all(): # asserts fields are present - status = hall_status(room) + status = room_status(room) machines = status["machines"] self.assertIn("washers", machines) self.assertIn("dryers", machines)