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.
282 lines
9.0 KiB
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
|
|
}
|