Build a Budget App Project - Build a Budget App Project

Tell us what’s happening:

I am failing a few tests which and i don’t understand why.

Your code so far

import math

class Category:

    def __init__(self, category):  # initialize the category
        self.category = category
        self.ledger = []  # different ledger for different category
    
    def __str__(self):  # rewrites how object is converted to a string when you print it
        title = f"{self.category:*^30}\n"  # max 30 width, ^aligned center, filled with *
        transactions = ""
        total = 0
        for item in self.ledger:
            desc = item['description'][:23]  # limit to 23 chars
            amount = f"{item['amount']:.2f}"  # 2 decimal places
            transactions += f"{desc:<23}{amount:>7}\n"  # desc: 23 width, amount: 7 width
            total += item['amount']
        return title + transactions + f"Total: {total:.2f}"

    def deposit(self, amount, description=""):
        self.ledger.append({'amount': amount, 'description': description})
        
    def withdraw(self, amount, description=""):
        # using the check_funds function
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            return True
        else:
            return False
                
    def get_balance(self):
        total_amount = 0
        for item in self.ledger:
            total_amount += item['amount']  # add every amount to check total balance
        return total_amount
    
    def transfer(self, amount, category):
        # self is the category where we are transferring from
        if self.check_funds(amount):  # check funds
            self.withdraw(amount, f'Transfer to {category.category}')  # withdraw from self
            category.deposit(amount, f'Transfer from {self.category}')  # deposit in destination category
            return True
        else:
            return False

    def check_funds(self, amount):  # returns if the amount is greater than available balance
        if amount <= self.get_balance():
            return True
        else:
            return False


def create_spend_chart(categories):
    total = calculate_total(categories)  # calculate total
    percentage = {}
    for category in categories:
        withdrawals = calculate_withdrawals(category)  # calculate individual withdrawals
        # category is the object so category.category gives string name
        percentage[category.category] = math.floor((withdrawals / total) * 100 / 10) * 10  # rounds to nearest 10
    
    # now create chart
    row_strings = ""
    for percent in range(100, -1, -10):
        row_strings += f'{percent:>3}|'
        for category in categories:
            if percentage[category.category] >= percent:
                row_strings += ' o '
            else:
                row_strings += '   '
        row_strings += '  \n'  # Ensure 2 spaces after each bar (for separation)

    # create the horizontal line (correct dash length)
    dash_line = "    " + "-" * (len(categories) * 3 + 2)  # 3 spaces per category and 2 more spaces after the last category
    row_strings += dash_line + '\n'
    
    # write the category names vertically
    max_length = max(len(category.category) for category in categories)  # find the max length of category names
    for i in range(max_length):
        row = "     "  # 5 spaces to align the categories
        for category in categories:
            if i < len(category.category):  # to avoid index error (if there is no item in the index)
                row += category.category[i] + "  "
            else:
                row += "   "
        row_strings += row.rstrip() + "  \n"  # Ensure 2 extra spaces after the final category

    return 'Percentage spent by category\n' + row_strings.rstrip()  # Remove trailing newline


def calculate_withdrawals(category):  # calculate withdrawal amount for each category
    spending = 0
    for item in category.ledger:
        if item['amount'] < 0:
            spending -= item['amount']  # for the positive value of withdrawals
    return spending


def calculate_total(categories):
    total = 0
    for category in categories:
        for item in category.ledger:
            if item['amount'] <= 0:
                total -= item['amount']
    return total


# Example usage:
food = Category('Food')
clothing = Category('Clothing')
others = Category('Others')

food.deposit(1000, "deposit")
food.transfer(200, clothing)
food.transfer(300, others)
food.withdraw(50, "momos")
clothing.withdraw(98, 'Gucci')
others.withdraw(100, "entertainment")

print("Food Ledger:", food.ledger)
print("Clothing Ledger:", clothing.ledger)
print("Others Ledger: ", others.ledger)

print(create_spend_chart([food, clothing, others]))


Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 OPR/117.0.0.0

Challenge Information:

Build a Budget App Project - Build a Budget App Project

I’ve edited your post to improve the readability of the code. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

did you press F12 to open the browser console and see a more detailed output of the tests?

How to read an AssertionError and diff

The assertion error and diff gives you a lot of information to track down a problem. For example:

AssertionError: 'Year' != 'Years'
- Year
+ Years
?     +

Your output comes first, and the output that the test expects is second.

AssertionError: ‘Year’ != ‘Years’

Your output: Year does not equal what’s expected: Years

This is called a diff, and it shows you the differences between two files or blocks of code:

- Year
+ Years
?     +

- Dash indicates the incorrect output
+ Plus shows what it should be
? The Question mark line indicates the place of the character that’s different between the two lines. Here a + is placed under the missing s .

Here’s another example:

E       AssertionError: Expected different output when calling "arithmetic_arranger()" with ["3801 - 2", "123 + 49"]
E       assert '  3801      123    \n   - 2     + 49    \n------    -----    \n' == '  3801      123\n-    2    +  49\n------    -----'
E         -   3801      123
E         +   3801      123    
E         ?                ++++
E         - -    2    +  49
E         +    - 2     + 49    
E         - ------    -----
E         + ------    -----    
E         ?                +++++

The first line is long, and it helps to view it as 2 lines in fixed width characters, so you can compare it character by character:

'  3801      123    \n   - 2     + 49    \n------    -----    \n'
'  3801      123\n-    2    +  49\n------    -----'

Again, your output is first and the expected output is second. Here it’s easy to see extra spaces or \n characters.

E         -   3801      123
E         +   3801      123    
E         ?                ++++

Here the ? line indicates 4 extra spaces at the end of a line using four + symbols. Spaces are a little difficult to see this way, so it’s useful to use both formats together.

I hope this helps interpret your error!

The last test shows

AssertionError: 'Perc[35 chars]      \n 90|           \n 80|           \n 70|[349 chars]   t'
             != 'Perc[35 chars]     \n 90|          \n 80|          \n 70|   [339 chars] t  '

the first line is yours, it looks like you have an extra space right before the new line character on all lines

while you are missing some spaces at the end