Null makes missing values harder to convert to json using the Scan operation. 0 and '' will be used instead to be type consistent.master
@@ -7,7 +7,7 @@ CREATE TABLE comparison ( | |||||
CREATE TABLE branch ( | CREATE TABLE branch ( | ||||
id INT AUTO_INCREMENT, | id INT AUTO_INCREMENT, | ||||
type ENUM('NMLS', 'FSRA'), | |||||
type ENUM('NMLS', 'FSRA') NOT NULL, | |||||
num VARCHAR(40) NOT NULL, | num VARCHAR(40) NOT NULL, | ||||
PRIMARY KEY (id) | PRIMARY KEY (id) | ||||
); | ); | ||||
@@ -50,8 +50,8 @@ CREATE TABLE license ( | |||||
* Types with branch_id and user_id values of null will be general cases. */ | * Types with branch_id and user_id values of null will be general cases. */ | ||||
CREATE TABLE loan_type ( | CREATE TABLE loan_type ( | ||||
id INT AUTO_INCREMENT, | id INT AUTO_INCREMENT, | ||||
branch_id INT, | |||||
user_id INT, | |||||
branch_id INT NOT NULL, | |||||
user_id INT NOT NULL, | |||||
name VARCHAR(30) NOT NULL, | name VARCHAR(30) NOT NULL, | ||||
FOREIGN KEY (branch_id) REFERENCES branch(id), | FOREIGN KEY (branch_id) REFERENCES branch(id), | ||||
FOREIGN KEY (user_id) REFERENCES user(id), | FOREIGN KEY (user_id) REFERENCES user(id), | ||||
@@ -60,9 +60,9 @@ CREATE TABLE loan_type ( | |||||
CREATE TABLE borrower ( | CREATE TABLE borrower ( | ||||
id INT AUTO_INCREMENT, | id INT AUTO_INCREMENT, | ||||
credit_score SMALLINT, | |||||
monthly_income INT, | |||||
num TINYINT, /* Number of people borrowing. */ | |||||
credit_score SMALLINT NOT NULL, | |||||
monthly_income INT NOT NULL, | |||||
num TINYINT NOT NULL, /* Number of people borrowing. */ | |||||
PRIMARY KEY (`id`) | PRIMARY KEY (`id`) | ||||
); | ); | ||||
@@ -113,18 +113,19 @@ CREATE TABLE fee ( | |||||
); | ); | ||||
/* Templates to be reused by users or branches. Either user_id or branch_id must | /* Templates to be reused by users or branches. Either user_id or branch_id must | ||||
* be non-null. */ | |||||
* be non-null.*/ | |||||
CREATE TABLE fee_template ( | CREATE TABLE fee_template ( | ||||
id INT AUTO_INCREMENT, | id INT AUTO_INCREMENT, | ||||
user_id INT, | |||||
branch_id INT, | |||||
amount INT, | |||||
perc SMALLINT, /* Percentage of sale price instead of amount */ | |||||
user_id INT NOT NULL, | |||||
branch_id INT NOT NULL, | |||||
amount INT NOT NULL, | |||||
perc SMALLINT NOT NULL, | |||||
/* Percentage of sale price instead of amount */ | |||||
type ENUM('Goverment', 'Title', 'Required', 'Lender', 'Other'), | type ENUM('Goverment', 'Title', 'Required', 'Lender', 'Other'), | ||||
notes VARCHAR(255), | |||||
name VARCHAR(30), | |||||
notes VARCHAR(255) NOT NULL, | |||||
name VARCHAR(30) NOT NULL, | |||||
/* Group heading shown in report */ | /* Group heading shown in report */ | ||||
category VARCHAR(60), | |||||
category VARCHAR(60) NOT NULL, | |||||
auto BOOLEAN NOT NULL, | auto BOOLEAN NOT NULL, | ||||
/* If fee should be automatically applied */ | /* If fee should be automatically applied */ | ||||
PRIMARY KEY (`id`), | PRIMARY KEY (`id`), | ||||
@@ -32,7 +32,7 @@ INSERT IGNORE INTO user ( | |||||
'Giant', | 'Giant', | ||||
'Coltrane', | 'Coltrane', | ||||
sha2('test123', 256), | sha2('test123', 256), | ||||
null, | |||||
0, | |||||
'USA', | 'USA', | ||||
'Mortgage Broker', | 'Mortgage Broker', | ||||
'unverified@example.com', | 'unverified@example.com', | ||||
@@ -75,11 +75,11 @@ INSERT IGNORE INTO loan_type ( | |||||
) VALUES | ) VALUES | ||||
( | ( | ||||
(SELECT id FROM branch LIMIT 1), | (SELECT id FROM branch LIMIT 1), | ||||
NULL, | |||||
0, | |||||
'testType' | 'testType' | ||||
), | ), | ||||
( | ( | ||||
NULL, | |||||
0, | |||||
(SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | ||||
'manager idea' | 'manager idea' | ||||
); | ); | ||||
@@ -94,7 +94,7 @@ INSERT IGNORE INTO fee_template ( | |||||
name | name | ||||
) VALUES | ) VALUES | ||||
( | ( | ||||
NULL, | |||||
0, | |||||
(SELECT id FROM branch LIMIT 1), | (SELECT id FROM branch LIMIT 1), | ||||
0, | 0, | ||||
200, | 200, | ||||
@@ -113,7 +113,7 @@ INSERT IGNORE INTO fee_template ( | |||||
), | ), | ||||
( | ( | ||||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | ||||
NULL, | |||||
0, | |||||
9900, | 9900, | ||||
0, | 0, | ||||
"Government", | "Government", | ||||
@@ -122,7 +122,7 @@ INSERT IGNORE INTO fee_template ( | |||||
), | ), | ||||
( | ( | ||||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | ||||
NULL, | |||||
0, | |||||
0, | 0, | ||||
400, | 400, | ||||
'Lender', | 'Lender', | ||||
@@ -136,27 +136,27 @@ INSERT IGNORE INTO loan_type ( | |||||
name | name | ||||
) VALUES | ) VALUES | ||||
( | ( | ||||
NULL, | |||||
NULL, | |||||
0, | |||||
0, | |||||
"Conventional" | "Conventional" | ||||
), | ), | ||||
( | ( | ||||
NULL, | |||||
NULL, | |||||
0, | |||||
0, | |||||
"FHA" | "FHA" | ||||
), | ), | ||||
( | ( | ||||
NULL, | |||||
NULL, | |||||
0, | |||||
0, | |||||
"VA" | "VA" | ||||
), | ), | ||||
( | ( | ||||
NULL, | |||||
NULL, | |||||
0, | |||||
0, | |||||
"USDA" | "USDA" | ||||
), | ), | ||||
( | ( | ||||
NULL, | |||||
0, | |||||
(SELECT id FROM branch LIMIT 1), | (SELECT id FROM branch LIMIT 1), | ||||
"Test" | "Test" | ||||
); | ); | ||||
@@ -192,7 +192,7 @@ INSERT IGNORE INTO estimate ( | |||||
( | ( | ||||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | ||||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | (SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | ||||
NULL, | |||||
0, | |||||
'Purchase', | 'Purchase', | ||||
(SELECT id FROM loan_type WHERE name="Conventional"), | (SELECT id FROM loan_type WHERE name="Conventional"), | ||||
3300000, | 3300000, | ||||
@@ -209,7 +209,7 @@ INSERT IGNORE INTO estimate ( | |||||
( | ( | ||||
(SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | ||||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | (SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | ||||
NULL, | |||||
0, | |||||
'Purchase', | 'Purchase', | ||||
(SELECT id FROM loan_type WHERE name="FHA"), | (SELECT id FROM loan_type WHERE name="FHA"), | ||||
2510000, | 2510000, | ||||
@@ -226,7 +226,7 @@ INSERT IGNORE INTO estimate ( | |||||
( | ( | ||||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | (SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | ||||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | (SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | ||||
NULL, | |||||
0, | |||||
'Refinance', | 'Refinance', | ||||
(SELECT id FROM loan_type WHERE name="USDA"), | (SELECT id FROM loan_type WHERE name="USDA"), | ||||
8000000, | 8000000, | ||||
@@ -9,6 +9,7 @@ import ( | |||||
"database/sql" | "database/sql" | ||||
_ "github.com/go-sql-driver/mysql" | _ "github.com/go-sql-driver/mysql" | ||||
"fmt" | "fmt" | ||||
"encoding/json" | |||||
) | ) | ||||
type Page struct { | type Page struct { | ||||
@@ -18,23 +19,23 @@ type Page struct { | |||||
} | } | ||||
type LoanType struct { | type LoanType struct { | ||||
id int | |||||
user sql.NullInt64 | |||||
branch sql.NullInt64 | |||||
name string | |||||
Id int `json:"id"` | |||||
User int `json:"user"` | |||||
Branch int `json:"branch"` | |||||
Name string `json:"name"` | |||||
} | } | ||||
type FeeTemplate struct { | type FeeTemplate struct { | ||||
id sql.NullInt64 | |||||
user sql.NullInt64 | |||||
branch sql.NullInt64 | |||||
amount sql.NullInt64 | |||||
perc sql.NullInt64 | |||||
ftype sql.NullString | |||||
notes sql.NullString | |||||
name sql.NullString | |||||
category sql.NullString | |||||
auto bool | |||||
Id int | |||||
User int | |||||
Branch int | |||||
Amount int | |||||
Perc int | |||||
Ftype string | |||||
Notes string | |||||
Name string | |||||
Category string | |||||
Auto bool | |||||
} | } | ||||
type Estimate struct { | type Estimate struct { | ||||
@@ -113,7 +114,7 @@ func getLoanType(db *sql.DB, id int, isUser bool) ([]LoanType, error) { | |||||
// Should be changed to specify user | // Should be changed to specify user | ||||
rows, err := | rows, err := | ||||
db.Query("SELECT * FROM loan_type WHERE user_id = ? " + | db.Query("SELECT * FROM loan_type WHERE user_id = ? " + | ||||
"OR (user_id = NULL AND branch_id = NULL)", id) | |||||
"OR (user_id = 0 AND branch_id = 0)", id) | |||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("loan_type error: %v", err) | return nil, fmt.Errorf("loan_type error: %v", err) | ||||
@@ -125,9 +126,10 @@ func getLoanType(db *sql.DB, id int, isUser bool) ([]LoanType, error) { | |||||
var loan LoanType | var loan LoanType | ||||
if err := rows.Scan( | if err := rows.Scan( | ||||
&loan.user, | |||||
&loan.branch, | |||||
&loan.name) | |||||
&loan.Id, | |||||
&loan.User, | |||||
&loan.Branch, | |||||
&loan.Name) | |||||
err != nil { | err != nil { | ||||
log.Printf("Error occured fetching loan: %v", err) | log.Printf("Error occured fetching loan: %v", err) | ||||
return nil, fmt.Errorf("Error occured fetching loan: %v", err) | return nil, fmt.Errorf("Error occured fetching loan: %v", err) | ||||
@@ -136,6 +138,7 @@ func getLoanType(db *sql.DB, id int, isUser bool) ([]LoanType, error) { | |||||
loans = append(loans, loan) | loans = append(loans, loan) | ||||
} | } | ||||
log.Printf("The loans: %v", loans) | |||||
return loans, nil | return loans, nil | ||||
} | } | ||||
@@ -155,16 +158,16 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { | |||||
var fee FeeTemplate | var fee FeeTemplate | ||||
if err := rows.Scan( | if err := rows.Scan( | ||||
&fee.id, | |||||
&fee.user, | |||||
&fee.branch, | |||||
&fee.amount, | |||||
&fee.perc, | |||||
&fee.ftype, | |||||
&fee.notes, | |||||
&fee.name, | |||||
&fee.category, | |||||
&fee.auto) | |||||
&fee.Id, | |||||
&fee.User, | |||||
&fee.Branch, | |||||
&fee.Amount, | |||||
&fee.Perc, | |||||
&fee.Ftype, | |||||
&fee.Notes, | |||||
&fee.Name, | |||||
&fee.Category, | |||||
&fee.Auto) | |||||
err != nil { | err != nil { | ||||
return nil, fmt.Errorf("The fees %q: %v", user, err) | return nil, fmt.Errorf("The fees %q: %v", user, err) | ||||
} | } | ||||
@@ -179,8 +182,8 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { | |||||
func route(w http.ResponseWriter, r *http.Request) { | func route(w http.ResponseWriter, r *http.Request) { | ||||
var page Page | var page Page | ||||
var args []string | var args []string | ||||
p := r.URL.Path | p := r.URL.Path | ||||
switch { | switch { | ||||
case r.Method == "GET" && match(p, "/", &args): | case r.Method == "GET" && match(p, "/", &args): | ||||
page = pages[ "home" ] | page = pages[ "home" ] | ||||
@@ -198,24 +201,51 @@ func route(w http.ResponseWriter, r *http.Request) { | |||||
page.Render(w) | page.Render(w) | ||||
} | } | ||||
func main() { | |||||
files := http.FileServer(http.Dir("")) | |||||
func api(w http.ResponseWriter, r *http.Request) { | |||||
var args []string | |||||
// var response string | |||||
p := r.URL.Path | |||||
db, err := sql.Open("mysql", | db, err := sql.Open("mysql", | ||||
fmt.Sprintf( "%s:%s@tcp(127.0.0.1:3306)/skouter", | |||||
fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/skouter", | |||||
config["DBUser"], | config["DBUser"], | ||||
config["DBPass"])) | config["DBPass"])) | ||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8") | |||||
err = db.Ping() | err = db.Ping() | ||||
if err != nil { | if err != nil { | ||||
// do something here like abort | |||||
print("Bad database configuration: %v", err) | print("Bad database configuration: %v", err) | ||||
panic(err) | panic(err) | ||||
// maybe os.Exit(1) instead | // maybe os.Exit(1) instead | ||||
} | } | ||||
fmt.Print(getLoanType(db, 0, true)) | |||||
switch { | |||||
case match(p, "/api/loans", &args): | |||||
resp, err := getLoanType(db, 0, true) | |||||
if resp != nil { | |||||
json.NewEncoder(w).Encode(resp) | |||||
} else { | |||||
json.NewEncoder(w).Encode(err) | |||||
} | |||||
case match(p, "/api/fees", &args): | |||||
resp, err := getFees(db, 0) | |||||
if resp != nil { | |||||
json.NewEncoder(w).Encode(resp) | |||||
} else { | |||||
json.NewEncoder(w).Encode(err) | |||||
} | |||||
} | |||||
} | |||||
func main() { | |||||
files := http.FileServer(http.Dir("")) | |||||
http.Handle("/assets/", files) | http.Handle("/assets/", files) | ||||
http.HandleFunc("/api/", api) | |||||
http.HandleFunc("/", route) | http.HandleFunc("/", route) | ||||
log.Fatal(http.ListenAndServe(address, nil)) | log.Fatal(http.ListenAndServe(address, nil)) | ||||
} | } |