From 0164637384202bf446ee03291602c370be37fa84 Mon Sep 17 00:00:00 2001 From: Joshua Dirga Date: Wed, 9 Oct 2024 23:22:09 -0400 Subject: [PATCH 1/3] Implemented reports model and created reports mutation --- requirements.txt | 4 ++-- schema.graphql | 26 ++++++++++++++++++++++++ src/models/gym.py | 1 + src/models/report.py | 37 +++++++++++++++++++++++++++++++++++ src/models/user.py | 1 + src/schema.py | 35 +++++++++++++++++++++++++++++++++ src/scrapers/class_scraper.py | 2 +- 7 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/models/report.py diff --git a/requirements.txt b/requirements.txt index 55c818a..4b7f4d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,12 +40,12 @@ itsdangerous==2.0 jedi==0.18.2 Jinja2==3.0 lxml==4.9.2 -Mako==1.0.9 +Mako==1.2.0 MarkupSafe==2.1.1 marshmallow==3.0.0rc4 marshmallow-sqlalchemy==0.16.2 nodeenv==1.8.0 -pandas==2.1.4 +pandas==1.3.5 parso==0.8.3 platformdirs==3.10.0 pre-commit==1.18.3 diff --git a/schema.graphql b/schema.graphql index 07c4a26..7a657f4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -69,6 +69,10 @@ type CreateGiveaway { giveaway: Giveaway } +type CreateReport { + report: Report +} + type CreateUser { user: User } @@ -141,12 +145,14 @@ type Gym { facilities: [Facility] hours: [OpenHours] classes: [ClassInstance] + reports: [Report] } type Mutation { createGiveaway(name: String!): CreateGiveaway createUser(instagram: String, netId: String!): CreateUser enterGiveaway(giveawayId: Int!, userNetId: String!): EnterGiveaway + createReport(createdAt: DateTime!, description: String!, gymId: Int!, issue: String!, userId: Int!): CreateReport } type OpenHours { @@ -181,9 +187,29 @@ type Query { activities: [Activity] } +type Report { + id: ID! + userId: Int! + issue: ReportType! + description: String! + createdAt: DateTime! + gymId: Int! + gym: Gym + user: User +} + +enum ReportType { + INACCURATE_EQUIPMENT + INCORRECT_HOURS + INACCURATE_DESCRIPTION + WAIT_TIMES_NOT_UPDATED + OTHER +} + type User { id: ID! instagram: String netId: String! giveaways: [Giveaway] + reports: [Report] } diff --git a/src/models/gym.py b/src/models/gym.py index 8e85bfd..a83aa41 100644 --- a/src/models/gym.py +++ b/src/models/gym.py @@ -29,6 +29,7 @@ class Gym(Base): facilities = relationship("Facility") hours = relationship("OpenHours") classes = relationship("ClassInstance", back_populates="gym") + reports = relationship("Report", back_populates="gym") image_url = Column(String, nullable=True) latitude = Column(Float, nullable=False) longitude = Column(Float, nullable=False) diff --git a/src/models/report.py b/src/models/report.py new file mode 100644 index 0000000..02dd32a --- /dev/null +++ b/src/models/report.py @@ -0,0 +1,37 @@ +from sqlalchemy import Column, Integer, ForeignKey, String, DateTime, Enum +from sqlalchemy.orm import relationship +from src.database import Base +import enum + +class ReportType(enum.Enum): + inaccurate_equipment = 0 + incorrect_hours = 1 + inaccurate_description = 2 + wait_times_not_updated = 3 + other = 4 + +class Report(Base): + """ + A report object. + + Attributes: + - `id` The ID of the report. + - `user_id` The ID of the user who created the report. + - `issue` The issue reported (discrete options). + - `description` The description of the report. + - `created_at` The date and time the report was created. + - `updated_at` The date and time the report was last updated. + - `gym_id` The ID of the gym associated with the report. + """ + + __tablename__ = "report" + + id = Column(Integer, primary_key=True) + user_id = Column(Integer, ForeignKey("users.id"), nullable=False) + issue = Column(Enum(ReportType), nullable=False) # Discrete options (enumerate) + description = Column(String, nullable=False) # Text input + created_at = Column(DateTime, nullable=False) # Timestamp for user submission + gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) # One to many relationship with gym + # Make relationship with gym and user + gym = relationship("Gym", back_populates="reports") + user = relationship("User", back_populates="reports") diff --git a/src/models/user.py b/src/models/user.py index 8a61fdd..15b4eb2 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -18,5 +18,6 @@ class User(Base): id = Column(Integer, primary_key=True) giveaways = relationship("Giveaway", secondary="giveaway_instance", back_populates="users") + reports = relationship("Report", back_populates="user") instagram = Column(String, nullable=True) net_id = Column(String, nullable=False) diff --git a/src/schema.py b/src/schema.py index 72c6d03..6094248 100644 --- a/src/schema.py +++ b/src/schema.py @@ -13,6 +13,7 @@ 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.models.report import Report as ReportModel from src.database import db_session @@ -216,6 +217,22 @@ def resolve_get_users_by_giveaway_id(self, info, id): users = [User.get_query(info).filter(UserModel.id == entry.user_id).first() for entry in entries] return users +# MARK: - Report + +class Report(SQLAlchemyObjectType): + class Meta: + model = ReportModel + + gym = graphene.Field(lambda: Gym) + user = graphene.Field(lambda: User) + + def resolve_gym(self, info): + query = Gym.get_query(info).filter(GymModel.id == self.gym_id).first() + return query + + def resolve_user(self, info): + query = User.get_query(info).filter(UserModel.id == self.user_id).first() + return query # MARK: - Mutation @@ -288,11 +305,29 @@ def mutate(self, info, name): db_session.commit() return CreateGiveaway(giveaway=giveaway) +class CreateReport(graphene.Mutation): + class Arguments: + user_id = graphene.Int(required=True) + issue = graphene.String(required=True) + description = graphene.String(required=True) + created_at = graphene.DateTime(required=True) + gym_id = graphene.Int(required=True) + + report = graphene.Field(Report) + + def mutate(self, info, description, user_id, issue, created_at, gym_id): + report = ReportModel(description=description, user_id=user_id, issue=issue, + created_at=created_at, gym_id=gym_id) + db_session.add(report) + db_session.commit() + return CreateReport(report=report) + class Mutation(graphene.ObjectType): 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.") + create_report = CreateReport.Field(description="Creates a new report.") schema = graphene.Schema(query=Query, mutation=Mutation) diff --git a/src/scrapers/class_scraper.py b/src/scrapers/class_scraper.py index 4b935a2..69eb21f 100644 --- a/src/scrapers/class_scraper.py +++ b/src/scrapers/class_scraper.py @@ -66,7 +66,7 @@ def fetch_classes(num_pages): try: gym_class = db_session.query(Class).filter(Class.name == class_name).first() if gym_class is None: - Exception() + raise Exception() except Exception: gym_class = create_group_class(class_href) class_instance.class_id = gym_class.id From 309c5d809237b72e2e345dfa97c52c84408a263b Mon Sep 17 00:00:00 2001 From: Joshua Dirga Date: Fri, 11 Oct 2024 00:56:42 -0400 Subject: [PATCH 2/3] Fixed documentation on Report model --- src/models/report.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/models/report.py b/src/models/report.py index 02dd32a..414b18e 100644 --- a/src/models/report.py +++ b/src/models/report.py @@ -20,7 +20,6 @@ class Report(Base): - `issue` The issue reported (discrete options). - `description` The description of the report. - `created_at` The date and time the report was created. - - `updated_at` The date and time the report was last updated. - `gym_id` The ID of the gym associated with the report. """ From 1e40e3b16516dc94536989a882723d1d61b243a9 Mon Sep 17 00:00:00 2001 From: Joshua Dirga Date: Sun, 20 Oct 2024 14:32:04 -0400 Subject: [PATCH 3/3] Edited reports model and mutation based on reviews --- schema.graphql | 6 +++--- src/models/report.py | 16 ++++++++-------- src/schema.py | 11 +++++++++++ src/scrapers/class_scraper.py | 2 +- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/schema.graphql b/schema.graphql index 7a657f4..1e4bf65 100644 --- a/schema.graphql +++ b/schema.graphql @@ -189,11 +189,11 @@ type Query { type Report { id: ID! - userId: Int! - issue: ReportType! - description: String! createdAt: DateTime! + description: String! gymId: Int! + issue: ReportType! + userId: Int! gym: Gym user: User } diff --git a/src/models/report.py b/src/models/report.py index 414b18e..f7a7dfa 100644 --- a/src/models/report.py +++ b/src/models/report.py @@ -4,11 +4,11 @@ import enum class ReportType(enum.Enum): - inaccurate_equipment = 0 - incorrect_hours = 1 - inaccurate_description = 2 - wait_times_not_updated = 3 - other = 4 + INACCURATE_EQUIPMENT = 0 + INCORRECT_HOURS = 1 + INACCURATE_DESCRIPTION = 2 + WAIT_TIMES_NOT_UPDATED = 3 + OTHER = 4 class Report(Base): """ @@ -26,11 +26,11 @@ class Report(Base): __tablename__ = "report" id = Column(Integer, primary_key=True) - user_id = Column(Integer, ForeignKey("users.id"), nullable=False) - issue = Column(Enum(ReportType), nullable=False) # Discrete options (enumerate) - description = Column(String, nullable=False) # Text input created_at = Column(DateTime, nullable=False) # Timestamp for user submission + description = Column(String, nullable=False) # Text input gym_id = Column(Integer, ForeignKey("gym.id"), nullable=False) # One to many relationship with gym + issue = Column(Enum(ReportType), nullable=False) # Discrete options (enumerate) + user_id = Column(Integer, ForeignKey("users.id"), nullable=False) # Make relationship with gym and user gym = relationship("Gym", back_populates="reports") user = relationship("User", back_populates="reports") diff --git a/src/schema.py b/src/schema.py index 6094248..116bebf 100644 --- a/src/schema.py +++ b/src/schema.py @@ -316,6 +316,17 @@ class Arguments: report = graphene.Field(Report) def mutate(self, info, description, user_id, issue, created_at, gym_id): + # Check if user exists + user = User.get_query(info).filter(UserModel.id == user_id).first() + if not user: + raise GraphQLError("User with given ID does not exist.") + # Check if gym exists + gym = Gym.get_query(info).filter(GymModel.id == gym_id).first() + if not gym: + raise GraphQLError("Gym with given ID does not exist.") + # Check if issue is a valid enumeration + if issue not in ["INACCURATE_EQUIPMENT", "INCORRECT_HOURS", "INACCURATE_DESCRIPTION", "WAIT_TIMES_NOT_UPDATED", "OTHER"]: + raise GraphQLError("Issue is not a valid enumeration.") report = ReportModel(description=description, user_id=user_id, issue=issue, created_at=created_at, gym_id=gym_id) db_session.add(report) diff --git a/src/scrapers/class_scraper.py b/src/scrapers/class_scraper.py index 69eb21f..51ca30f 100644 --- a/src/scrapers/class_scraper.py +++ b/src/scrapers/class_scraper.py @@ -66,7 +66,7 @@ def fetch_classes(num_pages): try: gym_class = db_session.query(Class).filter(Class.name == class_name).first() if gym_class is None: - raise Exception() + raise Exception("Gym class is none, creating new gym class") except Exception: gym_class = create_group_class(class_href) class_instance.class_id = gym_class.id