From 0206e1ff0f386858a500280675dd7bf5ad606440 Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Tue, 12 Mar 2024 00:39:37 -0400 Subject: [PATCH 01/52] add giveaway and user models, queries, and mutations --- schema.graphql | 7 +++++ src/models/giveaway.py | 37 ++++++++++++++++++++++++ src/models/user.py | 31 ++++++++++++++++++++ src/schema.py | 64 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 src/models/giveaway.py create mode 100644 src/models/user.py diff --git a/schema.graphql b/schema.graphql index 5a0f6eb..74a2f3e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -95,4 +95,11 @@ type OpenHours { type Query { gyms: [Gym] + usersByGiveawayid(giveawayId: Int!): [User] +} + +type User { + id: ID! + netId: String! + giveawayId: Int } diff --git a/src/models/giveaway.py b/src/models/giveaway.py new file mode 100644 index 0000000..5186866 --- /dev/null +++ b/src/models/giveaway.py @@ -0,0 +1,37 @@ +import enum +from sqlalchemy import Column, Integer, Float, ForeignKey, String +from sqlalchemy.orm import relationship +from src.database import Base +from src.models.user import User + +# class GiveawayType(enum.Enum): +# """ +# An enumeration representing a giveaway type. +# """ + +# utea_giftcard = 0 +# stanley = 1 + +class Giveaway(Base): + """ + A giveaway object. + + Attributes: + - `id` The ID of the giveaway. + - `user_ids` (nullable) The IDs of users entered into this giveaway. + """ + + __tablename__ = "giveaway" + + id = Column(Integer, primary_key=True) + user_ids = relationship(User) + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.user_ids = kwargs.get("user_id") + + def serialize(self): + return { + "id": self.id, + "user_ids": self.user_ids + } \ No newline at end of file diff --git a/src/models/user.py b/src/models/user.py new file mode 100644 index 0000000..4057340 --- /dev/null +++ b/src/models/user.py @@ -0,0 +1,31 @@ +from sqlalchemy import Column, Integer, Float, ForeignKey, String +from src.database import Base + + +class User(Base): + """ + A user who enters a giveaway. + + Attributes: + - `id` The ID of user. + - `net_id` The user's Net ID. + - `giveaway_id` (nullable) The giveaway a user is entered into. //check this + """ + + __tablename__ = "user" + + id = Column(Integer, primary_key=True) + net_id = Column(String, nullable=False) + giveaway_id = Column(Integer, ForeignKey("giveaway.id"), nullable=True) + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.net_id = kwargs.get("net_id") + self.giveaway_id = kwargs.get("giveaways") + + def serialize(self): + return { + "id": self.id, + "net_id": self.net_id, + "giveaway_id": self.giveaway_id + } \ No newline at end of file diff --git a/src/schema.py b/src/schema.py index fe63f09..6748b61 100644 --- a/src/schema.py +++ b/src/schema.py @@ -6,6 +6,8 @@ from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel +from src.models.user import User as UserModel +from src.models.giveaway import Giveaway as GiveawayModel # MARK: - Gym @@ -92,24 +94,82 @@ class Capacity(SQLAlchemyObjectType): class Meta: model = CapacityModel +# MARK: - User + +class User(SQLAlchemyObjectType): + class Meta: + model = UserModel + +class UserInput(graphene.InputObjectType): + net_id = graphene.String(required=True) + giveaway_id = graphene.Int(required=True) + +#MARK: - Giveaway + +class Giveaway(SQLAlchemyObjectType): + class Meta: + model = GiveawayModel + + user_ids = graphene.List(lambda: User) + + def resolve_userids(self, info): + query = User.get_query(info=info).filter(UserModel.giveaway_id == self.id) + return query + # MARK: - Activity # class Activity(SQLAlchemyObjectType): # class Meta: # model = ActivityModel # facilities = graphene.List(lambda: Facility) + +# MARK: - Query -# MARK: - Query + # user_data = UserInput(required=True) + + # user = graphene.Field(User) + + # def mutate(root, info, user_data=None): + # user = User( + # net_id=user_data.net_id, + # age=user_data.giveaway_id + # ) + # return CreateUser(user=user) class Query(graphene.ObjectType): gyms = graphene.List(Gym) + users_by_giveawayid = graphene.List(User, giveaway_id=graphene.Int(required=True)) def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() + + def resolve_users_by_giveawayid(self, giveaway_id, info): + try: + return User.objects.filter(giveaway_id=giveaway_id) + except User.DoesNotExist: + return None + + +#MARK: - Mutation + +class createUser(graphene.Mutation): + class Arguments: + net_id = graphene.String() + giveaway_id = graphene.Int() + + user = graphene.Field(lambda: User) + + def mutate(root, info, net_id, giveaway_id): + user = User(net_id=net_id, giveaway_id=giveaway_id) + user.save() + return createUser(user=user) + +class Mutation(graphene.ObjectType): + createUser = createUser.Field() +schema = graphene.Schema(query=Query, mutation=Mutation) -schema = graphene.Schema(query=Query) From 66751be8cc1698d79e79a4aa28e84b6207cc55e2 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 20 Mar 2024 17:28:33 -0400 Subject: [PATCH 02/52] Created Activities model --- .python-version | 1 + schema.graphql | 19 ++++++++++ src/models/activity.py | 78 ++++++++++++++++++++++++++++++++++++++++++ src/models/gym.py | 2 ++ src/schema.py | 37 ++++++++++++++++---- 5 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 .python-version create mode 100644 src/models/activity.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..43077b2 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9.18 diff --git a/schema.graphql b/schema.graphql index 5a0f6eb..1811431 100644 --- a/schema.graphql +++ b/schema.graphql @@ -6,6 +6,16 @@ enum AccessibilityType { WHEELCHAIR } +type Activity { + id: ID! + name: String! + facilityId: Int! + gymId: Int! + oneTimePrice: Boolean! + needsReserve: Boolean! + gear: [Gear] +} + type Amenity { id: ID! gymId: Int! @@ -69,6 +79,13 @@ enum FacilityType { COURT } +type Gear { + id: ID! + name: String! + price: Float! + activityId: Int! +} + type Gym { id: ID! address: String! @@ -79,6 +96,7 @@ type Gym { amenities: [Amenity] facilities: [Facility] hours: [OpenHours] + activities: [Activity] } type OpenHours { @@ -95,4 +113,5 @@ type OpenHours { type Query { gyms: [Gym] + activities: [Activity] } diff --git a/src/models/activity.py b/src/models/activity.py new file mode 100644 index 0000000..fb52f77 --- /dev/null +++ b/src/models/activity.py @@ -0,0 +1,78 @@ +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float +from sqlalchemy.orm import relationship +from src.database import Base + +class Activity(Base): + """ + Activity provided by a recreation center + + Attributes: + - `id` The ID of this activity. + - `name` The name of this activity. + - `facility_id` The ID of the facility this acticity belongs to. + - `gym_id` The ID of the gym this activity belongs to. + - `one_time_price` The one-time price of this activity. + - `needs_reserve` True if this activity requires group reservation. + - `gear` (nullable) This activity's gear. + """ + + __tablename__ = "activity" + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + facility_id = Column(Integer, nullable=False) + gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) + one_time_price = Column(Boolean, nullable=False) + needs_reserve = Column(Boolean, nullable=False) + gear = relationship("Gear", cascade="delete") + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.name = kwargs.get("name") + self.facility_id = kwargs.get("facility_id") + self.gym_id = kwargs.get("gym_id") + self.one_time_price = kwargs.get("one_time_price") + self.needs_reserve = kwargs.get("needs_reserve")\ + + def serialize(self): + return { + "id": self.id, + "name": self.name, + "facility_id": self.facility_id, + "gym_id": self.gym_id, + "one_time_price": self.one_time_price, + "needs_reserve": self.needs_reserve, + "gear": self.gear + } + + +class Gear(Base): + """ + Gear required for an activity + + Attributes: + - `id` The ID of this gear + - `name` The name of this gear + - `price` The price of this gear + - `activity_id` The ID of the activity this gear belonds to + """ + + __tablename__ = "gear" + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + price = Column(Float, nullable=-False) + activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.name = kwargs.get("name") + self.price = kwargs.get("price") + self.activity_id = kwargs.get("activity_id") + + def serialize(self): + return { + "id": self.id, + "name": self.name, + "price": self.price + } diff --git a/src/models/gym.py b/src/models/gym.py index 20de79a..b5ab202 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -14,6 +14,7 @@ class Gym(Base): - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. + - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -27,6 +28,7 @@ class Gym(Base): amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") + activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index fe63f09..66511c2 100644 --- a/src/schema.py +++ b/src/schema.py @@ -1,12 +1,13 @@ import graphene +from graphene import Enum from graphene_sqlalchemy import SQLAlchemyObjectType from src.models.capacity import Capacity as CapacityModel -from src.models.facility import Facility as FacilityModel +from src.models.facility import Facility as FacilityModel, FacilityType from src.models.gym import Gym as GymModel from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel - +from src.models.activity import Activity as ActivityModel, Gear as GearModel # MARK: - Gym @@ -18,6 +19,7 @@ class Meta: amenities = graphene.List(lambda: Amenity) facilities = graphene.List(lambda: Facility) hours = graphene.List(lambda: OpenHours) + activities = graphene.List(lambda: Activity) def resolve_amenities(self, info): query = Amenity.get_query(info=info).filter(AmenityModel.gym_id == self.id) @@ -30,6 +32,10 @@ def resolve_facilities(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.gym_id == self.id) return query + + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.gym_id == self.id) + return query # MARK: - Facility @@ -92,13 +98,27 @@ class Capacity(SQLAlchemyObjectType): class Meta: model = CapacityModel + +# MARK: - Gear + + +class Gear(SQLAlchemyObjectType): + class Meta: + model = GearModel + + # MARK: - Activity -# class Activity(SQLAlchemyObjectType): -# class Meta: -# model = ActivityModel + -# facilities = graphene.List(lambda: Facility) +class Activity(SQLAlchemyObjectType): + class Meta: + model = ActivityModel + gear = graphene.List(lambda: Gear) + + def resolve_gear(self, info): + query = Amenity.get_query(info=info).filter(GearModel.activity_id == self.id) + return query # MARK: - Query @@ -106,10 +126,15 @@ class Meta: class Query(graphene.ObjectType): gyms = graphene.List(Gym) + activities = graphene.List(Activity) def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() + + def resolve_activities(self, info): + query = Activity.get_query(info) + return query.all() schema = graphene.Schema(query=Query) From b81af59014bbc25e89c3608677ed56c3d140c31f Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 20 Mar 2024 17:28:33 -0400 Subject: [PATCH 03/52] Created Activities model --- .python-version | 1 + schema.graphql | 19 ++++++++++ src/models/activity.py | 78 ++++++++++++++++++++++++++++++++++++++++++ src/models/gym.py | 2 ++ src/schema.py | 37 ++++++++++++++++---- 5 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 .python-version create mode 100644 src/models/activity.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..43077b2 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9.18 diff --git a/schema.graphql b/schema.graphql index f5b31a7..aa98af9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -6,6 +6,16 @@ enum AccessibilityType { WHEELCHAIR } +type Activity { + id: ID! + name: String! + facilityId: Int! + gymId: Int! + oneTimePrice: Boolean! + needsReserve: Boolean! + gear: [Gear] +} + type Amenity { id: ID! gymId: Int! @@ -88,6 +98,13 @@ enum FacilityType { COURT } +type Gear { + id: ID! + name: String! + price: Float! + activityId: Int! +} + type Gym { id: ID! address: String! @@ -98,6 +115,7 @@ type Gym { amenities: [Amenity] facilities: [Facility] hours: [OpenHours] + activities: [Activity] } type OpenHours { @@ -110,4 +128,5 @@ type OpenHours { type Query { gyms: [Gym] + activities: [Activity] } diff --git a/src/models/activity.py b/src/models/activity.py new file mode 100644 index 0000000..fb52f77 --- /dev/null +++ b/src/models/activity.py @@ -0,0 +1,78 @@ +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float +from sqlalchemy.orm import relationship +from src.database import Base + +class Activity(Base): + """ + Activity provided by a recreation center + + Attributes: + - `id` The ID of this activity. + - `name` The name of this activity. + - `facility_id` The ID of the facility this acticity belongs to. + - `gym_id` The ID of the gym this activity belongs to. + - `one_time_price` The one-time price of this activity. + - `needs_reserve` True if this activity requires group reservation. + - `gear` (nullable) This activity's gear. + """ + + __tablename__ = "activity" + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + facility_id = Column(Integer, nullable=False) + gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) + one_time_price = Column(Boolean, nullable=False) + needs_reserve = Column(Boolean, nullable=False) + gear = relationship("Gear", cascade="delete") + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.name = kwargs.get("name") + self.facility_id = kwargs.get("facility_id") + self.gym_id = kwargs.get("gym_id") + self.one_time_price = kwargs.get("one_time_price") + self.needs_reserve = kwargs.get("needs_reserve")\ + + def serialize(self): + return { + "id": self.id, + "name": self.name, + "facility_id": self.facility_id, + "gym_id": self.gym_id, + "one_time_price": self.one_time_price, + "needs_reserve": self.needs_reserve, + "gear": self.gear + } + + +class Gear(Base): + """ + Gear required for an activity + + Attributes: + - `id` The ID of this gear + - `name` The name of this gear + - `price` The price of this gear + - `activity_id` The ID of the activity this gear belonds to + """ + + __tablename__ = "gear" + + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + price = Column(Float, nullable=-False) + activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.name = kwargs.get("name") + self.price = kwargs.get("price") + self.activity_id = kwargs.get("activity_id") + + def serialize(self): + return { + "id": self.id, + "name": self.name, + "price": self.price + } diff --git a/src/models/gym.py b/src/models/gym.py index 20de79a..b5ab202 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -14,6 +14,7 @@ class Gym(Base): - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. + - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -27,6 +28,7 @@ class Gym(Base): amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") + activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index fe63f09..66511c2 100644 --- a/src/schema.py +++ b/src/schema.py @@ -1,12 +1,13 @@ import graphene +from graphene import Enum from graphene_sqlalchemy import SQLAlchemyObjectType from src.models.capacity import Capacity as CapacityModel -from src.models.facility import Facility as FacilityModel +from src.models.facility import Facility as FacilityModel, FacilityType from src.models.gym import Gym as GymModel from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel - +from src.models.activity import Activity as ActivityModel, Gear as GearModel # MARK: - Gym @@ -18,6 +19,7 @@ class Meta: amenities = graphene.List(lambda: Amenity) facilities = graphene.List(lambda: Facility) hours = graphene.List(lambda: OpenHours) + activities = graphene.List(lambda: Activity) def resolve_amenities(self, info): query = Amenity.get_query(info=info).filter(AmenityModel.gym_id == self.id) @@ -30,6 +32,10 @@ def resolve_facilities(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.gym_id == self.id) return query + + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.gym_id == self.id) + return query # MARK: - Facility @@ -92,13 +98,27 @@ class Capacity(SQLAlchemyObjectType): class Meta: model = CapacityModel + +# MARK: - Gear + + +class Gear(SQLAlchemyObjectType): + class Meta: + model = GearModel + + # MARK: - Activity -# class Activity(SQLAlchemyObjectType): -# class Meta: -# model = ActivityModel + -# facilities = graphene.List(lambda: Facility) +class Activity(SQLAlchemyObjectType): + class Meta: + model = ActivityModel + gear = graphene.List(lambda: Gear) + + def resolve_gear(self, info): + query = Amenity.get_query(info=info).filter(GearModel.activity_id == self.id) + return query # MARK: - Query @@ -106,10 +126,15 @@ class Meta: class Query(graphene.ObjectType): gyms = graphene.List(Gym) + activities = graphene.List(Activity) def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() + + def resolve_activities(self, info): + query = Activity.get_query(info) + return query.all() schema = graphene.Schema(query=Query) From 1241924d6a9a091f6e21157d2248355c22f21acb Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:46:19 -0400 Subject: [PATCH 04/52] Delete .python-version --- .python-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .python-version diff --git a/.python-version b/.python-version deleted file mode 100644 index 43077b2..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.18 From ce882c3ae654175809fdcc6d0975cdc2c6db2e9e Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:48:15 -0400 Subject: [PATCH 05/52] Update activity.py --- src/models/activity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/activity.py b/src/models/activity.py index fb52f77..0788486 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -20,7 +20,7 @@ class Activity(Base): id = Column(Integer, primary_key=True) name = Column(String, nullable=False) - facility_id = Column(Integer, nullable=False) + facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) one_time_price = Column(Boolean, nullable=False) needs_reserve = Column(Boolean, nullable=False) From 05f51b248e776a9e8396579649220c1857146680 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:50:00 -0400 Subject: [PATCH 06/52] Update activity.py --- src/models/activity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/activity.py b/src/models/activity.py index 0788486..b327c69 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -9,7 +9,7 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `name` The name of this activity. - - `facility_id` The ID of the facility this acticity belongs to. + - `facility_id` The ID of the facility this activity belongs to. - `gym_id` The ID of the gym this activity belongs to. - `one_time_price` The one-time price of this activity. - `needs_reserve` True if this activity requires group reservation. @@ -32,7 +32,7 @@ def __init__(self, **kwargs): self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") self.one_time_price = kwargs.get("one_time_price") - self.needs_reserve = kwargs.get("needs_reserve")\ + self.needs_reserve = kwargs.get("needs_reserve") def serialize(self): return { @@ -54,7 +54,7 @@ class Gear(Base): - `id` The ID of this gear - `name` The name of this gear - `price` The price of this gear - - `activity_id` The ID of the activity this gear belonds to + - `activity_id` The ID of the activity this gear belongs to """ __tablename__ = "gear" From ecebcb53a6b41c09a2b0d8357f65854f224d4903 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:58:37 -0400 Subject: [PATCH 07/52] Added activities field to Facility --- src/models/facility.py | 3 +++ src/schema.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/models/facility.py b/src/models/facility.py index 5e1686d..1269c76 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -29,6 +29,8 @@ class Facility(Base): - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. + - `equipment` (nullable) The equipment of this facility. + - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" @@ -40,6 +42,7 @@ class Facility(Base): hours = relationship("OpenHours") name = Column(String, nullable=False) equipment = relationship("Equipment") + activities = relationship("Activity") def __init__(self, **kwargs): self.id = kwargs.get("id") diff --git a/src/schema.py b/src/schema.py index 66511c2..18498d7 100644 --- a/src/schema.py +++ b/src/schema.py @@ -48,6 +48,7 @@ class Meta: capacity = graphene.Field(lambda: Capacity) hours = graphene.List(lambda: OpenHours) equipment = graphene.List(lambda: Equipment) + activities = graphene.List(lambda: Activity) def resolve_capacity(self, info): query = ( @@ -65,6 +66,10 @@ def resolve_hours(self, info): def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query + + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) + return query From 78c8085637346abe7a023ba91d9b87954653e24b Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Sat, 23 Mar 2024 23:20:59 -0400 Subject: [PATCH 08/52] add giveaway and user models --- app.py | 6 ++--- schema.graphql | 11 +++++++- src/models/user.py | 2 +- src/schema.py | 62 ++++++++++++++++++++++------------------------ 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/app.py b/app.py index 71c96b8..e5806b3 100644 --- a/app.py +++ b/app.py @@ -5,7 +5,7 @@ from graphene import Schema from graphql.utils import schema_printer from src.database import db_session, init_db -from src.schema import Query +from src.schema import Query, Mutation from src.scrapers.capacities_scraper import fetch_capacities from src.scrapers.reg_hours_scraper import fetch_reg_building, fetch_reg_facility from src.scrapers.scraper_helpers import clean_past_hours @@ -16,7 +16,7 @@ app = Flask(__name__) app.debug = True -schema = Schema(query=Query) +schema = Schema(query=Query, mutation=Mutation) # Scheduler scheduler = APScheduler() @@ -72,4 +72,4 @@ def scrape_capacities(): schema_file.close() if __name__ == "__main__": - app.run(host="0.0.0.0", port=5000) + app.run(host="0.0.0.0", port=5000) \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 74a2f3e..a8ee7c6 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,5 +1,6 @@ schema { query: Query + mutation: Mutation } enum AccessibilityType { @@ -81,6 +82,10 @@ type Gym { hours: [OpenHours] } +type Mutation { + createUser(giveawayId: Int, netId: String): createUser +} + type OpenHours { id: ID! courtType: CourtType @@ -95,7 +100,7 @@ type OpenHours { type Query { gyms: [Gym] - usersByGiveawayid(giveawayId: Int!): [User] + usersByGiveawayid(id: Int): [User] } type User { @@ -103,3 +108,7 @@ type User { netId: String! giveawayId: Int } + +type createUser { + user: User +} diff --git a/src/models/user.py b/src/models/user.py index 4057340..7864070 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -12,7 +12,7 @@ class User(Base): - `giveaway_id` (nullable) The giveaway a user is entered into. //check this """ - __tablename__ = "user" + __tablename__ = "users" id = Column(Integer, primary_key=True) net_id = Column(String, nullable=False) diff --git a/src/schema.py b/src/schema.py index 6748b61..cbd6e8a 100644 --- a/src/schema.py +++ b/src/schema.py @@ -8,7 +8,7 @@ from src.models.equipment import Equipment as EquipmentModel from src.models.user import User as UserModel from src.models.giveaway import Giveaway as GiveawayModel - +from src.database import db_session # MARK: - Gym @@ -94,6 +94,7 @@ class Capacity(SQLAlchemyObjectType): class Meta: model = CapacityModel + # MARK: - User class User(SQLAlchemyObjectType): @@ -104,6 +105,7 @@ class UserInput(graphene.InputObjectType): net_id = graphene.String(required=True) giveaway_id = graphene.Int(required=True) + #MARK: - Giveaway class Giveaway(SQLAlchemyObjectType): @@ -122,54 +124,50 @@ def resolve_userids(self, info): # model = ActivityModel # facilities = graphene.List(lambda: Facility) - -# MARK: - Query +# MARK: - Activity +# class Activity(SQLAlchemyObjectType): +# class Meta: +# model = ActivityModel +# facilities = graphene.List(lambda: Facility) - # user_data = UserInput(required=True) - # user = graphene.Field(User) - # def mutate(root, info, user_data=None): - # user = User( - # net_id=user_data.net_id, - # age=user_data.giveaway_id - # ) - # return CreateUser(user=user) +# MARK: - Query class Query(graphene.ObjectType): gyms = graphene.List(Gym) - users_by_giveawayid = graphene.List(User, giveaway_id=graphene.Int(required=True)) + users_by_giveawayid = graphene.List(User, id=graphene.Int()) def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() - def resolve_users_by_giveawayid(self, giveaway_id, info): - try: - return User.objects.filter(giveaway_id=giveaway_id) - except User.DoesNotExist: - return None - - -#MARK: - Mutation + def resolve_users_by_giveawayid(self, info, id): + query = User.get_query(info).filter(UserModel.giveaway_id == id) + return query.all() + -class createUser(graphene.Mutation): - class Arguments: - net_id = graphene.String() - giveaway_id = graphene.Int() +# # MARK: - Mutation - user = graphene.Field(lambda: User) +# class createUser(graphene.Mutation): +# class Arguments: +# net_id = graphene.String() +# giveaway_id = graphene.Int() - def mutate(root, info, net_id, giveaway_id): - user = User(net_id=net_id, giveaway_id=giveaway_id) - user.save() - return createUser(user=user) +# user = graphene.Field(lambda: User) -class Mutation(graphene.ObjectType): - createUser = createUser.Field() +# def mutate(root, info, net_id, giveaway_id): +# user = User(net_id=net_id, giveaway_id=giveaway_id) +# db_session.add(user) +# db_session.commit() +# return createUser(user=user) + +# class Mutation(graphene.ObjectType): +# createUser = createUser.Field() + -schema = graphene.Schema(query=Query, mutation=Mutation) +schema = graphene.Schema(query=Query, mutation=Mutation) \ No newline at end of file From 3eee7b9ec5a009e73dcfa400efffd73a62acff30 Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Sun, 24 Mar 2024 00:07:12 -0400 Subject: [PATCH 09/52] updated schema.py --- src/models/giveaway.py | 4 ++++ src/schema.py | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/models/giveaway.py b/src/models/giveaway.py index 5186866..d5353ac 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -18,20 +18,24 @@ class Giveaway(Base): Attributes: - `id` The ID of the giveaway. + - `name` The name of the giveaway. - `user_ids` (nullable) The IDs of users entered into this giveaway. """ __tablename__ = "giveaway" id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) user_ids = relationship(User) def __init__(self, **kwargs): self.id = kwargs.get("id") + self.name = kwargs.get("name") self.user_ids = kwargs.get("user_id") def serialize(self): return { "id": self.id, + "name": self.name, "user_ids": self.user_ids } \ No newline at end of file diff --git a/src/schema.py b/src/schema.py index cbd6e8a..4902c9d 100644 --- a/src/schema.py +++ b/src/schema.py @@ -150,23 +150,23 @@ def resolve_users_by_giveawayid(self, info, id): return query.all() -# # MARK: - Mutation +# MARK: - Mutation -# class createUser(graphene.Mutation): -# class Arguments: -# net_id = graphene.String() -# giveaway_id = graphene.Int() +class createUser(graphene.Mutation): + class Arguments: + net_id = graphene.String() + giveaway_id = graphene.Int() -# user = graphene.Field(lambda: User) + user = graphene.Field(lambda: User) -# def mutate(root, info, net_id, giveaway_id): -# user = User(net_id=net_id, giveaway_id=giveaway_id) -# db_session.add(user) -# db_session.commit() -# return createUser(user=user) + def mutate(root, info, net_id, giveaway_id): + user = User(net_id=net_id, giveaway_id=giveaway_id) + db_session.add(user) + db_session.commit() + return createUser(user=user) -# class Mutation(graphene.ObjectType): -# createUser = createUser.Field() +class Mutation(graphene.ObjectType): + createUser = createUser.Field() From 3a7fee4d9f020f72e19465878376b36e35f87b8c Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Sun, 24 Mar 2024 00:11:51 -0400 Subject: [PATCH 10/52] Update giveaway.py --- src/models/giveaway.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/models/giveaway.py b/src/models/giveaway.py index d5353ac..204379f 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -4,14 +4,6 @@ from src.database import Base from src.models.user import User -# class GiveawayType(enum.Enum): -# """ -# An enumeration representing a giveaway type. -# """ - -# utea_giftcard = 0 -# stanley = 1 - class Giveaway(Base): """ A giveaway object. @@ -38,4 +30,4 @@ def serialize(self): "id": self.id, "name": self.name, "user_ids": self.user_ids - } \ No newline at end of file + } From eaf63b81d1f8211f3e75fff54cf448de4e2f55ab Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Sun, 24 Mar 2024 00:12:26 -0400 Subject: [PATCH 11/52] Update user.py --- src/models/user.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/models/user.py b/src/models/user.py index 7864070..4365d1f 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -1,7 +1,6 @@ from sqlalchemy import Column, Integer, Float, ForeignKey, String from src.database import Base - class User(Base): """ A user who enters a giveaway. @@ -28,4 +27,4 @@ def serialize(self): "id": self.id, "net_id": self.net_id, "giveaway_id": self.giveaway_id - } \ No newline at end of file + } From a4a55aa6f4df4197123216e74789f1f54be8e248 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Mon, 25 Mar 2024 11:14:19 -0400 Subject: [PATCH 12/52] Update src/models/activity.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/activity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/activity.py b/src/models/activity.py index b327c69..799c491 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -4,7 +4,7 @@ class Activity(Base): """ - Activity provided by a recreation center + Activity provided by a recreation center. Attributes: - `id` The ID of this activity. From 1c688d9ff26a9eb6d70658537269cd497f4a290b Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Mon, 25 Mar 2024 11:21:39 -0400 Subject: [PATCH 13/52] Reformatted code --- src/models/activity.py | 47 ++++++++++++++++++++---------------------- src/models/facility.py | 8 +++---- src/models/gym.py | 4 ++-- src/schema.py | 12 +++++------ 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/models/activity.py b/src/models/activity.py index b327c69..179e8ea 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -2,77 +2,74 @@ from sqlalchemy.orm import relationship from src.database import Base + class Activity(Base): """ - Activity provided by a recreation center + Activity provided by a recreation center. Attributes: - `id` The ID of this activity. - - `name` The name of this activity. - `facility_id` The ID of the facility this activity belongs to. + - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. - - `one_time_price` The one-time price of this activity. + - `name` The name of this activity. - `needs_reserve` True if this activity requires group reservation. - - `gear` (nullable) This activity's gear. + - `one_time_price` The one-time price of this activity. """ __tablename__ = "activity" id = Column(Integer, primary_key=True) - name = Column(String, nullable=False) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) + gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) - one_time_price = Column(Boolean, nullable=False) + name = Column(String, nullable=False) needs_reserve = Column(Boolean, nullable=False) - gear = relationship("Gear", cascade="delete") + one_time_price = Column(Boolean, nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") - self.name = kwargs.get("name") self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") - self.one_time_price = kwargs.get("one_time_price") + self.name = kwargs.get("name") self.needs_reserve = kwargs.get("needs_reserve") + self.one_time_price = kwargs.get("one_time_price") def serialize(self): return { "id": self.id, - "name": self.name, "facility_id": self.facility_id, + "gear": self.gear, "gym_id": self.gym_id, - "one_time_price": self.one_time_price, + "name": self.name, "needs_reserve": self.needs_reserve, - "gear": self.gear + "one_time_price": self.one_time_price, } - - + + class Gear(Base): """ Gear required for an activity Attributes: - - `id` The ID of this gear - - `name` The name of this gear - - `price` The price of this gear - - `activity_id` The ID of the activity this gear belongs to + - `id` The ID of this gear. + - `activity_id` The ID of the activity this gear belongs to. + - `name` The name of this gear. + - `price` The price of this gear. """ __tablename__ = "gear" id = Column(Integer, primary_key=True) + activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) name = Column(String, nullable=False) price = Column(Float, nullable=-False) - activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") + self.activity_id = kwargs.get("activity_id") self.name = kwargs.get("name") self.price = kwargs.get("price") - self.activity_id = kwargs.get("activity_id") def serialize(self): - return { - "id": self.id, - "name": self.name, - "price": self.price - } + return {"id": self.id, "name": self.name, "price": self.price} diff --git a/src/models/facility.py b/src/models/facility.py index 1269c76..a112d61 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -24,25 +24,25 @@ class Facility(Base): Attributes: - `id` The ID of this facility. + - `activities` (nullable) The activities of this facility. - `capacity` (nullable) The capacity of this facility. + - `equipment` (nullable) The equipment of this facility. - `facility_type` The type of this facility (FITNESS, POOL, BOWLING, COURT). - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. - - `equipment` (nullable) The equipment of this facility. - - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" id = Column(Integer, primary_key=True) + activities = relationship("Activity") capacity = relationship("Capacity") + equipment = relationship("Equipment") facility_type = Column(Enum(FacilityType), nullable=False) gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) hours = relationship("OpenHours") name = Column(String, nullable=False) - equipment = relationship("Equipment") - activities = relationship("Activity") def __init__(self, **kwargs): self.id = kwargs.get("id") diff --git a/src/models/gym.py b/src/models/gym.py index b5ab202..4e6f752 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -10,11 +10,11 @@ class Gym(Base): Attributes: - `id` The ID of this gym (building). + - `activities` (nullable) The gym's activities. - `address` The address of the buildling. - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. - - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -24,11 +24,11 @@ class Gym(Base): __tablename__ = "gym" id = Column(Integer, primary_key=True) + activities = relationship("Activity") address = Column(String, nullable=False) amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") - activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index 18498d7..695ecb4 100644 --- a/src/schema.py +++ b/src/schema.py @@ -32,7 +32,7 @@ def resolve_facilities(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.gym_id == self.id) return query - + def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.gym_id == self.id) return query @@ -62,17 +62,16 @@ def resolve_capacity(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.facility_id == self.id) return query - + def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query - + def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) return query - # MARK: - Open Hours @@ -80,6 +79,7 @@ class OpenHours(SQLAlchemyObjectType): class Meta: model = OpenHoursModel + # MARK: - Equipment @@ -113,7 +113,7 @@ class Meta: # MARK: - Activity - + class Activity(SQLAlchemyObjectType): class Meta: @@ -136,7 +136,7 @@ class Query(graphene.ObjectType): def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() - + def resolve_activities(self, info): query = Activity.get_query(info) return query.all() From c76395f1510f8d27395cf1861c82d28d1d1a5ca3 Mon Sep 17 00:00:00 2001 From: Vin Bui Date: Tue, 26 Mar 2024 03:53:07 -0400 Subject: [PATCH 14/52] Update test.yml --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9648f36..ec4f310 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,9 @@ jobs: run: | sudo apt-get update sudo apt-get install libxml2-dev libxslt-dev + sudo apt-get install --yes --no-install-recommends postgresql-client + createdb uplift + createuser -P -s -e local pip install --force-reinstall pip==20.0.2 pip install --force-reinstall setuptools==44.0.0 pip freeze From 5223b56048c7f360b051856a3ba21e7cc6f45a4a Mon Sep 17 00:00:00 2001 From: Vin Bui Date: Tue, 26 Mar 2024 04:06:19 -0400 Subject: [PATCH 15/52] Update test.yml --- .github/workflows/test.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec4f310..061f85f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,20 @@ on: jobs: build: runs-on: ubuntu-latest + services: + postgres: + image: postgres:latest + env: + POSTGRES_DB: uplift + POSTGRES_PASSWORD: password + POSTGRES_USER: local + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -22,9 +36,6 @@ jobs: run: | sudo apt-get update sudo apt-get install libxml2-dev libxslt-dev - sudo apt-get install --yes --no-install-recommends postgresql-client - createdb uplift - createuser -P -s -e local pip install --force-reinstall pip==20.0.2 pip install --force-reinstall setuptools==44.0.0 pip freeze From ec3492b7c80ef251c7eeb867bc85474a9b283a7d Mon Sep 17 00:00:00 2001 From: Vin Bui Date: Tue, 26 Mar 2024 04:10:16 -0400 Subject: [PATCH 16/52] Update test.yml --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 061f85f..8c408ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,7 @@ on: jobs: build: runs-on: ubuntu-latest + services: postgres: image: postgres:latest @@ -27,6 +28,7 @@ jobs: --health-interval 10s --health-timeout 5s --health-retries 5 + steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -36,6 +38,7 @@ jobs: run: | sudo apt-get update sudo apt-get install libxml2-dev libxslt-dev + sudo apt-get install --yes --no-install-recommends postgresql-client pip install --force-reinstall pip==20.0.2 pip install --force-reinstall setuptools==44.0.0 pip freeze From 681a875505edb2f1e6609a7a81195dc799fe7af9 Mon Sep 17 00:00:00 2001 From: Vin Bui Date: Tue, 26 Mar 2024 04:45:30 -0400 Subject: [PATCH 17/52] Fixed GitHub actions for testing --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c408ec..8920685 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,3 +44,11 @@ jobs: pip freeze pip install -r requirements.txt python -m unittest src.tests.test_scraper + env: + DB_HOST: localhost + DB_NAME: uplift + DB_PORT: 5432 + DB_PASSWORD: password + DB_USERNAME: local + FLASK_ENV: dev + GOOGLE_SERVICE_ACCOUNT_PATH: service-account-key.json From ff15b38b49104ab7e6ae8dce1b15968e8dfa40b3 Mon Sep 17 00:00:00 2001 From: isabellahoie <68919125+isabellahoie@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:21:56 -0400 Subject: [PATCH 18/52] Bella/classes (#141) * Created activity model and many to many relationship with gym model; added activity and gym rresolvers to the schema * added activity model to import statements on init_db() * deleted testing objects in init_db() * deleted duplicate code * Implemented PR edits in activity.py * Implemented PR edits in gym.py * Implemented PR changes in schema.py and added Price and Amenity class and price resolver in Activity class * Populated models to test * Cleaning up some merge conflicts * almost implementing Facilities * Created activity model and many to many relationship with gym model; added activity and gym rresolvers to the schema * added activity model to import statements on init_db() * deleted testing objects in init_db() * deleted duplicate code * Implemented PR edits in activity.py * Implemented PR edits in gym.py * Implemented PR changes in schema.py and added Price and Amenity class and price resolver in Activity class * Populated models to test * Cleaning up some merge conflicts * almost implementing Facilities * Activity model and some changes to gym * Created some of gym scraper * fixed facility.py * wrote some of gym hour scraper * Implement scraper for fitness center hours * changed some of activities * class changes * bug fixes on the scraper * fixing scraping hours * fixing activities * completed fixed activities * modified gym_scraper to accomodate special_hours * Scraped equipment and added it to the Schema * Upgrade python version for the test workflow * added back classes and class scraper * fixed scheduling of classes scraper and cleaned up code --------- Co-authored-by: Isabella Hoie Co-authored-by: Kidus Zegeye <51487468+kidzegeye@users.noreply.github.com> --- app.py | 9 +++ schema.graphql | 39 ++++++------ src/models/classes.py | 90 +++++++++++++++++++++++++++ src/models/gym.py | 2 + src/schema.py | 10 +-- src/scrapers/class_scraper.py | 114 ++++++++++++++++++++++++++++++++++ src/utils/constants.py | 9 +++ 7 files changed, 247 insertions(+), 26 deletions(-) create mode 100644 src/models/classes.py create mode 100644 src/scrapers/class_scraper.py diff --git a/app.py b/app.py index 71c96b8..54f6c76 100644 --- a/app.py +++ b/app.py @@ -11,6 +11,7 @@ from src.scrapers.scraper_helpers import clean_past_hours from src.scrapers.sp_hours_scraper import fetch_sp_facility from src.scrapers.equipment_scraper import scrape_equipment +from src.scrapers.class_scraper import fetch_classes from src.utils.utils import create_gym_table @@ -58,10 +59,18 @@ def scrape_capacities(): fetch_capacities() +# Scrape classes every hour +@scheduler.task("interval", id="scrape_classes", seconds=3600) +def scrape_classes(): + logging.info("Scraping classes from group-fitness-classes...") + + fetch_classes(3) + # Create database and fill it with data init_db() create_gym_table() +scrape_classes() scrape_hours() scrape_capacities() scrape_equipment() diff --git a/schema.graphql b/schema.graphql index 5a0f6eb..fad30f3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -27,29 +27,31 @@ type Capacity { updated: Int! } -enum CourtType { - BASKETBALL - VOLLEYBALL - BADMINTON +type Class { + id: ID! + name: String! + description: String! + gyms: [ClassInstance] } -type Equipment { +type ClassInstance { id: ID! - name: String! - equipmentType: EquipmentType! - facilityId: Int! - quantity: Int - accessibility: AccessibilityType + gymId: Int + classId: Int! + location: String! + instructor: String! + isCanceled: Boolean! + isVirtual: Boolean! + startTime: DateTime + endTime: DateTime + class_: Class + gym: Gym } -enum EquipmentType { - CARDIO - RACKS_AND_BENCHES - SELECTORIZED - MULTI_CABLE - FREE_WEIGHTS - MISCELLANEOUS - PLATE_LOADED +enum CourtType { + BASKETBALL + VOLLEYBALL + BADMINTON } type Facility { @@ -79,6 +81,7 @@ type Gym { amenities: [Amenity] facilities: [Facility] hours: [OpenHours] + classes: [ClassInstance] } type OpenHours { diff --git a/src/models/classes.py b/src/models/classes.py new file mode 100644 index 0000000..f425509 --- /dev/null +++ b/src/models/classes.py @@ -0,0 +1,90 @@ +import datetime +from src.database import Base +from sqlalchemy import ( + Table, + Column, + DateTime, + ForeignKey, + Integer, + Float, + String, + Boolean, + func, +) +from sqlalchemy.orm import backref, relationship + +classes_to_gyms = Table( + "classes_to_gyms", + Base.metadata, + Column("id", Integer(), primary_key=True), + Column("gym_id", ForeignKey("gym.id")), + Column("class_id", ForeignKey("class.id")), + Column("location", String()), + Column("instructor", String()), + Column("isCancelled", Boolean()), + Column("start_time", DateTime()), + Column("end_time", DateTime()), +) + + +class Class(Base): + __tablename__ = "class" + + id = Column(Integer, primary_key=True) + name = Column(String(), nullable=False) + description = Column(String(), nullable=False) + gyms = relationship("ClassInstance", back_populates="class_") + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.name = kwargs.get("name") + self.description = kwargs.get("description") + + def serialize(self): + return { + "id": self.id, + "name": self.name, + "description": self.description, + } + + +class ClassInstance(Base): + __tablename__ = "class_instance" + + id = Column(Integer, primary_key=True) + gym_id = Column(Integer, ForeignKey("gym.id"), nullable=True) + class_id = Column(Integer, ForeignKey("class.id"), nullable=False) + location = Column(String(), nullable=False) + instructor = Column(String(), nullable=False) + isCanceled = Column(Boolean(), nullable=False, default=False) + isVirtual = Column(Boolean(), nullable=False, default=False) + start_time = Column(DateTime(), nullable=True) + end_time = Column(DateTime(), nullable=True) + class_ = relationship("Class", back_populates="gyms") + gym = relationship("Gym", back_populates="classes") + + def __init__(self, **kwargs): + self.id = kwargs.get("id") + self.gym_id = kwargs.get("gym_id") + self.class_id = kwargs.get("class_id") + self.location = kwargs.get("location") + self.instructor = kwargs.get("instructor") + self.isCanceled = kwargs.get("isCanceled") + self.isVirtual = kwargs.get("isVirtual") + self.start_time = kwargs.get("start_time") + self.end_time = kwargs.get("end_time") + + def serialize(self): + return { + "id": self.id, + "gym_id": self.gym_id, + "class_id": self.class_id, + "location": self.location, + "instructor": self.instructor, + "isCanceled": self.isCanceled, + "isVirtual": self.isVirtual, + "start_time": self.start_time, + "end_time": self.end_time, + } + + diff --git a/src/models/gym.py b/src/models/gym.py index 20de79a..734cc84 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -2,6 +2,7 @@ from sqlalchemy.orm import relationship from src.database import Base from src.models.openhours import OpenHours +from src.models.classes import ClassInstance, Class class Gym(Base): @@ -27,6 +28,7 @@ class Gym(Base): amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") + classes = relationship("ClassInstance", back_populates="gym") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index fe63f09..5211734 100644 --- a/src/schema.py +++ b/src/schema.py @@ -6,6 +6,8 @@ from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel +from src.models.classes import Class as ClassModel +from src.models.classes import ClassInstance as ClassInstanceModel # MARK: - Gym @@ -92,14 +94,6 @@ class Capacity(SQLAlchemyObjectType): class Meta: model = CapacityModel -# MARK: - Activity -# class Activity(SQLAlchemyObjectType): -# class Meta: -# model = ActivityModel - -# facilities = graphene.List(lambda: Facility) - - # MARK: - Query diff --git a/src/scrapers/class_scraper.py b/src/scrapers/class_scraper.py new file mode 100644 index 0000000..6406bb7 --- /dev/null +++ b/src/scrapers/class_scraper.py @@ -0,0 +1,114 @@ +from datetime import datetime +from src.database import db_session +import time as t +import datetime as dt +import random +from bs4 import BeautifulSoup +import re +import requests +from src.utils.utils import get_gym_id +from src.utils.constants import GYMS, BASE_URL, CLASSES_PATH +from src.models.classes import Class, ClassInstance +from src.models.openhours import OpenHours + +from src.models.facility import Facility + +""" +Create a group class from a class page +Params: + class_href: href of class page from group-fitness-classes page +Returns: + Class Object created +""" +def create_group_class(class_href): + page = requests.get(BASE_URL + class_href).text + soup = BeautifulSoup(page, "lxml") + container = soup.select_one("#main-article") + name = container.select_one("h1").text + try: + contents = container.select("p") + except AttributeError as e: + print(e) + contents = [""] + description = "" + for c in contents: + if isinstance(c, str): + description += c + else: + description += c.text + model = Class(name=name, description=description) + db_session.add(model) + db_session.commit() + return model + + +""" +Scrape classes from the group-fitness-classes page +Params: + num_pages: number of pages to scrape - this determines how far in advance we scrape classes +Returns: + dict of ClassInstance objects +""" +def fetch_classes(num_pages): + classes = {} + db_session.query(ClassInstance).delete() + db_session.commit() + for i in range(num_pages): + page = requests.get(BASE_URL + CLASSES_PATH + str(i)).text + soup = BeautifulSoup(page, "lxml") + if len(soup.find_all("table")) == 1: + continue + schedule = soup.find_all("table")[1] # first table is irrelevant + data = schedule.find_all("tr")[1:] # first row is header + for row in data: + row_elems = row.find_all("td") + class_instance = ClassInstance() + class_name = row_elems[0].a.text + class_href = row_elems[0].a["href"] + try: + gym_class = db_session.query(Class).filter(Class.name == class_name).first() + assert gym_class is not None + except AssertionError: + gym_class = create_group_class(class_href) + class_instance.class_id = gym_class.id + date_string = row_elems[1].text.strip() + if "Today" in date_string: + date_string = datetime.strftime(datetime.now(), "%m/%d/%Y") + + # special handling for time (cancelled) + + time_str = row_elems[3].string.replace("\n", "").strip() + if time_str != "" and time_str != 'Canceled': + class_instance.is_canceled = False + time_strs = time_str.split(" - ") + start_time_string = time_strs[0].strip() + end_time_string = time_strs[1].strip() + + class_instance.start_time = datetime.strptime(f"{date_string} {start_time_string}", "%m/%d/%Y %I:%M%p") + class_instance.end_time = datetime.strptime(f"{date_string} {end_time_string}", "%m/%d/%Y %I:%M%p") + if class_instance.end_time < datetime.now(): + continue + else: + class_instance.isCanceled = True + + try: + class_instance.instructor = row_elems[4].a.string + except: + class_instance.instructor = "" + try: + location = row_elems[5].a.string + class_instance.location = location + for gym in GYMS: + if gym in location: + if gym == "Virtual": + class_instance.isVirtual = True + else: + gym_id = get_gym_id(gym) + class_instance.gym_id = gym_id + break + except: + gym_class.location = "" + db_session.add(class_instance) + db_session.commit() + classes[class_instance.id] = class_instance + return classes \ No newline at end of file diff --git a/src/utils/constants.py b/src/utils/constants.py index 21814e9..13caaba 100644 --- a/src/utils/constants.py +++ b/src/utils/constants.py @@ -3,6 +3,9 @@ # URL for Uplift image assets ASSET_BASE_URL = "https://raw.githubusercontent.com/cuappdev/assets/master/uplift/" +# Base URL for Cornell Recreation Website +BASE_URL = "https://scl.cornell.edu/recreation/" + # The path for capacities C2C_URL = "https://connect2concepts.com/connect2/?type=bar&key=355de24d-d0e4-4262-ae97-bc0c78b92839&loc_status=false" @@ -30,12 +33,18 @@ # The marker for last updated in the HTML CAPACITY_MARKER_UPDATED = "Updated: " +# The path for group classes +CLASSES_PATH = "/fitness-centers/group-fitness-classes?&page=" + # Days of the week used in the spreadsheet DAYS_OF_WEEK = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] # Eastern Timezone EASTERN_TIMEZONE = "America/New_York" +# The list of gyms +GYMS = ["Helen Newman", "Toni Morrison", "Noyes", "Teagle"] + # The path for general gym hours GYM_HOUR_BASE_URL = "https://scl.cornell.edu/recreation/cornell-fitness-centers" From e35546c101ddcf48f950f9b01cd1f25b563b6fcc Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Tue, 9 Apr 2024 00:06:45 -0400 Subject: [PATCH 19/52] reformat code, split mutation into two, create joint table for users and giveaways --- app.py | 2 +- schema.graphql | 33 +++++++++++++--- src/models/giveaway.py | 43 ++++++++++++-------- src/models/user.py | 21 +++++----- src/schema.py | 89 +++++++++++++++++++++++++++--------------- 5 files changed, 121 insertions(+), 67 deletions(-) diff --git a/app.py b/app.py index e5806b3..44a3b26 100644 --- a/app.py +++ b/app.py @@ -72,4 +72,4 @@ def scrape_capacities(): schema_file.close() if __name__ == "__main__": - app.run(host="0.0.0.0", port=5000) \ No newline at end of file + app.run(host="0.0.0.0", port=5000) diff --git a/schema.graphql b/schema.graphql index a8ee7c6..07ca57c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -34,6 +34,15 @@ enum CourtType { BADMINTON } +type CreateUser { + user: User +} + +type EnterGiveaway { + success: Boolean + giveawayInstance: GiveawayInstance +} + type Equipment { id: ID! name: String! @@ -70,6 +79,21 @@ enum FacilityType { COURT } +type Giveaway { + id: ID! + name: String! + userIds: [User] +} + +type GiveawayInstance { + id: ID! + userId: Int! + giveawayId: Int! + numEntries: Int! + users: Giveaway + giveaways: User +} + type Gym { id: ID! address: String! @@ -83,7 +107,8 @@ type Gym { } type Mutation { - createUser(giveawayId: Int, netId: String): createUser + createUser(netId: String): CreateUser + enterGiveaway(giveawayId: Int!, userNetId: String!): EnterGiveaway } type OpenHours { @@ -106,9 +131,5 @@ type Query { type User { id: ID! netId: String! - giveawayId: Int -} - -type createUser { - user: User + giveawayIds: [GiveawayInstance] } diff --git a/src/models/giveaway.py b/src/models/giveaway.py index d5353ac..26c23c0 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -1,16 +1,8 @@ -import enum from sqlalchemy import Column, Integer, Float, ForeignKey, String from sqlalchemy.orm import relationship from src.database import Base from src.models.user import User -# class GiveawayType(enum.Enum): -# """ -# An enumeration representing a giveaway type. -# """ - -# utea_giftcard = 0 -# stanley = 1 class Giveaway(Base): """ @@ -21,21 +13,38 @@ class Giveaway(Base): - `name` The name of the giveaway. - `user_ids` (nullable) The IDs of users entered into this giveaway. """ - + __tablename__ = "giveaway" - id = Column(Integer, primary_key=True) + id = Column(Integer, primary_key=True) name = Column(String, nullable=False) - user_ids = relationship(User) + user_ids = relationship("GiveawayInstance", back_populates="users") def __init__(self, **kwargs): self.id = kwargs.get("id") self.name = kwargs.get("name") self.user_ids = kwargs.get("user_id") - def serialize(self): - return { - "id": self.id, - "name": self.name, - "user_ids": self.user_ids - } \ No newline at end of file + def serialize(self): + return {"id": self.id, "name": self.name, "user_ids": self.user_ids} + + +class GiveawayInstance(Base): + """ + An entry into a giveaway. + + Attributes: + - `id` The ID of the giveaway entry. + - `giveaway_id` The ID of the giveaway. + - `user_id` The ID of the user entered into the giveaway. + - `numEntries` The number of entries of this user into the giveaway. + """ + + __tablename__ = "giveaway_instance" + + id = Column(Integer, primary_key=True) + user_id = Column(Integer, ForeignKey("users.id"), nullable=False) + giveaway_id = Column(Integer, ForeignKey("giveaway.id"), nullable=False) + numEntries = Column(Integer, nullable=False) + users = relationship("Giveaway", back_populates="user_ids") + giveaways = relationship("User", back_populates="giveaway_ids") diff --git a/src/models/user.py b/src/models/user.py index 7864070..08129d6 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -1,31 +1,28 @@ from sqlalchemy import Column, Integer, Float, ForeignKey, String +from sqlalchemy.orm import backref, relationship from src.database import Base class User(Base): """ - A user who enters a giveaway. + An uplift user. Attributes: - `id` The ID of user. + - `giveaway_id` (nullable) The list of giveaways a user is entered into. - `net_id` The user's Net ID. - - `giveaway_id` (nullable) The giveaway a user is entered into. //check this """ - + __tablename__ = "users" - id = Column(Integer, primary_key=True) + id = Column(Integer, primary_key=True) + giveaway_ids = relationship("GiveawayInstance", back_populates="giveaways") net_id = Column(String, nullable=False) - giveaway_id = Column(Integer, ForeignKey("giveaway.id"), nullable=True) def __init__(self, **kwargs): self.id = kwargs.get("id") + self.giveaway_ids = kwargs.get("giveaway_ids") self.net_id = kwargs.get("net_id") - self.giveaway_id = kwargs.get("giveaways") - def serialize(self): - return { - "id": self.id, - "net_id": self.net_id, - "giveaway_id": self.giveaway_id - } \ No newline at end of file + def serialize(self): + return {"id": self.id, "giveaway_ids": self.giveaway_ids, "net_id": self.net_id} diff --git a/src/schema.py b/src/schema.py index 4902c9d..ecd497d 100644 --- a/src/schema.py +++ b/src/schema.py @@ -8,8 +8,10 @@ from src.models.equipment import Equipment as EquipmentModel from src.models.user import User as UserModel from src.models.giveaway import Giveaway as GiveawayModel +from src.models.giveaway import GiveawayInstance as GiveawayInstanceModel from src.database import db_session + # MARK: - Gym @@ -57,13 +59,12 @@ def resolve_capacity(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.facility_id == self.id) return query - + def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query - # MARK: - Open Hours @@ -71,6 +72,7 @@ class OpenHours(SQLAlchemyObjectType): class Meta: model = OpenHoursModel + # MARK: - Equipment @@ -96,42 +98,38 @@ class Meta: # MARK: - User - + + class User(SQLAlchemyObjectType): class Meta: model = UserModel + class UserInput(graphene.InputObjectType): net_id = graphene.String(required=True) giveaway_id = graphene.Int(required=True) -#MARK: - Giveaway - +# MARK: - Giveaway + + class Giveaway(SQLAlchemyObjectType): class Meta: model = GiveawayModel user_ids = graphene.List(lambda: User) - def resolve_userids(self, info): + def resolve_user_ids(self, info): query = User.get_query(info=info).filter(UserModel.giveaway_id == self.id) return query -# MARK: - Activity -# class Activity(SQLAlchemyObjectType): -# class Meta: -# model = ActivityModel - -# facilities = graphene.List(lambda: Facility) -# MARK: - Activity -# class Activity(SQLAlchemyObjectType): -# class Meta: -# model = ActivityModel +# MARK: - Giveaway -# facilities = graphene.List(lambda: Facility) +class GiveawayInstance(SQLAlchemyObjectType): + class Meta: + model = GiveawayInstanceModel # MARK: - Query @@ -144,30 +142,59 @@ class Query(graphene.ObjectType): def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() - - def resolve_users_by_giveawayid(self, info, id): - query = User.get_query(info).filter(UserModel.giveaway_id == id) - return query.all() + + +def resolve_users_by_giveaway_id(self, info, id): + query = User.get_query(info).filter(UserModel.giveaway_ids.any(GiveawayInstance.giveaway_id == id)) + return query.all() # MARK: - Mutation -class createUser(graphene.Mutation): + +class CreateUser(graphene.Mutation): class Arguments: net_id = graphene.String() - giveaway_id = graphene.Int() - user = graphene.Field(lambda: User) + user = graphene.Field(User) + + def mutate(root, info, net_id): + existing_user = db_session.query(UserModel).filter(UserModel.net_id == net_id).first() + if existing_user: + return CreateUser(user=existing_user) + + new_user = UserModel(net_id=net_id, giveaway_ids=[]) + db_session.add(new_user) + db_session.commit() + return CreateUser(user=new_user) + - def mutate(root, info, net_id, giveaway_id): - user = User(net_id=net_id, giveaway_id=giveaway_id) - db_session.add(user) +class EnterGiveaway(graphene.Mutation): + class Arguments: + user_net_id = graphene.String(required=True) + giveaway_id = graphene.Int(required=True) + + success = graphene.Boolean() + giveaway_instance = graphene.Field(GiveawayInstance) + + def mutate(self, info, user_net_id, giveaway_id): + user = db_session.query(UserModel).filter_by(net_id=user_net_id).first() + if not user: + return EnterGiveaway(success=False, giveaway_instance=None) + + giveaway = db_session.query(GiveawayModel).get(giveaway_id) + if not giveaway or any(instance.giveaway_id == giveaway_id for instance in user.giveaway_ids): + return EnterGiveaway(success=False, giveaway_instance=None) + + giveaway_instance = GiveawayInstanceModel(user_id=user.id, giveaway_id=giveaway_id, numEntries=1) + db_session.add(giveaway_instance) db_session.commit() - return createUser(user=user) + return EnterGiveaway(success=True, giveaway_instance=giveaway_instance) + class Mutation(graphene.ObjectType): - createUser = createUser.Field() - + createUser = CreateUser.Field() + enterGiveaway = EnterGiveaway.Field() -schema = graphene.Schema(query=Query, mutation=Mutation) \ No newline at end of file +schema = graphene.Schema(query=Query, mutation=Mutation) From 923812dbb5cebfb1503a1b49035ad1de1ab6306a Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Tue, 9 Apr 2024 01:04:14 -0400 Subject: [PATCH 20/52] resove merge conflicts --- schema.graphql | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/schema.graphql b/schema.graphql index f92aedf..07ca57c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -61,25 +61,6 @@ enum EquipmentType { MISCELLANEOUS PLATE_LOADED } - description: String! - gyms: [ClassInstance] -} - -type ClassInstance { - id: ID! - gymId: Int - classId: Int! - location: String! - instructor: String! - isCanceled: Boolean! - isVirtual: Boolean! - startTime: DateTime - endTime: DateTime - class_: Class - gym: Gym -} - -scalar DateTime type Facility { id: ID! @@ -132,10 +113,14 @@ type Mutation { type OpenHours { id: ID! - facilityId: Int! - day: Int! - startTime: String - endTime: String + courtType: CourtType + endTime: Int! + facilityId: Int + gymId: Int + isShallow: Boolean + isSpecial: Boolean! + isWomen: Boolean + startTime: Int! } type Query { From 34dae6436fda67082563f8729cc8c551fe8a81bb Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:02:03 -0400 Subject: [PATCH 21/52] Update src/models/giveaway.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/giveaway.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/models/giveaway.py b/src/models/giveaway.py index 26c23c0..26450a8 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -45,6 +45,4 @@ class GiveawayInstance(Base): id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) giveaway_id = Column(Integer, ForeignKey("giveaway.id"), nullable=False) - numEntries = Column(Integer, nullable=False) - users = relationship("Giveaway", back_populates="user_ids") - giveaways = relationship("User", back_populates="giveaway_ids") + num_entries = Column(Integer, nullable=False) From 1ca96ea291e0defec77d37b06dfaf76708be992e Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:02:10 -0400 Subject: [PATCH 22/52] Update src/models/giveaway.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/giveaway.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/models/giveaway.py b/src/models/giveaway.py index 26450a8..42b4454 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -18,15 +18,7 @@ class Giveaway(Base): id = Column(Integer, primary_key=True) name = Column(String, nullable=False) - user_ids = relationship("GiveawayInstance", back_populates="users") - - def __init__(self, **kwargs): - self.id = kwargs.get("id") - self.name = kwargs.get("name") - self.user_ids = kwargs.get("user_id") - - def serialize(self): - return {"id": self.id, "name": self.name, "user_ids": self.user_ids} + users = relationship("User", secondary="giveaway_instance", back_populates="giveaways") class GiveawayInstance(Base): From 20efafd1bbc4fa1d1fa9405e273c1af019dc9852 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:02:23 -0400 Subject: [PATCH 23/52] Update src/models/giveaway.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/giveaway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/giveaway.py b/src/models/giveaway.py index 42b4454..ae5ef23 100644 --- a/src/models/giveaway.py +++ b/src/models/giveaway.py @@ -11,7 +11,7 @@ class Giveaway(Base): Attributes: - `id` The ID of the giveaway. - `name` The name of the giveaway. - - `user_ids` (nullable) The IDs of users entered into this giveaway. + - `users` (nullable) The users that entered into this giveaway. """ __tablename__ = "giveaway" From dc6c1ef361b8c3e2cca74ac1ae738e99073486cd Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:02:59 -0400 Subject: [PATCH 24/52] Update src/models/user.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/user.py b/src/models/user.py index 01cc1c1..52dea6c 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -9,7 +9,7 @@ class User(Base): Attributes: - `id` The ID of user. - - `giveaway_id` (nullable) The list of giveaways a user is entered into. + - `giveaways` (nullable) The list of giveaways a user is entered into. - `net_id` The user's Net ID. """ From c1a27cc97f651db38e15784e583f8e691d06a361 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:04:13 -0400 Subject: [PATCH 25/52] Update src/models/user.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/user.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/models/user.py b/src/models/user.py index 52dea6c..8972d77 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -18,11 +18,3 @@ class User(Base): id = Column(Integer, primary_key=True) giveaway_ids = relationship("GiveawayInstance", back_populates="giveaways") net_id = Column(String, nullable=False) - - def __init__(self, **kwargs): - self.id = kwargs.get("id") - self.giveaway_ids = kwargs.get("giveaway_ids") - self.net_id = kwargs.get("net_id") - - def serialize(self): - return {"id": self.id, "net_id": self.net_id, "giveaway_id": self.giveaway_id} From 7349aa6b39350cd72eee37c906e80bce5679d40b Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:26:52 -0400 Subject: [PATCH 26/52] Update src/models/user.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/models/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/user.py b/src/models/user.py index 8972d77..fc19168 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -16,5 +16,5 @@ class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) - giveaway_ids = relationship("GiveawayInstance", back_populates="giveaways") + giveaways = relationship("Giveaway", secondary="giveaway_instance", back_populates="users") net_id = Column(String, nullable=False) From 3ee80a2c919a913332be47c3227740c5bcae3e04 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:37:19 -0400 Subject: [PATCH 27/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/schema.py b/src/schema.py index b5786cd..a46d192 100644 --- a/src/schema.py +++ b/src/schema.py @@ -161,11 +161,13 @@ class Arguments: user = graphene.Field(User) def mutate(root, info, net_id): - existing_user = db_session.query(UserModel).filter(UserModel.net_id == net_id).first() + # Check to see if NetID already exists + existing_user = User.get_query(info).filter(UserModel.net_id == net_id).first() if existing_user: - return CreateUser(user=existing_user) + raise GraphQLError("NetID already exists.") - new_user = UserModel(net_id=net_id, giveaway_ids=[]) + # NetID does not exist + new_user = UserModel(net_id=net_id) db_session.add(new_user) db_session.commit() return CreateUser(user=new_user) From c240ad815259641e67f43f1acf4c0dbe61dcbd9a Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:37:56 -0400 Subject: [PATCH 28/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/schema.py b/src/schema.py index a46d192..b3a1027 100644 --- a/src/schema.py +++ b/src/schema.py @@ -178,7 +178,6 @@ class Arguments: user_net_id = graphene.String(required=True) giveaway_id = graphene.Int(required=True) - success = graphene.Boolean() giveaway_instance = graphene.Field(GiveawayInstance) def mutate(self, info, user_net_id, giveaway_id): From 0ad189f1961ba1e29fd8ed4b069844f2ff27b049 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:38:03 -0400 Subject: [PATCH 29/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/schema.py b/src/schema.py index b3a1027..e443ec1 100644 --- a/src/schema.py +++ b/src/schema.py @@ -181,18 +181,32 @@ class Arguments: giveaway_instance = graphene.Field(GiveawayInstance) def mutate(self, info, user_net_id, giveaway_id): - user = db_session.query(UserModel).filter_by(net_id=user_net_id).first() + # Check if NetID and Giveaway ID exists + user = User.get_query(info).filter(UserModel.net_id == user_net_id).first() if not user: - return EnterGiveaway(success=False, giveaway_instance=None) + raise GraphQLError("User with given NetID does not exist.") - giveaway = db_session.query(GiveawayModel).get(giveaway_id) - if not giveaway or any(instance.giveaway_id == giveaway_id for instance in user.giveaway_ids): - return EnterGiveaway(success=False, giveaway_instance=None) + giveaway = Giveaway.get_query(info).filter(GiveawayModel.id == giveaway_id).first() + if not giveaway: + raise GraphQLError("Giveaway does not exist.") + + # Compute number of entries + giveaway_instance = ( + GiveawayInstance.get_query(info) + .filter(GiveawayInstanceModel.giveaway_id == giveaway_id) + .filter(GiveawayInstanceModel.user_id == user.id) + .first() + ) + if not giveaway_instance: + # Giveaway does not exist + giveaway_instance = GiveawayInstanceModel(user_id=user.id, giveaway_id=giveaway_id, num_entries=1) + db_session.add(giveaway_instance) + else: + # Giveaway exists + giveaway_instance.num_entries += 1 - giveaway_instance = GiveawayInstanceModel(user_id=user.id, giveaway_id=giveaway_id, numEntries=1) - db_session.add(giveaway_instance) db_session.commit() - return EnterGiveaway(success=True, giveaway_instance=giveaway_instance) + return EnterGiveaway(giveaway_instance=giveaway_instance) class Mutation(graphene.ObjectType): From 041fc883968c88173927f14e65441df1dfb82c0f Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:38:11 -0400 Subject: [PATCH 30/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/schema.py b/src/schema.py index e443ec1..112aa0a 100644 --- a/src/schema.py +++ b/src/schema.py @@ -209,6 +209,18 @@ def mutate(self, info, user_net_id, giveaway_id): return EnterGiveaway(giveaway_instance=giveaway_instance) +class CreateGiveaway(graphene.Mutation): + class Arguments: + name = graphene.String(required=True) + + giveaway = graphene.Field(Giveaway) + + def mutate(self, info, name): + giveaway = GiveawayModel(name=name) + db_session.add(giveaway) + db_session.commit() + return CreateGiveaway(giveaway=giveaway) + class Mutation(graphene.ObjectType): createUser = CreateUser.Field() enterGiveaway = EnterGiveaway.Field() From 30990efc6ae32f9ad80b3ee1d27568ac57b2cb6b Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:38:18 -0400 Subject: [PATCH 31/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/schema.py b/src/schema.py index 112aa0a..f1b1b92 100644 --- a/src/schema.py +++ b/src/schema.py @@ -222,8 +222,9 @@ def mutate(self, info, name): return CreateGiveaway(giveaway=giveaway) class Mutation(graphene.ObjectType): - createUser = CreateUser.Field() - enterGiveaway = EnterGiveaway.Field() + create_giveaway = CreateGiveaway.Field(description="Creates a new giveaway.") + create_user = CreateUser.Field(description="Creates a new user.") + enter_giveaway = EnterGiveaway.Field(description="Enters a user into a giveaway.") schema = graphene.Schema(query=Query, mutation=Mutation) From f37c897d9312ee265cafaeb0b9179f06ce1ba31e Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:38:28 -0400 Subject: [PATCH 32/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/schema.py b/src/schema.py index f1b1b92..f648384 100644 --- a/src/schema.py +++ b/src/schema.py @@ -119,11 +119,6 @@ class Giveaway(SQLAlchemyObjectType): class Meta: model = GiveawayModel - user_ids = graphene.List(lambda: User) - - def resolve_user_ids(self, info): - query = User.get_query(info=info).filter(UserModel.giveaway_id == self.id) - return query # MARK: - Giveaway From f767cf8eba6ed8b18940f16ff6dd00b0699ee390 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:41:41 -0400 Subject: [PATCH 33/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schema.py b/src/schema.py index f648384..db3c3cf 100644 --- a/src/schema.py +++ b/src/schema.py @@ -133,8 +133,8 @@ class Meta: class Query(graphene.ObjectType): - gyms = graphene.List(Gym) - users_by_giveawayid = graphene.List(User, id=graphene.Int()) + get_all_gyms = graphene.List(Gym, description="Get all gyms.") + get_users_by_giveaway_id = graphene.List(User, id=graphene.Int(), description="Get all users given a giveaway ID.") def resolve_gyms(self, info): query = Gym.get_query(info) From ab84b784f7219dbcfbbdfb1077ad9ca0ce63fae3 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:42:02 -0400 Subject: [PATCH 34/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema.py b/src/schema.py index db3c3cf..fe12f06 100644 --- a/src/schema.py +++ b/src/schema.py @@ -136,7 +136,7 @@ class Query(graphene.ObjectType): get_all_gyms = graphene.List(Gym, description="Get all gyms.") get_users_by_giveaway_id = graphene.List(User, id=graphene.Int(), description="Get all users given a giveaway ID.") - def resolve_gyms(self, info): + def resolve_get_all_gyms(self, info): query = Gym.get_query(info) return query.all() From 4f815607683051905d52feba881c4996b5a947d4 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:42:13 -0400 Subject: [PATCH 35/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/schema.py b/src/schema.py index fe12f06..3dc8cf3 100644 --- a/src/schema.py +++ b/src/schema.py @@ -141,9 +141,10 @@ def resolve_get_all_gyms(self, info): return query.all() -def resolve_users_by_giveaway_id(self, info, id): - query = User.get_query(info).filter(UserModel.giveaway_ids.any(GiveawayInstance.giveaway_id == id)) - return query.all() + def resolve_get_users_by_giveaway_id(self, info, id): + entries = GiveawayInstance.get_query(info).filter(GiveawayInstanceModel.giveaway_id == id).all() + users = [User.get_query(info).filter(UserModel.id == entry.user_id).first() for entry in entries] + return users # MARK: - Mutation From ebcf0ea5c4d7c6b57da8763b3a36bae661f6a981 Mon Sep 17 00:00:00 2001 From: sophiestrausberg <68089631+sophiestrausberg@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:42:24 -0400 Subject: [PATCH 36/52] Update src/schema.py Co-authored-by: Vin Bui <75594943+vinnie4k@users.noreply.github.com> --- src/schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema.py b/src/schema.py index 3dc8cf3..8845465 100644 --- a/src/schema.py +++ b/src/schema.py @@ -152,7 +152,7 @@ def resolve_get_users_by_giveaway_id(self, info, id): class CreateUser(graphene.Mutation): class Arguments: - net_id = graphene.String() + net_id = graphene.String(required=True) user = graphene.Field(User) From f8069529e1ea19dfe3f94535c61b6d33b0ddf41e Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Tue, 9 Apr 2024 23:00:04 -0400 Subject: [PATCH 37/52] add import statement --- schema.graphql | 18 ++++++++++-------- src/schema.py | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/schema.graphql b/schema.graphql index 07ca57c..4de92e6 100644 --- a/schema.graphql +++ b/schema.graphql @@ -34,12 +34,15 @@ enum CourtType { BADMINTON } +type CreateGiveaway { + giveaway: Giveaway +} + type CreateUser { user: User } type EnterGiveaway { - success: Boolean giveawayInstance: GiveawayInstance } @@ -82,7 +85,7 @@ enum FacilityType { type Giveaway { id: ID! name: String! - userIds: [User] + users: [User] } type GiveawayInstance { @@ -90,8 +93,6 @@ type GiveawayInstance { userId: Int! giveawayId: Int! numEntries: Int! - users: Giveaway - giveaways: User } type Gym { @@ -107,7 +108,8 @@ type Gym { } type Mutation { - createUser(netId: String): CreateUser + createGiveaway(name: String!): CreateGiveaway + createUser(netId: String!): CreateUser enterGiveaway(giveawayId: Int!, userNetId: String!): EnterGiveaway } @@ -124,12 +126,12 @@ type OpenHours { } type Query { - gyms: [Gym] - usersByGiveawayid(id: Int): [User] + getAllGyms: [Gym] + getUsersByGiveawayId(id: Int): [User] } type User { id: ID! netId: String! - giveawayIds: [GiveawayInstance] + giveaways: [Giveaway] } diff --git a/src/schema.py b/src/schema.py index 8845465..3b2735a 100644 --- a/src/schema.py +++ b/src/schema.py @@ -1,5 +1,6 @@ import graphene from graphene_sqlalchemy import SQLAlchemyObjectType +from graphql import GraphQLError from src.models.capacity import Capacity as CapacityModel from src.models.facility import Facility as FacilityModel from src.models.gym import Gym as GymModel From 9459149d6392608281a789b3dea46fbe474a30b4 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 10 Apr 2024 17:48:36 -0400 Subject: [PATCH 38/52] Change Gear model to Price model --- schema.graphql | 63 +++++++++++++++++++----------------------- src/models/activity.py | 56 ++++++++++++++++++++++++++----------- src/schema.py | 14 +++++----- 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/schema.graphql b/schema.graphql index aa98af9..70b5ec3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -8,12 +8,12 @@ enum AccessibilityType { type Activity { id: ID! - name: String! facilityId: Int! gymId: Int! - oneTimePrice: Boolean! + hasMembership: Boolean! + name: String! needsReserve: Boolean! - gear: [Gear] + pricing: [Price] } type Amenity { @@ -61,34 +61,16 @@ enum EquipmentType { MISCELLANEOUS PLATE_LOADED } - description: String! - gyms: [ClassInstance] -} - -type ClassInstance { - id: ID! - gymId: Int - classId: Int! - location: String! - instructor: String! - isCanceled: Boolean! - isVirtual: Boolean! - startTime: DateTime - endTime: DateTime - class_: Class - gym: Gym -} - -scalar DateTime type Facility { id: ID! facilityType: FacilityType! gymId: Int! name: String! + activities: [Activity] capacity: Capacity - hours: [OpenHours] equipment: [Equipment] + hours: [OpenHours] } enum FacilityType { @@ -98,13 +80,6 @@ enum FacilityType { COURT } -type Gear { - id: ID! - name: String! - price: Float! - activityId: Int! -} - type Gym { id: ID! address: String! @@ -112,18 +87,36 @@ type Gym { latitude: Float! longitude: Float! name: String! + activities: [Activity] amenities: [Amenity] facilities: [Facility] hours: [OpenHours] - activities: [Activity] } type OpenHours { id: ID! - facilityId: Int! - day: Int! - startTime: String - endTime: String + courtType: CourtType + endTime: Int! + facilityId: Int + gymId: Int + isShallow: Boolean + isSpecial: Boolean! + isWomen: Boolean + startTime: Int! +} + +type Price { + id: ID! + activityId: Int! + name: String! + cost: Float! + rate: String + type: PriceType! +} + +enum PriceType { + RATE + GEAR } type Query { diff --git a/src/models/activity.py b/src/models/activity.py index 179e8ea..c5e7f08 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -1,8 +1,18 @@ -from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float +import enum +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float, Enum from sqlalchemy.orm import relationship from src.database import Base +class PriceType(enum.Enum): + """ + An enumeration representing a price type. + """ + + rate = 0 + gear = 1 + + class Activity(Base): """ Activity provided by a recreation center. @@ -10,30 +20,30 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `facility_id` The ID of the facility this activity belongs to. - - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. + - `has_membership True if this activity is available with memberships. - `name` The name of this activity. - `needs_reserve` True if this activity requires group reservation. - - `one_time_price` The one-time price of this activity. + - `pricing` (nullable) This activity's pricing. """ __tablename__ = "activity" id = Column(Integer, primary_key=True) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) - gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) + has_membership = Column(Boolean, nullable=False) name = Column(String, nullable=False) needs_reserve = Column(Boolean, nullable=False) - one_time_price = Column(Boolean, nullable=False) + pricing = relationship("Price", cascade="delete") def __init__(self, **kwargs): self.id = kwargs.get("id") self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") + self.has_membership = kwargs.get("has_membership") self.name = kwargs.get("name") self.needs_reserve = kwargs.get("needs_reserve") - self.one_time_price = kwargs.get("one_time_price") def serialize(self): return { @@ -41,21 +51,24 @@ def serialize(self): "facility_id": self.facility_id, "gear": self.gear, "gym_id": self.gym_id, + "has_membership": self.has_membership, "name": self.name, "needs_reserve": self.needs_reserve, - "one_time_price": self.one_time_price, + "pricing": self.pricing, } -class Gear(Base): +class Price(Base): """ - Gear required for an activity + The price of a gear or pricing option. Attributes: - - `id` The ID of this gear. - - `activity_id` The ID of the activity this gear belongs to. - - `name` The name of this gear. - - `price` The price of this gear. + - `id` The ID of this price. + - `activity_id` The ID of the activity this price belongs to. + - `name` The name associated with this price. + - `cost` The cost of this price. + - `rate` (nullable) The pricing rate of this price. + = `type` The type of this price. """ __tablename__ = "gear" @@ -63,13 +76,24 @@ class Gear(Base): id = Column(Integer, primary_key=True) activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) name = Column(String, nullable=False) - price = Column(Float, nullable=-False) + cost = Column(Float, nullable=-False) + rate = Column(String) + type = Column(Enum(PriceType), nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") self.activity_id = kwargs.get("activity_id") self.name = kwargs.get("name") - self.price = kwargs.get("price") + self.cost = kwargs.get("price") + self.rate = kwargs.get("rate") + self.type = kwargs.get("type") def serialize(self): - return {"id": self.id, "name": self.name, "price": self.price} + return { + "id": self.id, + "activity_id": self.activity_id, + "name": self.name, + "cost": self.cost, + "rate": self.rate, + "type": self.type, + } diff --git a/src/schema.py b/src/schema.py index 695ecb4..bd2c6d6 100644 --- a/src/schema.py +++ b/src/schema.py @@ -7,7 +7,7 @@ from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel -from src.models.activity import Activity as ActivityModel, Gear as GearModel +from src.models.activity import Activity as ActivityModel, Price as PriceModel # MARK: - Gym @@ -104,12 +104,12 @@ class Meta: model = CapacityModel -# MARK: - Gear +# MARK: - Price -class Gear(SQLAlchemyObjectType): +class Price(SQLAlchemyObjectType): class Meta: - model = GearModel + model = PriceModel # MARK: - Activity @@ -119,10 +119,10 @@ class Activity(SQLAlchemyObjectType): class Meta: model = ActivityModel - gear = graphene.List(lambda: Gear) + pricing = graphene.List(lambda: Price) - def resolve_gear(self, info): - query = Amenity.get_query(info=info).filter(GearModel.activity_id == self.id) + def resolve_pricing(self, info): + query = Amenity.get_query(info=info).filter(PriceModel.activity_id == self.id) return query From 9c17890d10d4df6077775e8b2e3563e8fb75c723 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:46:19 -0400 Subject: [PATCH 39/52] Delete .python-version --- .python-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .python-version diff --git a/.python-version b/.python-version deleted file mode 100644 index 43077b2..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.18 From adb9929314808f32949391fb5d8a82e33a2fb961 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:48:15 -0400 Subject: [PATCH 40/52] Update activity.py --- src/models/activity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/activity.py b/src/models/activity.py index fb52f77..0788486 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -20,7 +20,7 @@ class Activity(Base): id = Column(Integer, primary_key=True) name = Column(String, nullable=False) - facility_id = Column(Integer, nullable=False) + facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) one_time_price = Column(Boolean, nullable=False) needs_reserve = Column(Boolean, nullable=False) From 73ca23a5e9f304cf9c90bed235a63cbf2f3a0560 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:50:00 -0400 Subject: [PATCH 41/52] Update activity.py --- src/models/activity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/activity.py b/src/models/activity.py index 0788486..b327c69 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -9,7 +9,7 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `name` The name of this activity. - - `facility_id` The ID of the facility this acticity belongs to. + - `facility_id` The ID of the facility this activity belongs to. - `gym_id` The ID of the gym this activity belongs to. - `one_time_price` The one-time price of this activity. - `needs_reserve` True if this activity requires group reservation. @@ -32,7 +32,7 @@ def __init__(self, **kwargs): self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") self.one_time_price = kwargs.get("one_time_price") - self.needs_reserve = kwargs.get("needs_reserve")\ + self.needs_reserve = kwargs.get("needs_reserve") def serialize(self): return { @@ -54,7 +54,7 @@ class Gear(Base): - `id` The ID of this gear - `name` The name of this gear - `price` The price of this gear - - `activity_id` The ID of the activity this gear belonds to + - `activity_id` The ID of the activity this gear belongs to """ __tablename__ = "gear" From 16c3404de517ff5fb6d1200a48f587f378eee605 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:58:37 -0400 Subject: [PATCH 42/52] Added activities field to Facility --- src/models/facility.py | 3 +++ src/schema.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/models/facility.py b/src/models/facility.py index 5e1686d..1269c76 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -29,6 +29,8 @@ class Facility(Base): - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. + - `equipment` (nullable) The equipment of this facility. + - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" @@ -40,6 +42,7 @@ class Facility(Base): hours = relationship("OpenHours") name = Column(String, nullable=False) equipment = relationship("Equipment") + activities = relationship("Activity") def __init__(self, **kwargs): self.id = kwargs.get("id") diff --git a/src/schema.py b/src/schema.py index 66511c2..18498d7 100644 --- a/src/schema.py +++ b/src/schema.py @@ -48,6 +48,7 @@ class Meta: capacity = graphene.Field(lambda: Capacity) hours = graphene.List(lambda: OpenHours) equipment = graphene.List(lambda: Equipment) + activities = graphene.List(lambda: Activity) def resolve_capacity(self, info): query = ( @@ -65,6 +66,10 @@ def resolve_hours(self, info): def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query + + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) + return query From 631c219cd99a29e9787e42fb7f87e4fe258c1149 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Mon, 25 Mar 2024 11:21:39 -0400 Subject: [PATCH 43/52] Reformatted code --- src/models/activity.py | 47 ++++++++++++++++++++---------------------- src/models/facility.py | 8 +++---- src/models/gym.py | 4 ++-- src/schema.py | 12 +++++------ 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/models/activity.py b/src/models/activity.py index b327c69..179e8ea 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -2,77 +2,74 @@ from sqlalchemy.orm import relationship from src.database import Base + class Activity(Base): """ - Activity provided by a recreation center + Activity provided by a recreation center. Attributes: - `id` The ID of this activity. - - `name` The name of this activity. - `facility_id` The ID of the facility this activity belongs to. + - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. - - `one_time_price` The one-time price of this activity. + - `name` The name of this activity. - `needs_reserve` True if this activity requires group reservation. - - `gear` (nullable) This activity's gear. + - `one_time_price` The one-time price of this activity. """ __tablename__ = "activity" id = Column(Integer, primary_key=True) - name = Column(String, nullable=False) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) + gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) - one_time_price = Column(Boolean, nullable=False) + name = Column(String, nullable=False) needs_reserve = Column(Boolean, nullable=False) - gear = relationship("Gear", cascade="delete") + one_time_price = Column(Boolean, nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") - self.name = kwargs.get("name") self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") - self.one_time_price = kwargs.get("one_time_price") + self.name = kwargs.get("name") self.needs_reserve = kwargs.get("needs_reserve") + self.one_time_price = kwargs.get("one_time_price") def serialize(self): return { "id": self.id, - "name": self.name, "facility_id": self.facility_id, + "gear": self.gear, "gym_id": self.gym_id, - "one_time_price": self.one_time_price, + "name": self.name, "needs_reserve": self.needs_reserve, - "gear": self.gear + "one_time_price": self.one_time_price, } - - + + class Gear(Base): """ Gear required for an activity Attributes: - - `id` The ID of this gear - - `name` The name of this gear - - `price` The price of this gear - - `activity_id` The ID of the activity this gear belongs to + - `id` The ID of this gear. + - `activity_id` The ID of the activity this gear belongs to. + - `name` The name of this gear. + - `price` The price of this gear. """ __tablename__ = "gear" id = Column(Integer, primary_key=True) + activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) name = Column(String, nullable=False) price = Column(Float, nullable=-False) - activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") + self.activity_id = kwargs.get("activity_id") self.name = kwargs.get("name") self.price = kwargs.get("price") - self.activity_id = kwargs.get("activity_id") def serialize(self): - return { - "id": self.id, - "name": self.name, - "price": self.price - } + return {"id": self.id, "name": self.name, "price": self.price} diff --git a/src/models/facility.py b/src/models/facility.py index 1269c76..a112d61 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -24,25 +24,25 @@ class Facility(Base): Attributes: - `id` The ID of this facility. + - `activities` (nullable) The activities of this facility. - `capacity` (nullable) The capacity of this facility. + - `equipment` (nullable) The equipment of this facility. - `facility_type` The type of this facility (FITNESS, POOL, BOWLING, COURT). - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. - - `equipment` (nullable) The equipment of this facility. - - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" id = Column(Integer, primary_key=True) + activities = relationship("Activity") capacity = relationship("Capacity") + equipment = relationship("Equipment") facility_type = Column(Enum(FacilityType), nullable=False) gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) hours = relationship("OpenHours") name = Column(String, nullable=False) - equipment = relationship("Equipment") - activities = relationship("Activity") def __init__(self, **kwargs): self.id = kwargs.get("id") diff --git a/src/models/gym.py b/src/models/gym.py index b5ab202..4e6f752 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -10,11 +10,11 @@ class Gym(Base): Attributes: - `id` The ID of this gym (building). + - `activities` (nullable) The gym's activities. - `address` The address of the buildling. - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. - - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -24,11 +24,11 @@ class Gym(Base): __tablename__ = "gym" id = Column(Integer, primary_key=True) + activities = relationship("Activity") address = Column(String, nullable=False) amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") - activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index 18498d7..695ecb4 100644 --- a/src/schema.py +++ b/src/schema.py @@ -32,7 +32,7 @@ def resolve_facilities(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.gym_id == self.id) return query - + def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.gym_id == self.id) return query @@ -62,17 +62,16 @@ def resolve_capacity(self, info): def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.facility_id == self.id) return query - + def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query - + def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) return query - # MARK: - Open Hours @@ -80,6 +79,7 @@ class OpenHours(SQLAlchemyObjectType): class Meta: model = OpenHoursModel + # MARK: - Equipment @@ -113,7 +113,7 @@ class Meta: # MARK: - Activity - + class Activity(SQLAlchemyObjectType): class Meta: @@ -136,7 +136,7 @@ class Query(graphene.ObjectType): def resolve_gyms(self, info): query = Gym.get_query(info) return query.all() - + def resolve_activities(self, info): query = Activity.get_query(info) return query.all() From 0a0cc7d3969b41284d594c2e77f654b15e89c3a2 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 10 Apr 2024 17:48:36 -0400 Subject: [PATCH 44/52] Change Gear model to Price model --- schema.graphql | 63 +++++++++++++++++++----------------------- src/models/activity.py | 56 ++++++++++++++++++++++++++----------- src/schema.py | 14 +++++----- 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/schema.graphql b/schema.graphql index aa98af9..70b5ec3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -8,12 +8,12 @@ enum AccessibilityType { type Activity { id: ID! - name: String! facilityId: Int! gymId: Int! - oneTimePrice: Boolean! + hasMembership: Boolean! + name: String! needsReserve: Boolean! - gear: [Gear] + pricing: [Price] } type Amenity { @@ -61,34 +61,16 @@ enum EquipmentType { MISCELLANEOUS PLATE_LOADED } - description: String! - gyms: [ClassInstance] -} - -type ClassInstance { - id: ID! - gymId: Int - classId: Int! - location: String! - instructor: String! - isCanceled: Boolean! - isVirtual: Boolean! - startTime: DateTime - endTime: DateTime - class_: Class - gym: Gym -} - -scalar DateTime type Facility { id: ID! facilityType: FacilityType! gymId: Int! name: String! + activities: [Activity] capacity: Capacity - hours: [OpenHours] equipment: [Equipment] + hours: [OpenHours] } enum FacilityType { @@ -98,13 +80,6 @@ enum FacilityType { COURT } -type Gear { - id: ID! - name: String! - price: Float! - activityId: Int! -} - type Gym { id: ID! address: String! @@ -112,18 +87,36 @@ type Gym { latitude: Float! longitude: Float! name: String! + activities: [Activity] amenities: [Amenity] facilities: [Facility] hours: [OpenHours] - activities: [Activity] } type OpenHours { id: ID! - facilityId: Int! - day: Int! - startTime: String - endTime: String + courtType: CourtType + endTime: Int! + facilityId: Int + gymId: Int + isShallow: Boolean + isSpecial: Boolean! + isWomen: Boolean + startTime: Int! +} + +type Price { + id: ID! + activityId: Int! + name: String! + cost: Float! + rate: String + type: PriceType! +} + +enum PriceType { + RATE + GEAR } type Query { diff --git a/src/models/activity.py b/src/models/activity.py index 179e8ea..c5e7f08 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -1,8 +1,18 @@ -from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float +import enum +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float, Enum from sqlalchemy.orm import relationship from src.database import Base +class PriceType(enum.Enum): + """ + An enumeration representing a price type. + """ + + rate = 0 + gear = 1 + + class Activity(Base): """ Activity provided by a recreation center. @@ -10,30 +20,30 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `facility_id` The ID of the facility this activity belongs to. - - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. + - `has_membership True if this activity is available with memberships. - `name` The name of this activity. - `needs_reserve` True if this activity requires group reservation. - - `one_time_price` The one-time price of this activity. + - `pricing` (nullable) This activity's pricing. """ __tablename__ = "activity" id = Column(Integer, primary_key=True) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) - gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) + has_membership = Column(Boolean, nullable=False) name = Column(String, nullable=False) needs_reserve = Column(Boolean, nullable=False) - one_time_price = Column(Boolean, nullable=False) + pricing = relationship("Price", cascade="delete") def __init__(self, **kwargs): self.id = kwargs.get("id") self.facility_id = kwargs.get("facility_id") self.gym_id = kwargs.get("gym_id") + self.has_membership = kwargs.get("has_membership") self.name = kwargs.get("name") self.needs_reserve = kwargs.get("needs_reserve") - self.one_time_price = kwargs.get("one_time_price") def serialize(self): return { @@ -41,21 +51,24 @@ def serialize(self): "facility_id": self.facility_id, "gear": self.gear, "gym_id": self.gym_id, + "has_membership": self.has_membership, "name": self.name, "needs_reserve": self.needs_reserve, - "one_time_price": self.one_time_price, + "pricing": self.pricing, } -class Gear(Base): +class Price(Base): """ - Gear required for an activity + The price of a gear or pricing option. Attributes: - - `id` The ID of this gear. - - `activity_id` The ID of the activity this gear belongs to. - - `name` The name of this gear. - - `price` The price of this gear. + - `id` The ID of this price. + - `activity_id` The ID of the activity this price belongs to. + - `name` The name associated with this price. + - `cost` The cost of this price. + - `rate` (nullable) The pricing rate of this price. + = `type` The type of this price. """ __tablename__ = "gear" @@ -63,13 +76,24 @@ class Gear(Base): id = Column(Integer, primary_key=True) activity_id = Column(Integer, ForeignKey("activity.id"), nullable=False) name = Column(String, nullable=False) - price = Column(Float, nullable=-False) + cost = Column(Float, nullable=-False) + rate = Column(String) + type = Column(Enum(PriceType), nullable=False) def __init__(self, **kwargs): self.id = kwargs.get("id") self.activity_id = kwargs.get("activity_id") self.name = kwargs.get("name") - self.price = kwargs.get("price") + self.cost = kwargs.get("price") + self.rate = kwargs.get("rate") + self.type = kwargs.get("type") def serialize(self): - return {"id": self.id, "name": self.name, "price": self.price} + return { + "id": self.id, + "activity_id": self.activity_id, + "name": self.name, + "cost": self.cost, + "rate": self.rate, + "type": self.type, + } diff --git a/src/schema.py b/src/schema.py index 695ecb4..bd2c6d6 100644 --- a/src/schema.py +++ b/src/schema.py @@ -7,7 +7,7 @@ from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel -from src.models.activity import Activity as ActivityModel, Gear as GearModel +from src.models.activity import Activity as ActivityModel, Price as PriceModel # MARK: - Gym @@ -104,12 +104,12 @@ class Meta: model = CapacityModel -# MARK: - Gear +# MARK: - Price -class Gear(SQLAlchemyObjectType): +class Price(SQLAlchemyObjectType): class Meta: - model = GearModel + model = PriceModel # MARK: - Activity @@ -119,10 +119,10 @@ class Activity(SQLAlchemyObjectType): class Meta: model = ActivityModel - gear = graphene.List(lambda: Gear) + pricing = graphene.List(lambda: Price) - def resolve_gear(self, info): - query = Amenity.get_query(info=info).filter(GearModel.activity_id == self.id) + def resolve_pricing(self, info): + query = Amenity.get_query(info=info).filter(PriceModel.activity_id == self.id) return query From 08bc9e91ba1f3fae44bba06158b81ab483a8f3cc Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 20 Mar 2024 17:28:33 -0400 Subject: [PATCH 45/52] Created Activities model --- .python-version | 1 + schema.graphql | 8 ++++++++ src/models/gym.py | 2 ++ 3 files changed, 11 insertions(+) create mode 100644 .python-version diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..43077b2 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9.18 diff --git a/schema.graphql b/schema.graphql index 70b5ec3..5598d63 100644 --- a/schema.graphql +++ b/schema.graphql @@ -80,6 +80,13 @@ enum FacilityType { COURT } +type Gear { + id: ID! + name: String! + price: Float! + activityId: Int! +} + type Gym { id: ID! address: String! @@ -91,6 +98,7 @@ type Gym { amenities: [Amenity] facilities: [Facility] hours: [OpenHours] + activities: [Activity] } type OpenHours { diff --git a/src/models/gym.py b/src/models/gym.py index 4e6f752..5cec0b9 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -15,6 +15,7 @@ class Gym(Base): - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. + - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -29,6 +30,7 @@ class Gym(Base): amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") + activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) From a0d0de96e2881c2ccb3a1a3bf32178a05bf88ab5 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:46:19 -0400 Subject: [PATCH 46/52] Delete .python-version --- .python-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .python-version diff --git a/.python-version b/.python-version deleted file mode 100644 index 43077b2..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.18 From e46d4f048129a34d8fa74222bbc92548692927b3 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Sat, 23 Mar 2024 11:58:37 -0400 Subject: [PATCH 47/52] Added activities field to Facility --- src/models/facility.py | 2 ++ src/schema.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/models/facility.py b/src/models/facility.py index a112d61..ac314cd 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -31,6 +31,8 @@ class Facility(Base): - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. + - `equipment` (nullable) The equipment of this facility. + - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" diff --git a/src/schema.py b/src/schema.py index bd2c6d6..4897dc0 100644 --- a/src/schema.py +++ b/src/schema.py @@ -66,6 +66,10 @@ def resolve_hours(self, info): def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query + + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) + return query def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) From 719747603b93d8b2a3a6def58e3787f7506e1230 Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Mon, 25 Mar 2024 11:21:39 -0400 Subject: [PATCH 48/52] Reformatted code --- src/models/activity.py | 2 ++ src/models/facility.py | 2 -- src/models/gym.py | 2 -- src/schema.py | 3 +-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/models/activity.py b/src/models/activity.py index c5e7f08..6d0f06b 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -20,6 +20,7 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `facility_id` The ID of the facility this activity belongs to. + - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. - `has_membership True if this activity is available with memberships. - `name` The name of this activity. @@ -31,6 +32,7 @@ class Activity(Base): id = Column(Integer, primary_key=True) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) + gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) has_membership = Column(Boolean, nullable=False) name = Column(String, nullable=False) diff --git a/src/models/facility.py b/src/models/facility.py index ac314cd..a112d61 100644 --- a/src/models/facility.py +++ b/src/models/facility.py @@ -31,8 +31,6 @@ class Facility(Base): - `gym_id` The ID of the gym this facility belongs to. - `hours` (nullable) The open hours of this facility. - `name` The name of this facility. - - `equipment` (nullable) The equipment of this facility. - - `activities` (nullable) The activities of this facility """ __tablename__ = "facility" diff --git a/src/models/gym.py b/src/models/gym.py index 5cec0b9..4e6f752 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -15,7 +15,6 @@ class Gym(Base): - `amenities` (nullable) This gym's amenities. - `facilities` (nullable) This gym's facilities. - `hours` (nullable) The building hours. - - `activities` (nullable) The gym's activities. - `image_url` The URL of this gym's image. - `latitude` The latitude coordinate of this gym. - `longitude` The longitude coordinate of this gym. @@ -30,7 +29,6 @@ class Gym(Base): amenities = relationship("Amenity") facilities = relationship("Facility") hours = relationship("OpenHours") - activities = relationship("Activity") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/schema.py b/src/schema.py index 4897dc0..8c8cd9e 100644 --- a/src/schema.py +++ b/src/schema.py @@ -66,7 +66,7 @@ def resolve_hours(self, info): def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query - + def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) return query @@ -75,7 +75,6 @@ def resolve_activities(self, info): query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) return query - # MARK: - Open Hours From 76e339a96265e688b715dcc5dfa43689077e060c Mon Sep 17 00:00:00 2001 From: Daisy Chang Date: Wed, 10 Apr 2024 17:48:36 -0400 Subject: [PATCH 49/52] Change Gear model to Price model --- schema.graphql | 8 -------- src/models/activity.py | 2 -- 2 files changed, 10 deletions(-) diff --git a/schema.graphql b/schema.graphql index 5598d63..70b5ec3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -80,13 +80,6 @@ enum FacilityType { COURT } -type Gear { - id: ID! - name: String! - price: Float! - activityId: Int! -} - type Gym { id: ID! address: String! @@ -98,7 +91,6 @@ type Gym { amenities: [Amenity] facilities: [Facility] hours: [OpenHours] - activities: [Activity] } type OpenHours { diff --git a/src/models/activity.py b/src/models/activity.py index 6d0f06b..c5e7f08 100644 --- a/src/models/activity.py +++ b/src/models/activity.py @@ -20,7 +20,6 @@ class Activity(Base): Attributes: - `id` The ID of this activity. - `facility_id` The ID of the facility this activity belongs to. - - `gear` (nullable) This activity's gear. - `gym_id` The ID of the gym this activity belongs to. - `has_membership True if this activity is available with memberships. - `name` The name of this activity. @@ -32,7 +31,6 @@ class Activity(Base): id = Column(Integer, primary_key=True) facility_id = Column(Integer, ForeignKey("facility.id"), nullable=False) - gear = relationship("Gear", cascade="delete") gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) has_membership = Column(Boolean, nullable=False) name = Column(String, nullable=False) From 5bf21824426535765d8b0bf4b47060b36dba0cd6 Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Fri, 12 Apr 2024 01:22:23 -0400 Subject: [PATCH 50/52] resolve merge conflicts --- schema.graphql | 28 +++++++++++++++++++++++++++- src/schema.py | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/schema.graphql b/schema.graphql index 4de92e6..9eeae6c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -7,6 +7,16 @@ enum AccessibilityType { WHEELCHAIR } +type Activity { + id: ID! + facilityId: Int! + gymId: Int! + hasMembership: Boolean! + name: String! + needsReserve: Boolean! + pricing: [Price] +} + type Amenity { id: ID! gymId: Int! @@ -70,9 +80,10 @@ type Facility { facilityType: FacilityType! gymId: Int! name: String! + activities: [Activity] capacity: Capacity - hours: [OpenHours] equipment: [Equipment] + hours: [OpenHours] } enum FacilityType { @@ -102,6 +113,7 @@ type Gym { latitude: Float! longitude: Float! name: String! + activities: [Activity] amenities: [Amenity] facilities: [Facility] hours: [OpenHours] @@ -125,6 +137,20 @@ type OpenHours { startTime: Int! } +type Price { + id: ID! + activityId: Int! + name: String! + cost: Float! + rate: String + type: PriceType! +} + +enum PriceType { + RATE + GEAR +} + type Query { getAllGyms: [Gym] getUsersByGiveawayId(id: Int): [User] diff --git a/src/schema.py b/src/schema.py index 3b2735a..68e7a5b 100644 --- a/src/schema.py +++ b/src/schema.py @@ -1,12 +1,14 @@ import graphene +from graphene import Enum from graphene_sqlalchemy import SQLAlchemyObjectType from graphql import GraphQLError from src.models.capacity import Capacity as CapacityModel -from src.models.facility import Facility as FacilityModel +from src.models.facility import Facility as FacilityModel, FacilityType from src.models.gym import Gym as GymModel from src.models.openhours import OpenHours as OpenHoursModel from src.models.amenity import Amenity as AmenityModel from src.models.equipment import Equipment as EquipmentModel +from src.models.activity import Activity as ActivityModel, Price as PriceModel from src.models.classes import Class as ClassModel from src.models.classes import ClassInstance as ClassInstanceModel from src.models.user import User as UserModel @@ -25,6 +27,7 @@ class Meta: amenities = graphene.List(lambda: Amenity) facilities = graphene.List(lambda: Facility) hours = graphene.List(lambda: OpenHours) + activities = graphene.List(lambda: Activity) def resolve_amenities(self, info): query = Amenity.get_query(info=info).filter(AmenityModel.gym_id == self.id) @@ -38,6 +41,10 @@ def resolve_hours(self, info): query = OpenHours.get_query(info=info).filter(OpenHoursModel.gym_id == self.id) return query + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.gym_id == self.id) + return query + # MARK: - Facility @@ -49,6 +56,7 @@ class Meta: capacity = graphene.Field(lambda: Capacity) hours = graphene.List(lambda: OpenHours) equipment = graphene.List(lambda: Equipment) + activities = graphene.List(lambda: Activity) def resolve_capacity(self, info): query = ( @@ -67,6 +75,10 @@ def resolve_equipment(self, info): query = Equipment.get_query(info=info).filter(EquipmentModel.facility_id == self.id) return query + def resolve_activities(self, info): + query = Activity.get_query(info=info).filter(ActivityModel.facility_id == self.id) + return query + # MARK: - Open Hours @@ -100,6 +112,28 @@ class Meta: model = CapacityModel +# MARK: - Price + + +class Price(SQLAlchemyObjectType): + class Meta: + model = PriceModel + + +# MARK: - Activity + + +class Activity(SQLAlchemyObjectType): + class Meta: + model = ActivityModel + + pricing = graphene.List(lambda: Price) + + def resolve_pricing(self, info): + query = Amenity.get_query(info=info).filter(PriceModel.activity_id == self.id) + return query + + # MARK: - User @@ -121,7 +155,6 @@ class Meta: model = GiveawayModel - # MARK: - Giveaway @@ -141,6 +174,9 @@ def resolve_get_all_gyms(self, info): query = Gym.get_query(info) return query.all() + def resolve_activities(self, info): + query = Activity.get_query(info) + return query.all() def resolve_get_users_by_giveaway_id(self, info, id): entries = GiveawayInstance.get_query(info).filter(GiveawayInstanceModel.giveaway_id == id).all() @@ -218,6 +254,7 @@ def mutate(self, info, name): db_session.commit() return CreateGiveaway(giveaway=giveaway) + class Mutation(graphene.ObjectType): create_giveaway = CreateGiveaway.Field(description="Creates a new giveaway.") create_user = CreateUser.Field(description="Creates a new user.") From cc037888f44dad7618d12e71610ec500b4fdaf53 Mon Sep 17 00:00:00 2001 From: Sophie Strausberg Date: Fri, 12 Apr 2024 01:32:38 -0400 Subject: [PATCH 51/52] resolve merge conflicts --- schema.graphql | 1 + src/schema.py | 1 + 2 files changed, 2 insertions(+) diff --git a/schema.graphql b/schema.graphql index 9eeae6c..9fbce07 100644 --- a/schema.graphql +++ b/schema.graphql @@ -154,6 +154,7 @@ enum PriceType { type Query { getAllGyms: [Gym] getUsersByGiveawayId(id: Int): [User] + activities: [Activity] } type User { diff --git a/src/schema.py b/src/schema.py index 68e7a5b..3bc520a 100644 --- a/src/schema.py +++ b/src/schema.py @@ -169,6 +169,7 @@ class Meta: class Query(graphene.ObjectType): get_all_gyms = graphene.List(Gym, description="Get all gyms.") get_users_by_giveaway_id = graphene.List(User, id=graphene.Int(), description="Get all users given a giveaway ID.") + activities = graphene.List(Activity) def resolve_get_all_gyms(self, info): query = Gym.get_query(info) From e6fb3eb32a70adaa7fa0614f77127d4b736680fa Mon Sep 17 00:00:00 2001 From: Vin Bui Date: Mon, 15 Apr 2024 16:56:57 -0400 Subject: [PATCH 52/52] Fix issue where all tables were cleared --- app.py | 5 +++++ src/database.py | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app.py b/app.py index 6f15f05..0790170 100644 --- a/app.py +++ b/app.py @@ -13,6 +13,7 @@ from src.scrapers.equipment_scraper import scrape_equipment from src.scrapers.class_scraper import fetch_classes from src.utils.utils import create_gym_table +from src.models.openhours import OpenHours app = Flask(__name__) @@ -46,6 +47,9 @@ def shutdown_session(exception=None): def scrape_hours(): logging.info("Scraping hours from sheets...") + # Clear hours + db_session.query(OpenHours).delete() + fetch_reg_facility() fetch_reg_building() fetch_sp_facility() @@ -59,6 +63,7 @@ def scrape_capacities(): fetch_capacities() + # Scrape classes every hour @scheduler.task("interval", id="scrape_classes", seconds=3600) def scrape_classes(): diff --git a/src/database.py b/src/database.py index 73e4045..25cb416 100644 --- a/src/database.py +++ b/src/database.py @@ -3,8 +3,6 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker -# engine = create_engine("sqlite:///database.sqlite3") - db_user = os.environ.get("DB_USERNAME") db_password = os.environ.get("DB_PASSWORD") db_name = os.environ.get("DB_NAME") @@ -12,7 +10,7 @@ db_port = os.environ.get("DB_PORT") db_url = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}" -engine = create_engine(db_url) # Soley for temp dev testing +engine = create_engine(db_url) db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() @@ -23,8 +21,8 @@ def init_db(): """ Initialize database for Uplift. """ - # Clear all tables and then repopulate logging.info("Initializing database") - Base.metadata.drop_all(bind=engine) + + # Load initial data Base.metadata.create_all(bind=engine) db_session.commit()