From 95dffe5e4efe529c01d9cc328cbb5ef1837d8c41 Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Mon, 2 Jun 2025 13:55:24 +0100 Subject: [PATCH 1/7] Some initial changes based on feedback --- src/front/home.py | 76 ++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/src/front/home.py b/src/front/home.py index 9d75d1f..d92251f 100644 --- a/src/front/home.py +++ b/src/front/home.py @@ -22,6 +22,7 @@ def home_page(): # Debug log to see what's being passed to the template logger.debug(f"User ID from session: {user_id}, User Name from session: {selected_user_name}") + logger.info(f"{selected_user_name} is logged in") categories = db_call.get_categories(user_id) if user_id else [] return render_template( @@ -29,33 +30,36 @@ def home_page(): users=users, categories=categories, selected_user_id=user_id, - selected_user_name=selected_user_name + selected_user_name=selected_user_name, ) + @home_bp.route("/submit_user", methods=["POST"]) def submit_user_name(): user_name = request.form.get("userName") logger.debug(f"Request Received: {request.form}") if not user_name: - flash("Please enter a user name.", "error") + flash("Please enter a user name.", "danger") return redirect(url_for("home.home_page")) db_call = data_handler.database(verity_config) # More efficient check for existing user exists = db_call.read_database("SELECT 1 FROM user WHERE name = ?", (user_name,)) if exists: - flash("A user with that name already exists.", "error") + logger.warning(f"username already exists in the database: {user_name}") + flash("A user with that name already exists.", "danger") return redirect(url_for("home.home_page")) - logger.info(f"User submitted new user name: {user_name}") user_id = db_call.add_user_name(user_name) if user_id == 0: - flash("User Name not saved, please check the logs", "error") + flash("User Name not saved, please check the logs", "danger") return redirect(url_for("home.home_page")) - - flash("user name saved! Now select the user from the dropdown to continue.", "success") + session["user_id"] = user_id + session["user_name"] = user_name + flash("user name saved! Start adding categories.", "success") return redirect(url_for("home.home_page")) + @home_bp.route("/select_user", methods=["POST"]) def select_user(): selected_user_id = request.form.get("selectedUserId") @@ -65,14 +69,6 @@ def select_user(): session.pop("user_name", None) return redirect(url_for("home.home_page")) - # Convert selected_user_id to int and handle invalid input - try: - selected_user_id = int(selected_user_id) - except ValueError: - logger.error(f"Invalid user ID: {selected_user_id}") - flash("Invalid user ID", "error") - return redirect(url_for("home.home_page")) - # Get the user details directly from the database using the ID db_call = data_handler.database(verity_config) result = db_call.read_database("SELECT name FROM user WHERE id = ?", (selected_user_id,)) @@ -85,35 +81,47 @@ def select_user(): else: session.pop("user_id", None) session.pop("user_name", None) - flash("User not found!", "error") + flash("User not found!", "danger") return redirect(url_for("home.home_page")) + +def convert_to_universal_currency(input_value: float) -> int: + """ + Converts the the input value to remove all decimal places and return an int. + This will be the starting point for our universal currency, + (see docs/data_dictionary). + for now, we will just focus on making this an int. + it will need change later once we have the basics done + """ + logger.info(f"received {input_value} to convert to universal currency") + input_value = float(input_value) + while input_value % 1 != 0: + logger.debug(f"input value is not a whole number {input_value}") + input_value = input_value * 10 + logger.info(f"returning {int(input_value)}") + return int(input_value) + + @home_bp.route("/submit_category", methods=["POST"]) def submit_category(): user_id = session.get("user_id") if not user_id: - flash("No user selected!", "error") + logger.warning("No user selected and trying to add a category... how?") + flash("No user selected!", "danger") return redirect(url_for("home.home_page")) # Get and validate category name (required) category_name = request.form.get("categoryName") - if not category_name: - flash("Category name is required", "error") - return redirect(url_for("home.home_page")) - - # Handle form values more concisely - # Convert budget_value to float if provided - budget_value = None - budget_value_str = request.form.get("budgetValue", "").strip() - if budget_value_str: - try: - budget_value = float(budget_value_str) - except ValueError: - logger.error(f"Invalid budget value: {budget_value_str}") - flash("Invalid budget value - please enter a valid number", "error") - return redirect(url_for("home.home_page")) + # Convert budget_value to our universal currency + budget_value: int = 0 + budget_value_input = request.form.get("budgetValue", "0") + logger.debug(f"budget value input: {budget_value_input}") + if budget_value_input: + logger.info(f"Category:{category_name}, Assigned amount: {budget_value_input}") + # User might either add a whole currency or a decimal of. we need to handle both + budget_value = convert_to_universal_currency(budget_value_input) # Convert parent_id to int if provided parent_id = None parent_id_str = request.form.get("parentId", "").strip() @@ -122,13 +130,13 @@ def submit_category(): parent_id = int(parent_id_str) except ValueError: logger.error(f"Invalid parent ID: {parent_id_str}") - flash("Invalid parent category ID", "error") + flash("Invalid parent category ID", "danger") return redirect(url_for("home.home_page")) db_call = data_handler.database(verity_config) category_id = db_call.add_category(user_id, category_name, budget_value, parent_id) if category_id == 0: - flash("Category not saved, please check the logs", "error") + flash("Category not saved, please check the logs", "danger") else: flash("Category saved!", "success") return redirect(url_for("home.home_page")) From 3a8233ef7ae9edef65852765ed8c4082e3ff3fe3 Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Mon, 2 Jun 2025 19:26:26 +0100 Subject: [PATCH 2/7] More additions --- src/front/home.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/front/home.py b/src/front/home.py index d92251f..9dd6c57 100644 --- a/src/front/home.py +++ b/src/front/home.py @@ -118,20 +118,18 @@ def submit_category(): budget_value: int = 0 budget_value_input = request.form.get("budgetValue", "0") logger.debug(f"budget value input: {budget_value_input}") - if budget_value_input: + if not budget_value_input: + logger.info("no budget value assigned to category") + else: logger.info(f"Category:{category_name}, Assigned amount: {budget_value_input}") # User might either add a whole currency or a decimal of. we need to handle both + if int(budget_value_input) < 0: + logger.info("user is stupid and tried to assign a negative amount to the category") + flash("Negative amounts don`t really make sense here, removed budget amount", "danger") + budget_value_input = 0 budget_value = convert_to_universal_currency(budget_value_input) # Convert parent_id to int if provided - parent_id = None - parent_id_str = request.form.get("parentId", "").strip() - if parent_id_str: - try: - parent_id = int(parent_id_str) - except ValueError: - logger.error(f"Invalid parent ID: {parent_id_str}") - flash("Invalid parent category ID", "danger") - return redirect(url_for("home.home_page")) + parent_id = int(request.form.get("parentId", "").strip()) db_call = data_handler.database(verity_config) category_id = db_call.add_category(user_id, category_name, budget_value, parent_id) From 0e3443158324b57897d920cbd88c39fb59a62113 Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Tue, 3 Jun 2025 08:57:35 +0100 Subject: [PATCH 3/7] Resolved most comments from Pull Request 8 --- src/data_handler.py | 122 +++++++++++---------------------- src/tests/test_data_handler.py | 9 +-- 2 files changed, 46 insertions(+), 85 deletions(-) diff --git a/src/data_handler.py b/src/data_handler.py index f3d9677..7eb77cf 100644 --- a/src/data_handler.py +++ b/src/data_handler.py @@ -15,9 +15,11 @@ def __init__(self, config) -> None: self.schema = self.verity_config.DATABASE_SCHEMA self.database = self.verity_config.DATABASE - def execute_sql(self, sql_statement: str, return_id: bool = False) -> (bool, int): + def execute_sql( + self, sql_statement: str, params: tuple = (), return_id: bool = False + ) -> (bool, int): "send the query here, returns true if successful, false if fail" - logging.debug(f"received request to execute {sql_statement}") + logger.debug(f"received request to execute {sql_statement}") new_id: int = 0 is_success: bool = False try: @@ -25,44 +27,47 @@ def execute_sql(self, sql_statement: str, return_id: bool = False) -> (bool, int database=self.database, timeout=10, # seconds i hope ) - logging.debug("opened connection to database") + logger.info("opened connection to database") cursor = connection.cursor() - cursor.execute(sql_statement, {}) + cursor.execute("PRAGMA foreign_keys = ON;") + cursor.execute(sql_statement, params) connection.commit() + logger.debug(f"executed {sql_statement} with params: {params}") + logger.info("executed sql command") if return_id: new_id = cursor.lastrowid + logger.debug(f"New id created {new_id}") is_success = True except Exception as e: # TODO: better Exception handling - logging.error(e) + logger.error(e) is_success = False finally: connection.close() + logger.info("closed connection to database") if return_id: return (is_success, new_id) else: return is_success - def read_database(self, sql_statement: str, params=()) -> list: + def read_database(self, sql_statement: str, params: tuple = ()) -> list: "reads the database query and returns the results" - logging.debug(f"received request to read {sql_statement}") + logger.debug(f"received request to read {sql_statement}") results = [] try: connection = sqlite3.connect(self.database) cursor = connection.cursor() results = cursor.execute(sql_statement, params) results = results.fetchall() - logging.debug(f"query returned: {results}") + logger.debug(f"query returned: {results}") except Exception as e: - logging.error(f"Read error occurred: {e}") + logger.error(f"Read error occurred: {e}") finally: connection.close() return results @staticmethod def _build_column(column: dict) -> str: - logging.debug( - f"building column {column}" - ) + logging.debug(f"building column {column}") name = column["column_name"] is_pk = column["is_pk"] is_fk = column.get("is_fk") @@ -77,7 +82,6 @@ def _build_column(column: dict) -> str: column_string += " NOT NULL" return column_string - def _add_table_to_db(self, table: dict) -> bool: "Creates the table in the verity database, based on the schema yaml" sql = f"""CREATE TABLE IF NOT EXISTS {table["table_name"]} ( @@ -132,9 +136,7 @@ def print_table_schema(self, table_name): # Print the schema logger.debug(f"Schema for table: {table_name}") for row in cursor.fetchall(): - logger.debug( - f"Column Name: {row[1]}, Data Type: {row[2]}, Not Null: {row[3]}" - ) + logger.debug(f"Column Name: {row[1]}, Data Type: {row[2]}, Not Null: {row[3]}") except Exception as e: logger.error(f"An error occurred: {e}") @@ -148,79 +150,37 @@ def print_table_schema(self, table_name): def add_user_name(self, user_name: str) -> int: "takes user name string, returns user id" logger.debug(f"attempting to insert values into user table {user_name}") - try: - connection = sqlite3.connect(self.database) - cursor = connection.cursor() - cursor.execute( - """ - INSERT INTO user ( - name - ) - VALUES (?) - """, - (user_name,), - ) - connection.commit() - user_id = cursor.lastrowid - if user_id is None: - user_id = 0 - except Exception as e: - logger.error(f"Failed to insert user name, error: {e}") - user_id = 0 - finally: - try: - connection.close() - logger.debug("connection to db closed") - return user_id - except Exception as e: - logger.error(f"failed to close connection message: {e}") - return 0 + sql_statement = """ + INSERT INTO user (name) + VALUES (?) + """ + params = (user_name,) + success, user_id = self.execute_sql(sql_statement, params, True) + if not success: + logger.error("Failed to execute sql, check the logs") + return user_id def get_users(self) -> list: """Returns all users in the database.""" get_user_sql = "SELECT id, name FROM user" return self.read_database(get_user_sql) - def add_category(self, user_id: int, category_name: str,budget_value: int = 0, - parent_id = None) -> int: + def add_category( + self, user_id: int, category_name: str, budget_value: int = 0, parent_id=None + ) -> int: """Inserts a new category. Returns the category id.""" logger.debug(f"attempting to insert category '{category_name}' for user {user_id}") - try: - connection = sqlite3.connect(self.database) - cursor = connection.cursor() - cursor.execute( - """ - INSERT INTO category (user_id, name, budget_value, parent_id) - VALUES (?, ?, ?, ?) - """, - (user_id, category_name, budget_value, parent_id), - ) - connection.commit() - category_id = cursor.lastrowid or 0 - except Exception as e: - logger.error(f"Failed to insert category name, error: {e}") - category_id = 0 - finally: - try: - connection.close() - except Exception as e: - logger.error(f"failed to close connection: {e}") - return category_id + sql_statement = """ + INSERT INTO category (user_id, name, budget_value, parent_id) + VALUES (?, ?, ?, ?)""" + params = (user_id, category_name, budget_value, parent_id) + + success, category_id = self.execute_sql(sql_statement, params, True) + if not success: + logger.error("Failed to execute sql, check the logs") + return category_id def get_categories(self, user_id: int) -> list: """Returns all categories for a given user.""" - try: - connection = sqlite3.connect(self.database) - cursor = connection.cursor() - sql = "SELECT id, name, budget_value, parent_id FROM category WHERE user_id = ?" - cursor.execute(sql, (user_id,)) - categories = cursor.fetchall() - except Exception as e: - logger.error(f"Failed to fetch categories: {e}") - categories = [] - finally: - try: - connection.close() - except Exception as e: - logger.error(f"failed to close connection: {e}") - return categories + sql = "SELECT id, name, budget_value, parent_id FROM category WHERE user_id = ?" + return self.read_database(sql_statement=sql, params=(user_id,)) diff --git a/src/tests/test_data_handler.py b/src/tests/test_data_handler.py index becf155..283ae80 100644 --- a/src/tests/test_data_handler.py +++ b/src/tests/test_data_handler.py @@ -83,10 +83,10 @@ def test_read_database_with_params(test_db_call): def test_build_database(test_db_call): """Test that the database builds correctly with all required tables""" # Check if all tables have been created - tables_to_check = ["user", "account", "account_type", "party", "transaction_type", - "category", "transaction_log"] - for table in tables_to_check: - sql = f"SELECT name FROM sqlite_master WHERE type='table' AND name='{table}';" + config = VerityConfig() + for table in config.DATABASE_SCHEMA["tables"]: + table_name = table["table_name"] + sql = f"SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';" results = test_db_call.read_database(sql) assert len(results) == 1, f"Table '{table}' should exist" @@ -182,4 +182,5 @@ def test_add_category_invalid_user(test_db_call): # Try to add a category with a non-existent user_id # (should still succeed in SQLite unless foreign keys are enforced) category_id = test_db_call.add_category(99999, "InvalidUserCategory") + assert category_id == 0 assert isinstance(category_id, int) From 574341b30d224a615cc19dca4ac0ed9778f085fb Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Tue, 3 Jun 2025 18:33:26 +0100 Subject: [PATCH 4/7] Moved convert to universal currency to its own module. --- src/currency_handler.py | 23 +++++++++++++++++++++++ src/front/home.py | 20 ++------------------ src/tests/test_currency_handler.py | 22 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 src/currency_handler.py create mode 100644 src/tests/test_currency_handler.py diff --git a/src/currency_handler.py b/src/currency_handler.py new file mode 100644 index 0000000..cb92036 --- /dev/null +++ b/src/currency_handler.py @@ -0,0 +1,23 @@ +import logging + +logger = logging.getLogger(__name__) + +# TODO: Make this into a proper class so we can scale currrency handling + + +def convert_to_universal_currency(input_value: float) -> int: + """ + Converts the the input value to remove all decimal places and return an int. + This will be the starting point for our universal currency, + (see docs/data_dictionary). + for now, we will just focus on making this an int. + it will need change later once we have the basics done + """ + logger.info(f"received {input_value} to convert to universal currency") + input_value = float(input_value) + while input_value % 1 != 0: + logger.debug(f"input value is not a whole number {input_value}") + input_value = input_value * 10 + logger.info(f"returning {int(input_value)}") + return int(input_value) + diff --git a/src/front/home.py b/src/front/home.py index 9dd6c57..453a54a 100644 --- a/src/front/home.py +++ b/src/front/home.py @@ -3,6 +3,7 @@ from flask import Blueprint, flash, redirect, render_template, request, session, url_for import data_handler +import currency_handler from config import VerityConfig logger = logging.getLogger(__name__) @@ -86,23 +87,6 @@ def select_user(): return redirect(url_for("home.home_page")) -def convert_to_universal_currency(input_value: float) -> int: - """ - Converts the the input value to remove all decimal places and return an int. - This will be the starting point for our universal currency, - (see docs/data_dictionary). - for now, we will just focus on making this an int. - it will need change later once we have the basics done - """ - logger.info(f"received {input_value} to convert to universal currency") - input_value = float(input_value) - while input_value % 1 != 0: - logger.debug(f"input value is not a whole number {input_value}") - input_value = input_value * 10 - logger.info(f"returning {int(input_value)}") - return int(input_value) - - @home_bp.route("/submit_category", methods=["POST"]) def submit_category(): user_id = session.get("user_id") @@ -127,7 +111,7 @@ def submit_category(): logger.info("user is stupid and tried to assign a negative amount to the category") flash("Negative amounts don`t really make sense here, removed budget amount", "danger") budget_value_input = 0 - budget_value = convert_to_universal_currency(budget_value_input) + budget_value = currency_handler.convert_to_universal_currency(budget_value_input) # Convert parent_id to int if provided parent_id = int(request.form.get("parentId", "").strip()) diff --git a/src/tests/test_currency_handler.py b/src/tests/test_currency_handler.py new file mode 100644 index 0000000..a2b03db --- /dev/null +++ b/src/tests/test_currency_handler.py @@ -0,0 +1,22 @@ +import pytest + +from src import currency_handler + + +def test_convert_to_universal_currency(): + input = 87.82 + result = currency_handler.convert_to_universal_currency(input) + assert result == 8782 + + +def test_whole_number(): + input = 123 + result = currency_handler.convert_to_universal_currency(input) + assert result == input + + +def test_negative_number(): + input = -123.45 + result = currency_handler.convert_to_universal_currency(input) + print(result) + assert result == -12345 From c3003a5bf34ac3615671bfac7b76c7614f75c4f9 Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Tue, 3 Jun 2025 21:25:11 +0100 Subject: [PATCH 5/7] Working towards adding default rows, need to add system user? --- src/config.py | 1 + src/config_files/default_data.yaml | 4 ++++ src/data_handler.py | 32 +++++++++++++++++++++++++++--- src/front/home.py | 21 +++++++++++++++----- src/tests/test_currency_handler.py | 1 - src/verity.py | 1 + 6 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 src/config_files/default_data.yaml diff --git a/src/config.py b/src/config.py index 975c89e..851119d 100644 --- a/src/config.py +++ b/src/config.py @@ -10,6 +10,7 @@ def __init__(self): self.CONFIG_FILE_DIRECTORY = "config_files" self.LOGGING_CONFIG = self.load_config_file("logging_config.yaml") self.DATABASE_SCHEMA = self.load_config_file("verity_schema.yaml") + self.DEFAULT_DATA = self.load_config_file("default_data.yaml") def load_config_file(self, file): config = "" diff --git a/src/config_files/default_data.yaml b/src/config_files/default_data.yaml new file mode 100644 index 0000000..fb9cac2 --- /dev/null +++ b/src/config_files/default_data.yaml @@ -0,0 +1,4 @@ +category: + - name: 'internal_master_category' + - name: 'tesing more categories' + budget_value: '100' diff --git a/src/data_handler.py b/src/data_handler.py index 7eb77cf..20db8c3 100644 --- a/src/data_handler.py +++ b/src/data_handler.py @@ -14,12 +14,13 @@ def __init__(self, config) -> None: self.verity_config = config self.schema = self.verity_config.DATABASE_SCHEMA self.database = self.verity_config.DATABASE + self.default_data = self.verity_config.DEFAULT_DATA def execute_sql( - self, sql_statement: str, params: tuple = (), return_id: bool = False + self, sql_statement: str, params: tuple = (), return_id: bool = False, seed: bool = False ) -> (bool, int): "send the query here, returns true if successful, false if fail" - logger.debug(f"received request to execute {sql_statement}") + logger.debug(f"received request to execute {sql_statement} with params {params}") new_id: int = 0 is_success: bool = False try: @@ -29,7 +30,8 @@ def execute_sql( ) logger.info("opened connection to database") cursor = connection.cursor() - cursor.execute("PRAGMA foreign_keys = ON;") + if seed: + cursor.execute("PRAGMA foreign_keys = OFF;") cursor.execute(sql_statement, params) connection.commit() logger.debug(f"executed {sql_statement} with params: {params}") @@ -42,6 +44,7 @@ def execute_sql( logger.error(e) is_success = False finally: + cursor.execute("PRAGMA foreign_keys = ON;") connection.close() logger.info("closed connection to database") if return_id: @@ -116,6 +119,27 @@ def build_database(self): logger.info(f"Checking {table['table_name']}") # Add true/false handling here to gracefully handle errors self._add_table_to_db(table) + for table in self.default_data: + # check if default row is there + data = self.read_database(f"select * from {table}") + logger.info(f"data in {table} is {data}") + # if not there, make default row. + if data == []: + logger.info("no data, need to add default row(s)") + for row in self.default_data[table]: + logger.debug(row) + col_string = ", ".join(row.keys()) + logger.debug(col_string) + val_string = ", ".join(row.values()) + logger.debug(val_string) + logger.info(f"insert into {table} ({col_string}) values ({val_string})") + self.execute_sql( + f"insert into {table} ({col_string}) VALUES (?)", + (val_string,), + seed=True, + ) + # seed = true + exit() def print_table_schema(self, table_name): """ @@ -173,6 +197,8 @@ def add_category( sql_statement = """ INSERT INTO category (user_id, name, budget_value, parent_id) VALUES (?, ?, ?, ?)""" + if not parent_id: + parent_id = "NULL" params = (user_id, category_name, budget_value, parent_id) success, category_id = self.execute_sql(sql_statement, params, True) diff --git a/src/front/home.py b/src/front/home.py index 453a54a..0bf3eb0 100644 --- a/src/front/home.py +++ b/src/front/home.py @@ -2,8 +2,8 @@ from flask import Blueprint, flash, redirect, render_template, request, session, url_for -import data_handler import currency_handler +import data_handler from config import VerityConfig logger = logging.getLogger(__name__) @@ -55,7 +55,7 @@ def submit_user_name(): if user_id == 0: flash("User Name not saved, please check the logs", "danger") return redirect(url_for("home.home_page")) - session["user_id"] = user_id + session["user_id"] = int(user_id) session["user_name"] = user_name flash("user name saved! Start adding categories.", "success") return redirect(url_for("home.home_page")) @@ -70,6 +70,14 @@ def select_user(): session.pop("user_name", None) return redirect(url_for("home.home_page")) + # Convert selected_user_id to int and handle invalid input + try: + selected_user_id = int(selected_user_id) + except ValueError: + logger.error(f"Invalid user ID: {selected_user_id}") + flash("Invalid user ID", "error") + return redirect(url_for("home.home_page")) + # Get the user details directly from the database using the ID db_call = data_handler.database(verity_config) result = db_call.read_database("SELECT name FROM user WHERE id = ?", (selected_user_id,)) @@ -107,16 +115,19 @@ def submit_category(): else: logger.info(f"Category:{category_name}, Assigned amount: {budget_value_input}") # User might either add a whole currency or a decimal of. we need to handle both - if int(budget_value_input) < 0: + if float(budget_value_input) < 0: logger.info("user is stupid and tried to assign a negative amount to the category") flash("Negative amounts don`t really make sense here, removed budget amount", "danger") budget_value_input = 0 budget_value = currency_handler.convert_to_universal_currency(budget_value_input) # Convert parent_id to int if provided - parent_id = int(request.form.get("parentId", "").strip()) + parent_id = request.form.get("parentId", "0").strip() db_call = data_handler.database(verity_config) - category_id = db_call.add_category(user_id, category_name, budget_value, parent_id) + if parent_id == 0: + category_id = db_call.add_category(user_id, category_name, budget_value) + else: + category_id = db_call.add_category(user_id, category_name, budget_value, parent_id) if category_id == 0: flash("Category not saved, please check the logs", "danger") else: diff --git a/src/tests/test_currency_handler.py b/src/tests/test_currency_handler.py index a2b03db..8111018 100644 --- a/src/tests/test_currency_handler.py +++ b/src/tests/test_currency_handler.py @@ -1,4 +1,3 @@ -import pytest from src import currency_handler diff --git a/src/verity.py b/src/verity.py index 69df55b..0bf866c 100644 --- a/src/verity.py +++ b/src/verity.py @@ -28,6 +28,7 @@ def set_up_logging(config): # database initialise verity = database(verity_config) + logger.debug(verity_config.DEFAULT_DATA) verity.build_database() # app initialise From fc61b98c1ded8ce38b0327f44896df2258a39b9f Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Mon, 9 Jun 2025 09:09:38 +0100 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E2=9C=A8We=20now=20add=20an=20inte?= =?UTF-8?q?rnal=20master=20category=20per=20user=20that=20is=20hidden=20Wi?= =?UTF-8?q?ll=20be=20useful=20for=20various=20key=20restraints.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/data_handler.py | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/src/data_handler.py b/src/data_handler.py index 20db8c3..bbd730a 100644 --- a/src/data_handler.py +++ b/src/data_handler.py @@ -30,6 +30,7 @@ def execute_sql( ) logger.info("opened connection to database") cursor = connection.cursor() + cursor.execute("PRAGMA foreign_keys = ON;") if seed: cursor.execute("PRAGMA foreign_keys = OFF;") cursor.execute(sql_statement, params) @@ -54,7 +55,7 @@ def execute_sql( def read_database(self, sql_statement: str, params: tuple = ()) -> list: "reads the database query and returns the results" - logger.debug(f"received request to read {sql_statement}") + logger.debug(f"received request to read {sql_statement} with params {params}") results = [] try: connection = sqlite3.connect(self.database) @@ -119,27 +120,6 @@ def build_database(self): logger.info(f"Checking {table['table_name']}") # Add true/false handling here to gracefully handle errors self._add_table_to_db(table) - for table in self.default_data: - # check if default row is there - data = self.read_database(f"select * from {table}") - logger.info(f"data in {table} is {data}") - # if not there, make default row. - if data == []: - logger.info("no data, need to add default row(s)") - for row in self.default_data[table]: - logger.debug(row) - col_string = ", ".join(row.keys()) - logger.debug(col_string) - val_string = ", ".join(row.values()) - logger.debug(val_string) - logger.info(f"insert into {table} ({col_string}) values ({val_string})") - self.execute_sql( - f"insert into {table} ({col_string}) VALUES (?)", - (val_string,), - seed=True, - ) - # seed = true - exit() def print_table_schema(self, table_name): """ @@ -182,6 +162,7 @@ def add_user_name(self, user_name: str) -> int: success, user_id = self.execute_sql(sql_statement, params, True) if not success: logger.error("Failed to execute sql, check the logs") + self.add_category(user_id, "internal_master_category", seed=True) return user_id def get_users(self) -> list: @@ -190,23 +171,30 @@ def get_users(self) -> list: return self.read_database(get_user_sql) def add_category( - self, user_id: int, category_name: str, budget_value: int = 0, parent_id=None + self, user_id: int, category_name: str, budget_value: int = 0, parent_id=None, seed=False ) -> int: """Inserts a new category. Returns the category id.""" logger.debug(f"attempting to insert category '{category_name}' for user {user_id}") sql_statement = """ INSERT INTO category (user_id, name, budget_value, parent_id) VALUES (?, ?, ?, ?)""" - if not parent_id: - parent_id = "NULL" + if not seed: + if not parent_id: + parent_id = self.read_database( + "SELECT id FROM category WHERE user_id = ? AND name = ?", + (user_id, "internal_master_category"), + ) + parent_id = parent_id[0][0] params = (user_id, category_name, budget_value, parent_id) - success, category_id = self.execute_sql(sql_statement, params, True) + success, category_id = self.execute_sql(sql_statement, params, True, seed) if not success: logger.error("Failed to execute sql, check the logs") return category_id def get_categories(self, user_id: int) -> list: """Returns all categories for a given user.""" - sql = "SELECT id, name, budget_value, parent_id FROM category WHERE user_id = ?" - return self.read_database(sql_statement=sql, params=(user_id,)) + sql = ( + "SELECT id, name, budget_value, parent_id FROM category WHERE user_id = ? and name != ?" + ) + return self.read_database(sql_statement=sql, params=(user_id, "internal_master_category")) From 7efc613c497638501d7ea86b94ef52a97bf603a5 Mon Sep 17 00:00:00 2001 From: Jake Pullen Date: Mon, 9 Jun 2025 09:16:03 +0100 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=F0=9F=A9=B9=20Fixed=20a=20test=20fa?= =?UTF-8?q?ilure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/data_handler.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/data_handler.py b/src/data_handler.py index bbd730a..c1d970d 100644 --- a/src/data_handler.py +++ b/src/data_handler.py @@ -184,7 +184,10 @@ def add_category( "SELECT id FROM category WHERE user_id = ? AND name = ?", (user_id, "internal_master_category"), ) - parent_id = parent_id[0][0] + try: + parent_id = parent_id[0][0] + except IndexError: + parent_id = None params = (user_id, category_name, budget_value, parent_id) success, category_id = self.execute_sql(sql_statement, params, True, seed)