From 6887e1f8247b5692243b50b5a590d12de30a4339 Mon Sep 17 00:00:00 2001 From: Immanuel Onyeka Date: Mon, 21 Nov 2022 20:09:09 -0500 Subject: [PATCH] Seperate loans from estimates in models --- migrations/0_29092022_create_main_tables.sql | 39 +++-- migrations/reset.sql | 2 +- skouter.go | 170 ++++++++++++++----- 3 files changed, 153 insertions(+), 58 deletions(-) diff --git a/migrations/0_29092022_create_main_tables.sql b/migrations/0_29092022_create_main_tables.sql index 22d49c9..6f56d96 100644 --- a/migrations/0_29092022_create_main_tables.sql +++ b/migrations/0_29092022_create_main_tables.sql @@ -1,10 +1,5 @@ /* Precision for all money amounts assumes cents are excluded. */ -CREATE TABLE comparison ( - id INT AUTO_INCREMENT, - PRIMARY KEY (id) -); - CREATE TABLE branch ( id INT AUTO_INCREMENT, type ENUM('NMLS', 'FSRA') NOT NULL, @@ -30,7 +25,8 @@ CREATE TABLE user ( status ENUM('Trial', 'Free', 'Subscribed', - 'Branch Subscribed'), + 'Branch', + 'Admin'), PRIMARY KEY (`id`), FOREIGN KEY (branch_id) REFERENCES branch(id) ); @@ -52,7 +48,7 @@ CREATE TABLE loan_type ( id INT AUTO_INCREMENT, branch_id INT NOT NULL, user_id INT NOT NULL, - name VARCHAR(30) NOT NULL, + name VARCHAR(30) UNIQUE NOT NULL, /* FOREIGN KEY (branch_id) REFERENCES branch(id), */ /* FOREIGN KEY (user_id) REFERENCES user(id), */ PRIMARY KEY (`id`) @@ -70,10 +66,7 @@ CREATE TABLE estimate ( 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, price INT NOT NULL, property ENUM('Single Detached', 'Single Attached', @@ -82,24 +75,34 @@ CREATE TABLE estimate ( occupancy ENUM('Primary', 'Secondary', 'Investment'), zip VARCHAR(10), pud BOOLEAN, /* Property under development */ + PRIMARY KEY (`id`), + FOREIGN KEY (borrower_id) REFERENCES borrower(id) +); + +CREATE TABLE loan ( + id INT, + estimate_id INT NOT NULL, + type_id INT NOT NULL, + amount INT NOT NULL, 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 */ + hoi INT DEFAULT 0, /* Hazard insurance annual payments */ + mi_name VARCHAR(50) NOT NULL, + /* Mortgage insurance title shown in menu */ mi_amount INT, /* Mortgage insurance amount */ - lender VARCHAR(30) DEFAULT "", - name VARCHAR(30) DEFAULT "", + lender VARCHAR(30) DEFAULT '', + name VARCHAR(30) DEFAULT '', PRIMARY KEY (`id`), + FOREIGN KEY (estimate_id) REFERENCES estimate(id), FOREIGN KEY (loan_type_id) REFERENCES loan_type(id) - ON UPDATE RESTRICT, - FOREIGN KEY (borrower_id) REFERENCES borrower(id) + ON UPDATE RESTRICT ); /* template = true fees are saved for users or branches. If template or default * are true, estimate_id should be null.*/ CREATE TABLE fee ( id INT AUTO_INCREMENT NOT NULL, - estimate_id INT, + loan_id INT, amount INT NOT NULL, perc SMALLINT, /* Percentage of sale price instead of amount */ type ENUM('Goverment', 'Title', 'Required', 'Lender', 'Other'), @@ -108,7 +111,7 @@ CREATE TABLE fee ( /* Group heading shown in report */ category VARCHAR(60), PRIMARY KEY (`id`), - FOREIGN KEY (estimate_id) REFERENCES estimate(id) + FOREIGN KEY (loan_id) REFERENCES loan(id) ); /* Templates to be reused by users or branches. Either user_id or branch_id must diff --git a/migrations/reset.sql b/migrations/reset.sql index 661455c..e5228f8 100644 --- a/migrations/reset.sql +++ b/migrations/reset.sql @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS fee; DROP TABLE IF EXISTS fee_template; +DROP TABLE IF EXISTS loan; DROP TABLE IF EXISTS estimate; -DROP TABLE IF EXISTS comparison; DROP TABLE IF EXISTS borrower; DROP TABLE IF EXISTS loan_type; DROP TABLE IF EXISTS license; diff --git a/skouter.go b/skouter.go index 375540a..650cd20 100644 --- a/skouter.go +++ b/skouter.go @@ -21,11 +21,11 @@ type Page struct { Name string } -type LoanType struct { - Id int `json:"id"` - User int `json:"user"` - Branch int `json:"branch"` - Name string `json:"name"` +type Borrower struct { + Id int `json:"id"` + Credit int `json:"credit"` + Income int `json:"income"` + Num int `json:"num"` } type FeeTemplate struct { @@ -41,34 +41,52 @@ type FeeTemplate struct { Auto bool `json:"auto"` } +type Fee struct { + Id int `json:"id"` + LoanId int `json:"loan_id"` + Amount int `json:"amount"` + Perc int `json:"perc"` + Type string `json:"type"` + Notes string `json:"notes"` + Name string `json:"name"` + Category string `json:"category"` +} + +type LoanType struct { + Id int `json:"id"` + User int `json:"user"` + Branch int `json:"branch"` + Name string `json:"name"` +} + +type Loan struct { + Id int `json:id` + EstimateId int `json:estimate_id` + Type LoanType `json:"loanType"` + LoanAmount int `json:"loanAmount"` + Term int `json:"term"` + Ltv int `json:"ltv"` + Dti int `json:"dti"` + Hoi int `json:"hoi"` + Interest int `json:"interest"` + Lender string `json:"lender"` + MiName string `json:"miName"` + MiAmount int `json:"miAmount"` + Fees []Fee `json:"fees"` + Name string `json:"name"` +} + type Estimate struct { Id int `json:"id"` User int `json:"user"` Borrower Borrower `json:"borrower"` - Comparison int `json:"comparison"` Transaction string `json:"transaction"` - LoanType LoanType `json:"loanType"` - LoanAmount int `json:"loanAmount"` Price int `json:"price"` Property string `json:"property"` Occupancy string `json:"occupancy"` Zip string `json:"zip"` Pud bool `json:"pud"` - Term int `json:"term"` - Interest int `json:"interest"` - 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"` + Loans []Loan `json:"loans"` } var ( @@ -165,31 +183,24 @@ func getLoanType( func getEstimate(db *sql.DB, id int) (Estimate, error) { var estimate Estimate + // Inner join should always be valid because a borrower is a required + // foreign key. row := db.QueryRow( - "SELECT * FROM estimate " + - "WHERE id = ? LIMIT 1", + "SELECT * FROM estimate "+ + "WHERE id = ? " + + "INNER JOIN borrower ON estimate.borrower = borrower.id", 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) @@ -198,8 +209,45 @@ func getEstimate(db *sql.DB, id int) (Estimate, error) { return estimate, nil } +func getFees(db *sql.DB, loan int) ([]Fee, error) { + var fees []Fee + + rows, err := db.Query( + "SELECT * FROM fees " + + "WHERE loan_id = ?", + loan) + + if err != nil { + return nil, fmt.Errorf("Fee query error %v", err) + } + + defer rows.Close() + + for rows.Next() { + var fee FeeTemplate + + if err := rows.Scan( + &fee.Id, + &fee.LoanId, + &fee.Amount, + &fee.Perc, + &fee.Ftype, + &fee.Notes, + &fee.Name, + &fee.Category, + ) + err != nil { + return nil, fmt.Errorf("Fees scanning error: %v", err) + } + + fees = append(fees, fee) + } + + return fees, nil +} + // Fetch fees from the database -func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { +func getFeesTemp(db *sql.DB, user int) ([]FeeTemplate, error) { var fees []FeeTemplate rows, err := db.Query( @@ -208,7 +256,7 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { user) if err != nil { - return nil, fmt.Errorf("Fee query error %v", err) + return nil, fmt.Errorf("Fee template query error %v", err) } defer rows.Close() @@ -222,13 +270,57 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { &fee.Branch, &fee.Amount, &fee.Perc, + &fee.Type, + &fee.Notes, + &fee.Name, + &fee.Category, + &fee.Auto) + err != nil { + return nil, fmt.Errorf("FeesTemplate 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 getLoans(db *sql.DB, estimate int) { + var loans []Loan + + rows, err := db.Query( + "SELECT loan.id, loan.amount, loan.term, loan.interest, loan.ltv, + loan.dti, loan.hoi, loan.mi_name, loan.mi_amount FROM loan " + + "INNER JOIN loan_type ON loan.type_id = loan_type(id)" + + "WHERE loan.estimate_id = ?", + 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.EstimateId, + &loan.Branch, + &fee.Amount, + &fee.Perc, &fee.Ftype, &fee.Notes, &fee.Name, &fee.Category, &fee.Auto) err != nil { - return nil, fmt.Errorf("Fees scanning error: %v", err) + return nil, fmt.Errorf("FeesTemplate scanning error: %v", err) } fees = append(fees, fee) @@ -387,7 +479,7 @@ func api(w http.ResponseWriter, r *http.Request) { } case match(p, "/api/fees", &args): - resp, err := getFees(db, 0) + resp, err := getFeesTemp(db, 0) if resp != nil { json.NewEncoder(w).Encode(resp)