diff --git a/in-ou/budget_manager.py b/in-ou/budget_manager.py index 1880c10..fa8e79f 100644 --- a/in-ou/budget_manager.py +++ b/in-ou/budget_manager.py @@ -1,12 +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) @@ -18,7 +22,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 @@ -54,33 +58,36 @@ 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"): - if entry_type not in ["income", "outcome"]: + 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: 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.") @@ -106,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): @@ -115,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): @@ -123,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 @@ -142,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: @@ -157,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: @@ -172,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}). ") @@ -187,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}).") @@ -197,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() @@ -207,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ść.") @@ -217,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']}") @@ -226,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() @@ -241,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}") diff --git a/in-ou/income-outcome-test.py b/in-ou/income-outcome-test.py index 0dfdbf6..0544a65 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' ) @@ -117,4 +128,4 @@ def test_show_outcomes(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main()