From 5c165eae655dc3fc80868423f50832c233a144b8 Mon Sep 17 00:00:00 2001 From: Marek Wocka Date: Thu, 5 Dec 2024 21:39:58 +0100 Subject: [PATCH 01/13] Refactor entry type checking from repeated list to private tuple parameter --- in-ou/budget_manager.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/in-ou/budget_manager.py b/in-ou/budget_manager.py index 1880c10..132c677 100644 --- a/in-ou/budget_manager.py +++ b/in-ou/budget_manager.py @@ -7,6 +7,7 @@ def __init__(self, db_name='budget.db'): self.budget = [] self.create_table() self.load_budget_from_file() + self.__entry_types = ('income', 'outcome') def create_connection(self): return sqlite3.connect(self.db_name) @@ -55,7 +56,7 @@ def load_budget_from_file(self): print("Budżet został załadowany z bazy danych.") def add_budget_entry(self, entry_type, amount, description, category="brak kategorii"): - if entry_type not in ["income", "outcome"]: + if entry_type not in self.__entry_types: print("Blad: Nieprawidłowy rodzaj wpisu. Wybierz 'income' lub 'outcome'.") #Zmienić na I / O, czy zostawić pełne słowa? return if not isinstance(amount, (int, float)) or amount <= 0: @@ -74,13 +75,13 @@ def add_budget_entry(self, entry_type, amount, description, category="brak kateg } self.budget.append(entry) self.save_budget_to_file() - print(f"Pomyślnie dodano wpis: {entry_type}, - {amount} PLN, opis: {description}, kategoria: {category}") + print(f"Pomyślnie dodano wpis: {entry_type} - {amount} PLN, opis: {description}, kategoria: {category}") def add_budget_entry_input(self): #Dodawanie wpisów z inputem, również do usunięcia w przyszłości. while True: entry_type = input( "Wprowadź rodzaj wpisu ('income' dla dochodu lub 'outcome' dla wydatku, lub 'exit' aby zakończyć): ").strip().lower() # To samo co wyżej, może warto zmienić na I/O? - if entry_type in ["income", "outcome"]: + if entry_type in self.__entry_types: break elif entry_type == "exit": print("Zakończono dodawanie wpisu.") From 4e1727420eba06d96be13ac7541336f399d0d34d Mon Sep 17 00:00:00 2001 From: Marek Wocka Date: Thu, 5 Dec 2024 21:40:33 +0100 Subject: [PATCH 02/13] Refactor amount type in sql db from REAL to BIGINT --- in-ou/budget_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/in-ou/budget_manager.py b/in-ou/budget_manager.py index 132c677..57153b8 100644 --- a/in-ou/budget_manager.py +++ b/in-ou/budget_manager.py @@ -19,7 +19,7 @@ def create_table(self): CREATE TABLE IF NOT EXISTS budget ( id INTEGER PRIMARY KEY AUTOINCREMENT, entry_type TEXT NOT NULL, - amount REAL NOT NULL, + amount BIGINT NOT NULL, description TEXT, category TEXT, date TEXT NOT NULL From dc0521bec36843dfa0b3c9685be2123ba5929a82 Mon Sep 17 00:00:00 2001 From: Marek Wocka Date: Thu, 5 Dec 2024 23:53:49 +0100 Subject: [PATCH 03/13] Update with Monetary class --- in-ou/budget_manager.py | 65 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/in-ou/budget_manager.py b/in-ou/budget_manager.py index 57153b8..fa8e79f 100644 --- a/in-ou/budget_manager.py +++ b/in-ou/budget_manager.py @@ -1,13 +1,16 @@ import sqlite3 from datetime import datetime +from money import Monetary, Currency + class BudgetManager: - def __init__(self, db_name='budget.db'): + def __init__(self, currency: Currency, db_name='budget.db'): self.db_name = db_name self.budget = [] self.create_table() self.load_budget_from_file() self.__entry_types = ('income', 'outcome') + self.__currency = currency def create_connection(self): return sqlite3.connect(self.db_name) @@ -55,27 +58,30 @@ def load_budget_from_file(self): } for row in rows] print("Budżet został załadowany z bazy danych.") - def add_budget_entry(self, entry_type, amount, description, category="brak kategorii"): + def add_budget_entry(self, entry_type: str, entry: Monetary, description: str, category: str="brak kategorii") -> None: if entry_type not in self.__entry_types: print("Blad: Nieprawidłowy rodzaj wpisu. Wybierz 'income' lub 'outcome'.") #Zmienić na I / O, czy zostawić pełne słowa? return - if not isinstance(amount, (int, float)) or amount <= 0: - print("Blad: Kwota musi być liczbą dodatnią.") + if not isinstance(entry, Monetary): + print("Blad: Wpis jest złego typu danych") + return + if entry.amount < 0: + print("Blad: Kwota musi być liczbą nieujemną.") return if len(description) > 255: print("Blad: Opis jest za długi (maksymalnie 255 znaków).") return - entry = { + record = { "type": entry_type, - "amount": amount, + "amount": entry.amount, "description": description, "category": category, "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } - self.budget.append(entry) + self.budget.append(record) self.save_budget_to_file() - print(f"Pomyślnie dodano wpis: {entry_type} - {amount} PLN, opis: {description}, kategoria: {category}") + print(f"Pomyślnie dodano wpis: {entry_type} - {entry}, opis: {description}, kategoria: {category}") def add_budget_entry_input(self): #Dodawanie wpisów z inputem, również do usunięcia w przyszłości. while True: @@ -107,6 +113,8 @@ def add_budget_entry_input(self): #Dodawanie wpisów z inputem, również do usu if not category: category = "Brak kategorii" # domyśla kategoria + amount = Monetary.major_to_minor_unit(amount, self.__currency) + amount = Monetary(amount, self.__currency) self.add_budget_entry(entry_type, amount, description, category) def show_budget(self): @@ -116,7 +124,8 @@ def show_budget(self): sorted_budget = sorted(self.budget, key=lambda x: x['date']) for i, entry in enumerate(sorted_budget, 1): category = entry.get('category', 'Brak kategorii') - print(f"{i}. {entry['type']}: {entry['amount']} PLN, {entry['description']} " + amount = Monetary(entry['amount'], self.__currency) + print(f"{i}. {entry['type']}: {amount}, {entry['description']} " f"(Kategoria: {category}, Data: {entry['date']})") # status konta ( wydatki, przychody, saldo ) def show_budget_summary(self): @@ -124,13 +133,15 @@ def show_budget_summary(self): print("Brak danych do podsumowania.") return try: - income = sum(entry['amount'] for entry in self.budget if entry['type'] == 'income') + incomes = sum(entry['amount'] for entry in self.budget if entry['type'] == 'income') expenses = sum(entry['amount'] for entry in self.budget if entry['type'] == 'outcome') - balance = income - expenses + incomes = Monetary(incomes, self.__currency) + expenses = Monetary(expenses, self.__currency) + balance = incomes - expenses print("Podsumowanie budżetu:") - print(f" - Dochody: {income:.2f} PLN") - print(f" - Wydatki: {expenses:.2f} PLN") - print(f" - Saldo: {balance:.2f} PLN") + print(f" - Dochody: {incomes}") + print(f" - Wydatki: {expenses}") + print(f" - Saldo: {balance}") except KeyError as e: print(f"Blad: brakuje klucza w danych wpisu budzetowego ({e})") #filtracja TYLKO przychodów zamiast ogólnych wpisów @@ -143,7 +154,8 @@ def show_incomes_by_category(self, category): return print(f"Lista dochodów w kategorii '{category}':") for i, entry in enumerate(incomes, 1): - print(f"{i}. Kwota: {entry['amount']} PLN, Opis: {entry['description']}, Data: {entry['date']}") + entry_monetary = Monetary(entry['amount'], self.__currency) + print(f"{i}. Kwota: {entry_monetary}, Opis: {entry['description']}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych budżetu ({e}).") except Exception as e: @@ -158,7 +170,8 @@ def show_outcomes_by_category(self, category): return print(f"Lista wydatków w kategorii '{category}:") for i, entry in enumerate(outcomes, 1): - print(f"{i}. Kwota: {entry['amount']} PLN, Opis: {entry['description']}, Data: {entry['date']}") + entry_monetary = Monetary(entry['amount'], self.__currency) + print(f"{i}. Kwota: {entry_monetary}, Opis: {entry['description']}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych budżetu ({e}).") except Exception as e: @@ -173,7 +186,8 @@ def show_incomes(self): return print("Lista dochodów: ") for i, entry in enumerate(incomes, 1): - print(f"{i}. Kwota: {entry['amount']} PLN, Opis: {entry['description']}, Kategoria: " + entry_monetary = Monetary(entry['amount'], self.__currency) + print(f"{i}. Kwota: {entry_monetary}, Opis: {entry['description']}, Kategoria: " f"{entry.get('category', 'Brak kategorii')}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych budżetu ({e}). ") @@ -188,7 +202,8 @@ def show_outcomes(self): return print("Lista wydatków: ") for i, entry in enumerate(outcomes, 1): - print(f"{i}. Kwota: {entry['amount']} PLN, Opis: {entry['description']}, " + entry_monetary = Monetary(entry['amount'], self.__currency) + print(f"{i}. Kwota: {entry_monetary}, Opis: {entry['description']}, " f"Kategoria: {entry.get('category', 'Brak kategorii')}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych budżetu ({e}).") @@ -198,7 +213,8 @@ def show_outcomes(self): def edit_budget_entry(self, index): try: entry = self.budget[index - 1] - print(f"Edycja wpisu: {entry['type']}: {entry['amount']} PLN, {entry['description']}") + entry_monetary = Monetary(entry['amount'], self.__currency) + print(f"Edycja wpisu: {entry['type']}: {entry_monetary}, {entry['description']}") #Tu użytkownik wpisuje nowe dane, Value Error wystarczy czy coś więcej? new_type = input("Nowy typ (income/outcome): ").strip().lower() @@ -208,7 +224,9 @@ def edit_budget_entry(self, index): try: new_amount = input("Nowa kwota: ").strip() if new_amount: - entry["amount"] = float(new_amount) + new_amount = float(new_amount) + new_amount = Monetary.major_to_minor_unit(new_amount, self.__currency) + new_amount = Monetary(new_amount, self.__currency) except ValueError: print("Błąd: niepoprawna kwota. Pozostawiono starą wartość.") @@ -218,7 +236,7 @@ def edit_budget_entry(self, index): # Pokazanie zmian przed zapisaniem print("\nProponowane zmiany:") print(f" - Typ: {entry['type']}") - print(f" - Kwota: {entry['amount']:.2f} PLN") + print(f" - Kwota: {new_amount}") print(f" - Opis: {entry['description']}") print(f" - Kategoria: {entry['category']}") @@ -227,7 +245,7 @@ def edit_budget_entry(self, index): if confirm != "tak": print("Edycja anulowana.") return - + entry["amount"] = new_amount.amount # Aktualizacja daty i zapisanie zmian entry["date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.save_budget_to_file() @@ -242,7 +260,8 @@ def delete_budget_entry(self, index): try: print(f"Próba usunięcia wpisu o indeksie: {index}") entry = self.budget.pop(index - 1) + entry_monetary = Monetary(entry['amount'], self.__currency) self.save_budget_to_file() - print(f"Wpis usunięty: {entry['type']} - {entry['amount']} PLN, {entry['description']}") + print(f"Wpis usunięty: {entry['type']} - {entry_monetary}, {entry['description']}") except IndexError: print(f"Nie ma wpisu z podanym indeksem: {index}") From 79d0ce862d90c01a1aa3710bad86a0eeae8611cc Mon Sep 17 00:00:00 2001 From: Marek Wocka Date: Thu, 5 Dec 2024 23:59:37 +0100 Subject: [PATCH 04/13] Update tests with Monetary class --- in-ou/income-outcome-test.py | 41 +++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/in-ou/income-outcome-test.py b/in-ou/income-outcome-test.py index 0dfdbf6..547c146 100644 --- a/in-ou/income-outcome-test.py +++ b/in-ou/income-outcome-test.py @@ -2,35 +2,39 @@ import os from datetime import datetime from budget_manager import BudgetManager +from money import Monetary, Currency +from currencies import PLN - +currency_for_test = PLN class TestBudgetManager(unittest.TestCase): def setUp(self): self.test_db = 'test_budget.db' - self.manager = BudgetManager(db_name=self.test_db) + self.manager = BudgetManager(currency_for_test, db_name=self.test_db) def tearDown(self): if os.path.exists(self.test_db): os.remove(self.test_db) def test_add_budget_entry(self): + money = Monetary.major_to_minor_unit(100.50, currency_for_test) self.manager.add_budget_entry( entry_type='income', - amount=100.50, + entry = Monetary(money, currency_for_test), description='Test income', category='Test category' ) self.manager.load_budget_from_file() self.assertEqual(len(self.manager.budget), 1) self.assertEqual(self.manager.budget[0]['type'], 'income') - self.assertEqual(self.manager.budget[0]['amount'], 100.50) + self.assertEqual(self.manager.budget[0]['amount'], 10050) self.assertEqual(self.manager.budget[0]['description'], 'Test income') self.assertEqual(self.manager.budget[0]['category'], 'Test category') def test_delete_budget_entry(self): + money = Monetary.major_to_minor_unit(50, currency_for_test) self.manager.add_budget_entry( entry_type='income', - amount=50, + entry = Monetary(money, currency_for_test), description='To delete', category='Test' ) @@ -40,15 +44,17 @@ def test_delete_budget_entry(self): self.assertEqual(len(self.manager.budget), 0) def test_show_budget_summary(self): + money = Monetary.major_to_minor_unit(200, currency_for_test) self.manager.add_budget_entry( entry_type='income', - amount=200, + entry = Monetary(money, currency_for_test), description='Test income', category='Category1' ) + money = Monetary.major_to_minor_unit(50, currency_for_test) self.manager.add_budget_entry( entry_type='outcome', - amount=50, + entry = Monetary(money, currency_for_test), description='Test outcome', category='Category2' ) @@ -56,16 +62,19 @@ def test_show_budget_summary(self): income = sum(entry['amount'] for entry in self.manager.budget if entry['type'] == 'income') outcome = sum(entry['amount'] for entry in self.manager.budget if entry['type'] == 'outcome') + income = Monetary(income, currency_for_test) + outcome = Monetary(outcome, currency_for_test) balance = income - outcome - self.assertEqual(income, 200) - self.assertEqual(outcome, 50) - self.assertEqual(balance, 150) + self.assertEqual(income.amount, 20000) + self.assertEqual(outcome.amount, 5000) + self.assertEqual(balance.amount, 15000) def test_edit_budget_entry(self): + money = Monetary.major_to_minor_unit(100, currency_for_test) self.manager.add_budget_entry( entry_type='income', - amount=100, + entry = Monetary(money, currency_for_test), description='Initial description', category='Initial category' ) @@ -74,11 +83,13 @@ def test_edit_budget_entry(self): entry_index = 1 new_type = 'outcome' new_amount = 75.50 + new_amount = Monetary.major_to_minor_unit(new_amount, currency_for_test) + new_amount = Monetary(new_amount, currency_for_test) new_description = 'Updated description' new_category = 'Updated category' self.manager.budget[entry_index - 1]['type'] = new_type - self.manager.budget[entry_index - 1]['amount'] = new_amount + self.manager.budget[entry_index - 1]['amount'] = new_amount.amount self.manager.budget[entry_index - 1]['description'] = new_description self.manager.budget[entry_index - 1]['category'] = new_category @@ -87,14 +98,14 @@ def test_edit_budget_entry(self): edited_entry = self.manager.budget[0] self.assertEqual(edited_entry['type'], new_type) - self.assertEqual(edited_entry['amount'], new_amount) + self.assertEqual(edited_entry['amount'], new_amount.amount) self.assertEqual(edited_entry['description'], new_description) self.assertEqual(edited_entry['category'], new_category) def test_show_incomes(self): self.manager.add_budget_entry( entry_type='income', - amount=300, + entry=Monetary(300, currency_for_test), description='Income test', category='Income category' ) @@ -106,7 +117,7 @@ def test_show_incomes(self): def test_show_outcomes(self): self.manager.add_budget_entry( entry_type='outcome', - amount=150, + entry=Monetary(150, currency_for_test), description='Outcome test', category='Outcome category' ) From 20f98173b07e0e7f7ac3ef0e815fbdc8830642f2 Mon Sep 17 00:00:00 2001 From: Marek Wocka Date: Fri, 6 Dec 2024 00:04:38 +0100 Subject: [PATCH 05/13] Add empty last line --- in-ou/income-outcome-test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/in-ou/income-outcome-test.py b/in-ou/income-outcome-test.py index 547c146..0544a65 100644 --- a/in-ou/income-outcome-test.py +++ b/in-ou/income-outcome-test.py @@ -128,4 +128,4 @@ def test_show_outcomes(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() From fc6f3699da44967f7fd27869fb6d14a73b038d33 Mon Sep 17 00:00:00 2001 From: marekwocka Date: Wed, 29 Jan 2025 00:03:16 +0100 Subject: [PATCH 06/13] Add method get_account_currency in AccountManager class --- desktop-app/account/account.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/desktop-app/account/account.py b/desktop-app/account/account.py index d86072e..39a840a 100644 --- a/desktop-app/account/account.py +++ b/desktop-app/account/account.py @@ -2,7 +2,7 @@ from peewee import SqliteDatabase, Model, AutoField, BigIntegerField, CharField, IntegrityError, \ DoesNotExist, OperationalError -from money import Monetary +from money import Monetary, Currency import currencies CURRENCY_MAP = { @@ -128,3 +128,14 @@ def modify_balance(account_id: int, transaction_amount: Monetary, transaction_ty Account.update({Account.balance: new_value}).where(Account.account_id == account_id).execute() except (IntegrityError, OperationalError): raise SQLError('Wystąpił błąd bazy danych.') from None + + @staticmethod + def get_account_currency(self, account_id: int) -> Currency: + if account_id: + try: + record = Account.select().where(Account.account_id == account_id).get() + except DoesNotExist: + raise SQLError('Konto o podanym ID nie istnieje.') from None + else: + account = Account.get(Account.account_id == account_id) + return CURRENCY_MAP[account.currency_id] \ No newline at end of file From 1758ce78ec0235ee967974cfdd2921722a9ca84c Mon Sep 17 00:00:00 2001 From: marekwocka Date: Wed, 29 Jan 2025 00:03:45 +0100 Subject: [PATCH 07/13] Add Currency import --- desktop-app/in_ou/income_outcome.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index 4a128f0..f737e5c 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -4,7 +4,8 @@ from datetime import datetime from peewee import IntegrityError, Model, CharField, BigIntegerField, ForeignKeyField from account.account import AccountManager, SQLError, db, Account, CURRENCY_MAP -from money import Monetary +from money import Monetary, Currency +from currencies import PLN class Operations(Model): From cc7ee0faa0ecd49f34a683ac0f688544ffabc207 Mon Sep 17 00:00:00 2001 From: marekwocka Date: Wed, 29 Jan 2025 00:03:52 +0100 Subject: [PATCH 08/13] Change GENERIC_CURRENCY to imported one from module currencies --- desktop-app/in_ou/income_outcome.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index f737e5c..11d8a2e 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -22,11 +22,7 @@ class Meta: database = db class Transactions: - GENERIC_CURRENCY = { - "code": "PLN", - "base": 10, - "exponent": 2 - } + GENERIC_CURRENCY = PLN def __init__(self, table_name='operations'): if not re.match(r'^\w+$', table_name): # bez znaków specjalnych w nazwie tabeli From 29b1b4c98c27f6890f37653eb2511f5f87a27a6d Mon Sep 17 00:00:00 2001 From: marekwocka Date: Wed, 29 Jan 2025 00:04:01 +0100 Subject: [PATCH 09/13] Refactor (again) entry type checking from repeated list to private tuple parameter --- desktop-app/in_ou/income_outcome.py | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index 11d8a2e..33f0bbb 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -30,6 +30,7 @@ def __init__(self, table_name='operations'): self.table_name = table_name self.transactions = [] self.load_budget_from_file() + self.__entry_types = ('income', 'outcome') def create_table(self): From df066023d58042078b3a97dc321068361d088874 Mon Sep 17 00:00:00 2001 From: marekwocka Date: Wed, 29 Jan 2025 00:04:12 +0100 Subject: [PATCH 10/13] Update (again) with Monetary class --- desktop-app/in_ou/income_outcome.py | 100 ++++++++++++++-------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index 33f0bbb..30b92ec 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -53,10 +53,9 @@ def save_budget_to_file(self): with db.atomic(): Operations.delete().execute() for entry in self.transactions: - amount_in_grosze = int(round(entry['amount'] * 100)) Operations.create( entry_type=entry['type'], - amount=amount_in_grosze, + amount=entry['amount'], description=entry['description'], category=entry['category'], date=entry['date'], @@ -76,13 +75,10 @@ def load_budget_from_file(self): for row in rows: try: - currency_code = row.account_id.currency_id - transaction_currency = CURRENCY_MAP.get(currency_code, self.GENERIC_CURRENCY) - self.transactions.append({ 'id': row.id, 'type': row.entry_type, - 'amount': Monetary(row.amount, transaction_currency).amount / 100, + 'amount': row.amount, 'description': row.description, 'category': row.category, 'date': row.date, @@ -93,7 +89,7 @@ def load_budget_from_file(self): self.transactions.append({ 'id': row.id, 'type': row.entry_type, - 'amount': row.amount / 100, + 'amount': row.amount, 'description': row.description, 'category': row.category, 'date': row.date, @@ -104,18 +100,17 @@ def load_budget_from_file(self): except Exception as e: print(f"Błąd podczas ładowania danych: {e}") - def add_budget_entry(self, account_id, entry_type, amount, description, category="brak kategorii"): + def add_budget_entry(self, account_id, entry_type: str, entry: Monetary, description: str, category: str="brak kategorii") -> None: errors = [] - if entry_type not in ["income", "outcome"]: + if entry_type not in self.__entry_types: errors.append("Błąd: Nieprawidłowy rodzaj wpisu. Wybierz 'income' lub 'outcome'.") - try: - amount = float(amount) - if amount <= 0: - errors.append("Błąd: Kwota musi być dodatnia.") - except ValueError: - errors.append("Błąd: Kwota musi być liczbą.") + if not isinstance(entry, Monetary): + errors.append("Blad: Wpis jest złego typu danych") + + if entry.amount < 0: + errors.append("Błąd: Kwota musi być liczbą nieujemną.") if len(description) > 255: errors.append("Błąd: Opis jest za długi (maksymalnie 255 znaków).") @@ -130,26 +125,23 @@ def add_budget_entry(self, account_id, entry_type, amount, description, category print(error) return - amount_in_grosze = int(round(amount * 100)) try: account = Account.get(Account.account_id == account_id) currency_code = account.currency_id - transaction_currency = CURRENCY_MAP[currency_code] Operations.create( entry_type=entry_type, - amount=amount_in_grosze, + amount=entry.amount, description=description, category=category, date=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), account_id=account_id ) - transaction_monetary = Monetary(amount_in_grosze, transaction_currency) - AccountManager.modify_balance(account_id, transaction_monetary, entry_type) + AccountManager.modify_balance(account_id, entry, entry_type) print( - f"Pomyślnie dodano wpis: {entry_type}, {amount:.2f} PLN, {description}, {category}, konto: {account_id}" + f"Pomyślnie dodano wpis: {entry_type}, {entry}, {description}, {category}, konto: {account_id}" ) except IntegrityError as e: @@ -178,10 +170,10 @@ def add_budget_entry_input(self): entry_type = input( "Wprowadź rodzaj wpisu ('income' dla dochodu lub 'outcome' dla wydatku, lub 'exit' aby zakończyć): " ).strip().lower() - if entry_type in ["income", "outcome"]: + if entry_type in self.__entry_types: break elif entry_type == "exit": - print("Zakończono dodawanie wpisu.") + print("Przerwano dodawanie wpisu.") return else: print("Niepoprawny rodzaj wpisu. Spróbuj ponownie.") @@ -204,6 +196,9 @@ def add_budget_entry_input(self): if not category: category = "Brak kategorii" # Domyślna kategoria + currency = AccountManager.get_account_currency(account_id) + amount = Monetary.major_to_minor_unit(amount, currency) + amount = Monetary(amount, currency) self.add_budget_entry(account_id, entry_type, amount, description, category) def show_budget(self, account_id=None): @@ -212,7 +207,7 @@ def show_budget(self, account_id=None): budgets = [{ 'id': row.id, 'type': row.entry_type, - 'amount': row.amount / 100, + 'amount': row.amount, 'description': row.description, 'category': row.category, 'date': row.date, @@ -226,7 +221,7 @@ def show_budget(self, account_id=None): budgets = [{ 'id': row.id, 'type': row.entry_type, - 'amount': row.amount / 100, + 'amount': row.amount, 'description': row.description, 'category': row.category, 'date': row.date, @@ -241,7 +236,7 @@ def show_budget(self, account_id=None): sorted_budgets = sorted(budgets, key=lambda x: x['date']) for i, entry in enumerate(sorted_budgets, 1): category = entry.get('category', 'Brak kategorii') - print(f"ID: {entry['id']}, {entry['type']}: {entry['amount']:.2f} PLN, {entry['description']} " + print(f"ID: {entry['id']}, {entry['type']}: {entry['amount']}, {entry['description']} " f"(Kategoria: {category}, Data: {entry['date']}, Konto: {entry['account_id']})") except Exception as e: @@ -252,13 +247,13 @@ def show_budget_summary(self): print("Brak danych do podsumowania.") return try: - income = sum(entry['amount'] for entry in self.transactions if entry['type'] == 'income') + incomes = sum(entry['amount'] for entry in self.transactions if entry['type'] == 'income') expenses = sum(entry['amount'] for entry in self.transactions if entry['type'] == 'outcome') - balance = income - expenses + balance = incomes - expenses print("Podsumowanie transakcji:") - print(f" - Dochody: {income:.2f} PLN") - print(f" - Wydatki: {expenses:.2f} PLN") - print(f" - Saldo: {balance:.2f} PLN") + print(f" - Dochody: {incomes}") + print(f" - Wydatki: {expenses}") + print(f" - Saldo: {balance}") except KeyError as e: print(f"Błąd: brakuje klucza w danych wpisu budżetowego ({e})") @@ -272,7 +267,7 @@ def show_incomes_by_category(self, category): return print(f"Lista dochodów w kategorii '{category}':") for i, entry in enumerate(incomes, 1): - print(f"{i}. Kwota: {entry['amount']:.2f} PLN, Opis: {entry['description']}, Data: {entry['date']}") + print(f"{i}. Kwota: {entry['amount']}, Opis: {entry['description']}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych transakcji: ({e}).") except Exception as e: @@ -288,7 +283,7 @@ def show_outcomes_by_category(self, category): return print(f"Lista wydatków w kategorii '{category}':") for i, entry in enumerate(outcomes, 1): - print(f"{i}. Kwota: {entry['amount']:.2f} PLN, Opis: {entry['description']}, Data: {entry['date']}") + print(f"{i}. Kwota: {entry['amount']}, Opis: {entry['description']}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych transakcji ({e}).") except Exception as e: @@ -303,7 +298,7 @@ def show_incomes(self): return print("Lista dochodów: ") for i, entry in enumerate(incomes, 1): - print(f"{i}. Kwota: {entry['amount']:.2f} PLN, Opis: {entry['description']}, Kategoria: " + print(f"{i}. Kwota: {entry['amount']}, Opis: {entry['description']}, Kategoria: " f"{entry.get('category', 'Brak kategorii')}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych transakcji ({e}). ") @@ -319,7 +314,7 @@ def show_outcomes(self): return print("Lista wydatków: ") for i, entry in enumerate(outcomes, 1): - print(f"{i}. Kwota: {entry['amount']:.2f} PLN, Opis: {entry['description']}, " + print(f"{i}. Kwota: {entry['amount']}, Opis: {entry['description']}, " f"Kategoria: {entry.get('category', 'Brak kategorii')}, Data: {entry['date']}") except KeyError as e: print(f"Błąd: Brakuje klucza w danych transakcji: ({e}).") @@ -341,24 +336,30 @@ def edit_budget_entry(self, entry_id, new_entry_type=None, new_amount=None, new_ # Pobranie transakcji entry = Operations.get_by_id(entry_id) + account_id = entry.account_id + currency = AccountManager.get_account_currency(account_id) + amount = Monetary.major_to_minor_unit(entry.get('amount'), currency) + old_entry_monetary = Monetary(amount, currency) + print( - f"Edycja wpisu: {entry.entry_type} - {entry.amount / 100:.2f} PLN, {entry.description}, {entry.category}" + f"Edycja wpisu: {entry.entry_type} - {old_entry_monetary}, {entry.description}, {entry.category}" ) old_type = entry.entry_type - old_amount = entry.amount account_id = entry.account_id.account_id - if new_entry_type and new_entry_type in ["income", "outcome"]: + if new_entry_type and new_entry_type in self.__entry_types: entry.entry_type = new_entry_type else: print("Nie zmieniono typu wpisu lub podano nieprawidłowy typ.") if new_amount is not None: try: - new_amount_grosze = int(round(float(new_amount) * 100)) - if new_amount_grosze > 0: - entry.amount = new_amount_grosze + new_amount = (float(new_amount)) + new_amount = Monetary.major_to_minor_unit(new_amount, currency) + new_entry_monetary = Monetary(new_amount, currency) + if new_entry_monetary.amount > 0: + entry.amount = new_entry_monetary.amount else: print("Kwota musi być dodatnia. Nie zmieniono wartości.") except ValueError: @@ -374,16 +375,16 @@ def edit_budget_entry(self, entry_id, new_entry_type=None, new_amount=None, new_ balance_difference = 0 if old_type == 'income': - balance_difference -= old_amount + balance_difference -= old_entry_monetary.amount elif old_type == 'outcome': - balance_difference += old_amount + balance_difference += old_entry_monetary.amount if entry.entry_type == 'income': - balance_difference += entry.amount + balance_difference += new_entry_monetary.amount elif entry.entry_type == 'outcome': - balance_difference -= entry.amount + balance_difference -= new_entry_monetary.amount - transaction_monetary = Monetary(abs(balance_difference), {"code": "PLN", "base": 10, "exponent": 2}) + transaction_monetary = Monetary(abs(balance_difference), currency) if balance_difference > 0: AccountManager.modify_balance(account_id, transaction_monetary, 'income') @@ -408,13 +409,14 @@ def delete_budget_entry(self, entry_id): return entry = Operations.get_by_id(entry_id) - account_id = entry.account_id.account_id - amount_in_grosze = entry.amount + account_id = entry.get('account_id') + amount = entry.amount + currency = AccountManager.get_account_currency(account_id) transaction_type = entry.entry_type entry.delete_instance() - transaction_monetary = Monetary(amount_in_grosze, {"code": "PLN", "base": 10, "exponent": 2}) + transaction_monetary = Monetary(amount, currency) if transaction_type == 'income': AccountManager.modify_balance(account_id, transaction_monetary, 'outcome') elif transaction_type == 'outcome': From af4e0fed392474e7a7200424fac144dcb65c55ff Mon Sep 17 00:00:00 2001 From: marekwocka Date: Thu, 30 Jan 2025 22:11:03 +0100 Subject: [PATCH 11/13] Fix getting property values --- desktop-app/in_ou/income_outcome.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index 30b92ec..e487e5b 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -338,7 +338,7 @@ def edit_budget_entry(self, entry_id, new_entry_type=None, new_amount=None, new_ entry = Operations.get_by_id(entry_id) account_id = entry.account_id currency = AccountManager.get_account_currency(account_id) - amount = Monetary.major_to_minor_unit(entry.get('amount'), currency) + amount = Monetary.major_to_minor_unit(entry.amount, currency) old_entry_monetary = Monetary(amount, currency) print( From 60169c161f0e8df58d1e59c5a78dcde48ca4db36 Mon Sep 17 00:00:00 2001 From: marekwocka Date: Thu, 30 Jan 2025 22:11:29 +0100 Subject: [PATCH 12/13] Fix getting property values --- desktop-app/in_ou/income_outcome.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop-app/in_ou/income_outcome.py b/desktop-app/in_ou/income_outcome.py index e487e5b..5afddde 100644 --- a/desktop-app/in_ou/income_outcome.py +++ b/desktop-app/in_ou/income_outcome.py @@ -409,7 +409,7 @@ def delete_budget_entry(self, entry_id): return entry = Operations.get_by_id(entry_id) - account_id = entry.get('account_id') + account_id = entry.account_id amount = entry.amount currency = AccountManager.get_account_currency(account_id) transaction_type = entry.entry_type From b8fb5b0a2ce0cdbe38ec1ea1ece68012bed84197 Mon Sep 17 00:00:00 2001 From: marekwocka Date: Thu, 30 Jan 2025 22:19:09 +0100 Subject: [PATCH 13/13] Fix import paths --- desktop-app/account/account.py | 6 +++--- desktop-app/currencies/_eur.py | 2 +- desktop-app/currencies/_pln.py | 2 +- desktop-app/currencies/_usd.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/desktop-app/account/account.py b/desktop-app/account/account.py index 39a840a..60cfb0b 100644 --- a/desktop-app/account/account.py +++ b/desktop-app/account/account.py @@ -2,8 +2,8 @@ from peewee import SqliteDatabase, Model, AutoField, BigIntegerField, CharField, IntegrityError, \ DoesNotExist, OperationalError -from money import Monetary, Currency -import currencies +from ..money import Monetary, Currency +from .. import currencies CURRENCY_MAP = { 'EUR': currencies.EUR, @@ -130,7 +130,7 @@ def modify_balance(account_id: int, transaction_amount: Monetary, transaction_ty raise SQLError('Wystąpił błąd bazy danych.') from None @staticmethod - def get_account_currency(self, account_id: int) -> Currency: + def get_account_currency(account_id: int) -> Currency: if account_id: try: record = Account.select().where(Account.account_id == account_id).get() diff --git a/desktop-app/currencies/_eur.py b/desktop-app/currencies/_eur.py index b3b5680..0340da5 100644 --- a/desktop-app/currencies/_eur.py +++ b/desktop-app/currencies/_eur.py @@ -1,4 +1,4 @@ -from money.currency import Currency +from ..money.currency import Currency EUR: Currency = { "code": "EUR", diff --git a/desktop-app/currencies/_pln.py b/desktop-app/currencies/_pln.py index eb964ac..82cf6af 100644 --- a/desktop-app/currencies/_pln.py +++ b/desktop-app/currencies/_pln.py @@ -1,4 +1,4 @@ -from money.currency import Currency +from ..money.currency import Currency PLN: Currency = { "code": "PLN", diff --git a/desktop-app/currencies/_usd.py b/desktop-app/currencies/_usd.py index b961b8f..f16de97 100644 --- a/desktop-app/currencies/_usd.py +++ b/desktop-app/currencies/_usd.py @@ -1,4 +1,4 @@ -from money.currency import Currency +from ..money.currency import Currency USD: Currency = { "code": "USD",