Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 116 additions & 12 deletions abcbank/account.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from abcbank.date_provider import DateUtils
from abcbank.transaction import Transaction

CHECKING = 0
Expand All @@ -9,35 +10,138 @@ class Account:
def __init__(self, accountType):
self.accountType = accountType
self.transactions = []
self.availableBalance = 0

def deposit(self, amount):
if (amount <= 0):
def deposit(self, amount, date_deposited=None):
"""

:param amount: amount to be deposited
:param date_deposited: optional param; date of deposit
:return:
"""
if amount <= 0:
raise ValueError("amount must be greater than zero")
else:
self.transactions.append(Transaction(amount))
if date_deposited:
try:
date = DateUtils.toDate(date_deposited)
self.transactions.append(Transaction(amount, date))
except ValueError:
return ValueError("Incorrect date format")
else:
self.transactions.append(Transaction(amount))
self.availableBalance += amount

def withdraw(self, amount):
if (amount <= 0):
"""

:param amount: amount to be withdrawn
:return: None
"""
if amount <= 0:
raise ValueError("amount must be greater than zero")
elif amount > self.availableBalance:
raise ValueError("amount greater than available balance")
else:
self.transactions.append(Transaction(-amount))
self.availableBalance -= amount

def interestEarned(self):
amount = self.sumTransactions()
"""
calculate the interest annually

:return: interest payout for the customer
"""
amount = self.availableBalance
if self.accountType == SAVINGS:
if (amount <= 1000):
if amount <= 1000:
return amount * 0.001
else:
return 1 + (amount - 1000) * 0.002
if self.accountType == MAXI_SAVINGS:
if (amount <= 1000):
return amount * 0.02
elif (amount <= 2000):
return 20 + (amount - 1000) * 0.05
endDate = DateUtils.now()
startDate = DateUtils.add(endDate, -10)
_transactions = self.getTransaction(startDate, endDate)
withdrawn = 0
for t in _transactions:
if t.amount < 0:
withdrawn = 1
break
if withdrawn == 1:
return amount * (0.1 / 100.0)
else:
return 70 + (amount - 2000) * 0.1
return amount * (5 / 100.0)
else:
return amount * 0.001

def interest_earned_after_x_days(self, days=1):
"""
Calculate the interest after x days

:param days:
:return: return the Amount along with accrued interest
"""
amount = self.availableBalance
if self.accountType == SAVINGS:
if amount <= 1000:
return Account.daily_interest(amount, 0.1, days)
else:
return Account.daily_interest(amount - 1000, 0.2, days) + Account.daily_interest(1000, 0.1, days)
if self.accountType == MAXI_SAVINGS:
endDate = DateUtils.now()
startDate = DateUtils.add(endDate, -10)
_transactions = self.getTransaction(startDate, endDate)
withdrawn = 0
for t in _transactions:
if t.amount < 0:
withdrawn = 1
break
if withdrawn == 1:
return Account.daily_interest(amount, 0.1, days)
else:
return Account.daily_interest(amount, 5, days)
else:
return Account.daily_interest(amount, 0.1, days)

def sumTransactions(self, checkAllTransactions=True):
return sum([t.amount for t in self.transactions])
"""

:param checkAllTransactions:
:return: Return the sum of all transaction including debits and credits
"""
return sum([t.amount for t in self.transactions])

def getTransaction(self, startDate, endDate):
"""
Get the Customer Transaction between any time frame

:param startDate: Start Date
:param endDate: End Date
:return: List of Transaction between the start date and end date
"""
transaction_data = []
try:
start_date = DateUtils.toDate(startDate)
end_date = DateUtils.toDate(endDate)
except ValueError:
return ValueError("Incorrect date format")
for transaction in self.transactions:
if DateUtils.isDateWithinRange(transaction.transactionDate, startDate, endDate):
transaction_data.append(transaction)
return transaction_data

@staticmethod
def daily_interest(P, r, days):
"""
Calculate the Daily/Continuous Interest

:param P: Prinicipal Amount
:param r: Rate of Interest
:param days: No. of days upto which the interest is calculated
:return: Final amount with Interest accrued daily
"""
I = P
for x in range(days):
I *= 1 + ((r / 100.0) / 365.0)
return round(I, 2)

17 changes: 16 additions & 1 deletion abcbank/bank.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,38 @@ def __init__(self):
self.customers = []

def addCustomer(self, customer):
"""
Add a customer to the bank

:param customer: Customer Name
:return: None
"""
self.customers.append(customer)

def customerSummary(self):
summary = "Customer Summary"
for customer in self.customers:
summary = summary + "\n - " + customer.name + " (" + self._format(customer.numAccs(), "account") + ")"
return summary

def _format(self, number, word):
return str(number) + " " + (word if (number == 1) else word + "s")

def totalInterestPaid(self):
"""
Total Interest Paid for all customer for all acounts the customer possess

:return: interest payout
"""
total = 0
for c in self.customers:
total += c.totalInterestEarned()
return total

def getFirstCustomer(self):
try:
self.customers = None
return self.customers[0].name
except Exception as e:
print(e)
return "Error"
return "Error"
50 changes: 43 additions & 7 deletions abcbank/customer.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,66 @@
from account import CHECKING, SAVINGS, MAXI_SAVINGS
from account import CHECKING, SAVINGS, MAXI_SAVINGS, Account
from transaction import Transaction


class Customer:
def __init__(self, name):
self.name = name
self.accounts = []
self.accounts = {}

def openAccount(self, account):
self.accounts.append(account)
"""
Create/Open an account

:param account: account type
:return: Customer object
"""
if isinstance(account, Account):
self.accounts[account.accountType] = account
elif isinstance(account, int):
self.accounts[account] = Account(account)
return self

def transfer(self, fromAccount, toAccount, amount):
"""
Transfer money between the customer accounts

:param fromAccount: Account Type
:param toAccount: Account Type
:param amount: Amount to be transfered
:return: status of the transfer
"""
if fromAccount not in self.accounts or toAccount not in self.accounts:
return "Invalid Account"
_from = self.accounts[fromAccount]
_to = self.accounts[toAccount]
if _from.availableBalance < 0 or amount > _from.availableBalance:
return "Account does not have sufficient balance"
_from.availableBalance -= amount
_to.availableBalance += amount
_from.transactions.append(Transaction(-amount))
_to.transactions.append(Transaction(amount))
return "Transfer Succeeded"

def numAccs(self):
"""

:return: number of accounts the customer has opened
"""
return len(self.accounts)

def totalInterestEarned(self):
return sum([a.interestEarned() for a in self.accounts])
return sum([self.accounts[accountType].interestEarned() for accountType in self.accounts.keys()])

# This method gets a statement
def getStatement(self):
# JIRA-123 Change by Joe Bloggs 29/7/1988 start
statement = None # reset statement to null here
# JIRA-123 Change by Joe Bloggs 29/7/1988 end
totalAcrossAllAccounts = sum([a.sumTransactions() for a in self.accounts])
totalAcrossAllAccounts = sum(
[self.accounts[accountType].sumTransactions() for accountType in self.accounts.keys()])
statement = "Statement for %s" % self.name
for account in self.accounts:
statement = statement + self.statementForAccount(account)
for accountType in self.accounts.keys():
statement += self.statementForAccount(self.accounts[accountType])
statement = statement + "\n\nTotal In All Accounts " + _toDollars(totalAcrossAllAccounts)
return statement

Expand Down
81 changes: 78 additions & 3 deletions abcbank/date_provider.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,82 @@
from datetime import datetime
import datetime


class DateProvider:
class DateUtils:
@staticmethod
def now():
return datetime.now()
"""

:return: Current date time
"""
return datetime.datetime.now()

@staticmethod
def add(date, days):
"""
Add x days to the date

:param date: date in string format
:param days: number of days to be added
:return: date in string format
"""
return (DateUtils.toDate(date) + datetime.timedelta(days=days)).strftime("%m/%d/%Y")

@staticmethod
def toDate(date_str):
"""
Convert the date in string format to datetime format

:param date_str: date in string format
:return: date in datetime format
"""
if isinstance(date_str,str):
return datetime.datetime.strptime(date_str, '%m/%d/%Y')
else:
return date_str

@staticmethod
def find_no_days(date1_str, date2_str):
"""
Find no of days between 2 dates

:param date1_str: date1 in string format
:param date2_str: date2 in string format
:return: no of day between 2 dates
"""
if isinstance(date1_str, str):
date1 = DateUtils.toDate(date1_str)
else:
date1 = date1_str
if isinstance(date2_str, str):
date2 = DateUtils.toDate(date2_str)
else:
date2 = date2_str
return (date2 - date1).days

@staticmethod
def toString(date):
"""
Return datetime object in string format

:param date: datetime object
:return: datetime in string
"""
return date.strftime("%m/%d/%Y")

@staticmethod
def isDateWithinRange(date, startDate, endDate):
"""
Checks if the given date is within the time frame

:param date:
:param startDate:
:param endDate:
:return: boolean true/false
"""
if isinstance(date, str):
date = DateUtils.toDate(date)
if isinstance(startDate, str):
startDate = DateUtils.toDate(startDate)
if isinstance(endDate, str):
endDate = DateUtils.toDate(endDate)
return DateUtils.find_no_days(date, startDate) <= 0 <= DateUtils.find_no_days(date, endDate)
17 changes: 15 additions & 2 deletions abcbank/transaction.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
from datetime import datetime
from date_provider import DateUtils


class Transaction:
def __init__(self, amount):
def __init__(self, amount, date=None):
self.amount = amount
self.transactionDate = datetime.now()
if not date:
self.transactionDate = datetime.now()
else:
if isinstance(date, str):
self.transactionDate = DateUtils.toDate(date)
else:
self.transactionDate = date

def __eq__(self, other):
if isinstance(other, self.__class__):
return self.amount == other.amount and DateUtils.toString(self.transactionDate) == DateUtils.toString(
other.transactionDate)
return False
Loading