package items import ( "encoding/json" "net/http" "strconv" "github.com/dustinpianalto/errors" "github.com/dustinpianalto/quartermaster" "github.com/dustinpianalto/quartermaster/pkg/services" "github.com/gorilla/mux" ) type addItemRequest struct { Location quartermaster.Location `json:"location"` quartermaster.Item } type itemsResponse struct { Count int `json:"count"` *quartermaster.Item } func items(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items" if r.Method == "POST" { err := addItem(w, r, user) if err != nil { return errors.E(method, "there was a problem adding the item", err) } } else if r.Method == "GET" { err := getItems(w, r, user) if err != nil { return errors.E(method, "there was a problem getting items", err) } } else { return errors.E(method, errors.Malformed, "http method not allowed") } return nil } func addItem(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/addItem" var ir addItemRequest err := json.NewDecoder(r.Body).Decode(&ir) if err != nil { return errors.E(method, errors.Malformed, "failed to decode item request", err) } if ir.Name == "" || ir.Description == "" || ir.Size == 0.0 || ir.Barcode == "" { return errors.E(method, errors.Malformed, "name, description, and size, and barcode are requred") } i, err := services.ItemService.AddItem(&ir.Item, &ir.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 getItems(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/getItems" var l *quartermaster.Location err := json.NewDecoder(r.Body).Decode(&l) if err != nil { return errors.E(method, errors.Malformed, "failed to decode location", err) } if l.ID == 0 { return errors.E(method, errors.Malformed, "id is required") } items, err := services.LocationService.GetItems(l, 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}) } 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 getItemByBarcode(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/getItemByBarcode" params := mux.Vars(r) barcodeString := params["barcode"] item, err := services.ItemService.GetItemByBarcode(barcodeString, user) if err != nil { return errors.E(method, "problem getting items", err) } if item != nil { itemJson, err := json.Marshal(item) 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(itemJson) } else { (*w).Header().Set("Content-Type", "application/json") (*w).WriteHeader(http.StatusNotFound) } return nil } func moveItem(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/moveItem" params := mux.Vars(r) itemID, err := strconv.Atoi(params["id"]) if err != nil { return errors.E(method, errors.Malformed, "id must be a valid number") } var req map[string]int err = json.NewDecoder(r.Body).Decode(&req) if err != nil { return errors.E(method, errors.Malformed, "failed to decode request", err) } if _, ok := req["old_id"]; !ok { return errors.E(method, errors.Malformed, "old_id is required") } if _, ok := req["new_id"]; !ok { return errors.E(method, errors.Malformed, "new_id is required") } item := &quartermaster.Item{ ID: itemID, } old := &quartermaster.Location{ ID: req["old_id"], } new := &quartermaster.Location{ ID: req["new_id"], } err = services.ItemService.MoveItem(item, old, new, user) if err != nil { return errors.E(method, errors.Internal, "error moving item", err) } (*w).WriteHeader(http.StatusOK) return nil } func removeItem(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/removeItem" params := mux.Vars(r) itemID, err := strconv.Atoi(params["id"]) if err != nil { return errors.E(method, errors.Malformed, "id must be a valid number") } var req map[string]int err = json.NewDecoder(r.Body).Decode(&req) if err != nil { return errors.E(method, errors.Malformed, "failed to decode request", err) } if _, ok := req["location_id"]; !ok { return errors.E(method, errors.Malformed, "location_id is required") } item := &quartermaster.Item{ ID: itemID, } location := &quartermaster.Location{ ID: req["location_id"], } err = services.ItemService.RemoveItem(item, location, user) if err != nil { return errors.E(method, errors.Internal, "error removing item", err) } (*w).WriteHeader(http.StatusOK) return nil } func getLocationCount(w *http.ResponseWriter, r *http.Request, user *quartermaster.User) error { const method errors.Method = "items/getLocationCount" params := mux.Vars(r) itemID, err := strconv.Atoi(params["id"]) if err != nil { return errors.E(method, errors.Malformed, "id must be a valid number", err) } i := &quartermaster.Item{ ID: itemID, } locations, err := services.ItemService.GetItemLocations(i, user) 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 }