us-dop-api/internal/handlers/api/institution.go
maximo tejeda eeebd4c25c
Some checks failed
dev test / test (push) Successful in 7s
dev test / vulnCheck (push) Successful in 12s
dev test / Ci-Lint (push) Successful in 10s
${{ github.actor }} executed Build Push Prod / build (push) Failing after 42s
${{ github.actor }} executed Build Push Prod / deploy (push) Has been skipped
FIX lint
2024-12-03 22:30:32 -04:00

230 lines
6.3 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"slices"
"strings"
"time"
"git.maximotejeda.com/maximo/us-dop-api/internal/domain"
"git.maximotejeda.com/maximo/us-dop-api/internal/helpers"
)
// handler to parse query to the api
func (api *API) GetInstitutionHistory(w http.ResponseWriter, r *http.Request) {
var (
timeSearch time.Duration
historyResult []*domain.History
)
err := r.ParseForm()
if err != nil {
api.log.Error("parsing form ", "error", err)
http.Error(w, "parsing form", http.StatusNotFound)
}
queryP := r.Form
timeAmount := queryP.Get("ta") // numeric amount
timeFrame := queryP.Get("tf") // minute, hour, day, week, month, now ago until now
resType := queryP.Get("format") // can be multiples html or a json
inst := queryP.Get("name")
resource := queryP.Get("res")
inst = strings.ToLower(inst)
// match time amount number
re := regexp.MustCompile(`[0-9]{1,3}`)
// api.log.Info("parsing inst", "name", inst)
if timeFrame != "now" {
if !re.Match([]byte(timeAmount)) {
api.log.Error("matching time", "error", "incorrect time amount")
http.Error(w, "incorrect time amount", http.StatusNotFound)
return
}
}
timeSearch, err = helpers.ParseTimeAmount(timeFrame, timeAmount)
if err != nil {
api.log.Error("parsing time ", "error", err)
http.Error(w, "incorrect time amount", http.StatusNotFound)
return
}
if timeFrame == "now" {
hist, err := api.dolar.GetLatest(inst)
//hist, err := api.db.GetLastPrice(inst)
if err != nil {
api.log.Error("GetLastPrice", "time Frame", "now", "error", err)
http.Error(w, "price not found", http.StatusNotFound)
return
}
historyResult = append(historyResult, hist)
} else {
historyResult, err = api.dolar.GetSince(inst, int64(timeSearch.Minutes()))
//historyResult, err = api.db.GetChangeSince(inst, timeSearch)
if err != nil {
api.log.Error("GetLastPrice", "time Frame", timeFrame, "amount", timeAmount, "error", err)
http.Error(w, "price not found for time frame", http.StatusNotFound)
return
}
api.log.Info("resultados", "=", historyResult)
}
searchRes := SearchResult{
InstRequested: inst,
Date: time.Now(),
TimeAmount: timeAmount,
TimeFrame: timeFrame,
Results: historyResult,
}
// check if we want a json
if resType == "html" {
switch resource {
case "card":
err = api.templ.ExecuteTemplate(w, "card-history", searchRes)
case "list":
// by default we crate simple query
// we need a way to distinguish from mixed or more complex query
err = api.templ.ExecuteTemplate(w, "list-history", searchRes)
case "table":
// by default we crate simple query
// we need a way to distinguish from mixed or more complex query
err = api.templ.ExecuteTemplate(w, "table-history", searchRes)
}
if err != nil {
api.log.Error("History", "error", err)
http.Error(w, "history error", http.StatusNotFound)
}
} else {
data, _ := json.Marshal(searchRes)
_, _ = w.Write(data)
}
}
// GetBanks
// as bank will only return a list of names
// we can assume we need a list of some html to the app
func (api *API) GetInstNames(w http.ResponseWriter, r *http.Request) {
queryP := r.URL.Query()
fType := queryP.Get("format")
resource := queryP.Get("res")
inst := r.PathValue("inst")
w.Header().Set("Etag", "institutions")
w.Header().Set("Cache-Control", "max-age=3600")
var (
institutions []string
err = *new(error)
)
switch inst {
case "bancos", "banco":
inst = "bancos"
institutions, err = api.dolar.GetInstByType("bancos")
case "caja", "cajas":
inst = "cajas"
institutions, err = api.dolar.GetInstByType("cajas")
case "agente", "agentes":
inst = "agentes"
institutions, err = api.dolar.GetInstByType("agentes")
case "all":
bancos, _ := api.dolar.GetInstByType("bancos")
cajas, _ := api.dolar.GetInstByType("cajas")
agentes, _ := api.dolar.GetInstByType("agentes")
inst = "all"
institutions = slices.Concat(bancos, cajas, agentes)
default:
http.NotFound(w, r)
return
}
if err != nil {
api.log.Error("GetInstName", "error", err)
http.Error(w, "", http.StatusNotFound)
}
searchResult := SearchResult{
InstRequested: inst,
Date: time.Now(),
TimeAmount: "none",
TimeFrame: "none",
}
removeDup := map[string]int{}
res := []string{}
for _, val := range institutions {
removeDup[val]++
if removeDup[val] == 1 {
res = append(res, val)
}
}
for _, banco := range res {
inst := domain.History{}
inst.Institution.Name = banco
searchResult.Results = append(searchResult.Results, &inst)
}
api.log.Info("institutions", "list", res)
if fType == "html" {
switch resource {
case "card":
err = api.templ.ExecuteTemplate(w, "card", searchResult)
case "list":
// by default we crate simple query
// we need a way to distinguish from mixed or more complex query
err = api.templ.ExecuteTemplate(w, "list", searchResult)
}
if err != nil {
api.log.Error("rendering institucion", "tipo", inst, "error", err)
}
} else {
dat, err := json.Marshal(searchResult)
if err != nil {
fmt.Println(err)
}
_, _ = w.Write(dat)
}
}
func (api *API) GetLatestPrice(w http.ResponseWriter, r *http.Request) {
inst := r.PathValue("inst")
if inst == "" {
http.Error(w, "no inst in request", http.StatusNotFound)
}
price, err := api.dolar.GetLatest(inst)
if err != nil {
api.log.Error("geting latest price", "error", err)
http.NotFound(w, r)
}
_ = api.templ.ExecuteTemplate(w, "latest-price", price)
}
func (api *API) GetAllLatestPrice(w http.ResponseWriter, r *http.Request) {
bancos, err := api.dolar.GetInstByType("bancos")
if err != nil {
api.log.Error("geting inst", "error", err)
http.NotFound(w, r)
}
cajas, err := api.dolar.GetInstByType("cajas")
if err != nil {
api.log.Error("geting inst cajas", "error", err)
http.NotFound(w, r)
}
agentes, err := api.dolar.GetInstByType("agentes")
if err != nil {
api.log.Error("geting inst agentes", "error", err)
http.NotFound(w, r)
}
instLastPriceList := []*domain.History{}
for _, inst := range slices.Concat(bancos, cajas, agentes) {
in, err := api.dolar.GetLatest(inst)
if err != nil {
api.log.Error("geting last price", "error", err)
continue
}
instLastPriceList = append(instLastPriceList, in)
}
_ = api.templ.ExecuteTemplate(w, "latest-price", instLastPriceList)
}