package api import ( "context" "database/sql" "net/http" "strconv" "github.com/labstack/echo/v4" "go.uber.org/zap" db "github.com/your-username/your-repo/database/sqlite/generated" ) type StorageHandler struct { db *db.Queries logger *zap.Logger } func NewStorageHandler(db *db.Queries, logger *zap.Logger) *StorageHandler { return &StorageHandler{ db: db, logger: logger, } } // GetStorageSpaces returns all storage spaces func (h *StorageHandler) GetStorageSpaces(c echo.Context) error { ctx := context.Background() storageSpaces, err := h.db.GetAllStorageSpaces(ctx) if err != nil { h.logger.Error("Failed to fetch storage spaces", zap.Error(err)) return c.JSON(http.StatusInternalServerError, map[string]string{ "error": "Failed to fetch storage spaces", }) } // Convert to a format suitable for the frontend result := make([]map[string]interface{}, len(storageSpaces)) for i, space := range storageSpaces { result[i] = map[string]interface{}{ "id": space.ID, "parent": space.Parent, "location": space.Location, } } return c.JSON(http.StatusOK, result) } // GetObjectsInStorage returns all objects in a specific storage space func (h *StorageHandler) GetObjectsInStorage(c echo.Context) error { ctx := context.Background() // Parse storage ID from URL storageIDStr := c.Param("id") storageID, err := strconv.ParseInt(storageIDStr, 10, 64) if err != nil { h.logger.Warn("Invalid storage ID", zap.String("id", storageIDStr)) return c.JSON(http.StatusBadRequest, map[string]string{ "error": "Invalid storage ID", }) } // Check if storage exists _, err = h.db.GetStorageSpaceByID(ctx, storageID) if err != nil { if err == sql.ErrNoRows { return c.JSON(http.StatusNotFound, map[string]string{ "error": "Storage space not found", }) } h.logger.Error("Failed to fetch storage space", zap.Error(err)) return c.JSON(http.StatusInternalServerError, map[string]string{ "error": "Failed to fetch storage space", }) } // Get objects in this storage objects, err := h.db.GetObjectsByStorageID(ctx, storageID) if err != nil { h.logger.Error("Failed to fetch objects in storage", zap.Error(err)) return c.JSON(http.StatusInternalServerError, map[string]string{ "error": "Failed to fetch objects in storage", }) } // Convert to a format suitable for the frontend result := make([]map[string]interface{}, len(objects)) for i, obj := range objects { result[i] = map[string]interface{}{ "id": obj.ID, "name": obj.Name, "storagespaceId": obj.StoragespaceID, "description": obj.Description.String, "serialnumber": obj.Serialnumber.String, } } return c.JSON(http.StatusOK, result) } // GetStorageHierarchyObjects returns all objects in a storage hierarchy func (h *StorageHandler) GetStorageHierarchyObjects(c echo.Context) error { ctx := context.Background() // Parse root storage ID from URL rootStorageIDStr := c.Param("id") rootStorageID, err := strconv.ParseInt(rootStorageIDStr, 10, 64) if err != nil { h.logger.Warn("Invalid storage ID", zap.String("id", rootStorageIDStr)) return c.JSON(http.StatusBadRequest, map[string]string{ "error": "Invalid storage ID", }) } // Check if root storage exists _, err = h.db.GetStorageSpaceByID(ctx, rootStorageID) if err != nil { if err == sql.ErrNoRows { return c.JSON(http.StatusNotFound, map[string]string{ "error": "Storage space not found", }) } h.logger.Error("Failed to fetch storage space", zap.Error(err)) return c.JSON(http.StatusInternalServerError, map[string]string{ "error": "Failed to fetch storage space", }) } // Get all storage spaces to build the hierarchy allStorageSpaces, err := h.db.GetAllStorageSpaces(ctx) if err != nil { h.logger.Error("Failed to fetch all storage spaces", zap.Error(err)) return c.JSON(http.StatusInternalServerError, map[string]string{ "error": "Failed to fetch storage hierarchy", }) } // Build a list of all storage IDs in the hierarchy storageIDs := []int64{rootStorageID} storageIDs = append(storageIDs, h.getChildStorageIDs(allStorageSpaces, rootStorageID)...) // Get objects for all storage spaces in the hierarchy var allObjects []map[string]interface{} for _, storageID := range storageIDs { // Get objects in this storage objects, err := h.db.GetObjectsByStorageID(ctx, storageID) if err != nil { h.logger.Error("Failed to fetch objects in storage", zap.Int64("storageID", storageID), zap.Error(err)) continue // Skip this storage if there's an error } // Convert to a format suitable for the frontend for _, obj := range objects { allObjects = append(allObjects, map[string]interface{}{ "id": obj.ID, "name": obj.Name, "storagespaceId": obj.StoragespaceID, "description": obj.Description.String, "serialnumber": obj.Serialnumber.String, }) } } return c.JSON(http.StatusOK, allObjects) } // Helper function to recursively get all child storage IDs func (h *StorageHandler) getChildStorageIDs(spaces []db.Storagespace, parentID int64) []int64 { var childIDs []int64 for _, space := range spaces { if space.Parent.Valid && space.Parent.Int64 == parentID { childIDs = append(childIDs, space.ID) // Recursively get children of this child childIDs = append(childIDs, h.getChildStorageIDs(spaces, space.ID)...) } } return childIDs } // RegisterRoutes registers all storage-related routes func (h *StorageHandler) RegisterRoutes(g *echo.Group) { g.GET("/storageSpaces", h.GetStorageSpaces) g.GET("/storageSpaces/:id/objects", h.GetObjectsInStorage) g.GET("/storageSpaces/:id/hierarchy/objects", h.GetStorageHierarchyObjects) }