feat: better API returns, asset update

This commit is contained in:
2024-01-21 01:02:40 -06:00
parent a8ee837dee
commit b2c8c2915f
7 changed files with 93 additions and 10 deletions

View File

@@ -67,6 +67,7 @@ func (s *APIServer) handleIndex(w http.ResponseWriter, r *http.Request) error {
func makeHandler(f APIFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := f(w, r); err != nil {
log.Printf("Err: %v", err)
render.Render(w, r, errBadRequest(err))
}
}

View File

@@ -19,6 +19,7 @@ func (s *APIServer) setupAssetRoutes() func(r chi.Router) {
r.Use(s.AssetCtx)
r.Get("/", makeHandler(s.getAsset))
r.Delete("/", makeHandler(s.deleteAsset))
r.Put("/", makeHandler(s.updateAsset))
})
}
}
@@ -42,7 +43,7 @@ func (s *APIServer) AssetCtx(next http.Handler) http.Handler {
}
func (s *APIServer) getAssets(w http.ResponseWriter, r *http.Request) error {
assets, err := s.db.GetAssets(0, 50) // TODO: Proper Pagination
assets, err := s.db.GetAssets(0, 1000) // TODO: Proper Pagination
if err != nil {
return err
}
@@ -120,3 +121,41 @@ func (s *APIServer) createAsset(w http.ResponseWriter, r *http.Request) error {
Asset: asset,
})
}
func (s *APIServer) updateAsset(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
eAsset, ok := ctx.Value("asset").(*types.Asset)
if !ok {
return render.Render(w, r, errUnprocessable)
}
data := &types.CreateAssetRequest{}
if err := render.Bind(r, data); err != nil {
return render.Render(w, r, errBadRequest(err))
}
asset := &types.Asset{
ID: eAsset.ID,
Name: data.Name,
Quantity: data.Quantity,
Length: data.Length,
Manufacturer: data.Manufacturer,
ModelName: data.ModelName,
Price: data.Price,
Comments: data.Comments,
ShelfLocationID: data.ShelfLocationID,
CategoryID: data.CategoryID,
}
err := s.db.UpdateAsset(eAsset.ID, asset)
if err != nil {
return err
}
return render.Render(w, r, &types.AssetResponse{
Response: &types.Response{
HTTPStatusCode: http.StatusOK,
},
Asset: asset,
})
}

View File

@@ -2,6 +2,7 @@ package api
import (
"context"
"log"
"net/http"
"strconv"
@@ -15,24 +16,27 @@ func (s *APIServer) setupShelfRoutes() func(chi.Router) {
r.Get("/", makeHandler(s.getShelves))
r.Post("/", makeHandler(s.createShelf))
r.Route("/{shelfID}", func(r chi.Router) {
r.Route("/{shelfId}", func(r chi.Router) {
r.Use(s.ShelfCtx)
r.Get("/", makeHandler(s.getShelf))
r.Delete("/", makeHandler(s.deleteShelf))
r.Get("/count", makeHandler(s.getShelfAssetCount))
})
}
}
func (s *APIServer) ShelfCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
shelfIdStr := chi.URLParam(r, "shelfID")
shelfIdStr := chi.URLParam(r, "shelfId")
shelfId, err := strconv.ParseUint(shelfIdStr, 10, 64)
if err != nil {
log.Println("Test")
render.Render(w, r, errNotFound)
return
}
shelf, err := s.db.GetShelfByID(shelfId)
if err != nil {
log.Printf("Test 2: %v\n", err)
render.Render(w, r, errNotFound)
return
}
@@ -120,3 +124,23 @@ func (s *APIServer) createShelf(w http.ResponseWriter, r *http.Request) error {
ShelfLocation: shelf,
})
}
func (s *APIServer) getShelfAssetCount(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
shelf, ok := ctx.Value("shelf").(*types.ShelfLocation)
if !ok {
return render.Render(w, r, errUnprocessable)
}
count, err := s.db.AssetCountInLocation(shelf.ID)
if err != nil {
return err
}
return render.Render(w, r, &types.CountResponse{
Response: &types.Response{
HTTPStatusCode: http.StatusOK,
},
Count: count,
})
}

View File

@@ -7,6 +7,7 @@ import (
"git.brettb.xyz/goinv/server/internal/types"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/logger"
)
@@ -47,6 +48,11 @@ func (s *DataStore) CreateAsset(asset *types.Asset) error {
return result.Error
}
func (s *DataStore) UpdateAsset(id uint64, update *types.Asset) error {
result := s.db.Model(&types.Asset{}).Where("id = ?", id).Select("*").Updates(update)
return result.Error
}
func (s *DataStore) CreateBuilding(building *types.Building) error {
result := s.db.Create(building)
return result.Error
@@ -64,7 +70,7 @@ func (s *DataStore) CreateShelfLocation(shelf *types.ShelfLocation) error {
func (s *DataStore) GetAssetByID(id uint64) (*types.Asset, error) {
var result types.Asset
tx := s.db.Model(&types.Asset{}).Where("id = ?", id).First(&result)
tx := s.db.Model(&types.Asset{}).Where("id = ?", id).Preload(clause.Associations).First(&result)
if tx.Error != nil {
return nil, fmt.Errorf("asset %d not found", id)
}
@@ -88,6 +94,14 @@ func (s *DataStore) TotalAssets() (int64, error) {
return count, nil
}
func (s *DataStore) AssetCountInLocation(shelfId uint64) (int64, error) {
var count int64
if tx := s.db.Model(&types.Asset{}).Where("shelf_location_id = ?", shelfId).Find(&types.Asset{}).Count(&count); tx.Error != nil {
return 0, tx.Error
}
return count, nil
}
func (s *DataStore) DeleteAssetByID(id uint64) (bool, error) {
tx := s.db.Delete(&types.Asset{}, id)
if tx.Error != nil {
@@ -98,16 +112,16 @@ func (s *DataStore) DeleteAssetByID(id uint64) (bool, error) {
func (s *DataStore) GetShelfByID(id uint64) (*types.ShelfLocation, error) {
var result types.ShelfLocation
tx := s.db.Model(&types.ShelfLocation{}).Where("id = ?", id).First(&result)
tx := s.db.Joins("Building").Where(&types.ShelfLocation{ID: id}).First(&result)
if tx.Error != nil {
return nil, fmt.Errorf("shelf %d not found", id)
return nil, fmt.Errorf("shelf %d not found: %v", id, tx.Error)
}
return &result, nil
}
func (s *DataStore) GetShelves(offset, limit int) ([]*types.ShelfLocation, error) {
func (s *DataStore) GetShelves(offset, limit uint64) ([]*types.ShelfLocation, error) {
var shelves []*types.ShelfLocation
s.db.Offset(offset).Limit(limit).Find(&shelves)
s.db.Joins("Building").Order("id asc").Offset(int(offset)).Limit(int(limit)).Find(&shelves)
if len(shelves) == 0 {
return nil, fmt.Errorf("no shelves found")
}

View File

@@ -26,6 +26,11 @@ type IndexResponse struct {
Version APIVersion `json:"version"`
}
type CountResponse struct {
*Response
Count int64 `json:"count"`
}
type APIError struct {
*Response
Err error `json:"-"`

View File

@@ -14,7 +14,7 @@ import (
type Building struct {
ID uint64 `gorm:"primarykey" json:"id"`
Name string `json:"name"`
ShelfLocations []ShelfLocation `json:"shelves"`
ShelfLocations []ShelfLocation `json:"shelves,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"`

View File

@@ -17,7 +17,7 @@ type ShelfLocation struct {
RoomNumber string `json:"room_number,omitempty"`
Description string `json:"description,omitempty"`
BuildingID uint64 `json:"-"`
Building Building `json:"building"`
Building Building `json:"building",omitempty`
Assets []Asset `json:"assets,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`