Files
2025-09-12 21:25:28 -04:00

126 lines
4.7 KiB
Python

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()