Selaa lähdekoodia

Product

- retrieve more fields
Alexey Kim 2 vuotta sitten
vanhempi
commit
f1f0a0030d
3 muutettua tiedostoa jossa 83 lisäystä ja 25 poistoa
  1. 17 9
      db/clickhouse.go
  2. 23 9
      db/product.go
  3. 43 7
      relation/product.go

+ 17 - 9
db/clickhouse.go

@@ -111,15 +111,15 @@ func (db *clickhouse) Product(ln model.LanguageCode, handle *string, id *string)
 		vars   = []any{model.ProductStatusActive}
 	)
 
-	clause.WriteString("status=?")
+	clause.WriteString("t.status=?")
 
 	if id != nil {
-		clause.WriteString(" AND id=?")
+		clause.WriteString(" AND t.id=?")
 		vars = append(vars, *id)
 	}
 
 	if handle != nil {
-		clause.WriteString(" AND handle=?")
+		clause.WriteString(" AND t.handle=?")
 		vars = append(vars, *handle)
 	}
 
@@ -129,9 +129,13 @@ func (db *clickhouse) Product(ln model.LanguageCode, handle *string, id *string)
 			func(ttl *ttlcache.Cache[string, any], _ string) *ttlcache.Item[string, any] {
 				o := relation.Product{}
 				rows, err := db.session.
-					Select(productSelection(ln)...).
-					From(key.Table()).
+					Select(productSelection(ln, defaultCurrency)...).
+					From(fmt.Sprintf("%s as t", key.Table())).
+					LeftJoin("product_variant", "product_variant.product_id = t.id").
+					LeftJoin("inventory_item", "inventory_item.id = product_variant.inventory_item_id").
+					LeftJoin("inventory_level", "inventory_level.inventory_item_id = product_variant.inventory_item_id").
 					Where(key.Clause(), key.Args()...).
+					GroupBy("t.id").
 					Limit(1).
 					Load(&o)
 				if rows < 1 || err != nil {
@@ -209,7 +213,7 @@ func (db *clickhouse) ProductVariants(ctx *middleware.GShopifyContext, id string
 			"any(inventory_item.barcode) as barcode",
 			"any(inventory_item.requires_shipping) as requires_shipping",
 			"any(inventory_item.tracked) as tracked",
-			"if(tracked, if(available > 0, true, if(inventory_policy == 'continue', true, false)), false) as for_sale",
+			"if(tracked, if(available > 0, true, if(inventory_policy == 'continue', true, false)), true) as for_sale",
 		}
 		key = productVariantKey("t.product_id=?", id)
 		l   = ttlcache.LoaderFunc[string, any](
@@ -247,14 +251,18 @@ func (db *clickhouse) ProductVariants(ctx *middleware.GShopifyContext, id string
 func (db *clickhouse) CollectionProducts(ln model.LanguageCode, id string) ([]*generated.Product, error) {
 	var (
 		products []*generated.Product
-		key      = productKey("has(collections, ?)", id)
+		key      = productKey("has(t.collections, ?)", id)
 		l        = ttlcache.LoaderFunc[string, any](
 			func(ttl *ttlcache.Cache[string, any], _ string) *ttlcache.Item[string, any] {
 				var o []relation.Product
 				rows, err := db.session.
-					Select(productSelection(ln)...).
-					From(key.Table()).
+					Select(productSelection(ln, defaultCurrency)...).
+					From(fmt.Sprintf("%s as t", key.Table())).
+					LeftJoin("product_variant", "product_variant.product_id = t.id").
+					LeftJoin("inventory_item", "inventory_item.id = product_variant.inventory_item_id").
+					LeftJoin("inventory_level", "inventory_level.inventory_item_id = product_variant.inventory_item_id").
 					Where(key.Clause(), key.Args()...).
+					GroupBy("t.id").
 					Load(&o)
 				if rows < 1 || err != nil {
 					return nil

+ 23 - 9
db/product.go

@@ -1,8 +1,10 @@
 package db
 
 import (
+	"fmt"
 	"github.com/gshopify/service-wrapper/model"
 	"gshopper.com/gshopify/products/cache"
+	"gshopper.com/gshopify/products/graphql/generated"
 	"time"
 )
 
@@ -15,14 +17,26 @@ var (
 			time.Minute,
 			clause, args...)
 	}
-	productSelection = func(ln model.LanguageCode) []string {
+	productSelection = func(ln model.LanguageCode, currency generated.CurrencyCode) []string {
 		return append([]string{
-			"id", "handle", "type", "scope", "tags", "vendor",
-			"collections", "images", "options",
-			"created_at", "updated_at", "published_at", "deleted_at",
+			"t.id as id",
+			"any(handle) as handle", "any(type) as type", "any(scope) as scope", "any(tags) as tags", "any(vendor) as vendor",
+			"any(gift) as gift", "any(collections) as collections", "any(images) as images",
+			"any(product_variant.inventory_management) as inventory_management",
+			"any(product_variant.inventory_policy) as inventory_policy",
+			"any(product_variant.options) as options",
+			"any(inventory_item.requires_shipping) as requires_shipping",
+			"any(inventory_item.tracked) as tracked",
+			"any(inventory_level.available) as available",
+			"if(tracked, if(available > 0, true, if(inventory_policy == 'continue', true, false)), true) as for_sale",
+			fmt.Sprintf("min(product_variant.price['%s']) as price_min", currency),
+			fmt.Sprintf("max(product_variant.price['%s']) as price_max", currency),
+			fmt.Sprintf("min(product_variant.compare_at_price['%s']) as compare_at_price_min", currency),
+			fmt.Sprintf("max(product_variant.compare_at_price['%s']) as compare_at_price_max", currency),
+			"any(created_at) as created_at", "any(updated_at) as updated_at", "any(published_at) as published_at", "any(deleted_at) as deleted_at",
 		},
-			ln.SqlFieldSelection("title", ""),
-			ln.SqlFieldSelection("description", ""),
+			ln.SqlFieldSelection("title", "", "any"),
+			ln.SqlFieldSelection("description", "", "any"),
 		)
 	}
 	productCollectionSelection = func(ln model.LanguageCode) []string {
@@ -30,8 +44,8 @@ var (
 			"id", "handle", "scope", "sort_order", "image", "template_suffix",
 			"created_at", "updated_at", "published_at", "deleted_at",
 		},
-			ln.SqlFieldSelection("title", ""),
-			ln.SqlFieldSelection("description", ""),
+			ln.SqlFieldSelection("title", "", ""),
+			ln.SqlFieldSelection("description", "", ""),
 		)
 	}
 	productCollectionKey = func(clause string, args ...any) *cache.SqlKey {
@@ -44,7 +58,7 @@ var (
 	}
 	productOptionSelection = func(ln model.LanguageCode) []string {
 		return append([]string{"id", "position", "created_at", "updated_at", "published_at", "deleted_at"},
-			ln.SqlFieldSelection("name", ""),
+			ln.SqlFieldSelection("name", "", ""),
 			ln.SqlArraySelection("values"),
 		)
 	}

+ 43 - 7
relation/product.go

@@ -24,25 +24,60 @@ type Product struct {
 	Tags           []string       `db:"tags"`
 	TemplateSuffix dbr.NullString `db:"template_suffix"`
 	Vendor         dbr.NullString `db:"vendor"`
+	Gift           bool           `db:"gift"`
 	Collections    []string       `db:"collections"`
 	Images         []string       `db:"images"`
-	Options        []string       `db:"options"`
+	Options        []struct {
+		Field0 string
+		Field1 int32
+	} `db:"options"`
+
+	InventoryManagement string  `db:"inventory_management"`
+	InventoryPolicy     string  `db:"inventory_policy"`
+	RequiresShipping    bool    `db:"requires_shipping"`
+	QuantityAvailable   int     `db:"available"`
+	ForSale             bool    `db:"for_sale"`
+	PriceMin            float64 `db:"price_min"`
+	PriceMax            float64 `db:"price_max"`
+	CompareAtPriceMin   float64 `db:"compare_at_price_min"`
+	CompareAtPriceMax   float64 `db:"compare_at_price_max"`
 }
 
 func (p *Product) As() *generated.Product {
 	description := bluemonday.StrictPolicy().Sanitize(p.Description.String)
 	product := generated.Product{
-		AvailableForSale:         false,
-		CompareAtPriceRange:      nil,
+		AvailableForSale: p.ForSale,
+		PriceRange: &generated.ProductPriceRange{
+			MaxVariantPrice: &generated.MoneyV2{
+				Amount:       scalar.NewDecimal(p.PriceMax),
+				CurrencyCode: generated.CurrencyCodeUsd,
+			},
+			MinVariantPrice: &generated.MoneyV2{
+				Amount:       scalar.NewDecimal(p.PriceMin),
+				CurrencyCode: generated.CurrencyCodeUsd,
+			},
+		},
+		CompareAtPriceRange: &generated.ProductPriceRange{
+			MaxVariantPrice: &generated.MoneyV2{
+				Amount:       scalar.NewDecimal(p.CompareAtPriceMax),
+				CurrencyCode: generated.CurrencyCodeUsd,
+			},
+			MinVariantPrice: &generated.MoneyV2{
+				Amount:       scalar.NewDecimal(p.CompareAtPriceMin),
+				CurrencyCode: generated.CurrencyCodeUsd,
+			},
+		},
+		TotalInventory: func() *int {
+			i := p.QuantityAvailable
+			return &i
+		}(),
+
+		RequiresSellingPlan:      false, // TODO:
 		FeaturedImage:            nil,
 		Images:                   nil,
-		IsGiftCard:               false,
 		Media:                    nil,
 		OnlineStoreURL:           nil,
-		PriceRange:               nil,
-		RequiresSellingPlan:      false,
 		SellingPlanGroups:        nil,
-		TotalInventory:           nil,
 		VariantBySelectedOptions: nil,
 
 		ID:              model.NewId(model.GidProduct, p.Id),
@@ -52,6 +87,7 @@ func (p *Product) As() *generated.Product {
 		Description:     description,
 		DescriptionHTML: scalar.Html(p.Description.String),
 		ProductType:     p.Type.String,
+		IsGiftCard:      p.Gift,
 		Tags:            p.Tags,
 		Seo: &generated.Seo{
 			Description: &description,