def __init__(self, config: Optional[str] = None): create_db() fill_db() # parse config if exists try: _config_path = Path(config) with open(_config_path) as file: _config = yaml.safe_load(file)["config"] except TypeError: LOGGER.INFO("No config file specified. Falling back to default") _config = {} except FileNotFoundError: LOGGER.INFO("Config file not found. Falling back to default") _config = {} self.name = _config.get("name", "BankLite") # defaults to BankLite self.currency = _config.get("currency", "USD") # defaults to USD self.initial_reserve = _config.get("initial_reserve", 1e9) # defaults to 1 billion self.conn = sqlite3.connect("banklite.db", check_same_thread=False) # main services self.ledger_service = LedgerService(conn=self.conn) self.account_service = AccountService(conn=self.conn) self.customer_service = CustomerService(conn=self.conn) # create reserve account self.reserve_account = self.account_service.create_reserve_account() # fill reserve with initial deposit self.ledger_service.record_entry( account=self.reserve_account, amount=self.initial_reserve )
def test_get_account_by_id_not_exists(database_setup): conn = database_setup account_service = AccountService(conn=conn) acct = account_service.get_account_by_id("1234567890") assert acct is None
def test_get_account_balance(database_setup): conn = database_setup account_service = AccountService(conn=conn) ledger_service = LedgerService(conn=conn) acct = BaseAccount("0000000001", "0000000001") ledger_service.record_entry(account=acct, amount=100) ledger_service.record_entry(account=acct, amount=100) assert account_service.get_account_balance(acct.account_id) == 200.0
def test_savings_account_creation(database_setup): conn = database_setup account_service = AccountService(conn=conn) customer = BaseCustomer("1111111111", 11111, "555-555-5555", "*****@*****.**") account_service.create_savings_account(customer=customer, rate=0.03) acct_id, customer_id, _, acct_type, acct_rate = conn.execute( "SELECT * FROM accounts" ).fetchall()[0] assert acct_type == 2 assert acct_rate == 0.03
def test_get_reserve_account_by_id(database_setup): conn = database_setup account_service = AccountService(conn=conn) account_service.create_reserve_account() acct = account_service.get_account_by_id("1") assert acct is not None assert type(acct) == ReserveAccount assert acct.account_id == "0000000001" assert acct.customer_id is None assert acct.type == 0 assert acct.rate == 0.0
def test_reserve_account_creation(database_setup): conn = database_setup account_service = AccountService(conn=conn) account_service.create_reserve_account() acct_id, customer_id, _, acct_type, acct_rate = conn.execute( "SELECT * FROM accounts" ).fetchall()[0] assert acct_id == "1" assert customer_id is None assert acct_type == 0 assert acct_rate == 0.0
def open_checking_account(self, customer_id: Union[str, int], deposit_amount: float) -> CheckingAccount: """ Opens a checking account for the customer associated with the ID passed in :param customer_id: ID of customer :param deposit_amount: Amount for initial account deposit :return: Checking account created """ account_service = AccountService(conn=self.conn) ledger_service = LedgerService(conn=self.conn) customer = self.get_customer_by_id(customer_id=customer_id) acct = account_service.create_checking_account(customer=customer) ledger_service.record_entry(account=acct, amount=deposit_amount) return acct
def test_get_checking_account_by_id(database_setup): conn = database_setup account_service = AccountService(conn=conn) conn.execute( """ INSERT INTO accounts values ('1234567890', '1234567890', DATETIME('now'), 1, 0.0) """ ) acct = account_service.get_account_by_id("1234567890") assert acct is not None assert type(acct) == CheckingAccount assert acct.account_id == "1234567890" assert acct.customer_id == "1234567890" assert acct.type == 1 assert acct.rate == 0.0
def test_get_accounts_by_id(database_setup): conn = database_setup account_service = AccountService(conn=conn) conn.execute( """ INSERT INTO accounts VALUES ('1111111111', '1234567890', DATETIME('now'), 1, 0.0), ('2222222222', '1234567891', DATETIME('now'), 1, 0.0), ('3333333333', '1234567892', DATETIME('now'), 2, 0.03) """ ) accts = account_service.get_accounts_by_id(["1111111111", "2222222222", "3333333333"]) assert len(accts) == 3 acct1 = accts[0] assert type(acct1) == CheckingAccount assert acct1.account_id == "1111111111" assert acct1.customer_id == "1234567890" assert acct1.type == 1 assert acct1.rate == 0.0 acct2 = accts[1] assert type(acct2) == CheckingAccount assert acct2.account_id == "2222222222" assert acct2.customer_id == "1234567891" assert acct2.type == 1 assert acct2.rate == 0.0 acct3 = accts[2] assert type(acct3) == SavingsAccount assert acct3.account_id == "3333333333" assert acct3.customer_id == "1234567892" assert acct3.type == 2 assert acct3.rate == 0.03
def test_list_accounts(database_setup): conn = database_setup customer_service = CustomerService(conn) account_service = AccountService(conn) customer = customer_service.create_retail_customer(11111, "555-555-5555", "*****@*****.**", "111-11-1111", "John", "Doe") customer_id = customer.customer_id account_service.create_checking_account(customer) account_service.create_checking_account(customer) account_service.create_checking_account(customer) accounts = customer_service.list_accounts(customer_id) assert len(accounts) == 3
class BankLite: """ BankLite controller object """ def __init__(self, config: Optional[str] = None): create_db() fill_db() # parse config if exists try: _config_path = Path(config) with open(_config_path) as file: _config = yaml.safe_load(file)["config"] except TypeError: LOGGER.INFO("No config file specified. Falling back to default") _config = {} except FileNotFoundError: LOGGER.INFO("Config file not found. Falling back to default") _config = {} self.name = _config.get("name", "BankLite") # defaults to BankLite self.currency = _config.get("currency", "USD") # defaults to USD self.initial_reserve = _config.get("initial_reserve", 1e9) # defaults to 1 billion self.conn = sqlite3.connect("banklite.db", check_same_thread=False) # main services self.ledger_service = LedgerService(conn=self.conn) self.account_service = AccountService(conn=self.conn) self.customer_service = CustomerService(conn=self.conn) # create reserve account self.reserve_account = self.account_service.create_reserve_account() # fill reserve with initial deposit self.ledger_service.record_entry( account=self.reserve_account, amount=self.initial_reserve ) def __repr__(self): return f"BankLite(name={self.name!r})" def create_new_customer( self, customer_type: str, **kwargs ) -> Union[BaseCustomer, RetailCustomer, CommercialCustomer, None]: """ Factory object creator for customer objects :param customer_type: Either `retail` or `commercial` :return: Customer object """ if customer_type == "retail": customer = self.customer_service.create_retail_customer(**kwargs) elif customer_type == "commercial": customer = self.customer_service.create_commercial_customer(**kwargs) else: LOGGER.DEBUG("Invalid customer type: %s", customer_type) return None return customer def open_account( self, acct_type: str, customer_id: str, deposit_amount: float, savings_rate: Optional[float] = 0.0, ) -> Union[BaseAccount, None]: """ Factory object creator for account objects :param acct_type: Either `checking` or `savings` :param customer_id: ID of customer opening account :param deposit_amount: Amount to deposit (must be positive value) :param savings_rate: If the account is a savings account, a savings rate must be passed in :return: Account object """ if acct_type == "checking": account = self.customer_service.open_checking_account(customer_id, deposit_amount) elif acct_type == "savings": account = self.customer_service.open_savings_account( customer_id, deposit_amount, savings_rate ) else: LOGGER.DEBUG("Invalid account type: %s", acct_type) return None return account def deposit(self, account_id: str, amount: float) -> Union[float, None]: """ Deposit amount into an account :param account_id: ID of account :param amount: Amount to deposit :return: Resulting account balance """ account = self.account_service.get_account_by_id(account_id) if account and amount > 0: self.ledger_service.record_entry(account, amount) return self.account_service.get_account_balance(account.account_id) elif amount <= 0: return self.account_service.get_account_balance(account.account_id) else: return None def withdraw(self, account_id: str, amount: float) -> Union[float, None]: """ Withdraw amount from account :param account_id: ID of account :param amount: Amount to withdraw :return: Resulting account balance """ account = self.account_service.get_account_by_id(account_id) if amount > self.account_service.get_account_balance(account_id): return None if account and amount < 0: self.ledger_service.record_entry(account, amount) return self.account_service.get_account_balance(account.account_id) elif amount >= 0: return self.account_service.get_account_balance(account.account_id) else: return None