Bläddra i källkod

db

- impl ProductVariants
Alexey Kim 2 år sedan
förälder
incheckning
ea6e038fc0
5 ändrade filer med 156 tillägg och 1 borttagningar
  1. 42 0
      db/clickhouse.go
  2. 2 0
      db/database.go
  3. 9 1
      db/product.go
  4. 2 0
      graphql/gqlgen.yml
  5. 101 0
      relation/product_variant.go

+ 42 - 0
db/clickhouse.go

@@ -6,6 +6,7 @@ import (
 	"github.com/gshopify/service-wrapper/config"
 	"github.com/gshopify/service-wrapper/db"
 	"github.com/gshopify/service-wrapper/model"
+	"github.com/gshopify/service-wrapper/server/middleware"
 	"github.com/jellydator/ttlcache/v3"
 	"github.com/mailru/dbr"
 	_ "github.com/mailru/go-clickhouse"
@@ -192,6 +193,47 @@ func (db *clickhouse) ProductOptions(ln model.LanguageCode, id string) ([]*gener
 	return options, nil
 }
 
+func (db *clickhouse) ProductVariants(ctx *middleware.GShopifyContext, id string) ([]*generated.ProductVariant, error) {
+	var (
+		variants []*generated.ProductVariant
+		key      = productVariantKey("product_id=?", id)
+		l        = ttlcache.LoaderFunc[string, any](
+			func(ttl *ttlcache.Cache[string, any], _ string) *ttlcache.Item[string, any] {
+				var o []relation.ProductVariant
+				rows, err := db.session.
+					Select(
+						"id", "product_id", "options",
+						fmt.Sprintf("price['%s'] as price", defaultCurrency),
+						fmt.Sprintf("unit_price['%s'] as unit_price", defaultCurrency),
+						fmt.Sprintf("compare_at_price['%s'] as compare_at_price", defaultCurrency),
+						"barcode", "sku", "hs_code", "origin_country",
+						"allow_backorder", "manage_inventory", "unit_price_measurement",
+						"weight", "wight_unit", "created_at", "updated_at", "deleted_at",
+						ctx.Language.SqlFieldSelection("title"),
+					).
+					From(key.Table()).
+					Where(key.Clause(), key.Args()...).
+					OrderBy("created_at").
+					Load(&o)
+				if rows < 1 || err != nil {
+					return nil
+				}
+
+				return ttl.Set(key.String(), o, key.TTL())
+			},
+		)
+	)
+
+	p := db.cache.Get(key.String(), ttlcache.WithLoader[string, any](l))
+	if p != nil {
+		for _, v := range p.Value().([]relation.ProductVariant) {
+			variants = append(variants, v.As())
+		}
+	}
+
+	return variants, nil
+}
+
 func (db *clickhouse) CollectionProducts(ln model.LanguageCode, id string) ([]*generated.Product, error) {
 	var (
 		products []*generated.Product

+ 2 - 0
db/database.go

@@ -2,6 +2,7 @@ package db
 
 import (
 	"github.com/gshopify/service-wrapper/model"
+	"github.com/gshopify/service-wrapper/server/middleware"
 	"gshopper.com/gshopify/products/graphql/generated"
 	"time"
 )
@@ -18,5 +19,6 @@ type Database interface {
 	Product(ln model.LanguageCode, handle *string, id *string) (*generated.Product, error)
 	ProductCollections(ln model.LanguageCode, id string) ([]*generated.Collection, error)
 	ProductOptions(ln model.LanguageCode, id string) ([]*generated.ProductOption, error)
+	ProductVariants(ctx *middleware.GShopifyContext, id string) ([]*generated.ProductVariant, error)
 	CollectionProducts(ln model.LanguageCode, id string) ([]*generated.Product, error)
 }

+ 9 - 1
db/product.go

@@ -6,6 +6,8 @@ import (
 	"time"
 )
 
+const defaultCurrency = "USD"
+
 var (
 	productKey = func(clause string, args ...any) *cache.SqlKey {
 		return cache.NewSQLKey(
@@ -44,7 +46,13 @@ var (
 	productOptionKey = func(clause string, args ...any) *cache.SqlKey {
 		return cache.NewSQLKey(
 			"product_option",
-			time.Second*30,
+			time.Minute,
+			clause, args...)
+	}
+	productVariantKey = func(clause string, args ...any) *cache.SqlKey {
+		return cache.NewSQLKey(
+			"product_variant",
+			time.Minute,
 			clause, args...)
 	}
 )

+ 2 - 0
graphql/gqlgen.yml

@@ -29,3 +29,5 @@ models:
     model: github.com/gshopify/service-wrapper/scalar.Html
   JSON:
     model: github.com/gshopify/service-wrapper/scalar.Json
+  Decimal:
+    model: github.com/gshopify/service-wrapper/scalar.Decimal

+ 101 - 0
relation/product_variant.go

@@ -0,0 +1,101 @@
+package relation
+
+import (
+	"github.com/gshopify/service-wrapper/model"
+	"github.com/gshopify/service-wrapper/scalar"
+	"github.com/mailru/dbr"
+	"gshopper.com/gshopify/products/graphql/generated"
+	"time"
+)
+
+type ProductVariant struct {
+	Id        string `db:"id"`
+	ProductId string `db:"product_id"`
+	Title     string `db:"title"`
+	Options   []struct {
+		Field0 string
+		Field1 int32
+	} `db:"options"`
+	Price                float64        `db:"price"`
+	UnitPrice            float64        `db:"unit_price"`
+	CompareAtPrice       float64        `db:"compare_at_price"`
+	Barcode              dbr.NullString `db:"barcode"`
+	Sku                  dbr.NullString `db:"sku"`
+	HarmonizedSystemCode dbr.NullString `db:"hs_code"`
+	AllowBackorder       bool           `db:"allow_backorder"`
+	ManageInventory      bool           `db:"manage_inventory"`
+	OriginCountry        dbr.NullString `db:"origin_country"`
+	UnitPriceMeasurement struct {
+		Field0 string
+		Field1 string
+		Field2 float64
+		Field3 string
+		Field4 int32
+	} `db:"unit_price_measurement"`
+	Weight     dbr.NullFloat64 `db:"weight"`
+	WeightUnit string          `db:"wight_unit"`
+	CreatedAt  time.Time       `db:"created_at"`
+	UpdatedAt  time.Time       `db:"updated_at"`
+	DeletedAt  *time.Time      `db:"deleted_at"`
+}
+
+func (v *ProductVariant) As() *generated.ProductVariant {
+	variant := &generated.ProductVariant{
+		AvailableForSale:    false,
+		CurrentlyNotInStock: false,
+		RequiresShipping:    false,
+		QuantityAvailable:   nil,
+
+		ID:    model.NewId(model.GidVariant, v.Id),
+		Title: v.Title,
+
+		Price: &generated.MoneyV2{
+			Amount:       scalar.NewDecimal(v.Price),
+			CurrencyCode: generated.CurrencyCodeUsd,
+		},
+		CompareAtPrice: &generated.MoneyV2{
+			Amount:       scalar.NewDecimal(v.CompareAtPrice),
+			CurrencyCode: generated.CurrencyCodeUsd,
+		},
+		UnitPrice: &generated.MoneyV2{
+			Amount:       scalar.NewDecimal(v.UnitPrice),
+			CurrencyCode: generated.CurrencyCodeUsd,
+		},
+
+		Product:         &generated.Product{ID: model.NewId(model.GidProduct, v.ProductId)},
+		Image:           nil,
+		SelectedOptions: nil,
+
+		UnitPriceMeasurement: &generated.UnitPriceMeasurement{
+			QuantityValue:  v.UnitPriceMeasurement.Field2,
+			ReferenceValue: int(v.UnitPriceMeasurement.Field4),
+		},
+		WeightUnit: generated.WeightUnit(v.WeightUnit),
+	}
+
+	if enum := generated.UnitPriceMeasurementMeasuredType(v.UnitPriceMeasurement.Field0); enum.IsValid() {
+		variant.UnitPriceMeasurement.MeasuredType = &enum
+	}
+
+	if enum := generated.UnitPriceMeasurementMeasuredUnit(v.UnitPriceMeasurement.Field1); enum.IsValid() {
+		variant.UnitPriceMeasurement.QuantityUnit = &enum
+	}
+
+	if enum := generated.UnitPriceMeasurementMeasuredUnit(v.UnitPriceMeasurement.Field3); enum.IsValid() {
+		variant.UnitPriceMeasurement.ReferenceUnit = &enum
+	}
+
+	if v.Weight.Valid {
+		variant.Weight = &v.Weight.Float64
+	}
+
+	if v.Sku.Valid {
+		variant.Sku = &v.Sku.String
+	}
+
+	if v.Barcode.Valid {
+		variant.Barcode = &v.Barcode.String
+	}
+
+	return variant
+}