diff --git a/Colaborators/colaborators.md b/Colaborators/colaborators.md index ddb715d..a85f034 100644 --- a/Colaborators/colaborators.md +++ b/Colaborators/colaborators.md @@ -1,39 +1,35 @@ + # Our Amazing Collaborators 🌟 Thank you to all the wonderful people who have contributed to this project! ---- - 1. Harry Guajan [@Harry-GNS](https://github.com/Harry-GNS) Ecuador 🇪🇨 "To see the world, things dangerous to come to, to see behind walls, draw closer, to find each other and to feel. That is the purpose of life." ---- - 2. Srijani Das [@Srijani-Das07](https://github.com/Srijani-Das07) India 🇮🇳 "Small steps, lasting impact." ---- - 3. Ofek Hodis [@Ofek-Hodis](https://github.com/Ofek-Hodis) Anonymous :) "It is necessary to have been ruined over generations repairing the old, crumbling castle in order to learn to love it." ---- - 4. Shanmukh [@krishn212](https://github.com/krishn212) India 🇮🇳 "The secret of getting ahead is getting started." ---- - 1. Shyamsundar [@Shyamsundar-eng](https://github.com/Shyamsundar-eng) India 🇮🇳 "Learning in public, one commit at a time." +2. Diego Alexander +[@Dm2998](https://github.com/Dm2998) +Ireland 🇮🇪 +"Every small commit is a step toward becoming a better developer." + diff --git a/new_projects/banking_system/accounts.py b/new_projects/banking_system/accounts.py index d7aed7e..9d16c5e 100644 --- a/new_projects/banking_system/accounts.py +++ b/new_projects/banking_system/accounts.py @@ -1,43 +1,48 @@ +class InsufficientFundsError(Exception): + """Raised when withdrawal amount exceeds available balance.""" + pass + + class Account: - def __init__(self, account_number, customer_name, initial_balance=0): - self.__account_number = account_number - self.__customer_name = customer_name - self.__balance = initial_balance + """Represents a bank account.""" + + def __init__(self, account_number: str, customer_name: str, initial_balance: float = 0.0): + self._account_number = account_number + self._customer_name = customer_name + self._balance = initial_balance @property def account_number(self): - return self.__account_number + return self._account_number @property def customer_name(self): - return self.__customer_name + return self._customer_name @property def balance(self): - return self.__balance + return self._balance - def deposit(self, amount): + def deposit(self, amount: float) -> float: + """Deposit a positive amount into the account.""" if amount <= 0: raise ValueError("Deposit amount must be positive.") - self.__balance += amount - return self.__balance - - def to_dict(self): - return { - "account_number": self.__account_number, - "customer_name": self.__customer_name, - "balance": self.__balance - } + self._balance += amount + return self._balance - def withdraw(self, amount): + def withdraw(self, amount: float) -> float: + """Withdraw a positive amount from the account.""" if amount <= 0: raise ValueError("Withdrawal amount must be positive.") - if self.__balance >= amount: - self.__balance -= amount - return self.__balance - else: + if amount > self._balance: raise InsufficientFundsError("Insufficient funds.") + self._balance -= amount + return self._balance -class InsufficientFundsError(Exception): - pass - + def to_dict(self) -> dict: + """Convert account data to dictionary for persistence.""" + return { + "account_number": self._account_number, + "customer_name": self._customer_name, + "balance": self._balance + } diff --git a/new_projects/banking_system/bankmanager.py b/new_projects/banking_system/bankmanager.py index a71622f..ae64eee 100644 --- a/new_projects/banking_system/bankmanager.py +++ b/new_projects/banking_system/bankmanager.py @@ -1,62 +1,78 @@ +import json +import os +import random from accounts import Account -import random,os,json + + +class AccountIDError(Exception): + """Raised when an account ID is invalid or already exists.""" + pass + + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +DATA_FILE = os.path.join(BASE_DIR, "accounts.json") class BankManager: + """Handles account creation, transactions, and persistence.""" + def __init__(self): - self.__accounts = {} + self._accounts = {} self.load_accounts() def load_accounts(self): - if os.path.exists("accounts.json"): - with open("accounts.json", "r") as f: - accounts_data = json.load(f) - for acc_id, acc_info in accounts_data.items(): - account = Account(acc_info["account_number"], acc_info["customer_name"], acc_info["balance"]) - self.__accounts[acc_id] = account + """Load accounts from JSON file if it exists.""" + if os.path.exists(DATA_FILE): + with open(DATA_FILE, "r") as file: + data = json.load(file) + for acc_id, info in data.items(): + self._accounts[acc_id] = Account( + info["account_number"], + info["customer_name"], + info["balance"] + ) def save_accounts(self): - accounts_data = {acc_id: acc.to_dict() for acc_id, acc in self.__accounts.items()} - with open("accounts.json", "w") as f: - json.dump(accounts_data, f, indent=4) + """Save all accounts to JSON file.""" + with open(DATA_FILE, "w") as file: + json.dump( + {acc_id: acc.to_dict() for acc_id, acc in self._accounts.items()}, + file, + indent=4 + ) - def create_account_id(self): + def create_account_id(self) -> str: + """Generate a unique account ID.""" while True: - account_id = str(random.randint(100000, 999999)) - if account_id not in self.__accounts: - return account_id - - def create_account(self, account_id, name, initial_deposit=0.0): - if account_id in self.__accounts: - raise iderror("Account ID already exists.") - new_account = Account(account_id, name, initial_deposit) - self.__accounts[account_id] = new_account + acc_id = str(random.randint(100000, 999999)) + if acc_id not in self._accounts: + return acc_id + + def create_account(self, name: str, initial_deposit: float) -> Account: + """Create a new bank account.""" + acc_id = self.create_account_id() + account = Account(acc_id, name, initial_deposit) + self._accounts[acc_id] = account self.save_accounts() - return new_account - - def get_account(self, account_id): - return self.__accounts.get(account_id, None) - - def deposit_to_account(self, account_id, amount): - account = self.get_account(account_id) - if account: - self.save_accounts() - return account.deposit(amount) - else: - raise iderror("Account ID does not exist.") - - def withdraw_from_account(self, account_id, amount): - account = self.get_account(account_id) - if account: - self.save_accounts() - return account.withdraw(amount) - raise iderror("Account ID does not exist.") - - def get_account_balance(self, account_id): - account = self.get_account(account_id) - if account: - return account.balance - return None - -class iderror(Exception): - pass \ No newline at end of file + return account + + def get_account(self, acc_id: str) -> Account: + account = self._accounts.get(acc_id) + if not account: + raise AccountIDError("Account ID does not exist.") + return account + + def deposit(self, acc_id: str, amount: float) -> float: + account = self.get_account(acc_id) + account.deposit(amount) + self.save_accounts() + return account.balance + + def withdraw(self, acc_id: str, amount: float) -> float: + account = self.get_account(acc_id) + account.withdraw(amount) + self.save_accounts() + return account.balance + + def get_balance(self, acc_id: str) -> float: + return self.get_account(acc_id).balance diff --git a/new_projects/banking_system/main.py b/new_projects/banking_system/main.py index f1c1a47..23a04c1 100644 --- a/new_projects/banking_system/main.py +++ b/new_projects/banking_system/main.py @@ -1,64 +1,59 @@ +from bankmanager import BankManager, AccountIDError from accounts import InsufficientFundsError -from bankmanager import BankManager, iderror + + +def get_float(prompt: str) -> float: + while True: + try: + return float(input(prompt)) + except ValueError: + print("Please enter a valid number.") + def main(): - manager=BankManager() - print("Welcome to the Bank Management System") + manager = BankManager() + print("Welcome to the Banking Management System") + while True: - print("\nBank Management System") - print("1. Create Account") + print("\n1. Create Account") print("2. Deposit") print("3. Withdraw") print("4. Check Balance") print("5. Exit") - choice = input("Enter your choice: ") + choice = input("Choose an option: ") + + try: + if choice == "1": + name = input("Customer name: ") + amount = get_float("Initial deposit: ") + account = manager.create_account(name, amount) + print(f"Account created. ID: {account.account_number}") + + elif choice == "2": + acc_id = input("Account ID: ") + amount = get_float("Deposit amount: ") + print("New balance:", manager.deposit(acc_id, amount)) - if choice == '1': - name = input("Enter Customer Name: ") - initial_deposit = float(input("Enter Initial Deposit: ")) - account_id = manager.create_account_id() - try: - account = manager.create_account(account_id, name, initial_deposit) - print(f"Account ID: {account.account_number}") - print(f"Account created successfully for {account.customer_name} with balance {account.balance}.") - except iderror as e: - print(e) + elif choice == "3": + acc_id = input("Account ID: ") + amount = get_float("Withdrawal amount: ") + print("New balance:", manager.withdraw(acc_id, amount)) - elif choice == '2': - account_id = input("Enter Account ID: ") - amount = float(input("Enter Deposit Amount: ")) - try: - new_balance = manager.deposit_to_account(account_id, amount) - print(f"Deposit successful. New balance: {new_balance}.") - except iderror as e: - print(e) + elif choice == "4": + acc_id = input("Account ID: ") + print("Balance:", manager.get_balance(acc_id)) - elif choice == '3': - account_id = input("Enter Account ID: ") - amount = float(input("Enter Withdrawal Amount: ")) - try: - new_balance = manager.withdraw_from_account(account_id, amount) - print(f"Withdrawal successful. New balance: {new_balance}.") - except iderror as e: - print(e) - except InsufficientFundsError as e: - print(e) + elif choice == "5": + print("Goodbye!") + break - elif choice == '4': - account_id = input("Enter Account ID: ") - balance = manager.get_account_balance(account_id) - if balance is not None: - print(f"Account Balance: {balance}.") else: - print("Account ID does not exist.") + print("Invalid option.") - elif choice == '5': - print("Exiting the system.") - break + except (AccountIDError, InsufficientFundsError, ValueError) as e: + print("Error:", e) - else: - print("Invalid choice. Please try again.") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/new_projects/banking_system/tests/test_account.py b/new_projects/banking_system/tests/test_account.py new file mode 100644 index 0000000..96b8bc4 --- /dev/null +++ b/new_projects/banking_system/tests/test_account.py @@ -0,0 +1,32 @@ +# This file contains unit tests for the Account class in the banking system project. +# Unittest is used to create test cases for the deposit and withdraw methods, +# is a good practice to ensure that the Account class behaves as expected under various conditions, +# including handling insufficient funds and invalid deposit amounts. +# python -m unittest discover -s tests + +import unittest +from accounts import Account, InsufficientFundsError + + +class TestAccount(unittest.TestCase): + + def setUp(self): + self.account = Account("123456", "Test User", 100) + + def test_deposit(self): + self.assertEqual(self.account.deposit(50), 150) + + def test_withdraw(self): + self.assertEqual(self.account.withdraw(30), 70) + + def test_insufficient_funds(self): + with self.assertRaises(InsufficientFundsError): + self.account.withdraw(200) + + def test_negative_deposit(self): + with self.assertRaises(ValueError): + self.account.deposit(-10) + + +if __name__ == "__main__": + unittest.main()