From 6aab5796b5abce58a35a6c54cdd20a5e481b60a2 Mon Sep 17 00:00:00 2001
From: Immanuel Onyeka <immanuel@onyeka.ca>
Date: Sat, 19 Nov 2022 22:20:51 -0500
Subject: [PATCH] Query estimates and insert in models

---
 migrations/0_29092022_create_main_tables.sql |  35 ++--
 migrations/seed.sql                          |  22 ++-
 skouter.go                                   | 171 +++++++++++++++++--
 3 files changed, 194 insertions(+), 34 deletions(-)

diff --git a/migrations/0_29092022_create_main_tables.sql b/migrations/0_29092022_create_main_tables.sql
index 08d383d..22d49c9 100644
--- a/migrations/0_29092022_create_main_tables.sql
+++ b/migrations/0_29092022_create_main_tables.sql
@@ -47,14 +47,14 @@ CREATE TABLE license (
 );
 
 /* Officers or managers may need to create new loan types with custom settings.
- * Types with branch_id and user_id values of null will be general cases. */
+ * Types with branch_id and user_id values of 0 will be general cases. */
 CREATE TABLE loan_type (
 	id 				INT AUTO_INCREMENT,
 	branch_id 		INT NOT NULL,
 	user_id 		INT NOT NULL,
 	name 			VARCHAR(30) NOT NULL,
-	FOREIGN KEY (branch_id) REFERENCES branch(id),
-	FOREIGN KEY (user_id) REFERENCES user(id),
+	/* FOREIGN KEY (branch_id) REFERENCES branch(id), */
+	/* FOREIGN KEY (user_id) REFERENCES user(id), */
 	PRIMARY KEY (`id`)
 );
 
@@ -67,32 +67,31 @@ CREATE TABLE borrower (
 );
 
 CREATE TABLE estimate (
-	id 				INT AUTO_INCREMENT,
+	id 			INT AUTO_INCREMENT,
 	user_id 		INT NOT NULL,
-	borrower_id 	INT NOT NULL,
-	comparison_id  	INT,
-	transaction 	ENUM('Purchase', 'Refinance'),
-	loan_type_id 	INT NOT NULL,
-	loan_amount 	INT NOT NULL,
+	borrower_id 		INT NOT NULL,
+	comparison_id  		INT,
+	transaction 		ENUM('Purchase', 'Refinance'),
+	loan_type_id 		INT NOT NULL,
+	loan_amount 		INT NOT NULL,
 	price 			INT NOT NULL,
-	property 		ENUM('Single Family Detached',
-					'Single Family Attached',
-					'Condominium Lo-rise',
-					'Condominium Hi-rise'),
+	property 		ENUM('Single Detached',
+					'Single Attached',
+					'Condo Lo-rise',
+					'Condo Hi-rise'),
+	occupancy 		ENUM('Primary', 'Secondary', 'Investment'),
+	zip 			VARCHAR(10),
 	pud 			BOOLEAN, /* Property under development */
 	term 			INT, /* In years */
 	interest 		INT, /* Per year, precise to 2 decimals */
 	hoi 			INT, /* Hazard insurance annual payments */
 	mi_name 		VARCHAR(50), /* Mortgage insurance title shown in menu */
 	mi_amount 		INT, /* Mortgage insurance amount */
-	lender 			VARCHAR(30),
-	name 			VARCHAR(30),
+	lender 			VARCHAR(30) DEFAULT "",
+	name 			VARCHAR(30) DEFAULT "",
 	PRIMARY KEY (`id`),
 	FOREIGN KEY (loan_type_id) REFERENCES loan_type(id)
 	ON UPDATE RESTRICT,
-	FOREIGN KEY (comparison_id) REFERENCES comparison(id)
-	ON DELETE CASCADE
-	ON UPDATE RESTRICT,
 	FOREIGN KEY (borrower_id) REFERENCES borrower(id)
 );
 
diff --git a/migrations/seed.sql b/migrations/seed.sql
index a01b6a5..37af5ec 100644
--- a/migrations/seed.sql
+++ b/migrations/seed.sql
@@ -100,7 +100,7 @@ INSERT IGNORE INTO fee_template (
 	200,
 	'Title',
 	true,
-	"Lender's Title Insurance"
+	"LenderS's Title Insurance"
 ),
 (
 	(SELECT id FROM user WHERE email="manager@example.com" LIMIT 1),
@@ -172,7 +172,7 @@ INSERT IGNORE INTO borrower (
 	1
 );
 
-INSERT IGNORE INTO estimate (
+INSERT INTO estimate (
 	user_id,
 	borrower_id,
 	comparison_id,
@@ -181,13 +181,16 @@ INSERT IGNORE INTO estimate (
 	loan_amount,
 	price,
 	property,
+	occupancy,
+	zip,
 	pud,
 	term,
 	interest,
 	hoi,
 	mi_name,
 	mi_amount,
-	lender
+	lender,
+	name
 ) VALUES
 (
 	(SELECT id FROM user WHERE email="test@example.com" LIMIT 1),
@@ -197,13 +200,16 @@ INSERT IGNORE INTO estimate (
 	(SELECT id FROM loan_type WHERE name="Conventional"),
 	3300000,
 	100000000,
-	0,
+	1,
+	1,
+	'95051',
 	false,
 	30,
 	375,
 	10000,
 	"custom mi",
 	234000,
+	"National MI",
 	"For client 1"
 ),
 (
@@ -214,13 +220,16 @@ INSERT IGNORE INTO estimate (
 	(SELECT id FROM loan_type WHERE name="FHA"),
 	2510000,
 	25000000,
-	0,
+	2,
+	1,
+	'95051',
 	false,
 	30,
 	300,
 	10000,
 	"maybe MGIC",
 	234000,
+	"MGIC",
 	"For client 2"
 ),
 (
@@ -232,11 +241,14 @@ INSERT IGNORE INTO estimate (
 	8000000,
 	50000000,
 	3,
+	2,
+	'95051',
 	false,
 	10,
 	125,
 	15000,
 	"custom mi",
 	234000,
+	"another lender",
 	"Random name"
 );
diff --git a/skouter.go b/skouter.go
index d1a34c9..375540a 100644
--- a/skouter.go
+++ b/skouter.go
@@ -10,6 +10,9 @@ import (
 		_ "github.com/go-sql-driver/mysql"
 		"fmt"
 		"encoding/json"
+		// "io"
+		"strconv"
+		"bytes"
 )
 
 type Page struct {
@@ -19,7 +22,7 @@ type Page struct {
 }
 
 type LoanType struct {
-	Id 		int 	`json:"id"`
+	Id 	int 	`json:"id"`
 	User 	int 	`json:"user"`
 	Branch 	int 	`json:"branch"`
 	Name 	string 	`json:"name"`
@@ -39,21 +42,33 @@ type FeeTemplate struct {
 }
 
 type Estimate struct {
-	Id			int 	`json:"id"`
+	Id		int 	`json:"id"`
 	User		int 	`json:"user"`
-	Borrower	int 	`json:"borrower"`
+	Borrower	Borrower 	`json:"borrower"`
 	Comparison	int 	`json:"comparison"`
-	Transaction	int 	`json:"transaction"`
-	LoanType	LoanType `json:"loanType"`
+	Transaction	string 	`json:"transaction"`
+	LoanType	LoanType 	`json:"loanType"`
 	LoanAmount	int 	`json:"loanAmount"`
 	Price		int 	`json:"price"`
 	Property	string 	`json:"property"`
-	Pud			bool 	`json:"pud"`
+	Occupancy	string	`json:"occupancy"`
+	Zip		string 	`json:"zip"`
+	Pud		bool 	`json:"pud"`
 	Term		int 	`json:"term"`
 	Interest	int 	`json:"interest"`
-	Hoi			int 	`json:"hoi"`
+	Hoi		int 	`json:"hoi"`
 	MiName		string 	`json:"miName"`
 	MiAmount	int 	`json:"miAmount"`
+	Lender		string 	`json:"lender"`
+	Name		string 	`json:"name"`
+	Fees		[]Fee 	`json:"fees"`
+}
+
+type Borrower struct {
+	Id	int	`json:"id"`
+	Credit	int 	`json:"credit"`
+	Income	int 	`json:"income"`
+	Num	int	`json:"num"`
 }
 
 var (
@@ -147,17 +162,53 @@ func getLoanType(
 	return loans, nil
 }
 
+func getEstimate(db *sql.DB, id int) (Estimate, error) {
+	var estimate Estimate
+
+	row := db.QueryRow(
+		"SELECT * FROM estimate " +
+		"WHERE id = ? LIMIT 1",
+	id)
+	
+	if err := row.Scan(
+		&estimate.Id,
+		&estimate.User,
+		&estimate.Borrower.Id,
+		&estimate.Comparison,
+		&estimate.Transaction,
+		&estimate.LoanType.Id,
+		&estimate.LoanAmount,
+		&estimate.Price,
+		&estimate.Property,
+		&estimate.Occupancy,
+		&estimate.Zip,
+		&estimate.Pud,
+		&estimate.Term,
+		&estimate.Interest,
+		&estimate.Hoi,
+		&estimate.MiName,
+		&estimate.MiAmount,
+		&estimate.Lender,
+		&estimate.Name,
+		)
+	err != nil {
+		return estimate, fmt.Errorf("Estimate scanning error: %v", err)
+        }
+
+	return estimate, nil
+}
+
 // Fetch fees from the database
 func getFees(db *sql.DB, user int) ([]FeeTemplate, error) {
 	var fees []FeeTemplate
 
-	// Should be changed to specify user
 	rows, err := db.Query(
 		"SELECT * FROM fee_template " +
 		"WHERE user_id = ? OR user_id = 0",
 	user)
+	
 	if err != nil {
-		return nil, fmt.Errorf("Fee error %v", err)
+		return nil, fmt.Errorf("Fee query error %v", err)
 	}
 
 	defer rows.Close()
@@ -177,16 +228,113 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) {
 			&fee.Category,
 			&fee.Auto)
 		err != nil {
-			return nil, fmt.Errorf("The fees %q: %v", user, err)
+			return nil, fmt.Errorf("Fees scanning error: %v", err)
         }
 
 		fees = append(fees, fee)
 	}
+	
+	est, err := getEstimate(db, 1)
+	fmt.Printf("the estimate: %v,\nthe error %v\n", est, err)
+	// getMi(db, getEstimate(db, 1), getBorrower(db, 1))
 
 	return fees, nil
 }
 
-func getMi(db *sql.DB, )
+func getBorrower(db *sql.DB, id int) (Borrower, error) {
+	var borrower Borrower
+
+	row := db.QueryRow(
+		"SELECT * FROM borrower " +
+		"WHERE id = ? LIMIT 1",
+	id)
+
+	if err := row.Scan(
+		&borrower.Id,
+		&borrower.Credit,
+		&borrower.Income,
+		&borrower.Num,
+		)
+	err != nil {
+		return borrower, fmt.Errorf("Borrower scanning error: %v", err)
+        }
+
+	return borrower, nil
+}
+
+func getMi(db *sql.DB, estimate Estimate, borrower Borrower) {
+	// 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",
+		}
+
+	/* var occupancyCodes = map[string]string {
+		"Primary Residence": "PRS",
+		"Second Home": "SCH",
+		"Condominium Lo-rise": "CON",
+		"Condominium Hi-rise": "CON",
+		} */
+
+	body, _ := json.Marshal(map[string]any{
+		"zipCode": estimate.Zip,
+		// "stateCode": "CA",
+		// "address": "",
+		"propertyTypeCode": propertyCodes[estimate.Property],
+		"occupancyTypeCode": "PRS",
+		"loanPurposeCode": "PUR",
+		"loanAmount": strconv.Itoa(estimate.LoanAmount / 100),
+		"loanToValue": "LTV95",
+		"amortizationTerm": "A30",
+		"loanTypeCode": "FXD",
+		"duLpDecisionCode": "DAE",
+		"debtToIncome": 5,
+		"wholesaleLoan": 0,
+		"coveragePercentageCode": "L30",
+		"productCode": "BPM",
+		"renewalTypeCode": "CON",
+		"numberOfBorrowers": 1,
+		"borrowerCreditScore": strconv.Itoa(borrower.Credit),
+		"masterPolicy": nil,
+		"selfEmployedIndicator": false,
+		"armType": "",
+		"userId": 44504,
+	})
+	log.Println(bytes.NewBuffer(body))
+
+}
+
+func validateEstimate() {
+	return
+}
 
 func route(w http.ResponseWriter, r *http.Request) {
     var page Page
@@ -252,6 +400,7 @@ func api(w http.ResponseWriter, r *http.Request) {
 
 func main() {
 	files := http.FileServer(http.Dir(""))
+	
 
 	http.Handle("/assets/", files)
 	http.HandleFunc("/api/", api)