Added item managagement
the build was successful
Details
the build was successful
Details
+ Resolved quantity stuff - there now is a new table which links books or items to a quantity
This commit is contained in:
parent
c592de5daa
commit
3c08e18cd2
|
@ -27,51 +27,6 @@ func (Book) TableName() string {
|
|||
return "books"
|
||||
}
|
||||
|
||||
// Quantity is the quantity for a book
|
||||
type Quantity struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk"`
|
||||
BookID int64 `xorm:"int(11) not null"`
|
||||
Quantity int64 `xorm:"int(11) not null"`
|
||||
Created int64 `xorm:"created"`
|
||||
}
|
||||
|
||||
// TableName returns the name for the quantites table
|
||||
func (Quantity) TableName() string {
|
||||
return "books_quantities"
|
||||
}
|
||||
|
||||
// GetQuantityByBook returns the current quantity for a book
|
||||
func GetQuantityByBook(book Book) (quantity int64, err error) {
|
||||
bq := Quantity{BookID: book.ID}
|
||||
has, err := x.Desc("id").Get(&bq)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if has {
|
||||
quantity = bq.Quantity
|
||||
}
|
||||
|
||||
return quantity, nil
|
||||
}
|
||||
|
||||
// SetBookQuantity sets a new quantity for a book
|
||||
func (book Book) setBookQuantity(quantity int64) (err error) {
|
||||
// Check if the quantity already exists and only insert it if not
|
||||
qty, err := GetQuantityByBook(book)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if qty != quantity {
|
||||
q := Quantity{BookID: book.ID, Quantity: quantity}
|
||||
_, err = x.Insert(q)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBookByID gets a Book by its ID
|
||||
func GetBookByID(ID int64) (book Book, exists bool, err error) {
|
||||
// Get the Book
|
||||
|
@ -79,7 +34,7 @@ func GetBookByID(ID int64) (book Book, exists bool, err error) {
|
|||
|
||||
if has {
|
||||
// Get the books quantity. We can't join it because xorm ignores the Quantity option in struct
|
||||
book.Quantity, err = GetQuantityByBook(book)
|
||||
book.Quantity, err = book.getQuantity()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting quantity:", err)
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ func AddOrUpdateBook(book Book) (newBook Book, err error) {
|
|||
}
|
||||
|
||||
// Set the Quantity
|
||||
err = book.setBookQuantity(qty)
|
||||
err = book.setQuantity(qty)
|
||||
if err != nil {
|
||||
return Book{}, err
|
||||
}
|
||||
|
|
|
@ -18,6 +18,12 @@ func DeleteBookByID(id int64) error {
|
|||
|
||||
// Delete all authors associated with that book
|
||||
_, err = x.Delete(&AuthorBook{BookID: id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete all quantites for this book
|
||||
_, err = x.Delete(&Quantity{ItemID: id})
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ func ListBooks(searchterm string) (books []*Book, err error) {
|
|||
for i, book := range books {
|
||||
|
||||
// Get quantities
|
||||
books[i].Quantity, err = GetQuantityByBook(*book)
|
||||
books[i].Quantity, err = book.getQuantity()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting quantity:", err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package models
|
||||
|
||||
// Item holds an item
|
||||
type Item struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
Title string `xorm:"varchar(250)" json:"title"`
|
||||
Price float64 `xorm:"double" json:"price"`
|
||||
Description string `xorm:"varchar(750)" json:"description"`
|
||||
Other string `xorm:"varchar(750)" json:"other"`
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
Quantity int64 `xorm:"-" json:"quantity"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for items
|
||||
func (Item) TableName() string {
|
||||
return "items"
|
||||
}
|
||||
|
||||
// GetItemByID returns an item by its ID
|
||||
func GetItemByID(id int64) (item Item, exists bool, err error) {
|
||||
exists, err = x.Id(id).Get(&item)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
item.Quantity, err = item.getQuantity()
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package models
|
||||
|
||||
// AddOrUpdateItem adds or updates a item from a item struct
|
||||
func AddOrUpdateItem(item Item) (newItem Item, err error) {
|
||||
// save the quantity for later use
|
||||
qty := item.Quantity
|
||||
|
||||
if item.ID == 0 {
|
||||
if item.Title != "" { // Only insert it if the title is not empty
|
||||
_, err = x.Insert(&item)
|
||||
|
||||
if err != nil {
|
||||
return Item{}, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err = x.ID(item.ID).Update(&item)
|
||||
|
||||
if err != nil {
|
||||
return Item{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Quantity
|
||||
err = item.setQuantity(qty)
|
||||
if err != nil {
|
||||
return Item{}, err
|
||||
}
|
||||
|
||||
newItem, _, err = GetItemByID(item.ID)
|
||||
|
||||
return newItem, err
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package models
|
||||
|
||||
import "fmt"
|
||||
|
||||
// DeleteItemByID deletes a item by its ID
|
||||
func DeleteItemByID(id int64) error {
|
||||
// Check if the id is 0
|
||||
if id == 0 {
|
||||
return fmt.Errorf("ID cannot be 0")
|
||||
}
|
||||
|
||||
// Delete the item
|
||||
_, err := x.Id(id).Delete(&Item{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete all quantites for this item
|
||||
_, err = x.Delete(&Quantity{ItemID: id})
|
||||
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package models
|
||||
|
||||
// ListItems returns a list with all items, filtered by an optional searchstring
|
||||
func ListItems(searchterm string) (items []Item, err error) {
|
||||
|
||||
if searchterm == "" {
|
||||
err = x.Find(&items)
|
||||
} else {
|
||||
err = x.
|
||||
Where("title LIKE ?", "%"+searchterm+"%").
|
||||
Find(&items)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return []Item{}, err
|
||||
}
|
||||
|
||||
// Range over all items and get their quantity.
|
||||
// Yes I know how inperformant this is. But we can't use a join here because of the way xorm handels the quantity property.
|
||||
for i, item := range items {
|
||||
items[i].Quantity, err = item.getQuantity()
|
||||
if err != nil {
|
||||
return []Item{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
|
@ -32,6 +32,8 @@ func SetEngine() (err error) {
|
|||
x.Sync(&AuthorBook{})
|
||||
x.Sync(&Status{})
|
||||
x.Sync(&Quantity{})
|
||||
x.Sync(&quantityRelation{})
|
||||
x.Sync(&Item{})
|
||||
|
||||
x.ShowSQL(Config.Database.ShowQueries)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ func AddOrUpdatePublisher(publisher Publisher) (newPublisher Publisher, err erro
|
|||
}
|
||||
}
|
||||
} else {
|
||||
_, err = x.Where("id = ?", publisher.ID).Update(&publisher)
|
||||
_, err = x.ID(publisher.ID).Update(&publisher)
|
||||
|
||||
if err != nil {
|
||||
return Publisher{}, err
|
|
@ -0,0 +1,160 @@
|
|||
package models
|
||||
|
||||
// Quantity is the quantity for a book
|
||||
type Quantity struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk"`
|
||||
ItemID int64 `xorm:"int(11) not null"`
|
||||
Quantity int64 `xorm:"int(11) not null"`
|
||||
Created int64 `xorm:"created"`
|
||||
}
|
||||
|
||||
// TableName returns the name for the quantites table
|
||||
func (Quantity) TableName() string {
|
||||
return "quantities"
|
||||
}
|
||||
|
||||
// Quantityrelations holds information about wherether the quantity we are currently dealing with is one of a book or an item
|
||||
// We cannot directly link quantites to items and books because they can have the same id... which is why we need this.
|
||||
type quantityRelation struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk"`
|
||||
ItemID int64 `xorm:"int(11) not null"`
|
||||
BookID int64 `xorm:"int(11) not null"`
|
||||
Created int64 `xorm:"created"`
|
||||
}
|
||||
|
||||
// TableName returns the name for the quantites table
|
||||
func (quantityRelation) TableName() string {
|
||||
return "quantity_relations"
|
||||
}
|
||||
|
||||
// GetQuantity gets the latest quantity
|
||||
func GetQuantity(itemID int64) (quantity int64, err error) {
|
||||
|
||||
// Return nothing if we dont have an item
|
||||
if itemID == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Get the quanitty
|
||||
bq := Quantity{ItemID: itemID}
|
||||
has, err := x.Desc("id").Get(&bq)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if has {
|
||||
quantity = bq.Quantity
|
||||
}
|
||||
|
||||
return quantity, nil
|
||||
}
|
||||
|
||||
// SetQuantity sets the quantity for an item
|
||||
func SetQuantity(itemID, quantity int64) (err error) {
|
||||
// Check if the quantity already exists and only insert it if not
|
||||
qty, err := GetQuantity(itemID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if qty != quantity {
|
||||
q := Quantity{ItemID: itemID, Quantity: quantity}
|
||||
_, err = x.Insert(q)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ===== ITEMS =====
|
||||
|
||||
// Get item quantity with relation
|
||||
func (item Item) getQuantity() (quantity int64, err error) {
|
||||
// get the quantity relation for the item
|
||||
qtyID, _, err := item.getQuantityRelation()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return GetQuantity(qtyID)
|
||||
}
|
||||
|
||||
func (item Item) getQuantityRelation() (qtyID int64, exists bool, err error) {
|
||||
// get the quantity relation for the item
|
||||
qty := quantityRelation{ItemID: item.ID}
|
||||
has, err := x.Get(&qty)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
return qty.ID, has, nil
|
||||
}
|
||||
|
||||
// Set item quantity with relation
|
||||
func (item Item) setQuantity(quantity int64) (err error) {
|
||||
// Check if the relation already exists, if not, create a new one
|
||||
qtyItemID, exists, err := item.getQuantityRelation()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !exists {
|
||||
rel := quantityRelation{ItemID: item.ID}
|
||||
_, err := x.Insert(&rel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
qtyItemID = rel.ID
|
||||
}
|
||||
|
||||
// Insert the new quantity
|
||||
return SetQuantity(qtyItemID, quantity)
|
||||
}
|
||||
|
||||
// ===== BOOKS =====
|
||||
|
||||
// Get book quantity with relation
|
||||
func (book Book) getQuantity() (quantity int64, err error) {
|
||||
// get the quantity relation for the item
|
||||
qtyID, _, err := book.getQuantityRelation()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return GetQuantity(qtyID)
|
||||
}
|
||||
|
||||
// Get the quantity relation
|
||||
func (book Book) getQuantityRelation() (qtyID int64, exists bool, err error) {
|
||||
// get the quantity relation for the item
|
||||
qty := quantityRelation{BookID: book.ID}
|
||||
has, err := x.Get(&qty)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
return qty.ID, has, nil
|
||||
}
|
||||
|
||||
// Set book quantity with relation
|
||||
func (book Book) setQuantity(quantity int64) (err error) {
|
||||
// Check if the relation already exists, if not, create a new one
|
||||
qtyItemID, exists, err := book.getQuantityRelation()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !exists {
|
||||
rel := quantityRelation{BookID: book.ID}
|
||||
_, err := x.Insert(&rel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
qtyItemID = rel.ID
|
||||
}
|
||||
|
||||
// Insert the new quantity
|
||||
return SetQuantity(qtyItemID, quantity)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.mowie.cc/konrad/Library/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type itemPayload struct {
|
||||
Item models.Item `json:"item" form:"item"`
|
||||
}
|
||||
|
||||
// ItemAddOrUpdate is the handler to add a item
|
||||
func ItemAddOrUpdate(c echo.Context) error {
|
||||
// Check for Request Content
|
||||
itemFromString := c.FormValue("item")
|
||||
var datItem models.Item
|
||||
|
||||
if itemFromString == "" {
|
||||
b := new(itemPayload)
|
||||
if err := c.Bind(b); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"No item model provided"})
|
||||
}
|
||||
datItem = b.Item
|
||||
} else {
|
||||
// Decode the JSON
|
||||
dec := json.NewDecoder(strings.NewReader(itemFromString))
|
||||
err := dec.Decode(&datItem)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Error decoding item: " + err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have an ID other than the one in the struct
|
||||
id := c.Param("id")
|
||||
if id != "" {
|
||||
// Make int
|
||||
itemID, err := strconv.ParseInt(id, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get item id"})
|
||||
}
|
||||
datItem.ID = itemID
|
||||
}
|
||||
|
||||
// Insert or update the item
|
||||
newItem, err := models.AddOrUpdateItem(datItem)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Error"})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, newItem)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"git.mowie.cc/konrad/Library/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ItemDelete is the handler to delete a item
|
||||
func ItemDelete(c echo.Context) error {
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
// Make int
|
||||
itemID, err := strconv.ParseInt(id, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get item infos"})
|
||||
}
|
||||
|
||||
// Check if the item exists
|
||||
_, exists, err := models.GetItemByID(itemID)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could get item"})
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"The item does not exist."})
|
||||
}
|
||||
|
||||
// Delete it
|
||||
err = models.DeleteItemByID(itemID)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not delete item"})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, models.Message{"success"})
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"git.mowie.cc/konrad/Library/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ItemsList is the handler to list Items, optionally filtered
|
||||
func ItemsList(c echo.Context) error {
|
||||
|
||||
// Prepare the searchterm
|
||||
search := c.QueryParam("s")
|
||||
|
||||
list, err := models.ListItems(search)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Error getting items"})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, list)
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"git.mowie.cc/konrad/Library/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ItemShow is the handler to show informations about a item
|
||||
func ItemShow(c echo.Context) error {
|
||||
item := c.Param("id")
|
||||
|
||||
if item == "" {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"Item ID cannot be empty."})
|
||||
}
|
||||
|
||||
// Make int
|
||||
itemID, err := strconv.ParseInt(item, 10, 64)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Error getting item infos."})
|
||||
}
|
||||
|
||||
// Get item Infos
|
||||
itemInfos, exists, err := models.GetItemByID(itemID)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Error getting item infos."})
|
||||
}
|
||||
|
||||
// Check if it exists
|
||||
if !exists {
|
||||
return c.JSON(http.StatusNotFound, models.Message{"Item not found."})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, itemInfos)
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@ package v1
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.mowie.cc/konrad/Library/models"
|
||||
"github.com/labstack/echo"
|
||||
"net/http"
|
||||
|
@ -23,7 +22,6 @@ func PublisherAddOrUpdate(c echo.Context) error {
|
|||
if publisherFromString == "" {
|
||||
b := new(publisherPayload)
|
||||
if err := c.Bind(b); err != nil {
|
||||
fmt.Println(err)
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"No publisher model provided"})
|
||||
}
|
||||
datPublisher = b.Publisher
|
||||
|
@ -44,7 +42,7 @@ func PublisherAddOrUpdate(c echo.Context) error {
|
|||
publisherID, err := strconv.ParseInt(id, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get book id"})
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get item id"})
|
||||
}
|
||||
datPublisher.ID = publisherID
|
||||
}
|
||||
|
|
|
@ -74,6 +74,10 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
a.GET("/publishers/:id", apiv1.PublisherShow)
|
||||
a.GET("/publishers/search", apiv1.PublisherSearch)
|
||||
|
||||
// Lookup Items
|
||||
a.GET("/items", apiv1.ItemsList)
|
||||
a.GET("/items/:id", apiv1.ItemShow)
|
||||
|
||||
// Lookup Status
|
||||
a.GET("/status", apiv1.StatusListShow)
|
||||
a.GET("/status/:id", apiv1.StatusByIDShow)
|
||||
|
@ -98,6 +102,11 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
a.DELETE("/publishers/:id", apiv1.PublisherDelete)
|
||||
a.POST("/publishers/:id", apiv1.PublisherAddOrUpdate)
|
||||
|
||||
// Manage Items
|
||||
a.PUT("/items", apiv1.ItemAddOrUpdate)
|
||||
a.DELETE("/items/:id", apiv1.ItemDelete)
|
||||
a.POST("/items/:id", apiv1.ItemAddOrUpdate)
|
||||
|
||||
// Manage Users
|
||||
|
||||
/*
|
||||
|
@ -111,7 +120,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
POST /logout - ausloggen
|
||||
|
||||
GET /books/:id - ✔ Buch anzeigen
|
||||
POST /books/:id - |Buch bearbeiten (inkl mengen)
|
||||
POST /books/:id - ✔ |Buch bearbeiten (inkl mengen)
|
||||
DELETE /books/:id - ✔ |Buch löschen (+alle einträge in authors_books löschen dessen Bush dazu gehört)
|
||||
GET /books/search?s=se - ✔ Suchen
|
||||
GET /books/list - ✔ Auflisten
|
||||
|
|
Loading…
Reference in New Issue