You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
quartermaster/pkg/api/locations/views.go

282 lines
9.0 KiB

package locations
import (
"database/sql"
"encoding/json"
"net/http"
"strconv"
"github.com/dustinpianalto/errors"
"github.com/dustinpianalto/quartermaster"
"github.com/dustinpianalto/quartermaster/pkg/services"
"github.com/gorilla/mux"
)
type itemsResponse struct {
Count int `json:"count"`
*quartermaster.Item
}
func locations(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "locations"
if r.Method == "POST" {
err := addLocation(w, r, user)
if err != nil {
return errors.E(method, "there was a problem adding the location", err)
}
} else if r.Method == "GET" {
err := getTopLocations(w, r, user)
if err != nil {
return errors.E(method, "there was a problem getting locations", err)
}
} else {
return errors.E(method, errors.Malformed, "http method not allowed")
}
return nil
}
func addLocation(w *http.ResponseWriter, r *http.Request, u *quartermaster.User) error {
const method errors.Method = "locations/addLocation"
var l *quartermaster.Location
err := json.NewDecoder(r.Body).Decode(&l)
if err != nil {
return errors.E(method, errors.Malformed, "failed to decode location request", err)
}
if l.Name == "" || l.Description == "" {
return errors.E(method, errors.Malformed, "name and description are required")
}
if l.Parent != nil {
_, err := services.LocationService.Location(l.Parent.ID, u)
if err != nil {
return errors.E(method, errors.Malformed, "parent does not exist", err)
}
}
l, err = services.LocationService.AddLocation(l, u)
if err != nil {
return errors.E(method, errors.Internal, err)
}
lJson, err := json.Marshal(l)
if err != nil {
return errors.E(method, errors.Internal, "error marshalling location", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusCreated)
(*w).Write(lJson)
return nil
}
func getTopLocations(w *http.ResponseWriter, r *http.Request, u *quartermaster.User) error {
const method errors.Method = "locations/getTopLocations"
locations, err := services.LocationService.GetTopLocations(u)
if err != nil {
return errors.E(method, errors.Internal, "error getting locations", err)
}
locationsJson, err := json.Marshal(locations)
if err != nil {
return errors.E(method, errors.Internal, "error marshalling locations", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusOK)
(*w).Write(locationsJson)
return nil
}
func getChildren(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "locations/getChildren"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
if err == sql.ErrNoRows {
return errors.E(method, errors.Malformed, "location not found", err)
}
return errors.E(method, errors.Internal, "probem retrieving location", err)
}
children, err := services.LocationService.GetChildren(location, user)
if err != nil {
return errors.E(method, errors.Internal, "problem retrieving children", err)
}
var childrenJson []byte
if children == nil {
childrenJson = []byte("[]")
} else {
childrenJson, err = json.Marshal(children)
}
if err != nil {
return errors.E(method, errors.Internal, "problem marshalling children", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusOK)
(*w).Write(childrenJson)
return nil
}
func getLocation(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "locations/getLocation"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
if err == sql.ErrNoRows {
return errors.E(method, errors.Malformed, "location not found", err)
}
return errors.E(method, errors.Internal, "robem retrieving location", err)
}
locationJson, err := json.Marshal(location)
if err != nil {
return errors.E(method, errors.Internal, "problem marshalling location", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusOK)
(*w).Write(locationJson)
return nil
}
func getItems(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "locations/getItems"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
return errors.E(method, errors.Malformed, "location not found", err)
}
items, err := services.LocationService.GetItems(location, user)
if err != nil {
return errors.E(method, "problem getting items", err)
}
var itemsResp []itemsResponse
for i, c := range items {
itemsResp = append(itemsResp, itemsResponse{Count: c, Item: i})
}
var itemsJson []byte
if itemsResp == nil {
itemsJson = []byte("[]")
} else {
itemsJson, err = json.Marshal(itemsResp)
}
if err != nil {
return errors.E(method, errors.Internal, "error marshalling items", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusOK)
(*w).Write(itemsJson)
return nil
}
func addItem(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "items/addItem"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "location id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
return errors.E(method, errors.Malformed, "location not found", err)
}
itemIDString := params["item_id"]
itemID, err := strconv.Atoi(itemIDString)
if err != nil {
return errors.E(method, errors.Malformed, "item id must be a valid number")
}
item, err := services.ItemService.Item(itemID, user)
if err != nil {
return errors.E(method, errors.Malformed, "item not found", err)
}
i, err := services.ItemService.AddItem(item, location, user)
if err != nil {
return errors.E(method, errors.Internal, "error adding item to location", err)
}
iJson, err := json.Marshal(i)
if err != nil {
return errors.E(method, errors.Internal, "error marshalling item", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusCreated)
(*w).Write(iJson)
return nil
}
func removeItem(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "items/removeItem"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "location id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
return errors.E(method, errors.Malformed, "location not found", err)
}
itemIDString := params["item_id"]
itemID, err := strconv.Atoi(itemIDString)
if err != nil {
return errors.E(method, errors.Malformed, "item id must be a valid number")
}
item, err := services.ItemService.Item(itemID, user)
if err != nil {
return errors.E(method, errors.Malformed, "item not found", err)
}
err = services.ItemService.RemoveItem(item, location, user)
if err != nil {
return errors.E(method, errors.Internal, "error removing item from location", err)
}
iJson, err := json.Marshal(struct{ Status string }{Status: "ok"})
if err != nil {
return errors.E(method, errors.Internal, "error marshalling item", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusCreated)
(*w).Write(iJson)
return nil
}
func getItemCount(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error {
const method errors.Method = "items/getItemCount"
params := mux.Vars(r)
idString := params["id"]
id, err := strconv.Atoi(idString)
if err != nil {
return errors.E(method, errors.Malformed, "location id must be a valid number")
}
location, err := services.LocationService.Location(id, user)
if err != nil {
return errors.E(method, errors.Malformed, "location not found", err)
}
itemIDString := params["item_id"]
itemID, err := strconv.Atoi(itemIDString)
if err != nil {
return errors.E(method, errors.Malformed, "item id must be a valid number")
}
item, err := services.ItemService.Item(itemID, user)
if err != nil {
return errors.E(method, errors.Malformed, "item not found", err)
}
c, err := services.LocationService.GetItemCount(location, item, user)
if err != nil {
return errors.E(method, errors.Internal, "error getting count of items in location", err)
}
iJson, err := json.Marshal(struct{ Count int }{Count: c})
if err != nil {
return errors.E(method, errors.Internal, "error marshalling item", err)
}
(*w).Header().Set("Content-Type", "application/json")
(*w).WriteHeader(http.StatusCreated)
(*w).Write(iJson)
return nil
}