import json from decimal import * from datetime import * ############################################################################## # # This is the BQL query to put into Fava to generate the CSV that can be used # to create the JSON file for this. Might consider reading in the CSV directly # and prompting for the other information? # # select date, number where year=2022 And account~".*:CreditLine" # ############################################################################## # # Consider altering this program to generate the text to go into the beancount # files directly so that it can just be a cut and paste job. # ############################################################################## def main(): filename = '2023.gtploc.json' account = loadAccountInformation(getFullPathofFile(filename)) starting_balance = Decimal(account['starting_balance']) apr = Decimal(account['interest_rate']) / 100 daily_interest_rate = apr / 360 fiscal_year = account['fiscal_year'] first_day = datetime(fiscal_year, 1, 1) last_day = datetime(fiscal_year, 12, 31) days_in_year = (last_day - first_day).days + 2 print("Line of Credit Report") print("Fiscal Year: {1} Input File Name: {0}".format(filename, fiscal_year)) print("Starting Balance: {0} Interest Rate: {1}".format(starting_balance, account['interest_rate'])) print("Report Run Date: {0}".format(datetime.now())) print("\n=========================================================================================\n") day_nets = {} transactions = account['transactions'] print("Summarizing {0} transactions:".format(len(transactions))) for entry in transactions: entry_date = entry[0] entry_amount = Decimal(entry[1]) if entry_date not in day_nets: day_nets[entry_date] = entry_amount else: day_nets[entry_date] = day_nets[entry_date] + entry_amount for key in day_nets.keys(): print("Date: {0} Net Change: {1}".format(key, day_nets[key])) print("Summary complete.") current_balance = starting_balance accummulated_interest = Decimal('0.00') daily_interest = calculateDailyInterest(current_balance, daily_interest_rate) print("\n=========================================================================================\n") print("Calculating interest charges...") # print("Beginning Balance: {1} Daily Interest: {2}".format(first_day,starting_balance, daily_interest)) for i in range(1, days_in_year): current_date = (first_day + timedelta(days=i-1)).date() if current_date.day == 1: print("BEGIN MONTH: {0} Starting Balance: {1} Starting Daily Interest: {2}".format(current_date, current_balance, daily_interest)) if current_date.__str__() in day_nets: current_balance = current_balance + day_nets[current_date.__str__()] daily_interest = calculateDailyInterest(current_balance, daily_interest_rate) print("Balance Change: Date: {0} Net: {1} New Balance: {2}".format( current_date, day_nets[current_date.__str__()], current_balance)) accummulated_interest = accummulated_interest + daily_interest if is_last_day_of_month(current_date): current_balance = current_balance + accummulated_interest daily_interest = calculateDailyInterest(current_balance, daily_interest_rate) print("END MONTH: Date: {0} Post Accumulated Interest: {1} New Balance: {2} New Daily Interest: {3}".format( current_date, accummulated_interest, current_balance, daily_interest)) accummulated_interest = 0 def is_last_day_of_month(some_date): if some_date.day < 28: return False next_day = some_date + timedelta(days=1) if next_day.month == some_date.month: return False return True def calculateDailyInterest(principal, rate): return (principal*rate).quantize(Decimal('.001')) def loadAccountInformation(filename): return getDatastore(filename) def getDatastore(filename=None): try: if filename: with open(filename, 'r') as f: datastore = json.load(f) except Exception as e: print("An error occurred opening your file '%s'. " % filename) print("The Exception:") print(e.__repr__()) quit() return datastore def getFullPathofFile(filename): return '/Users/john/PycharmProjects/LoCInterestCalculator/' + filename if __name__ == '__main__': main()