diff --git a/components/estimates.vue b/components/estimates.vue
index 8e18241..744f0e9 100644
--- a/components/estimates.vue
+++ b/components/estimates.vue
@@ -33,12 +33,15 @@
Saved Estimates
- estimate = e">{{e.id}} - {{e.property}} - ${{e.price/100}}
+ estimate = e">
+ {{e.id}} - {{e.property}} - ${{e.price/100}}
+
{{estimate}}
-
+
+
@@ -86,6 +89,25 @@ function getEstimates() {
}
+function summarize() {
+ fetch(`/api/estimate/summarize`,
+ {method: 'POST',
+ headers: {
+ "Accept": "application/json",
+ "Authorization": `Bearer ${props.token}`,
+ },
+ body: JSON.stringify(estimate.value),
+ }).then(response => {
+ if (response.ok) { return response.json() } else {
+ response.text().then(t => console.log(t))
+ }
+ }).then (result => {
+ if (!result || !result.length) return // Exit if token is invalid or no fees are saved
+ console.log('done', result)
+ })
+
+}
+
onMounted(() => {
getEstimates()
})
diff --git a/components/new/summary.vue b/components/new/summary.vue
index d9670e7..21369c2 100644
--- a/components/new/summary.vue
+++ b/components/new/summary.vue
@@ -42,9 +42,7 @@ function amortize(principle, rate, periods) {
return principle * rate*(1+rate)**periods / ((1+rate)**periods - 1)
}
-const loanPayment = computed(() => {
- let amount = props.loan.amount
-
+const loanPayment = computed(() => {
return amortize(props.loan.amount,
props.loan.interest / 100 / 12,
props.loan.term*12)
diff --git a/skouter.go b/skouter.go
index 8da99c9..b44c43b 100644
--- a/skouter.go
+++ b/skouter.go
@@ -16,6 +16,7 @@ import (
"time"
"errors"
"strings"
+ "math"
// pdf "github.com/SebastiaanKlippert/go-wkhtmltopdf"
"github.com/golang-jwt/jwt/v4"
)
@@ -94,6 +95,7 @@ type Loan struct {
Ltv float32 `json:"ltv"`
Dti float32 `json:"dti"`
Hoi int `json:"hoi"`
+ Hazard int `json:"hazard"`
Tax int `json:"hoi"`
Interest float32 `json:"interest"`
Mi MI `json:"mi"`
@@ -116,15 +118,15 @@ type MI struct {
}
type Result struct {
- User int `json:"user"`
- Borrower Borrower `json:"borrower"`
- Transaction string `json:"transaction"`
- Price int `json:"price"`
- Property string `json:"property"`
- Occupancy string `json:"occupancy"`
+ Id int `json:"loanId"`
+ LoanId int `json:"loanId"`
+ LoanPayment int `json:"loanPayment"`
+ TotalMonthly int `json:"totalMonthly"`
+ Fees int `json:"fees"`
+ Credits int `json:"credits"`
+ CashToClose int `json:"cashToClose"`
Zip string `json:"zip"`
Pud bool `json:"pud"`
- Loans []Loan `json:"loans"`
}
type Estimate struct {
@@ -209,6 +211,41 @@ func match(path, pattern string, args *[]string) bool {
return true
}
+func summarize(w http.ResponseWriter, db *sql.DB, r *http.Request) {
+ var estimate Estimate
+ var result Result
+ err := json.NewDecoder(r.Body).Decode(&estimate)
+ if err != nil { http.Error(w, "Invalid estimate.", 422); return }
+
+ amortize := func(principle float64, rate float64, periods float64) int {
+ exp := math.Pow(1+rate, periods)
+ return int(principle * rate * exp / (exp - 1))
+ }
+ loan := estimate.Loans[0]
+ result.LoanPayment = amortize(float64(loan.Amount),
+ float64(loan.Interest / 100 / 12),
+ float64(loan.Term * 12))
+
+ result.TotalMonthly = result.LoanPayment + loan.Hoi + loan.Tax + loan.Hazard
+ if loan.Mi.Monthly {
+ result.TotalMonthly = result.TotalMonthly +
+ int(loan.Mi.Rate/100*float32(loan.Amount))
+ }
+
+ for i := range loan.Fees {
+ if loan.Fees[i].Amount > 0 {
+ result.Fees = result.Fees + loan.Fees[i].Amount
+ } else {
+ result.Credits = result.Credits + loan.Fees[i].Amount
+ }
+ }
+
+ result.CashToClose =
+ result.Fees + result.Credits + (estimate.Price - loan.Amount)
+
+ json.NewEncoder(w).Encode(result)
+}
+
func getLoanType(
db *sql.DB,
user int,
@@ -249,10 +286,11 @@ func getLoanType(
func getFees(db *sql.DB, loan int) ([]Fee, error) {
var fees []Fee
- rows, err := db.Query(
- "SELECT * FROM fees " +
- "WHERE loan_id = ?",
- loan)
+ query := `SELECT id, loan_id, amount, perc, type, notes, name, category
+ FROM fee
+ WHERE loan_id = ?`
+
+ rows, err := db.Query(query, loan)
if err != nil {
return nil, fmt.Errorf("Fee query error %v", err)
@@ -340,9 +378,14 @@ func getMi(db *sql.DB, loan int) (MI, error) {
initial_premium, initial_rate, initial_amount
FROM mi WHERE loan_id = ?`
- row := db.QueryRow(query, loan)
+ rows, err := db.Query(query, loan)
+ if err != nil { return mi, err }
+
+ defer rows.Close()
- if err := row.Scan(
+ if (!rows.Next()) { return mi, nil }
+
+ if err := rows.Scan(
&mi.Type,
&mi.Label,
&mi.Lender,
@@ -361,53 +404,6 @@ func getMi(db *sql.DB, loan int) (MI, error) {
return mi, nil
}
-func getLoans(db *sql.DB, estimate int) ([]Loan, error) {
- var loans []Loan
-
- query := `SELECT
- l.id, l.amount, l.term, l.interest, l.ltv, l.dti, l.hoi,
- lt.id, lt.user_id, lt.branch_id, lt.name
- FROM loan l INNER JOIN loan_type lt ON l.type_id = lt.id
- WHERE l.estimate_id = ?
- `
- rows, err := db.Query(query, estimate)
-
- if err != nil {
- return nil, fmt.Errorf("Loan query error %v", err)
- }
-
- defer rows.Close()
-
- for rows.Next() {
- var loan Loan
-
- if err := rows.Scan(
- &loan.Id,
- &loan.Amount,
- &loan.Term,
- &loan.Interest,
- &loan.Ltv,
- &loan.Dti,
- &loan.Hoi,
- &loan.Type.Id,
- &loan.Type.User,
- &loan.Type.Branch,
- &loan.Type.Name,
- )
- err != nil {
- return loans, fmt.Errorf("Loans scanning error: %v", err)
- }
- mi, err := getMi(db, loan.Id)
- if err != nil {
- return loans, err
- }
- loan.Mi = mi
- loans = append(loans, loan)
- }
-
- return loans, nil
-}
-
func getBorrower(db *sql.DB, id int) (Borrower, error) {
var borrower Borrower
@@ -867,7 +863,7 @@ func queryBorrower(db *sql.DB, id int) ( Borrower, error ) {
}
// Must have an estimate ID 'e', but not necessarily a loan id 'id'
-func queryLoan(db *sql.DB, e int, id int) ( []Loan, error ) {
+func getLoans(db *sql.DB, e int, id int) ( []Loan, error ) {
var loans []Loan
var query string
var rows *sql.Rows
@@ -913,6 +909,18 @@ func queryLoan(db *sql.DB, e int, id int) ( []Loan, error ) {
err != nil {
return loans, err
}
+
+ mi, err := getMi(db, loan.Id)
+ if err != nil {
+ return loans, err
+ }
+ loan.Mi = mi
+ fees, err := getFees(db, loan.Id)
+ if err != nil {
+ return loans, err
+ }
+ loan.Fees = fees
+
loans = append(loans, loan)
}
@@ -922,7 +930,7 @@ func queryLoan(db *sql.DB, e int, id int) ( []Loan, error ) {
return loans, nil
}
-func queryEstimate(db *sql.DB, id int, user int) ( []Estimate, error ) {
+func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
var estimates []Estimate
var query string
var rows *sql.Rows
@@ -974,7 +982,7 @@ func queryEstimate(db *sql.DB, id int, user int) ( []Estimate, error ) {
if len(estimates) == 0 { return estimates, errors.New("Estimate not found.") }
for i := range estimates {
- estimates[i].Loans, err = queryLoan(db, estimates[i].Id, 0)
+ estimates[i].Loans, err = getLoans(db, estimates[i].Id, 0)
if err != nil { return estimates, err }
}
@@ -1010,6 +1018,13 @@ func insertBorrower(db *sql.DB, borrower Borrower) (int, error) {
return id, nil
}
+func insertFee(db *sql.DB, fee Fee) (int, error) {
+ query := `INSERT INTO fee
+ id, loan_id, amount, perc, type, notes, name, category
+ FROM fee
+ WHERE loan_id = ?`
+}
+
func insertLoan(db *sql.DB, loan Loan) (Loan, error){
var query string
var row *sql.Row
@@ -1048,7 +1063,7 @@ func insertLoan(db *sql.DB, loan Loan) (Loan, error){
err = row.Scan(&id)
if err != nil { return Loan{}, err }
- loans, err := queryLoan(db, id, 0)
+ loans, err := getLoans(db, id, 0)
if err != nil { return Loan{}, err }
return loans[0], nil
@@ -1098,7 +1113,7 @@ func insertEstimate(db *sql.DB, estimate Estimate) (Estimate, error){
if err != nil { return estimate, err }
}
- estimates, err := queryEstimate(db, estimate.Id, 0)
+ estimates, err := getEstimates(db, estimate.Id, 0)
if err != nil { return Estimate{}, err }
return estimates[0], nil
@@ -1122,7 +1137,7 @@ func fetchEstimate(w http.ResponseWriter, db *sql.DB, r *http.Request) {
var estimates []Estimate
claims, err := getClaims(r)
- estimates, err = queryEstimate(db, 0, claims.Id)
+ estimates, err = getEstimates(db, 0, claims.Id)
if err != nil { http.Error(w, err.Error(), 500); return }
json.NewEncoder(w).Encode(estimates)
@@ -1300,6 +1315,10 @@ func api(w http.ResponseWriter, r *http.Request) {
r.Method == http.MethodPost &&
guard(r, 1):
validateEstimate(w, db, r)
+ case match(p, "/api/estimate/summarize", &args) &&
+ r.Method == http.MethodPost &&
+ guard(r, 1):
+ summarize(w, db, r)
default:
http.Error(w, "Invalid route or token", 404)
}