From 25079d7f33967617508f39e3242d1d263e00849b Mon Sep 17 00:00:00 2001
From: Immanuel Onyeka <immanuel@onyeka.ca>
Date: Thu, 24 Nov 2022 15:23:49 -0500
Subject: [PATCH] Fetch NationalMI rates with Loan type

---
 migrations/0_29092022_create_main_tables.sql |   4 +-
 migrations/seed.sql                          |  12 +-
 skouter.go                                   | 129 +++++++++++--------
 3 files changed, 86 insertions(+), 59 deletions(-)

diff --git a/migrations/0_29092022_create_main_tables.sql b/migrations/0_29092022_create_main_tables.sql
index aae9972..55c3316 100644
--- a/migrations/0_29092022_create_main_tables.sql
+++ b/migrations/0_29092022_create_main_tables.sql
@@ -86,8 +86,8 @@ CREATE TABLE loan (
 	amount 		INT NOT NULL,
 	term 			INT, /* In years */
 	interest 		INT, /* Per year, precise to 2 decimals */
-	ltv 		INT DEFAULT 0,
-	dti 		INT DEFAULT 0,
+	ltv 		FLOAT(5, 2) DEFAULT 0,
+	dti 		FLOAT(5, 2) DEFAULT 1,
 	hoi 			INT DEFAULT 0, /* Hazard insurance annual payments */
 	mi_name 		VARCHAR(50) NOT NULL,
 	/* Mortgage insurance title shown in menu */
diff --git a/migrations/seed.sql b/migrations/seed.sql
index 6d4853a..40aeb25 100644
--- a/migrations/seed.sql
+++ b/migrations/seed.sql
@@ -233,8 +233,8 @@ INSERT INTO loan (
 	3300000,
 	30,
 	375,
-	10000,
-	0,
+	88.00,
+	5.00,
 	0,
 	"custom mi",
 	234000,
@@ -247,8 +247,8 @@ INSERT INTO loan (
 	2510000,
 	30,
 	300,
-	10000,
-	0,
+	90.00,
+	6.70,
 	0,
 	"maybe MGIC",
 	234000,
@@ -261,8 +261,8 @@ INSERT INTO loan (
 	8000000,
 	10,
 	125,
-	15000,
-	0,
+	95.00,
+	4.90,
 	0,
 	"custom mi",
 	234000,
diff --git a/skouter.go b/skouter.go
index 11e2403..c2310c0 100644
--- a/skouter.go
+++ b/skouter.go
@@ -65,17 +65,22 @@ type Loan struct {
 	Type	LoanType 	`json:"loanType"`
 	Amount	int 	`json:"loanAmount"`
 	Term		int 	`json:"term"`
-	Ltv 	int 	`json:"ltv"`
-	Dti 	int 	`json:"dti"`
+	Ltv 	float32 	`json:"ltv"`
+	Dti 	float32 	`json:"dti"`
 	Hoi		int 	`json:"hoi"`
 	Interest	int 	`json:"interest"`
 	Lender		string 	`json:"lender"`
 	MiName		string 	`json:"miName"`
 	MiAmount	int 	`json:"miAmount"`
+	Mi	map[string]interface{} 	`json:"mi"`
 	Fees		[]Fee 	`json:"fees"`
 	Name		string 	`json:"name"`
 }
 
+type MI struct {
+	Id int
+}
+
 type Estimate struct {
 	Id		int 	`json:"id"`
 	User		int 	`json:"user"`
@@ -360,74 +365,96 @@ func getBorrower(db *sql.DB, id int) (Borrower, error) {
 	return borrower, nil
 }
 
-func getMi(db *sql.DB, estimate *Estimate) {
-	// body := map[string]string{
-	// 	"zipCode": estimate.Zip,
-	// 	// "stateCode": "CA",
-	// 	// "address": "",
-	// 	"propertyTypeCode": "SFO",
-	// 	"occupancyTypeCode": "PRS",
-	// 	"loanPurposeCode": "PUR",
-	// 	"loanAmount": "1000000",
-	// 	"loanToValue": "LTV95",
-	// 	"amortizationTerm": "A30",
-	// 	"loanTypeCode": "FXD",
-	// 	"duLpDecisionCode": "DAE",
-	// 	"loanProgramCodes": [],
-	// 	"debtToIncome": "5",
-	// 	"wholesaleLoan": 0,
-	// 	"coveragePercentageCode": "L30",
-	// 	"productCode": "BPM",
-	// 	"renewalTypeCode": "CON",
-	// 	"numberOfBorrowers": 1,
-	// 	"coBorrowerCreditScores": [],
-	// 	"borrowerCreditScore": "740",
-	// 	"masterPolicy": null,
-	// 	"selfEmployedIndicator": false,
-	// 	"armType": "",
-	// 	"userId": 44504
-	// }
-	
-	var propertyCodes = map[string]string {
-		"Single Family Attached": "SFO",
-		"Single Family Detached": "SFO",
-		"Condominium Lo-rise": "CON",
-		"Condominium Hi-rise": "CON",
+func getMi(db *sql.DB, estimate *Estimate, pos int) (*Estimate) {
+	var err error
+	var loan Loan = estimate.Loans[pos]
+
+	var ltv = func(l float32) string {
+		switch {
+		case l > 95: return "LTV97"
+		case l > 90: return "LTV95"
+		case l > 85: return "LTV90"
+		default: return "LTV85"
 		}
+	}
+
+	var term = func(t int) string {
+		switch {
+		case t <= 10: return "A10"
+		case t <= 15: return "A15"
+		case t <= 20: return "A20"
+		case t <= 25: return "A25"
+		case t <= 30: return "A30"
+		default: return "A40"
+		}
+	}
 
-	/* var occupancyCodes = map[string]string {
-		"Primary Residence": "PRS",
-		"Second Home": "SCH",
-		"Condominium Lo-rise": "CON",
-		"Condominium Hi-rise": "CON",
-		} */
+	var propertyCodes = map[string]string {
+		"Single Attached": "SFO",
+		"Single Detached": "SFO",
+		"Condo Lo-rise": "CON",
+		"Condo Hi-rise": "CON",
+	}
 
-	body, _ := json.Marshal(map[string]any{
+	var purposeCodes = map[string]string {
+		"Purchase": "PUR",
+		"Refinance": "RRT",
+	}
+
+	body, err := json.Marshal(map[string]any{
 		"zipCode": estimate.Zip,
-		// "stateCode": "CA",
-		// "address": "",
+		"stateCode": "CA",
+		"address": "",
 		"propertyTypeCode": propertyCodes[estimate.Property],
 		"occupancyTypeCode": "PRS",
-		"loanPurposeCode": "PUR",
-		"loanAmount": strconv.Itoa(500000 / 100),
-		"loanToValue": "LTV95",
-		"amortizationTerm": "A30",
+		"loanPurposeCode": purposeCodes[estimate.Transaction],
+		"loanAmount": loan.Amount,
+		"loanToValue": ltv(loan.Ltv),
+		"amortizationTerm": term(loan.Term),
 		"loanTypeCode": "FXD",
 		"duLpDecisionCode": "DAE",
-		"debtToIncome": 5,
+		"loanProgramCodes": []any{},
+		"debtToIncome": loan.Dti,
 		"wholesaleLoan": 0,
 		"coveragePercentageCode": "L30",
 		"productCode": "BPM",
 		"renewalTypeCode": "CON",
 		"numberOfBorrowers": 1,
+		"coBorrowerCreditScores": []any{},
 		"borrowerCreditScore": strconv.Itoa(estimate.Borrower.Credit),
 		"masterPolicy": nil,
 		"selfEmployedIndicator": false,
 		"armType": "",
 		"userId": 44504,
 	})
-	log.Println("the bytes: %v", bytes.NewBuffer(body))
+	
+	if err != nil {
+		log.Printf("Could not marshal NationalMI body: \n%v\n%v\n",
+		bytes.NewBuffer(body), err)
+	}
+
+	req, err := http.NewRequest("POST",
+	"https://rate-gps.nationalmi.com/rates/productRateQuote",
+	bytes.NewBuffer(body))
+	req.Header.Add("Content-Type", "application/json")
+
+	req.AddCookie(&http.Cookie{
+		Name: "nmirategps_email",
+		Value: config["NationalMIEmail"]})
+
+	resp, err := http.DefaultClient.Do(req)
+	var res map[string]interface{}
+
+	if resp.StatusCode != 200 {
+		log.Printf("the status: %v\nthe resp: %v\n the req: %v\n the body: %v\n",
+		resp.Status,  resp, req.Body, bytes.NewBuffer(body))
+	} else {
+		json.NewDecoder(resp.Body).Decode(&res)
+		log.Printf("the valid resp: %v", res)
+		estimate.Loans[pos].Mi = res
+	}
 
+	return estimate
 }
 
 func validateEstimate() {
@@ -503,7 +530,7 @@ func api(w http.ResponseWriter, r *http.Request) {
 			break
 		}
 
-		getMi(db, &est)
+		json.NewEncoder(w).Encode(getMi(db, &est, 0))
 
 		// if err != nil {
 		// 	json.NewEncoder(w).Encode(err)