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
Example #2
0
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