diff --git a/veza-backend-api/internal/core/marketplace/service.go b/veza-backend-api/internal/core/marketplace/service.go index f549699dc..db8fbeed7 100644 --- a/veza-backend-api/internal/core/marketplace/service.go +++ b/veza-backend-api/internal/core/marketplace/service.go @@ -153,10 +153,12 @@ func (s *Service) CreateProduct(ctx context.Context, product *Product) error { }) } -// GetProduct retrieves a product by ID +// GetProduct retrieves a product by ID with preloaded previews and images (v0.401 M1) func (s *Service) GetProduct(ctx context.Context, id uuid.UUID) (*Product, error) { var product Product - if err := s.db.First(&product, "id = ?", id).Error; err != nil { + if err := s.db.Preload("Previews").Preload("Images", func(db *gorm.DB) *gorm.DB { + return db.Order("product_images.sort_order ASC") + }).First(&product, "id = ?", id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrProductNotFound } @@ -257,6 +259,22 @@ func (s *Service) ListProducts(ctx context.Context, filters map[string]interface query = query.Where("price <= ?", maxPrice) } + // v0.401 M1: Filter by BPM, Musical Key, Category + if bpm, ok := filters["bpm"]; ok && bpm != nil { + switch v := bpm.(type) { + case int: + query = query.Where("bpm = ?", v) + case float64: + query = query.Where("bpm = ?", int(v)) + } + } + if musicalKey, ok := filters["musical_key"]; ok && musicalKey != "" { + query = query.Where("musical_key = ?", musicalKey) + } + if category, ok := filters["category"]; ok && category != "" { + query = query.Where("category = ?", category) + } + // Pagination limit := 20 if l, ok := filters["limit"].(int); ok && l > 0 { diff --git a/veza-backend-api/internal/handlers/marketplace.go b/veza-backend-api/internal/handlers/marketplace.go index 8853c6dcb..fa0a21069 100644 --- a/veza-backend-api/internal/handlers/marketplace.go +++ b/veza-backend-api/internal/handlers/marketplace.go @@ -352,6 +352,17 @@ func (h *MarketplaceHandler) ListProducts(c *gin.Context) { if pType := c.Query("type"); pType != "" { filters["product_type"] = pType } + if bpmStr := c.Query("bpm"); bpmStr != "" { + if val, err := strconv.Atoi(bpmStr); err == nil && val > 0 { + filters["bpm"] = val + } + } + if musicalKey := c.Query("musical_key"); musicalKey != "" { + filters["musical_key"] = musicalKey + } + if category := c.Query("category"); category != "" { + filters["category"] = category + } if minPriceStr := c.Query("min_price"); minPriceStr != "" { if val, err := strconv.ParseFloat(minPriceStr, 64); err == nil {