Updated all of the payment files to reflect new format. Updated the PDF generation template. Updated the email sending code. Fixed a few off by one errors when the last payment also is the last payment of the year.

This commit is contained in:
JohnKent
2019-01-06 16:39:54 -05:00
parent e274b96672
commit 45d6e32149
7 changed files with 409 additions and 191 deletions

63
10Kloan.json Normal file
View File

@@ -0,0 +1,63 @@
{
"htmlTemplate": "statement.pdf.jinja",
"txtTemplate": "statement.txt.jinja",
"format": "html",
"email": {
"from_address": "jkent3rd@gmail.com",
"to_address": "grady@gradystreet.com",
"server": "smtp.gmail.com",
"password": "pvyrbcnzrjoizprn",
"template": "./template.txt",
"send_pdf": "true",
"send_text": "true",
"subject": "Your loan statement...",
"body": "Your loan statement is attached.",
"text": "Please see your most recent account statement."
},
"parameters": {
"account_number": "100100",
"principal": 10020.00,
"interest_rate": 6.5,
"periods_per_year": 12,
"periods": 18,
"start_date": "2017-12-05",
"start_interest_date": "2017-12-05",
"first_payment_month": "2018-01-15",
"monthly_payment": 589.00,
"payment_day_of_month": "15"
},
"payments": [
["2018-01-16", "589.00"],
["2018-03-30", "589.00"],
["2018-04-06", "589.00"],
["2018-04-12", "589.00"],
["2018-05-28", "589.00"],
["2018-06-12", "589.00"],
["2018-07-13", "589.00"],
["2018-08-14", "589.00"],
["2018-09-26", "589.00"],
["2018-10-15", "0"],
["2018-11-29", "589.00"],
["2018-12-31", "589.00"]
],
"borrower": {
"name": "Bear Houses, LLC",
"address": "301 N Beauregard St Apt 203",
"city": "Alexandria",
"state": "VA",
"zip": "22312"
},
"lender": {
"name": "John Kent",
"phone": "703.343.0782",
"address": "743 Madison St NW",
"city": "Washington",
"state": "DC",
"zip": "20011"
},
"header": {
"title": "Installment Loan Statement",
"date": "Today"
}
}

56
brendamortgage.json Normal file
View File

@@ -0,0 +1,56 @@
{
"htmlTemplate": "statement.pdf.jinja",
"txtTemplate": "statement.txt.jinja",
"format": "html",
"email": {
"from_address": "jkent3rd@gmail.com",
"to_address": "bck@virginia.edu",
"server": "smtp.gmail.com",
"password": "pvyrbcnzrjoizprn",
"template": "./template.txt",
"send_pdf": "true",
"send_text": "true",
"subject": "Your loan statement...",
"body": "Your loan statement is attached.",
"text": "Please see your most recent account statement."
},
"parameters": {
"account_number": "100001",
"principal": 35000.00,
"interest_rate": 5.0,
"periods_per_year": 12,
"periods": 180,
"start_date": "2018-06-25",
"start_interest_date": "2018-07-01",
"first_payment_month": "2018-08-01",
"monthly_payment": 278.15,
"payment_day_of_month": "01"
},
"borrower": {
"name": "Grandma Tina's Properties, LLC",
"address": "743 Madison St NW",
"city": "Washington",
"state": "DC",
"zip": "20011"
},
"lender": {
"name": "John Kent",
"phone": "434-510-7272",
"address": "109 Shores Rd",
"city": "Palmyra",
"state": "VA",
"zip": "22963"
},
"header": {
"title": "Mortgage Loan Statement - 185 James River Rd, Scottsville VA",
"date": "Today"
},
"payments": [
["2018-08-01", "278.15"],
["2018-09-01", "278.15"],
["2018-10-01", "278.15"],
["2018-11-01", "278.15"],
["2018-12-01", "278.15"],
["2019-01-01", "278.15"]
]
}

56
dadmortgage.json Normal file
View File

@@ -0,0 +1,56 @@
{
"htmlTemplate": "statement.pdf.jinja",
"txtTemplate": "statement.txt.jinja",
"format": "html",
"email": {
"from_address": "jkent3rd@gmail.com",
"to_address": "johnkent49@gmail.com",
"server": "smtp.gmail.com",
"password": "pvyrbcnzrjoizprn",
"template": "./template.txt",
"send_pdf": "true",
"send_text": "true",
"subject": "Your loan statement...",
"body": "Your loan statement is attached.",
"text": "Please see your most recent account statement."
},
"parameters": {
"account_number": "100001",
"principal": 35000.00,
"interest_rate": 5.0,
"periods_per_year": 12,
"periods": 180,
"start_date": "2018-06-25",
"start_interest_date": "2018-07-01",
"first_payment_month": "2018-08-01",
"monthly_payment": 278.15,
"payment_day_of_month": "01"
},
"borrower": {
"name": "Grandma Tina's Properties, LLC",
"address": "743 Madison St NW",
"city": "Washington",
"state": "DC",
"zip": "20011"
},
"lender": {
"name": "John Kent",
"phone": "434-510-7272",
"address": "109 Shores Rd",
"city": "Palmyra",
"state": "VA",
"zip": "22963"
},
"header": {
"title": "Mortgage Loan Statement - 185 James River Rd, Scottsville VA",
"date": "Today"
},
"payments": [
["2018-08-01", "278.15"],
["2018-09-01", "278.15"],
["2018-10-01", "278.15"],
["2018-11-01", "278.15"],
["2018-12-01", "278.15"],
["2019-01-01", "278.15"]
]
}

63
greenfield_mortgage.json Normal file
View File

@@ -0,0 +1,63 @@
{
"htmlTemplate": "statement.pdf.jinja",
"txtTemplate": "statement.txt.jinja",
"format": "html",
"email": {
"from_address": "jkent3rd@gmail.com",
"to_address": "grady@gradystreet.com",
"server": "smtp.gmail.com",
"password": "pvyrbcnzrjoizprn",
"template": "./template.txt",
"send_pdf": "true",
"send_text": "true",
"subject": "Your loan statement...",
"body": "Your loan statement is attached.",
"text": "Please see your most recent account statement."
},
"parameters": {
"account_number": "100001",
"principal": 97750.00,
"interest_rate": 5.5,
"periods_per_year": 12,
"periods": 182,
"start_date": "2017-11-07",
"start_interest_date": "2017-11-11",
"first_payment_month": "2017-12-15",
"monthly_payment": 803.00,
"payment_day_of_month": "15"
},
"payments": [
["2017-12-11", "803.00"],
["2018-01-23", "803.00"],
["2018-03-23", "803.00"],
["2018-04-18", "803.00"],
["2018-04-26", "803.00"],
["2018-05-15", "0.00"],
["2018-06-15", "0.00"],
["2018-07-12", "803.00"],
["2018-08-07", "803.00"],
["2018-09-06", "803.00"],
["2018-10-11", "803.00"],
["2018-11-13", "803.00"],
["2018-12-13", "803.00"]
],
"borrower": {
"name": "Bear Houses, LLC",
"address": "301 N Beauregard St Apt 203",
"city": "Alexandria",
"state": "VA",
"zip": "22312"
},
"lender": {
"name": "Rivanna Graphite Investments, LLC",
"phone": "703.343.0782",
"address": "743 Madison St NW",
"city": "Washington",
"state": "DC",
"zip": "20011"
},
"header": {
"title": "Mortgage Loan Statement - 195 Greenfield Lane, Pearl MS",
"date": "Today"
}
}

View File

@@ -1,25 +0,0 @@
{
"principal": 97750.00,
"interest rate": 5.5,
"periods per year": 12,
"periods": 182,
"start date": "2017-11-07",
"start_interest_date": "2017-11-11",
"first payment month": "2017-12-15",
"monthly_payment": 803.00,
"payment day of month": "15",
"payments": [
["2017-12-11", "803.00"],
["2018-01-23", "803.00"],
["2018-03-23", "803.00"],
["2018-04-18", "803.00"],
["2018-04-26", "803.00"],
["2018-05-15", "0.00"],
["2018-06-15", "0.00"],
["2018-07-12", "803.00"],
["2018-08-07", "803.00"],
["2018-09-06", "803.00"],
["2018-10-11", "803.00"],
["2018-11-13", "803.00"]
]
}

View File

@@ -4,45 +4,47 @@ from datetime import *
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from fpdf import FPDF, HTMLMixin from fpdf import FPDF, HTMLMixin
import smtplib import smtplib
from email.MIMEMultipart import MIMEMultipart from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase from email.MIMEBase import MIMEBase
from email import Encoders from email import Encoders
def getPaymentHistory(datastore, loan, asOfDate): def getStatementHeader(datastore):
pass return datastore['header']
def getAmortization(datastore, loan, paymentHistory): def getEmailInformation(datastore):
pass return datastore['email']
def loadLoanInformation(filename): def loadLoanInformation(filename):
datastore = getDatastore(filename) datastore = getDatastore(filename)
loanModel = {}
loanModel['loan'] = getLoan(datastore) loanModel = {}
loanModel['datastore'] = datastore
loanModel['email'] = getEmailInformation(datastore)
loanModel['parameters'] = getLoanParameters(datastore)
loanModel['lender'] = getLender(datastore) loanModel['lender'] = getLender(datastore)
loanModel['borrower'] = getBorrower(datastore) loanModel['borrower'] = getBorrower(datastore)
loanModel['paymentHistory'] = getPaymentHistory(datastore, loan, asOfDate) loanModel['header'] = getStatementHeader(datastore)
loanModel['futureAmortization'] = getAmortization(datastore, loan, loanModel.paymentHistory)
return loanModel return loanModel
def getLoan(datastore): def getLoanParameters(datastore):
# read in the loan profile information # read in the loan profile information
loan = {} loan = datastore['parameters']
annual_rate = Decimal(datastore['loan.interest rate']) / 100 annual_rate = Decimal(loan['interest_rate']) / 100
daily_interest_rate = annual_rate / 360 daily_interest_rate = annual_rate / 360
principal = Decimal(datastore["loan.principal"]).quantize(Decimal("1.00")) principal = Decimal(loan["principal"]).quantize(Decimal("1.00"))
periods_per_year = Decimal(datastore["loan.periods per year"]) periods_per_year = Decimal(loan["periods_per_year"])
total_periods = Decimal(datastore["loan.periods"]) total_periods = Decimal(loan["periods"])
payment_day_of_month = int(datastore['loan.payment day of month']) payment_day_of_month = int(loan['payment_day_of_month'])
if "monthly_payment" in datastore: if "monthly_payment" in loan:
monthly_payment = Decimal(datastore["monthly_payment"]).quantize(Decimal("1.00")) monthly_payment = Decimal(loan["monthly_payment"]).quantize(Decimal("1.00"))
else: else:
# calculate expected monthly payment # calculate expected monthly payment
periodic_rate = annual_rate / periods_per_year periodic_rate = annual_rate / periods_per_year
@@ -50,38 +52,24 @@ def getLoan(datastore):
periodic_rate * ((1 + periodic_rate) ** total_periods)) periodic_rate * ((1 + periodic_rate) ** total_periods))
monthly_payment = (principal / discount_factor).quantize(Decimal("1.00")) monthly_payment = (principal / discount_factor).quantize(Decimal("1.00"))
loan['loan.account_number'] = '123456789' loan['principal'] = principal # standardizes the format
loan['principal'] = principal loan['annual_rate'] = annual_rate # standardizes the format
loan['term'] = total_periods
loan['annual_rate'] = annual_rate
loan['daily_interest_rate'] = daily_interest_rate loan['daily_interest_rate'] = daily_interest_rate
loan['rate'] = '' + (annual_rate * 100).__str__() + '%' loan['rate'] = '' + (annual_rate * 100).__str__() + '%'
loan['next_payment_amt'] = 0 loan['next_payment_amt'] = 0
loan['next_payment_date'] = '12/12/12' loan['next_payment_date'] = '12/12/12'
loan['total_periods'] = total_periods
loan['monthly_payment'] = monthly_payment
datastore['parameters'] = loan
return loan return loan
def getLender(datastore): def getLender(datastore):
lender = {} return datastore['lender']
# to be replaced with real loading code
lender['name'] = 'Rivanna Graphite Investments, LLC'
lender['phone'] = '703.343.0782'
lender['address'] = '743 Madison St NW'
lender['city'] = 'Washington'
lender['state'] = 'DC'
lender['zip'] = '20011'
return getLender
def getBorrower(datastore): def getBorrower(datastore):
borrower = {} return datastore['borrower']
# to be replaced with real loading code
borrower['name'] = 'Bear Houses, LLC'
borrower['address'] = '123 Any Street'
borrower['city'] = 'Alltown'
borrower['state'] = 'VA'
borrower['zip'] = '11111'
return borrower
def getDatastore(filename=None): def getDatastore(filename=None):
@@ -91,7 +79,7 @@ def getDatastore(filename=None):
datastore = json.load(f) datastore = json.load(f)
except Exception as e: except Exception as e:
print "An error occurred opening your loan file '#s'. " % filename print "An error occurred opening your loan file '%s'. " % filename
print "The Exception:" print "The Exception:"
print e.__repr__() print e.__repr__()
quit() quit()
@@ -99,109 +87,29 @@ def getDatastore(filename=None):
return datastore return datastore
def calculateLoanAmortization(loanModel): def amortizeLoan(loan):
return loanModel
def transformTemplate(template_fileName, loanModel):
# template_filename = "statement.txt.jinja"
# setup jinja for creating the statement
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template(template_fileName)
report = template.render(original_principal_balance=loanModel.principal, future_payments=loanModel.future_payments,
past_payments=loanModel.past_payments, balloon_payment=loanModel.remaining_principal,
total_interest_paid_to_date=loanModel.total_interest, statement=loanModel.statement)
return report
def generatePDFStatement():
template_filename = "statement.pdf.jinja"
pass
def generateHTMLStatement():
pass
def generateTextStatement():
pass
def generateEmail(from_address, to_address, subject, body, attachment):
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = from_address
msg['To'] = to_address
msg.attach(MIMEText(body))
part = MIMEBase('application', "octet-stream")
part.set_payload(attachment)
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="statement.pdf"')
msg.attach(part)
return msg
def main():
# this program reads the json file describing a mortgage and calculate the actual and projected amortization
# the first payment in the file should be the interest paid at closing
# the interest at closing covers interest that would be incurred from the date of closing until the first day
# that will be covered by the first loan payment
# i.e., the first loan payment is expected a month and a half after closing, the first two weeks interest is due
# at closing. The first payment will incur interest from one month before the bill is due.
from_address = 'jkent3rd@gmail.com'
passwd = "pvyrbcnzrjoizprn"
subject = "Mortgage or Loan Statement"
to_address = 'jkent3rd@gmail.com'
body = 'This email contains a PDF of your mortgage statement.'
# read in the file
# filename = "./10Kloan.txt"
# filename = "./10Kloan.test.txt"
# filename = "./dadmortgage.txt"
# filename = "./brendamortgage.txt"
filename = "./greenfield_mortgage.txt"
template_filename = "statement.pdf.jinja"
loanInformation = loadLoanInformation(filename)
loanModel = calculateLoanAmortization(loanInformation)
# read in the statement information
statement, lender, borrower, loan = {}, {}, {}, {}
lender = loanModel.lender
borrower = loanModel.borrower
past_payments = loanModel.past_payments
future_payments = loanModel.future_payments
statement['title'] = "Mortgage Statement - 185 James River Rd"
statement['date'] = "Today"
statement['lender'] = lender
statement['borrower'] = borrower
statement['loan'] = loan
# loop over the payments and calculate the actual amortization # loop over the payments and calculate the actual amortization
actual_payments = loanModel["payments"] monthly_payment = loan["parameters"]["monthly_payment"]
remaining_principal = loanModel.principal actual_payments = loan["datastore"]["payments"]
payment_day_of_month = loanInformation.payment_day_of_month
daily_interest_rate = loanInformation.daily_interest_rate remaining_principal = loan["parameters"]["principal"]
total_periods = loanInformation.total_periods 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 annual_interest = 0
total_interest = 0 total_interest = 0
interest_paid_through_date = datetime.strptime(loanModel["start_interest_date"], "%Y-%m-%d").date()
next_payment_date = datetime.strptime(loanModel["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)
old_bill_date = next_bill_date old_bill_date = next_bill_date
payment_number = 1
current_year = next_bill_date.year current_year = next_bill_date.year
past_payments = []
future_payments = []
for payment in actual_payments: for payment in actual_payments:
payment_date = datetime.strptime((payment[0]), '%Y-%m-%d').date() payment_date = datetime.strptime((payment[0]), '%Y-%m-%d').date()
payment_amount = Decimal(payment[1]).quantize(Decimal("1.00")) payment_amount = Decimal(payment[1]).quantize(Decimal("1.00"))
@@ -232,6 +140,16 @@ def main():
if old_bill_date.month < 12: 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) 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["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 # loop over remaining scheduled payments and present estimated amortization
while (payment_number <= total_periods) and (remaining_principal > 0): while (payment_number <= total_periods) and (remaining_principal > 0):
@@ -254,7 +172,7 @@ def main():
future_payment_record['payment_date'] = next_bill_date future_payment_record['payment_date'] = next_bill_date
future_payment_record['days_of_interest'] = days_since_last_payment future_payment_record['days_of_interest'] = days_since_last_payment
future_payment_record['payment_amount'] = monthly_payment future_payment_record['payment_amount'] = monthly_payment
future_payment_record['principal_payment'] = new_interest future_payment_record['principal_payment'] = new_principal
future_payment_record['interest_payment'] = new_interest future_payment_record['interest_payment'] = new_interest
future_payment_record['new_balance'] = remaining_principal future_payment_record['new_balance'] = remaining_principal
future_payments.append(future_payment_record) future_payments.append(future_payment_record)
@@ -266,8 +184,68 @@ def main():
else: else:
next_bill_date = date(year=old_bill_date.year + 1, month=1, day=payment_day_of_month) next_bill_date = date(year=old_bill_date.year + 1, month=1, day=payment_day_of_month)
report = transformTemplate('', loanModel)
loan["balloon_payment"] = remaining_principal
loan["past_payments"] = past_payments
loan["future_payments"] = future_payments
return
def transformTemplate(template_fileName, loanModel):
# template_filename = "statement.txt.jinja"
# setup jinja for creating the statement
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template(template_fileName)
print loanModel
report = template.render(model=loanModel)
return report
def generatePDFAttachment():
template_filename = "statement.pdf.jinja"
pass
def generateEmail(from_address, to_address, subject, body, pdfAttachment, txtAttachment):
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = from_address
msg['To'] = to_address
msg.attach(MIMEText(body))
if (pdfAttachment != None):
part = MIMEBase("application", "octet-stream")
part.set_payload(pdfAttachment)
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="statement.pdf"')
msg.attach(part)
if (txtAttachment != None):
part = MIMEBase("text", "html")
part.set_payload(txtAttachment)
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="statement.html"')
msg.attach(part)
return msg
def sendEmail(msg, from_address, to_address, passwd):
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(from_address, passwd)
server.sendmail(from_address, to_address, msg.as_string())
server.close()
except:
print "Couldn't send email."
def createPDF(report):
# create pdf # create pdf
class MyFPDF(FPDF, HTMLMixin): class MyFPDF(FPDF, HTMLMixin):
pass pass
@@ -277,22 +255,49 @@ def main():
pdf.add_page() pdf.add_page()
pdf.write_html(report) pdf.write_html(report)
# pdf.output(name='test.pdf', dest='F') # pdf.output(name='test.pdf', dest='F')
attachment = pdf.output(dest='S') return pdf.output(dest='S')
def selectTemplate(loan):
templateKey = loan["datastore"]["format"] + "Template"
if templateKey in loan:
template = loan[templateKey]
else:
template = 'statement.pdf.jinja'
return template
def main():
# this program reads the json file describing a mortgage and calculate the actual and projected amortization
# the first payment in the file should be the interest paid at closing
# the interest at closing covers interest that would be incurred from the date of closing until the first day
# that will be covered by the first loan payment
# i.e., the first loan payment is expected a month and a half after closing, the first two weeks interest is due
# at closing. The first payment will incur interest from one month before the bill is due.
# read in the file
# filename = "./10Kloan.txt"
#filename = "./10Kloan.json"
# filename = "./dadmortgage.json"
# filename = "./brendamortgage.json"
filename = "./greenfield_mortgage.json"
template_filename = "statement.pdf.jinja"
loan = loadLoanInformation(filename)
amortizeLoan(loan)
report = transformTemplate(selectTemplate(loan), loan)
if loan["email"]["send_pdf"] == "true":
pdfAttachment = createPDF(report)
# send email # send email
try: emailParameters = loan["email"]
server = smtplib.SMTP('smtp.gmail.com', 587) msg = generateEmail(emailParameters["from_address"], emailParameters["to_address"], emailParameters["subject"],
server.ehlo() emailParameters["body"], pdfAttachment, report)
server.starttls() sendEmail(msg, emailParameters["from_address"], emailParameters["to_address"], emailParameters['password'])
server.login(from_address, passwd)
email = generateEmail(from_address, to_address, subject, body, attachment)
server.sendmail(from_address, to_address, email.as_string())
server.close()
except:
print "Couldn't send email, dumping statement to file."
pdf.output(name='test.pdf', dest='F')
quit()
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -1,22 +1,22 @@
<html> <html>
<body> <body>
<font face='arial' size='14'><p align='center'>{{ statement.title }}</p></font> <font face='arial' size='14'><p align='center'>{{ model.header.title }}</p></font>
<font face='arial' size='10'><p align='center'>{{ statement.lender.name }}</p></font> <font face='arial' size='10'><p align='center'>{{ model.lender.name }}</p></font>
<font face='arial' size='8'> <font face='arial' size='8'>
<p align='center'>{{ statement.lender.phone }} - {{ statement.lender.address }} - <p align='center'>{{ model.lender.phone }} - {{ model.lender.address }} -
{{ statement.lender.city }} {{statement.lender.state }} {{ statement.lender.zip }}</p> {{ model.lender.city }} {{model.lender.state }} {{ model.lender.zip }}</p>
<p align='right'>Statement Date: {{ statement.date }}</p> <p align='right'>Statement Date: {{ model.header.date }}</p>
<p/> <p/>
<table> <table>
<thead><tr><th width='45%' align='left'>Loan Information</th><th width='45%'>&nbsp;</th></tr></thead> <thead><tr><th width='45%' align='left'>Loan Information</th><th width='45%'>&nbsp;</th></tr></thead>
<tbody> <tbody>
<tr><td>Borrower: {{ statement.borrower.name }}&nbsp;</td> <td>Account Number: {{ statement.loan.account_number }}</td></tr> <tr><td>Borrower: {{ model.borrower.name }}&nbsp;</td> <td>Account Number: {{ model.parameters.account_number }}</td></tr>
<tr><td>{{ statement.borrower.address }}&nbsp;</td> <td>Origination Date: {{ statement.loan.origination_date }}</td></tr> <tr><td>{{ model.borrower.address }}&nbsp;</td> <td>Origination Date: {{ model.parameters.start_date }}</td></tr>
<tr><td>{{ statement.borrower.city }}, {{statement.borrower.state }} {{ statement.borrower.zip }}</td> <tr><td>{{ model.borrower.city }}, {{model.borrower.state }} {{ model.borrower.zip }}</td>
<td>Original Principal: {{ "$%.2f"|format(statement.loan.principal) }}</td></tr> <td>Original Principal: {{ "$%.2f"|format(model.parameters.principal) }}</td></tr>
<tr><td>Rate: {{statement.loan.rate }} </td> <td>Term: {{statement.loan.term }} months </td></tr> <tr><td>Rate: {{model.parameters.interest_rate }}% </td> <td>Term: {{model.parameters.periods }} months </td></tr>
<tr><td>Next Payment Due Date: {{statement.loan.next_due_date}} </td> <td>Payment Due: {{ "$%.2f"|format(statement.loan.next_payment_amt) }} </td></tr> <tr><td>Next Payment Due Date: {{model.parameters.next_due_date}} </td> <td>Payment Due: {{ "$%.2f"|format(model.parameters.next_payment_amt) }} </td></tr>
</tbody> </tbody>
</table> </table>
<p/> <p/>
@@ -33,7 +33,7 @@
<th width='20%' align='right'>New Balance</th> <th width='20%' align='right'>New Balance</th>
</tr></thead> </tr></thead>
<tbody> <tbody>
{% for item in past_payments %} {% for item in model.past_payments %}
<tr><td align='center'> {{ item.payment_number }} </td> <tr><td align='center'> {{ item.payment_number }} </td>
<td align='center'> {{ item.bill_date }} </td> <td align='center'> {{ item.bill_date }} </td>
<td align='center'> {{ item.payment_date }} </td> <td align='center'> {{ item.payment_date }} </td>
@@ -49,7 +49,7 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<p>Total interest paid to date is {{ "$%.2f"|format(total_interest_paid_to_date) }}.</p> <p>Total interest paid to date is {{ "$%.2f"|format(model.total_interest_paid_to_date) }}.</p>
<p/> <p/> <p/> <p/>
<p class='section_header'><font face='arial' size='14'>Remaining Amortization</font></p> <p class='section_header'><font face='arial' size='14'>Remaining Amortization</font></p>
@@ -64,7 +64,7 @@
<th width='20%' align='right'>Principal Balance</th> <th width='20%' align='right'>Principal Balance</th>
</tr></thead> </tr></thead>
<tbody> <tbody>
{% for item in future_payments %} {% for item in model.future_payments %}
<tr><td align='center'> {{ item.payment_number }} </td> <tr><td align='center'> {{ item.payment_number }} </td>
<td align='center'> {{ item.payment_date }} </td> <td align='center'> {{ item.payment_date }} </td>
<td align='center'> {{ item.days_of_interest }} </td> <td align='center'> {{ item.days_of_interest }} </td>
@@ -76,7 +76,7 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<p>Balloon Payment Due: {{ "$%.2f"|format(balloon_payment) }} </p> <p>Balloon Payment Due: {{ "$%.2f"|format(model.balloon_payment) }} </p>
</font> </font>
</body> </body>
</html> </html>