Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

261 wiersze
5.0 KiB

  1. package main
  2. import (
  3. "net/http"
  4. "log"
  5. "sync"
  6. "regexp"
  7. "html/template"
  8. "database/sql"
  9. _ "github.com/go-sql-driver/mysql"
  10. "fmt"
  11. "encoding/json"
  12. )
  13. type Page struct {
  14. tpl *template.Template
  15. Title string
  16. Name string
  17. }
  18. type LoanType struct {
  19. Id int `json:"id"`
  20. User int `json:"user"`
  21. Branch int `json:"branch"`
  22. Name string `json:"name"`
  23. }
  24. type FeeTemplate struct {
  25. Id int `json:"id"`
  26. User int `json:"user"`
  27. Branch int `json:"branch"`
  28. Amount int `json:"amount"`
  29. Perc int `json:"perc"`
  30. Ftype string `json:"type"`
  31. Notes string `json:"notes"`
  32. Name string `json:"name"`
  33. Category string `json:"category"`
  34. Auto bool `json:"auto"`
  35. }
  36. type Estimate struct {
  37. Id int `json:"id"`
  38. User int `json:"user"`
  39. Borrower int `json:"borrower"`
  40. Comparison int `json:"comparison"`
  41. Transaction int `json:"transaction"`
  42. LoanType LoanType `json:"loanType"`
  43. LoanAmount int `json:"loanAmount"`
  44. Price int `json:"price"`
  45. Property string `json:"property"`
  46. Pud bool `json:"pud"`
  47. Term int `json:"term"`
  48. Interest int `json:"interest"`
  49. Hoi int `json:"hoi"`
  50. MiName string `json:"miName"`
  51. MiAmount int `json:"miAmount"`
  52. }
  53. var (
  54. regexen = make(map[string]*regexp.Regexp)
  55. relock sync.Mutex
  56. address = "127.0.0.1:8001"
  57. )
  58. var paths = map[string]string {
  59. "home": "home.tpl",
  60. "terms": "terms.tpl",
  61. "app": "app.tpl",
  62. }
  63. var pages = map[string]Page {
  64. "home": cache("home", "Home"),
  65. "terms": cache("terms", "Terms and Conditions"),
  66. "app": cache("app", "App"),
  67. }
  68. func cache(name string, title string) Page {
  69. var p = []string{"master.tpl", paths[name]}
  70. tpl := template.Must(template.ParseFiles(p...))
  71. return Page{tpl: tpl,
  72. Title: title,
  73. Name: name,
  74. }
  75. }
  76. func (page Page) Render(w http.ResponseWriter) {
  77. err := page.tpl.Execute(w, page)
  78. if err != nil {
  79. log.Print(err)
  80. }
  81. }
  82. func match(path, pattern string, args *[]string) bool {
  83. relock.Lock()
  84. defer relock.Unlock()
  85. regex := regexen[pattern]
  86. if regex == nil {
  87. regex = regexp.MustCompile("^" + pattern + "$")
  88. regexen[pattern] = regex
  89. }
  90. matches := regex.FindStringSubmatch(path)
  91. if len(matches) <= 0 {
  92. return false
  93. }
  94. *args = matches[1:]
  95. return true
  96. }
  97. func getLoanType(
  98. db *sql.DB,
  99. user int,
  100. branch int,
  101. isUser bool) ([]LoanType, error) {
  102. var loans []LoanType
  103. // Should be changed to specify user
  104. rows, err :=
  105. db.Query(`SELECT * FROM loan_type WHERE user_id = ? AND branch_id = ? ` +
  106. "OR (user_id = 0 AND branch_id = 0)", user, branch)
  107. if err != nil {
  108. return nil, fmt.Errorf("loan_type error: %v", err)
  109. }
  110. defer rows.Close()
  111. for rows.Next() {
  112. var loan LoanType
  113. if err := rows.Scan(
  114. &loan.Id,
  115. &loan.User,
  116. &loan.Branch,
  117. &loan.Name)
  118. err != nil {
  119. log.Printf("Error occured fetching loan: %v", err)
  120. return nil, fmt.Errorf("Error occured fetching loan: %v", err)
  121. }
  122. loans = append(loans, loan)
  123. }
  124. log.Printf("The loans: %v", loans)
  125. return loans, nil
  126. }
  127. // Fetch fees from the database
  128. func getFees(db *sql.DB, user int) ([]FeeTemplate, error) {
  129. var fees []FeeTemplate
  130. // Should be changed to specify user
  131. rows, err := db.Query(
  132. "SELECT * FROM fee_template " +
  133. "WHERE user_id = ? OR user_id = 0",
  134. user)
  135. if err != nil {
  136. return nil, fmt.Errorf("Fee error %v", err)
  137. }
  138. defer rows.Close()
  139. for rows.Next() {
  140. var fee FeeTemplate
  141. if err := rows.Scan(
  142. &fee.Id,
  143. &fee.User,
  144. &fee.Branch,
  145. &fee.Amount,
  146. &fee.Perc,
  147. &fee.Ftype,
  148. &fee.Notes,
  149. &fee.Name,
  150. &fee.Category,
  151. &fee.Auto)
  152. err != nil {
  153. return nil, fmt.Errorf("The fees %q: %v", user, err)
  154. }
  155. fees = append(fees, fee)
  156. }
  157. return fees, nil
  158. }
  159. func getMi(db *sql.DB, )
  160. func route(w http.ResponseWriter, r *http.Request) {
  161. var page Page
  162. var args []string
  163. p := r.URL.Path
  164. switch {
  165. case r.Method == "GET" && match(p, "/", &args):
  166. page = pages[ "home" ]
  167. case match(p, "/terms", &args):
  168. page = pages[ "terms" ]
  169. case match(p, "/app", &args):
  170. page = pages[ "app" ]
  171. case match(p, "/assets", &args):
  172. page = pages[ "app" ]
  173. default:
  174. http.NotFound(w, r)
  175. return
  176. }
  177. page.Render(w)
  178. }
  179. func api(w http.ResponseWriter, r *http.Request) {
  180. var args []string
  181. // var response string
  182. p := r.URL.Path
  183. db, err := sql.Open("mysql",
  184. fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/skouter",
  185. config["DBUser"],
  186. config["DBPass"]))
  187. w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  188. err = db.Ping()
  189. if err != nil {
  190. print("Bad database configuration: %v", err)
  191. panic(err)
  192. // maybe os.Exit(1) instead
  193. }
  194. switch {
  195. case match(p, "/api/loans", &args):
  196. resp, err := getLoanType(db, 0, 0, true)
  197. if resp != nil {
  198. json.NewEncoder(w).Encode(resp)
  199. } else {
  200. json.NewEncoder(w).Encode(err)
  201. }
  202. case match(p, "/api/fees", &args):
  203. resp, err := getFees(db, 0)
  204. if resp != nil {
  205. json.NewEncoder(w).Encode(resp)
  206. } else {
  207. json.NewEncoder(w).Encode(err)
  208. }
  209. }
  210. }
  211. func main() {
  212. files := http.FileServer(http.Dir(""))
  213. http.Handle("/assets/", files)
  214. http.HandleFunc("/api/", api)
  215. http.HandleFunc("/", route)
  216. log.Fatal(http.ListenAndServe(address, nil))
  217. }