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 ( | |||
id INT AUTO_INCREMENT, | |||
type ENUM('NMLS', 'FSRA'), | |||
type ENUM('NMLS', 'FSRA') NOT NULL, | |||
num VARCHAR(40) NOT NULL, | |||
PRIMARY KEY (id) | |||
); | |||
@@ -50,8 +50,8 @@ CREATE TABLE license ( | |||
* Types with branch_id and user_id values of null will be general cases. */ | |||
CREATE TABLE loan_type ( | |||
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, | |||
FOREIGN KEY (branch_id) REFERENCES branch(id), | |||
FOREIGN KEY (user_id) REFERENCES user(id), | |||
@@ -60,9 +60,9 @@ CREATE TABLE loan_type ( | |||
CREATE TABLE borrower ( | |||
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`) | |||
); | |||
@@ -113,18 +113,19 @@ CREATE TABLE fee ( | |||
); | |||
/* 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 ( | |||
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'), | |||
notes VARCHAR(255), | |||
name VARCHAR(30), | |||
notes VARCHAR(255) NOT NULL, | |||
name VARCHAR(30) NOT NULL, | |||
/* Group heading shown in report */ | |||
category VARCHAR(60), | |||
category VARCHAR(60) NOT NULL, | |||
auto BOOLEAN NOT NULL, | |||
/* If fee should be automatically applied */ | |||
PRIMARY KEY (`id`), | |||
@@ -32,7 +32,7 @@ INSERT IGNORE INTO user ( | |||
'Giant', | |||
'Coltrane', | |||
sha2('test123', 256), | |||
null, | |||
0, | |||
'USA', | |||
'Mortgage Broker', | |||
'unverified@example.com', | |||
@@ -75,11 +75,11 @@ INSERT IGNORE INTO loan_type ( | |||
) VALUES | |||
( | |||
(SELECT id FROM branch LIMIT 1), | |||
NULL, | |||
0, | |||
'testType' | |||
), | |||
( | |||
NULL, | |||
0, | |||
(SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | |||
'manager idea' | |||
); | |||
@@ -94,7 +94,7 @@ INSERT IGNORE INTO fee_template ( | |||
name | |||
) VALUES | |||
( | |||
NULL, | |||
0, | |||
(SELECT id FROM branch LIMIT 1), | |||
0, | |||
200, | |||
@@ -113,7 +113,7 @@ INSERT IGNORE INTO fee_template ( | |||
), | |||
( | |||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | |||
NULL, | |||
0, | |||
9900, | |||
0, | |||
"Government", | |||
@@ -122,7 +122,7 @@ INSERT IGNORE INTO fee_template ( | |||
), | |||
( | |||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | |||
NULL, | |||
0, | |||
0, | |||
400, | |||
'Lender', | |||
@@ -136,27 +136,27 @@ INSERT IGNORE INTO loan_type ( | |||
name | |||
) VALUES | |||
( | |||
NULL, | |||
NULL, | |||
0, | |||
0, | |||
"Conventional" | |||
), | |||
( | |||
NULL, | |||
NULL, | |||
0, | |||
0, | |||
"FHA" | |||
), | |||
( | |||
NULL, | |||
NULL, | |||
0, | |||
0, | |||
"VA" | |||
), | |||
( | |||
NULL, | |||
NULL, | |||
0, | |||
0, | |||
"USDA" | |||
), | |||
( | |||
NULL, | |||
0, | |||
(SELECT id FROM branch LIMIT 1), | |||
"Test" | |||
); | |||
@@ -192,7 +192,7 @@ INSERT IGNORE INTO estimate ( | |||
( | |||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | |||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | |||
NULL, | |||
0, | |||
'Purchase', | |||
(SELECT id FROM loan_type WHERE name="Conventional"), | |||
3300000, | |||
@@ -209,7 +209,7 @@ INSERT IGNORE INTO estimate ( | |||
( | |||
(SELECT id FROM user WHERE email="manager@example.com" LIMIT 1), | |||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | |||
NULL, | |||
0, | |||
'Purchase', | |||
(SELECT id FROM loan_type WHERE name="FHA"), | |||
2510000, | |||
@@ -226,7 +226,7 @@ INSERT IGNORE INTO estimate ( | |||
( | |||
(SELECT id FROM user WHERE email="test@example.com" LIMIT 1), | |||
(SELECT id FROM borrower ORDER BY id DESC LIMIT 1), | |||
NULL, | |||
0, | |||
'Refinance', | |||
(SELECT id FROM loan_type WHERE name="USDA"), | |||
8000000, | |||
@@ -9,6 +9,7 @@ import ( | |||
"database/sql" | |||
_ "github.com/go-sql-driver/mysql" | |||
"fmt" | |||
"encoding/json" | |||
) | |||
type Page struct { | |||
@@ -18,23 +19,23 @@ type Page 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 { | |||
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 { | |||
@@ -113,7 +114,7 @@ func getLoanType(db *sql.DB, id int, isUser bool) ([]LoanType, error) { | |||
// Should be changed to specify user | |||
rows, err := | |||
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 { | |||
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 | |||
if err := rows.Scan( | |||
&loan.user, | |||
&loan.branch, | |||
&loan.name) | |||
&loan.Id, | |||
&loan.User, | |||
&loan.Branch, | |||
&loan.Name) | |||
err != nil { | |||
log.Printf("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) | |||
} | |||
log.Printf("The loans: %v", loans) | |||
return loans, nil | |||
} | |||
@@ -155,16 +158,16 @@ func getFees(db *sql.DB, user int) ([]FeeTemplate, error) { | |||
var fee FeeTemplate | |||
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 { | |||
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) { | |||
var page Page | |||
var args []string | |||
p := r.URL.Path | |||
switch { | |||
case r.Method == "GET" && match(p, "/", &args): | |||
page = pages[ "home" ] | |||
@@ -198,24 +201,51 @@ func route(w http.ResponseWriter, r *http.Request) { | |||
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", | |||
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["DBPass"])) | |||
w.Header().Set("Content-Type", "application/json; charset=UTF-8") | |||
err = db.Ping() | |||
if err != nil { | |||
// do something here like abort | |||
print("Bad database configuration: %v", err) | |||
panic(err) | |||
// 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.HandleFunc("/api/", api) | |||
http.HandleFunc("/", route) | |||
log.Fatal(http.ListenAndServe(address, nil)) | |||
} |