From 2d41d8a23c35602afcb31713a9e6ffcd12e7b6a0 Mon Sep 17 00:00:00 2001 From: Manan Bhargava Date: Fri, 8 Nov 2024 17:45:47 -0800 Subject: [PATCH] Created db folder, db-scripts folder, database.py, and subfiles within those folders. Also updated requirements.txt for psycopg2 --- README.md | 6 +++ api/database.py | 23 +++++++++++ api/db-scripts/db_cron.sh | 2 + api/db-scripts/gradescope_to_db.py | 63 ++++++++++++++++++++++++++++++ api/db-scripts/init_database.py | 25 ++++++++++++ api/db-scripts/pl_to_db.py | 1 + api/db/config.env | 5 +++ api/db/init_db.sql | 24 ++++++++++++ api/requirements.txt | 1 + 9 files changed, 150 insertions(+) create mode 100644 api/database.py create mode 100644 api/db-scripts/db_cron.sh create mode 100644 api/db-scripts/gradescope_to_db.py create mode 100644 api/db-scripts/init_database.py create mode 100644 api/db-scripts/pl_to_db.py create mode 100644 api/db/config.env create mode 100644 api/db/init_db.sql diff --git a/README.md b/README.md index 8ab64f7a..4e18ad98 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,9 @@ GradeSync is a backend microservice that integrates with assessment platforms to - Click "New Request" to test the API endpoints. - Also, create test cases in `api/test_app.py`. 7. When you are finished, run `docker-compose down` or press CTRL+C to stop the server. + + +### Configuring the database +1. Install postgres through `brew update` then `brew install postgresql` +2. Start and enable the PostgreSQL Service through running `brew services start postgresql` +3. Set up the PostgreSQL User and Database with `sudo -i -u postgres` and then starting the PostgreSQL prompt with `psql` diff --git a/api/database.py b/api/database.py new file mode 100644 index 00000000..f12f7ecf --- /dev/null +++ b/api/database.py @@ -0,0 +1,23 @@ +# src/database.py + +import os +import psycopg2 +from dotenv import load_dotenv + +# Load environment variables from config.env +load_dotenv(dotenv_path='../db/config.env') + +def connect_db(): + try: + connection = psycopg2.connect( + dbname=os.getenv("DB_NAME"), + user=os.getenv("DB_USER"), + password=os.getenv("DB_PASSWORD"), + host=os.getenv("DB_HOST"), + port=os.getenv("DB_PORT") + ) + print("Database connection successful") + return connection + except Exception as e: + print(f"Error connecting to database: {e}") + return None \ No newline at end of file diff --git a/api/db-scripts/db_cron.sh b/api/db-scripts/db_cron.sh new file mode 100644 index 00000000..f49cbd2e --- /dev/null +++ b/api/db-scripts/db_cron.sh @@ -0,0 +1,2 @@ +# This needs to be fixed and updated +0 0 * * * /usr/bin/python3 /path/to/your/project/src/load_gradescope_data.py diff --git a/api/db-scripts/gradescope_to_db.py b/api/db-scripts/gradescope_to_db.py new file mode 100644 index 00000000..ae5e4539 --- /dev/null +++ b/api/db-scripts/gradescope_to_db.py @@ -0,0 +1,63 @@ +# src/load_gradescope_data.py + +# Heavily update this because it uses the wrong database schema for now +# This is placeholder code for the future + +import json +import psycopg2 +from src.database import connect_db + +def load_gradescope_data(json_file_path): + # Open the JSON file from Gradescope + with open(json_file_path, 'r') as file: + data = json.load(file) + + conn = connect_db() + if conn is None: + print("Failed to connect to the database.") + return + + try: + with conn.cursor() as cursor: + # Insert or update students + for student in data["students"]: + cursor.execute(""" + INSERT INTO students (name, email) + VALUES (%s, %s) + ON CONFLICT (email) DO NOTHING + """, (student["name"], student["email"])) + + # Insert assignments and grades + for assignment in data["assignments"]: + cursor.execute(""" + INSERT INTO assignments (assignment_name, due_date) + VALUES (%s, %s) + ON CONFLICT (assignment_name) DO NOTHING + RETURNING assignment_id + """, (assignment["name"], assignment["due_date"])) + assignment_id = cursor.fetchone()[0] + + for grade_entry in assignment["grades"]: + cursor.execute(""" + INSERT INTO grades (student_id, assignment_id, grade, submission_date) + VALUES ( + (SELECT student_id FROM students WHERE email = %s), + %s, %s, %s + ) + ON CONFLICT (student_id, assignment_id) DO UPDATE SET + grade = EXCLUDED.grade, + submission_date = EXCLUDED.submission_date + """, (grade_entry["student_email"], assignment_id, grade_entry["grade"], grade_entry["submission_date"])) + + conn.commit() + print("Gradescope data loaded successfully.") + except Exception as e: + print(f"Error loading Gradescope data: {e}") + conn.rollback() + finally: + conn.close() + +if __name__ == "__main__": + # Path to your Gradescope JSON file + json_file_path = "../data/gradescope_data.json" + load_gradescope_data(json_file_path) \ No newline at end of file diff --git a/api/db-scripts/init_database.py b/api/db-scripts/init_database.py new file mode 100644 index 00000000..f18c8b13 --- /dev/null +++ b/api/db-scripts/init_database.py @@ -0,0 +1,25 @@ +# scripts/init_database.py + +import psycopg2 +from src.database import connect_db + +def initialize_db(): + conn = connect_db() + if conn is None: + print("Failed to connect to the database.") + return + + try: + with conn.cursor() as cursor: + with open("db/init_db.sql", "r") as sql_file: + cursor.execute(sql_file.read()) + conn.commit() + print("Database initialized successfully.") + except Exception as e: + print(f"Error initializing database: {e}") + conn.rollback() + finally: + conn.close() + +if __name__ == "__main__": + initialize_db() \ No newline at end of file diff --git a/api/db-scripts/pl_to_db.py b/api/db-scripts/pl_to_db.py new file mode 100644 index 00000000..df7528e0 --- /dev/null +++ b/api/db-scripts/pl_to_db.py @@ -0,0 +1 @@ +# Placeholder for next file to implement \ No newline at end of file diff --git a/api/db/config.env b/api/db/config.env new file mode 100644 index 00000000..c0ac5510 --- /dev/null +++ b/api/db/config.env @@ -0,0 +1,5 @@ +DB_NAME=my_database +DB_USER=my_user +DB_PASSWORD=my_password +DB_HOST=localhost +DB_PORT=5432 \ No newline at end of file diff --git a/api/db/init_db.sql b/api/db/init_db.sql new file mode 100644 index 00000000..c80c2cc0 --- /dev/null +++ b/api/db/init_db.sql @@ -0,0 +1,24 @@ +-- Sample code to create a table in the database +-- We will be copying and pasting in the database schema from mermaid here + +-- This is wrong below this line but sample database schema + +CREATE TABLE IF NOT EXISTS students ( + student_id SERIAL PRIMARY KEY, + name VARCHAR(100), + email VARCHAR(100) UNIQUE +); + +CREATE TABLE IF NOT EXISTS assignments ( + assignment_id SERIAL PRIMARY KEY, + assignment_name VARCHAR(100), + due_date DATE +); + +CREATE TABLE IF NOT EXISTS grades ( + grade_id SERIAL PRIMARY KEY, + student_id INT REFERENCES students(student_id), + assignment_id INT REFERENCES assignments(assignment_id), + grade FLOAT, + submission_date TIMESTAMP +); diff --git a/api/requirements.txt b/api/requirements.txt index 77c46959..47b3d14b 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -7,3 +7,4 @@ httpx==0.27.0 gspread google-auth pydantic==2.9.2 +psycopg2