Tell us what’s happening:
the last test fails:
I’m generating the following error in the console on the last test:
ERROR: *test_create_spend_chart (test_module.UnitTests.test_create_spend_chart)*
Traceback (most recent call last):
File "/home/pyodide/test_module.py", line 21, in test_create_spend_chart
actual = **budget.create_spend_chart([self.business, self.food, self.entertainment])**
AttributeError: module 'budget' has no attribute 'create_spend_chart'
Your code so far
class Category:
def __str__(self):
asterisks = (30 - len(self.category)) // 2
ret_string = '*' * asterisks + self.category + '*' * asterisks + '\n'
for row in self.ledger:
amt = '{:.2f}'.format(row['amount']).rjust(7)
if len(row['description']) > 22 :
amt = '{:.2f}'.format(row['amount']).rjust(6)
ret_string += "{0:<22}".format(row['description'][0:23]) + ' ' + amt + '\n'
ret_string += 'Total: '+ '{:.2f}'.format(self.get_balance() )
return ret_string
def __init__(self,category):
self.ledger = []
self.category = category
self.chart = [
[' 0|'],
[' 10|'],
[' 20|'] ,
[' 30|'] ,
[' 40|' ],
[' 50|' ] ,
[' 60|'],
[' 70|' ],
[' 80|'],
[' 90|' ],
['100|']
]
def create_spend_chart(self, categories):
total_by_category = []
category_percent = []
category_total = 0
longest = 0
budget_chart_line = ''
for cat in categories:
if len( cat.category) > longest:
longest = len( cat.category)
for cat in categories:
#total witdrawls
total_by_category.append( \
{"category": cat.category, "total": cat._get_bal_withdraws()})
#print( 'category: ', cat.category )
category_total += cat._get_bal_withdraws()
#for item in total_by_category:
# amt = item["total"]
# category_percent = amt / category_total * 100
# print(f'{category_percent} = {amt} / {total} * 100 ')
# item['percent'] =category_percent - (category_percent % 10)
# print(f'calc {category_percent} % 10 = int {int(category_percent / 10)}')
#print(f"item['percent'] ={category_percent} - ({category_percent} % 10)")
col_switch = 0
# calculate precent and assing to row
for item in total_by_category:
percent = int(item['total'] / category_total * 10)
# print("new precct", 'total:', item['total'],'category_total',category_total,\
# 'precent:' , percent, int(item['total']))
col_format = ''
for i in range(11) :
if (col_switch != 0):
col_format = "{0:>3}"
else:
col_format = "{0:>2}"
# deal with percent 0 - 1 line '0|' has a value
if percent > i and item['total'] > 0 or percent == i and item['total'] > 0 :
self.chart[i].append( col_format.format("o"))
else :
self.chart[i].append( col_format.format(" ") )
col_switch = 1
# need to pass the right side of the chart to match the spaces
for i in range(11) :
self.chart[i].append(" ")
# the first column with 'o' has width of 2 and the rest 3
kluge = 0
#print('\nPercentage spent by category')
budget_chart_line +='\nPercentage spent by category \n'
for row in reversed(self.chart):
chart_line = ''
for col in row:
if col != ' ':
if col != '-' :
chart_line += col
else:
if kluge == 0:
chart_line += " {0:<1}".format(col)
kluge=1
else:
chart_line += (col * 3)
else:
chart_line += col
chart_line
budget_chart_line += chart_line + '\n'
#underline in chart
underline = [' -', ]
chart_line = ' '
for i in range(len(total_by_category)):
underline.append( "{0:>3}".format('-'* 3))
for col in underline:
chart_line += col
budget_chart_line += chart_line + '\n'
#pivot names
# [['F', 'o', 'o', 'd'], ['C', 'l', 'o', 't', 'h', 'i', 'n', 'g'], ['A', 'u', 't', 'o']]
chart_cat = []
for i in range(longest):
pivot_char = [' ']
for l in range(len(categories)):
if (l != 0):
col_format = "{0:>3}"
else:
col_format = "{0:>2}"
if (i < len(total_by_category[l]["category"])):
pivot_char.append(col_format.format(total_by_category[l]["category"][i] ))
else:
pivot_char.append(col_format.format(' '))
chart_cat.append(pivot_char)
chart_line = ' '
for row in chart_cat:
row.append(' ')
for row in chart_cat:
for col in row:
chart_line += col
chart_line+= '\n '
budget_chart_line += chart_line
return budget_chart_line
#A deposit method vthat accepts an amount and description. If no description is given, it should default to an empty string. The method should append an object to the ledger list in the form of {‘amount’: amount, ‘description’: description}.
def deposit(self, amount, description = ‘’):
self.ledger.append({‘amount’: amount, ‘description’: description})
#A withdraw method that is similar to the deposit method, but the amount passed in should be stored in the ledger as a negative number. If there are not enough funds, nothing should be added to the ledger. This method should return True if the withdrawal took place, and False otherwise.
def withdraw(self, amount,description='' ):
if amount > 0 and self.get_balance() > amount :
amount = amount * -1
self.ledger.append({ 'amount': amount, 'description': description})
return True
else:
return False
#A get_balance method that returns the current balance of the budget category based on the deposits and withdrawals that have occurred.
def get_balance(self):
balance = 0.0
for row in self.ledger:
balance += row[‘amount’]
return balance
return
def _get_bal_withdraws(self) :
withdraws = 0
for row in self.ledger:
if row['amount'] < 0 :
withdraws += row['amount']
return withdraws * -1
#A transfer method that accepts an amount and another budget category as arguments. The method should add a withdrawal with the amount and the description ‘Transfer to [Destination Budget Category]’. The method should then add a deposit to the other budget category with the amount and the description ‘Transfer from [Source Budget Category]’. If there are not enough funds, nothing should be added to either ledgers. This method should return True if the transfer took place, and False otherwise.
def transfer(self, amount, Category):
if self.get_balance() > amount :
self.withdraw(amount,"Transfer to " + Category.category)
Category.deposit(amount,'Transfer from ’ + self.category)
return True
else:
return False
A check_funds method that accepts an amount as an argument. It returns False if the amount is greater than the balance of the budget category and returns True otherwise. This method should be used by both the withdraw method and transfer method.
def check_funds(self, amount):
if amount > self.get_balance():
return False
return True
food = Category(‘Food’)
food.deposit(1000, ‘deposit’)
food.withdraw(10.15, ‘groceries’)
food.withdraw(15.89, ‘restaurant and more food for dessert’)
clothing = Category(‘Clothing’)
food.transfer(50, clothing)
clothing.withdraw(1.15, ‘groceries’)
print(food)
#print(clothing)
#print(auto)
#print(food.get_balance())
#print(clothing.get_balance())
print(food.create_spend_chart([food, clothing]))
#food.create_spend_chart([food, clothing, auto])
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Challenge Information:
Build a Budget App Project - Build a Budget App Project