Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python

Church Account Project: Asking for Comments

Hi Kenneth Love

Just wanted to share what I'm working in. I'm, for my many sins, the treasurer of a small church and I thought of making a python app to gather the accounts and do the maths so it can be presented to the council, and so on.

The thing is that an excell sheet is a pain to work with, and dedicated apps are often an overkill for our needs, so I'm writing my own app. Right now, I have something that is barely functional. I mean, it kinda works, but I'm sure I will have to do a few iterations of refactoring.

First Attempt, has issues, see below

# This bit adds a new entry into the Church Accounts Book (a csv file)
import os
import csv

entries = []

def choose_a_category(categories): # A helper function

    for key in sorted(categories):
            print("Enter {} for {}".format(key,categories[key]))

    menu = input("\n Choose a category:\t")  

    try:
        return categories[menu]
    except KeyError:
        print("Try again")
        choose_a_category(categories)

def add_entry(): # Main function
    goOn = True # seguir = "go on in Spanish"
    entries = []
    while goOn:

        entry = ["","","","","",""] # Entry - In/Out Date Amount Category Source/Payee Notes

        in_categories = {"1":"Collections","2":"Donations","3":"Events"}
        out_categories = {"1":"Stipend","2":"Electricity Church"}

        # In/Out

        InOut = "X"

        while InOut != "i" and InOut != "o":
            InOut = input("\n In or Out: i for In, o for Out \t").lower()

        if InOut == "i":
            entry[0] = "In"
        else:
            entry[0] = "Out"

        if entry[0] == "In": #In
            categories = in_categories
            payee_or_source_enter_text = "Source"
        else: #Out
            categories = out_categories
            payee_or_source_enter_text = "Payed by"

        #Date

        entry[1] = input("\n Date in dd/mm: \t")

        #Amount

        entry[2] = input("\n Amount, no + or - \t")

        # Category 


        entry[3] = choose_a_category(categories)

        # Subject

        entry[4] = input("\n {}: \n".format(payee_or_source_enter_text))


        # Notes

        entry[5] = input("\n Write a note if needed: \n")

        # Append entry to entries

        entries.append(entry)

        goOnText = input("\n Another entry? (n for no)\t").lower()
        if goOnText == "n":
            goOn = False

    # add entries to file

    with open('ca.csv', 'a', newline='') as f:
        writer = csv.writer(f)
        writer.writerows(entries)

    return entries  


add_entry()

# this bit gathers totals and subtotals by category of income, expense and source 

import os 
import csv

def open_book():
    with open('ca.csv', newline='') as f:
            book = []
            reader = csv.reader(f)
            for row in reader:
                book.append(row)
    return book

def gather_categories(book):
    category_list = []

    for x in range(0,len(book)):
        if book[x][3] not in category_list:
            category_list.append(book[x][3])

    return category_list

def gather_sources(book):
    sources_list = []

    for x in range(0,len(book)):
        if book[x][4] not in sources_list:
            sources_list.append(book[x][4])

    return sources_list

def add_income_expense():
    total_income = 0.00
    total_expense =0.00
    book = open_book()

    for x in range(0,len(book)):
        this_quantity = float(book[x][2])
        if book[x][0]=='In':
            total_income += this_quantity
        else:
            total_expense += this_quantity

    total_income = round(total_income,2)
    total_expense = round(total_expense,2)

    print("Total Income: {} \t Total Expense {}".format((total_income),total_expense))
    print("="*80)

def add_categories():
    total_categories = []
    book = open_book()
    categories = gather_categories(book)

    print("\n Categories")
    print(" ==========")

    for x in range(0,len(categories)):
        total_categories.append(0)
        for y in range(0,len(book)):
            if book[y][3]==categories[x]:
                total_categories[x] += float(book[y][2])

        print("\n {}\t {}".format(categories[x],round(total_categories[x],2)))

    print("-"*80)

def add_sources():
    total_sources = [[0.0,0.0]]
    book = open_book()
    sources = gather_sources(book)

    print("\n Sources")
    print(" =======")

    for x in range(0,len(sources)):
        total_sources.append([0.0,0.0])
        for y in range(0,len(book)):
            if book[y][4]==sources[x]:
                if book[y][0]=="In":
                    total_sources[x][0] += float(book[y][2])
                else:
                    total_sources[x][1] += float(book[y][2])

        total_sources[x][0] = round(total_sources[x][0],2)
        total_sources[x][1] = round(total_sources[x][1],2)
        subtotal = round(total_sources[x][0]-total_sources[x][1])

        print("\n {}\tIn: {}\t Out: {} \t Total: {}".format(sources[x], total_sources[x][0],total_sources[x][1], subtotal) )

    print("-"*80)   



add_categories()
add_sources()
add_income_expense()

3 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Looks like a pretty thorough app, Miguel de Luis Espinosa. If you have any specific questions, be sure to ping me.

OK, I ran into problems. The most serious was that I was using floats for currency. Floats do not work at all for currency, as I got rounding errors just for adding 4 numbers. So go figure what mess I could have run into in the long run. It made remember Superman III.

you want Decimal type, available as a module

from decimal import Decimal

# and then replace float(your_saved_string_with_money) with 

Decimal(your_saved_string_with_money) #notice capital D
# I use this bit to enter data on the console

import os
import csv

entries = []

def choose_a_category(categories):
# generates a menu and check if your category is within the menu

    for key in sorted(categories):
            print("Enter {} for {}".format(key,categories[key]))

    menu = input("\n Choose a category:\t")  

    try:
        return categories[menu]
    except KeyError:
        print("Try again")
        choose_a_category(categories)

def add_entry():
# add an entry or entries to the account book

    seguir = True
    entries = []
    while seguir:

        entry = ["","","","","",""] # Entry - In/Out Date Amount Category Source/Payee Notes

        in_categories = {"1":"Collections","2":"Events","3":"Interest","4":"Fees"}
        out_categories = {"1":"Stipend","2":"Chaplain Accomodation", 
                          "3":"Chaplain Expenses", "4":"Services & Administration", 
                          "5":"Church Fabric", "6":"Diocesan Quotas", "7":"Charity", "8":"Exceptional"}

        # In/Out

        InOut = "X"

        while InOut != "i" and InOut != "o":
            InOut = input("\n In or Out: i for In, o for Out \t").lower()

        if InOut == "i":
            entry[0] = "In"
        else:
            entry[0] = "Out"

        if entry[0] == "In": #In
            categories = in_categories
            payee_or_source_enter_text = "Source"
        else: #Out
            categories = out_categories
            payee_or_source_enter_text = "Assigned to"

        #Date
        day = ""
        month = ""

        day = input("\n Day (dd): \t")
        month = input("\n Month (mm): \t")

        entry[1] = day + "/" + month

        #Amount

        entry[2] = input("\n Amount").strip('+- ')      

        # Category      

        entry[3] = choose_a_category(categories)

        # Subject

        entry[4] = input("\n {}: \n".format(payee_or_source_enter_text))


        # Notes

        entry[5] = input("\n Write a note if needed: \n")

        # Append entry to entries

        entries.append(entry)   

        seguimos = input("\n Another entry? (n for no)\t")
        if seguimos.lower() == "n":
            seguir = False


    # append entries to file

    with open('ca.csv', 'a', newline='') as f:
        writer = csv.writer(f)
        writer.writerows(entries)

    return entries  


add_entry()
# This bit does the maths

import os
import csv
from decimal import Decimal

opening_balance = round(Decimal(1.01),2)  #1.01 is just a fake ammount

def open_book():
    with open('ca.csv', newline='') as f:
            book = []
            reader = csv.reader(f)
            for row in reader:
                book.append(row)
    return book

def gather_categories(book):
    category_list = []

    for x in range(0,len(book)):
        if book[x][3] not in category_list:
            category_list.append(book[x][3])

    return category_list

def gather_sources(book):
    sources_list = []

    for x in range(0,len(book)):
        if book[x][4] not in sources_list:
            sources_list.append(book[x][4])

    return sources_list

def add_income_expense():
    total_income = Decimal(0)
    total_expense = Decimal(0)
    book = open_book()

    for x in range(0,len(book)):
        this_quantity = Decimal(book[x][2])
        if book[x][0]=='In':
            total_income += this_quantity
        else:
            total_expense += this_quantity

    total_income = round(total_income,2)
    total_expense = round(total_expense,2)
    balance = total_income-total_expense
    historic_balance = opening_balance + balance

    print("\nTotal Income: {:8,} \tTotal Expense: {:8,}\t Balance: {:8,}".format(total_income,total_expense,balance))
    print("\nOpening Balance: {:8,}\tHistoric Balance: {:8,}".format(opening_balance,historic_balance))
    print("="*80)

def add_categories():
    total_categories = []
    book = open_book()
    categories = gather_categories(book)

    print("\n Categories")
    print(" ==========")

    for x in range(0,len(categories)):
        total_categories.append(Decimal(0))
        for y in range(0,len(book)):
            if book[y][3]==categories[x]:
                total_categories[x] += Decimal(book[y][2])

        print("\n {:<20}\t {:^8,}".format(categories[x],total_categories[x]))

    print("-"*80)

def add_sources():
    total_sources = [[Decimal(0),Decimal(0)]]
    book = open_book()
    sources = gather_sources(book)

    print("\n Sources")
    print(" =======")

    for x in range(0,len(sources)):
        total_sources.append([Decimal(0),Decimal(0)])
        for y in range(0,len(book)):
            if book[y][4]==sources[x]:
                if book[y][0]=="In":
                    total_sources[x][0] += Decimal(book[y][2])
                else:
                    total_sources[x][1] += Decimal(book[y][2])

        subtotal = total_sources[x][0]-total_sources[x][1]


        print("\n {:<20} In: {:^8,} Out: {:^8,} Total: {:^8,}".format(sources[x], total_sources[x][0], total_sources[x][1],  subtotal))

    print("-"*80)   



add_categories()
add_sources()
add_income_expense()