Created
March 18, 2024 09:48
-
-
Save azylinski/1c09e4ffd552d3a382ff3844ccc76268 to your computer and use it in GitHub Desktop.
katas/bank
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime | |
from dataclasses import dataclass | |
# exceptions.py | |
class NoMoneyException(Exception): | |
pass | |
class InvalidValueException(Exception): | |
pass | |
@dataclass | |
class TransactionLog: | |
created_at: datetime.datetime | |
amount: int | |
# 14/01/2012 || -500 || 2500 | |
def print(self, current_balance): | |
return f"{self.created_at} || {self.amount} || {current_balance}\n" | |
NO_TRANSACTIONS_MSG = "no transactions yet" | |
class AccountService: | |
transactionLog : list[TransactionLog] | |
blanace : int # RO: current balance; to speed up validation | |
def __init__(self): | |
self.transactionLog = [] | |
self.blanace = 0 | |
def deposit(self, amount:int): | |
if amount <= 0: | |
raise InvalidValueException(f"amount must be positive; got: {amount}") | |
self._update_balance(amount) | |
def withdraw(self, amount:int): | |
if amount <= 0: | |
raise InvalidValueException(f"amount must be positive; got: {amount}") | |
if amount > self.blanace: | |
raise NoMoneyException(f"not enough money on the accout; want: {amount} got {self.blanace}") | |
self._update_balance(-amount) | |
def printStatement(self): | |
# TODO: max transactions | |
# TODO: print from latest | |
if len(self.transactionLog) == 0: | |
return NO_TRANSACTIONS_MSG | |
self._prepre_for_print() | |
log = self.transactionLog # deepcopy | |
log.reverse() | |
out = "Date || Amount || Balance\n" | |
current_balance = self.blanace | |
for tl in log: | |
out += tl.print(current_balance) | |
current_balance += -tl.amount | |
return out | |
def _update_balance(self, amount:int): | |
# TODO: wrap for test with static time | |
time_now = datetime.datetime.now() | |
tl = TransactionLog( | |
created_at=time_now, | |
amount=amount, | |
) | |
self.transactionLog.append(tl) | |
self.blanace += amount | |
def test_NoTransactions(): | |
ac = AccountService() | |
got = ac.printStatement() | |
want = NO_TRANSACTIONS_MSG | |
assert got == want | |
def test_NoMoneyValidation(): | |
ac = AccountService() | |
ac.deposit(100) | |
# assert NoMoneyException: | |
# ac.withdraw(300) | |
def test_SingleTransaction(): | |
ac = AccountService() | |
ac.deposit(100) | |
want = """ | |
Date || Amount || Balance | |
14/01/2012 || 100 || 100 | |
""" | |
got = ac.printStatement() | |
assert got == want | |
def test_ProvidedInput(): | |
ac = AccountService() | |
ac.deposit(1000) | |
ac.deposit(2000) | |
ac.withdraw(500) | |
want = """ | |
Date || Amount || Balance | |
14/01/2012 || -500 || 2500 | |
13/01/2012 || 2000 || 3000 | |
10/01/2012 || 1000 || 1000 | |
""" | |
got = ac.printStatement() | |
assert got == want | |
# #2: validation: not an int; float, "above limit" (max-int), ... | |
# #3: possive scenario: 10x deposits, 10x withdraw, print - expect 0 balance left; expect 20 lines in print... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment