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:
63
10Kloan.json
Normal file
63
10Kloan.json
Normal 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
56
brendamortgage.json
Normal 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
56
dadmortgage.json
Normal 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
63
greenfield_mortgage.json
Normal 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"
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
]
|
||||
}
|
||||
@@ -4,45 +4,47 @@ 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
|
||||
|
||||
|
||||
def getPaymentHistory(datastore, loan, asOfDate):
|
||||
pass
|
||||
def getStatementHeader(datastore):
|
||||
return datastore['header']
|
||||
|
||||
|
||||
def getAmortization(datastore, loan, paymentHistory):
|
||||
pass
|
||||
def getEmailInformation(datastore):
|
||||
return datastore['email']
|
||||
|
||||
|
||||
def loadLoanInformation(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['borrower'] = getBorrower(datastore)
|
||||
loanModel['paymentHistory'] = getPaymentHistory(datastore, loan, asOfDate)
|
||||
loanModel['futureAmortization'] = getAmortization(datastore, loan, loanModel.paymentHistory)
|
||||
loanModel['header'] = getStatementHeader(datastore)
|
||||
return loanModel
|
||||
|
||||
|
||||
def getLoan(datastore):
|
||||
def getLoanParameters(datastore):
|
||||
# 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
|
||||
principal = Decimal(datastore["loan.principal"]).quantize(Decimal("1.00"))
|
||||
periods_per_year = Decimal(datastore["loan.periods per year"])
|
||||
total_periods = Decimal(datastore["loan.periods"])
|
||||
payment_day_of_month = int(datastore['loan.payment day of month'])
|
||||
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 datastore:
|
||||
monthly_payment = Decimal(datastore["monthly_payment"]).quantize(Decimal("1.00"))
|
||||
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
|
||||
@@ -50,38 +52,24 @@ def getLoan(datastore):
|
||||
periodic_rate * ((1 + periodic_rate) ** total_periods))
|
||||
monthly_payment = (principal / discount_factor).quantize(Decimal("1.00"))
|
||||
|
||||
loan['loan.account_number'] = '123456789'
|
||||
loan['principal'] = principal
|
||||
loan['term'] = total_periods
|
||||
loan['annual_rate'] = annual_rate
|
||||
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):
|
||||
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
|
||||
return datastore['lender']
|
||||
|
||||
|
||||
def getBorrower(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
|
||||
return datastore['borrower']
|
||||
|
||||
|
||||
def getDatastore(filename=None):
|
||||
@@ -91,7 +79,7 @@ def getDatastore(filename=None):
|
||||
datastore = json.load(f)
|
||||
|
||||
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 e.__repr__()
|
||||
quit()
|
||||
@@ -99,109 +87,29 @@ def getDatastore(filename=None):
|
||||
return datastore
|
||||
|
||||
|
||||
def calculateLoanAmortization(loanModel):
|
||||
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
|
||||
|
||||
def amortizeLoan(loan):
|
||||
# loop over the payments and calculate the actual amortization
|
||||
actual_payments = loanModel["payments"]
|
||||
monthly_payment = loan["parameters"]["monthly_payment"]
|
||||
|
||||
remaining_principal = loanModel.principal
|
||||
payment_day_of_month = loanInformation.payment_day_of_month
|
||||
daily_interest_rate = loanInformation.daily_interest_rate
|
||||
total_periods = loanInformation.total_periods
|
||||
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
|
||||
|
||||
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
|
||||
payment_number = 1
|
||||
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"))
|
||||
@@ -232,6 +140,16 @@ def main():
|
||||
|
||||
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["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):
|
||||
@@ -254,7 +172,7 @@ def main():
|
||||
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_interest
|
||||
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)
|
||||
@@ -266,8 +184,68 @@ def main():
|
||||
else:
|
||||
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
|
||||
class MyFPDF(FPDF, HTMLMixin):
|
||||
pass
|
||||
@@ -277,22 +255,49 @@ def main():
|
||||
pdf.add_page()
|
||||
pdf.write_html(report)
|
||||
# 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
|
||||
try:
|
||||
server = smtplib.SMTP('smtp.gmail.com', 587)
|
||||
server.ehlo()
|
||||
server.starttls()
|
||||
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()
|
||||
emailParameters = loan["email"]
|
||||
msg = generateEmail(emailParameters["from_address"], emailParameters["to_address"], emailParameters["subject"],
|
||||
emailParameters["body"], pdfAttachment, report)
|
||||
sendEmail(msg, emailParameters["from_address"], emailParameters["to_address"], emailParameters['password'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<html>
|
||||
<body>
|
||||
<font face='arial' size='14'><p align='center'>{{ statement.title }}</p></font>
|
||||
<font face='arial' size='10'><p align='center'>{{ statement.lender.name }}</p></font>
|
||||
<font face='arial' size='14'><p align='center'>{{ model.header.title }}</p></font>
|
||||
<font face='arial' size='10'><p align='center'>{{ model.lender.name }}</p></font>
|
||||
<font face='arial' size='8'>
|
||||
<p align='center'>{{ statement.lender.phone }} - {{ statement.lender.address }} -
|
||||
{{ statement.lender.city }} {{statement.lender.state }} {{ statement.lender.zip }}</p>
|
||||
<p align='right'>Statement Date: {{ statement.date }}</p>
|
||||
<p align='center'>{{ model.lender.phone }} - {{ model.lender.address }} -
|
||||
{{ model.lender.city }} {{model.lender.state }} {{ model.lender.zip }}</p>
|
||||
<p align='right'>Statement Date: {{ model.header.date }}</p>
|
||||
|
||||
<p/>
|
||||
<table>
|
||||
<thead><tr><th width='45%' align='left'>Loan Information</th><th width='45%'> </th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Borrower: {{ statement.borrower.name }} </td> <td>Account Number: {{ statement.loan.account_number }}</td></tr>
|
||||
<tr><td>{{ statement.borrower.address }} </td> <td>Origination Date: {{ statement.loan.origination_date }}</td></tr>
|
||||
<tr><td>{{ statement.borrower.city }}, {{statement.borrower.state }} {{ statement.borrower.zip }}</td>
|
||||
<td>Original Principal: {{ "$%.2f"|format(statement.loan.principal) }}</td></tr>
|
||||
<tr><td>Rate: {{statement.loan.rate }} </td> <td>Term: {{statement.loan.term }} 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>Borrower: {{ model.borrower.name }} </td> <td>Account Number: {{ model.parameters.account_number }}</td></tr>
|
||||
<tr><td>{{ model.borrower.address }} </td> <td>Origination Date: {{ model.parameters.start_date }}</td></tr>
|
||||
<tr><td>{{ model.borrower.city }}, {{model.borrower.state }} {{ model.borrower.zip }}</td>
|
||||
<td>Original Principal: {{ "$%.2f"|format(model.parameters.principal) }}</td></tr>
|
||||
<tr><td>Rate: {{model.parameters.interest_rate }}% </td> <td>Term: {{model.parameters.periods }} months </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>
|
||||
</table>
|
||||
<p/>
|
||||
@@ -33,7 +33,7 @@
|
||||
<th width='20%' align='right'>New Balance</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for item in past_payments %}
|
||||
{% for item in model.past_payments %}
|
||||
<tr><td align='center'> {{ item.payment_number }} </td>
|
||||
<td align='center'> {{ item.bill_date }} </td>
|
||||
<td align='center'> {{ item.payment_date }} </td>
|
||||
@@ -49,7 +49,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</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 class='section_header'><font face='arial' size='14'>Remaining Amortization</font></p>
|
||||
@@ -64,7 +64,7 @@
|
||||
<th width='20%' align='right'>Principal Balance</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for item in future_payments %}
|
||||
{% for item in model.future_payments %}
|
||||
<tr><td align='center'> {{ item.payment_number }} </td>
|
||||
<td align='center'> {{ item.payment_date }} </td>
|
||||
<td align='center'> {{ item.days_of_interest }} </td>
|
||||
@@ -76,7 +76,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Balloon Payment Due: {{ "$%.2f"|format(balloon_payment) }} </p>
|
||||
<p>Balloon Payment Due: {{ "$%.2f"|format(model.balloon_payment) }} </p>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user