IEnableMuch: Amortization Calculator
This is the computation routine for a real estate app I made a real estate app long time ago(2003, made in VB6), what it don't compute then is how long you will pay something based on your budget. A new feature Author: Michael Buen
by meetravi
HTML
<body ng-controller="RealEstateController" ng-app="RealEstateApp">
<div style='float: left' class='input'>
<fieldset>
<legend>Selling</legend>
<div><label for='TotalContractPrice'>Total Contract Price</label></div>
<div>
<input
id='TotalContractPrice'
ng-model='TotalContractPrice'
ng-change='ComputeFromTotalContractPrice()'
ng-disabled='DeterminePaymentTerms'/>
</div>
<div><label for='DownPaymentPercent'>Downpayment %</label></div>
<div><input
id='DownpaymentPercent' ng-model='DownPaymentPercent' ng-change='ComputeFromDownPaymentPercent()'
ng-disabled='DeterminePaymentTerms'
percent/></div>
<div><label for='DownPayment'>Downpayment</label></div>
<div><input id='DownPayment' ng-model='DownPayment' ng-change='ComputeFromDownPayment()' ng-disabled='DeterminePaymentTerms' type='number'/></div>
<div><label for='InstallmentPrincipal'>Installment Principal</label></div>
<div><input id='InstallmentPrincipal' ng-model='InstallmentPrincipal' ng-change='ComputeFromInstallmentPrincipal()' ng-disabled='DeterminePaymentTerms'/></div>
</fieldset>
<fieldset>
<legend>Payment Terms</legend>
<div><label for='NumberOfYearsToPay'>Number of years to pay</label></div>
<div><input ng-disabled='DeterminePaymentTerms' id='NumberOfYearsToPay' ng-model='NumberOfYearsToPay' ng-change='ComputeFromYears()' type='number'/></div>
<div><label for='NumberOfMonthsToPay'>Number of months to pay</label></div>
<div><input ng-disabled='DeterminePaymentTerms' id='NumberOfMonthsToPay' ng-model='NumberOfMonthsToPay' ng-change='ComputeFromMonths()' type='number'/></div>
<div><label for='PaymentModeInMonths'>Payment Mode(1 = Monthly, 3 = Quarterly, ..., 12 = Yearly)</label></div>
<div><input...
CSS
fieldset { font-size: 13px; font-family : 'Calibri'}
div.input { width: 380px; }
div.amort { width: auto; }
table, th, td { font-size: 13px; font-family : 'Calibri'; }
input {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 5px;
}
fieldset {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
table.table {
margin: 20px;
color: 666;
font-size: 12px;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 2px #d1d1d1;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 2px #d1d1d1;
background: #eaebec;
border: #ccc 1px solid;
border-radius: 3px;
box-shadow: 0 1px 2px #d1d1d1;
font-family: Arial, Helvetica, sans-serif;
text-shadow: 1px 1px 0px #fff;
}
table.table tr.even td {
background: #f6f6f6;
background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#f6f6f6));
background: -moz-linear-gradient(top, #f8f8f8, #f6f6f6);
}
table.table th {
padding: 21px 25px 22px 25px;
border-bottom: 1px solid #e0e0e0; border-top: 1px solid #fafafa;
background: #ededed;
background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#ebebeb));
background: -moz-linear-gradient(top, #ededed, #ebebeb);
}
table.table th:first-child {
padding-left: 20px;
text-align: left
}
table.table a:visited {
color: #999999;
font-weight: bold;
text-decoration: none
}
table.table a:active,
table.table a:hover {
color: #bd5a35;
text-decoration: underline
}
table.table a:link {
color: #666;
font-weight: bold;
text-decoration: none
}
table.table tr {
padding-left: 20px;
text-align: center
}
table.table tr:first-child th:first-child {
-moz-border-radius-topleft: 3px;
-webkit-border-top-left-radius: 3px;
border-top-left-radius: 3px;
}
table.table tr:first-child th:last-child {
-moz-border-radius-topright: 3px;
-webkit-border-top-right-radius: 3px;
...
JavaScript
var myApp = angular.module('RealEstateApp', []);
myApp.directive("percent", function($filter){
var p = function(viewValue){
var m = viewValue.match(/^(\d+)\/(\d+)/);
if (m != null)
return $filter('number')(parseInt(m[1])/parseInt(m[2]), 4);
return $filter('number')(parseFloat(viewValue)/100, 4);
};
var f = function(modelValue){
return $filter('number')(parseFloat(modelValue)*100, 2);
};
return {
require: 'ngModel',
link: function(scope, ele, attr, ctrl){
ctrl.$parsers.unshift(p);
ctrl.$formatters.unshift(f);
}
};
});
myApp.controller('RealEstateController',['$scope', function($scope) {
// ------- MODELS --------
// Month number, amortization date, interest, principal, principal balance
$scope.Amortizations = [];
$scope.TotalContractPrice = 4000000;
$scope.DownPaymentPercent = .2;
$scope.DownPayment = 0;
$scope.InstallmentPrincipal = 0;
$scope.TotalInterest = 0;
$scope.TotalPrincipal = 0;
$scope.TotalAmortization = 0;
$scope.NumberOfYearsToPay = 5;
$scope.NumberOfMonthsToPay = 0;
$scope.PaymentModeInMonths = 1; // monthly
$scope.InterestRatePerAnnum = 0.21;
$scope.PeriodicInterestRate = 0;
$scope.AmortizationFactor = 0;
$scope.AmortizationAmount = 0;
$scope.AmortizationStartDate = new Date('May 5, 2000');
// determine payment terms based on budget
$scope.DeterminePaymentTerms = false;
$scope.Budget = 0;
$scope.AdvancedPayments = [
{ MonthNumber: null, Payment: null }
];
// ------- CONTROLLER's ACTIONS -----------
$scope.ComputeYears = function() {
$scope.NumberOfYearsToPay = $scope.NumberOfMonthsToPay / 12;
}
$scope.ComputeFromTotalContractPrice = function() {
$scope.ComputeDownPayment();
$scope.ComputeInstallmentPrincipal();
...