from flask import Flask, render_template, request, redirect, url_for import json from decimal import * from datetime import * from jinja2 import Environment, FileSystemLoader from fpdf import FPDF, HTMLMixin import smtplib from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText from email.MIMEBase import MIMEBase from email import Encoders app = Flask(__name__) @app.route('/') def hello(): loans = [] loans.append( addLoan("1 Greenfield Lane Mortgage", "greenfield_mortgage.json" ) ) loans.append( addLoan("2 Bear Houses LLC Loan", "9Kloan.json" ) ) loans.append( addLoan("3 Brenda Mortgage", "brendamortgage.json" ) ) loans.append( addLoan("4 Dad Mortgage", "dadmortgage.json") ) if 'loan' in request.args: filename = request.args["loan"] else: return redirect('/?loan=' + loans[0]['filename']) loan = loadLoanInformation('/Users/john/PycharmProjects/mortgage/' + filename) amortizeLoan(loan) return render_template('main.html', filename=filename, loans=loans, model=loan) @app.route('/update_file') def update_file(): return @app.route('/send_statement', methods=['POST']) def send_statement(): loan = request.form["loan"] redirect( '/?loan=' + loan ) def addLoan(loanName, fileName): x = {} x['name'] = loanName x['filename'] = fileName return x '''from old code''' def getStatementHeader(datastore): return datastore['header'] def getEmailInformation(datastore): return datastore['email'] def loadLoanInformation(filename): datastore = getDatastore(filename) loanModel = {} loanModel['datastore'] = datastore loanModel['email'] = getEmailInformation(datastore) loanModel['parameters'] = getLoanParameters(datastore) loanModel['lender'] = getLender(datastore) loanModel['borrower'] = getBorrower(datastore) loanModel['header'] = getStatementHeader(datastore) return loanModel def getLoanParameters(datastore): # read in the loan profile information loan = datastore['parameters'] annual_rate = Decimal(loan['interest_rate']) / 100 daily_interest_rate = annual_rate / 360 principal = Decimal(loan["principal"]).quantize(Decimal("1.00")) periods_per_year = Decimal(loan["periods_per_year"]) total_periods = Decimal(loan["periods"]) payment_day_of_month = int(loan['payment_day_of_month']) if "monthly_payment" in loan: monthly_payment = Decimal(loan["monthly_payment"]).quantize(Decimal("1.00")) else: # calculate expected monthly payment periodic_rate = annual_rate / periods_per_year discount_factor = (((1 + periodic_rate) ** total_periods) - 1) / ( periodic_rate * ((1 + periodic_rate) ** total_periods)) monthly_payment = (principal / discount_factor).quantize(Decimal("1.00")) loan['principal'] = principal # standardizes the format loan['annual_rate'] = annual_rate # standardizes the format loan['daily_interest_rate'] = daily_interest_rate loan['rate'] = '' + (annual_rate * 100).__str__() + '%' loan['next_payment_amt'] = 0 loan['next_payment_date'] = '12/12/12' loan['total_periods'] = total_periods loan['monthly_payment'] = monthly_payment datastore['parameters'] = loan return loan def getLender(datastore): return datastore['lender'] def getBorrower(datastore): return datastore['borrower'] 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 loan file '%s'. " % filename print "The Exception:" print e.__repr__() quit() return datastore def amortizeLoan(loan): # loop over the payments and calculate the actual amortization monthly_payment = loan["parameters"]["monthly_payment"] actual_payments = loan["datastore"]["payments"] remaining_principal = loan["parameters"]["principal"] payment_day_of_month = int(loan["parameters"]["payment_day_of_month"]) daily_interest_rate = loan["parameters"]["daily_interest_rate"] total_periods = loan["parameters"]["total_periods"] interest_paid_through_date = datetime.strptime(loan["parameters"]["start_interest_date"], "%Y-%m-%d").date() next_payment_date = datetime.strptime(loan["parameters"]["first_payment_month"], '%Y-%m-%d').date() next_bill_date = date(year=next_payment_date.year, month=next_payment_date.month, day=payment_day_of_month) payment_number = 1 annual_interest = 0 total_interest = 0 old_bill_date = next_bill_date current_year = next_bill_date.year past_payments = [] future_payments = [] for payment in actual_payments: payment_date = datetime.strptime((payment[0]), '%Y-%m-%d').date() payment_amount = Decimal(payment[1]).quantize(Decimal("1.00")) days_since_last_payment = (payment_date - interest_paid_through_date).days #check for out of order payments, generally a sign of a data entry problem, especially years if days_since_last_payment < 0: print "Payment Number %s appears out of order. The payment date '%s' is before the previous payment on '%s'." \ % (payment_number, payment_date, interest_paid_through_date) quit() new_interest = (days_since_last_payment * remaining_principal * daily_interest_rate).quantize(Decimal("0.00")) new_principal = payment_amount - new_interest interest_paid_through_date = payment_date total_interest = total_interest + new_interest annual_interest = annual_interest + new_interest remaining_principal = remaining_principal - new_principal # create the payment record for the template to render payment_record = {} payment_record['year']=next_bill_date.year payment_record['month']=next_bill_date.month payment_record['payment_number'] = payment_number payment_record['bill_date'] = next_bill_date payment_record['payment_date'] = payment_date payment_record['days_of_interest'] = days_since_last_payment payment_record['payment_amount'] = payment_amount payment_record['principal_payment'] = payment_amount - new_interest payment_record['interest_payment'] = new_interest payment_record['new_balance'] = remaining_principal payment_record['interest_to_date'] = total_interest payment_record['annual_interest_to_date'] = annual_interest past_payments.append(payment_record) payment_number = payment_number + 1 old_bill_date = next_bill_date if old_bill_date.month < 12: next_bill_date = date(year=old_bill_date.year, month=old_bill_date.month + 1, day=payment_day_of_month) else: annual_interest = Decimal("0.00") next_bill_date = date(year=old_bill_date.year + 1, month=1, day = payment_day_of_month) loan["total_interest_paid_to_date"] = total_interest loan["parameters"]["next_due_date"] = next_bill_date if (remaining_principal < monthly_payment): loan["parameters"]["next_payment_amt"] = remaining_principal else: loan["parameters"]["next_payment_amt"] = monthly_payment # loop over remaining scheduled payments and present estimated amortization while (payment_number <= total_periods) and (remaining_principal > 0): days_since_last_payment = (next_bill_date - interest_paid_through_date).days new_interest = (days_since_last_payment * remaining_principal * daily_interest_rate).quantize(Decimal("0.00")) # make sure the last payment isn't too much if new_interest + remaining_principal < monthly_payment: monthly_payment = new_interest + remaining_principal new_principal = monthly_payment - new_interest remaining_principal = remaining_principal - new_principal interest_paid_through_date = next_bill_date # complete the future payment amortization record future_payment_record = {} future_payment_record['payment_number'] = payment_number future_payment_record['payment_date'] = next_bill_date future_payment_record['days_of_interest'] = days_since_last_payment future_payment_record['payment_amount'] = monthly_payment future_payment_record['principal_payment'] = new_principal future_payment_record['interest_payment'] = new_interest future_payment_record['new_balance'] = remaining_principal future_payments.append(future_payment_record) payment_number = payment_number + 1 old_bill_date = next_bill_date if old_bill_date.month < 12: next_bill_date = date(year=old_bill_date.year, month=old_bill_date.month + 1, day=payment_day_of_month) else: next_bill_date = date(year=old_bill_date.year + 1, month=1, day=payment_day_of_month) loan["balloon_payment"] = remaining_principal loan["past_payments"] = past_payments loan["future_payments"] = future_payments return if __name__ == '__main__': app.debug = True app.run()