diff --git a/repositories/ImportRepository.go b/repositories/ImportRepository.go index e8aa9d2..e8fa836 100644 --- a/repositories/ImportRepository.go +++ b/repositories/ImportRepository.go @@ -5,10 +5,12 @@ import ( "db_service/models" helper "db_service/pkg" "encoding/json" + "errors" "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "log" + "math" "os" "sync" ) @@ -202,27 +204,121 @@ func getTotalDocumentCount(db string) int { func (importer *Importer) ImportProduct(product models.Product) (instance *Importer) { - productRepo := InitProductRepo(&product, importer.GetColorOption(product.Color), importer.GetSexOption(product.Cinsiyet)) - var categories []gm.Category - - if categories, importer.Error = gm.GetCatKeywords(importer.baza, product.Categories); importer.Error != nil { - log.Println("ERR0 Categories" + importer.Error.Error()) - return importer + var linkedProducts []gm.Product + if firstProduct, err := importer.importVariant(product); err == nil { + linkedProducts = append(linkedProducts, *firstProduct) } - productRepo.SetCategories(categories) + if product.ColorVariants != nil && len(*product.ColorVariants) > 0 { + for _, colorVariant := range *product.ColorVariants { - if productRepo.Brand, importer.Error = gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); importer.Error != nil { - log.Println("ERR BRAND" + importer.Error.Error()) - return importer + if variant, err := importer.importVariant(colorVariant); err == nil { + linkedProducts = append(linkedProducts, *variant) + } + } } - //BEGIN TRANSACTION - //tx := *importer.baza.Begin() + if len(linkedProducts) > 0 { + //todo link products + } return importer } +func (importer *Importer) importVariant(product models.Product) (*gm.Product, error) { + productRepo := InitProductRepo(&product, importer.GetColorOption(product.Color), importer.GetSexOption(product.Cinsiyet)) + + if categories, err := gm.GetCatKeywords(importer.baza, product.Categories); err != nil { + return nil, err + } else { + productRepo.SetCategories(categories) + } + + if brand, err := gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); err != nil { + return nil, err + } else { + productRepo.Brand = brand + } + + mainPorduct := productRepo.makeProduct(importer) + + //BEGIN TRANSACTION + tx := *importer.baza.Begin() + + importer.Error = tx.Omit("Categories.*", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error + + if err := tx.Omit("Categories.*", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error; err != nil { + tx.Rollback() + return nil, err + } + + mainFlat := productRepo.makeProductFlat(mainPorduct.ID) + + if err := tx.Create(&mainFlat).Error; err != nil { + tx.Rollback() + return nil, err + } + + if productRepo.HasSizeVariants() { + var sizeVariants []gm.ProductFlat + for _, variant := range *product.SizeVariants { + tx.SavePoint(variant.ListingID) + sizeOPtion := gm.GetAttributeOption(&tx, importer.AttributesMap["size"].ID, variant.AttributeValue) + + variantProduct := productRepo.makeVariant(mainPorduct.ID, mainPorduct.AttributeFamilyID) + + variantProduct.AttributeValues = productRepo.getVariantAttributes(importer.AttributesMap, &variant, sizeOPtion.ID) + + if err := tx.Omit("Categories.*").Create(&variantProduct).Error; err != nil { + log.Println("Variant Product Create Error: " + err.Error()) + tx.RollbackTo(variant.ListingID) + continue + } + + variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, mainFlat.ID) + + if err := tx.Create(&variantFlat).Error; err != nil { + log.Println("Variant Flat Create Error: " + err.Error()) + tx.RollbackTo(variant.ListingID) + continue + } + + sizeVariants = append(sizeVariants, variantFlat) + } + + if len(sizeVariants) > 0 { + tx.Rollback() + return nil, errors.New("siz variantlary yok bolsa main productam girayenok") + } else { + calcPrice(sizeVariants, &mainFlat) + + err := tx.Omit("ParentID", "CreatedAt", "Variants", "SpecialPrice").Save(&mainFlat).Error + if err != nil { + tx.Rollback() + return nil, err + } + } + + } + + if err := tx.Commit().Error; err != nil { + return nil, err + } + + return &mainPorduct, nil +} + +func calcPrice(variants []gm.ProductFlat, flat *gm.ProductFlat) { + for _, variant := range variants { + + if flat.MinPrice == 0 || flat.MinPrice > variant.MinPrice { + flat.MinPrice = variant.MinPrice + } + + flat.MaxPrice = math.Max(flat.MaxPrice, variant.MaxPrice) + } +} + func (importer *Importer) GetColorOption(optionName string) gm.AttributeOption { if optionName == "" { return gm.AttributeOption{} diff --git a/repositories/ProductRepository.go b/repositories/ProductRepository.go index 70ce223..40d60da 100644 --- a/repositories/ProductRepository.go +++ b/repositories/ProductRepository.go @@ -58,6 +58,14 @@ func (pr *ProductRepo) SetCategories(categories []gm.Category) { } } +func (pr *ProductRepo) HasSizeVariants() bool { + return pr.Data.SizeVariants != nil && len(*pr.Data.SizeVariants) > 0 +} + +func (pr *ProductRepo) HasColorVariants() bool { + return pr.Data.ColorVariants != nil && len(*pr.Data.ColorVariants) > 0 +} + func (pr *ProductRepo) makeProduct(imp *Importer) gm.Product { var famID uint = 1 @@ -67,17 +75,20 @@ func (pr *ProductRepo) makeProduct(imp *Importer) gm.Product { product := gm.Product{ Sku: pr.Data.ProductNumber, - Type: "simple", AttributeFamilyID: famID, - BrandID: pr.Brand.ID, Categories: pr.Categories, AttributeValues: pr.getProductAttributes(imp.AttributesMap, pr.Data), } - if pr.Data.SizeVariants != nil && len(*pr.Data.SizeVariants) > 0 { + if pr.Data.Brand != "" { + product.BrandID = pr.Brand.ID + } + + if pr.HasSizeVariants() { product.Type = "configurable" product.SuperAttributes = []gm.Attribute{imp.AttributesMap["size"]} } else { + product.Type = "simple" price := pr.Data.Price if price.OriginalPrice.Value > price.DiscountedPrice.Value { @@ -101,23 +112,25 @@ func (pr *ProductRepo) makeProduct(imp *Importer) gm.Product { func (pr *ProductRepo) makeVariant(parentID, famID uint) gm.Product { - //todo product := gm.Product{ Sku: pr.Data.ProductNumber, Type: "simple", AttributeFamilyID: famID, - BrandID: pr.Brand.ID, Categories: pr.Categories, ParentID: parentID, } + if pr.Data.Brand != "" { + product.BrandID = pr.Brand.ID + } + return product } -func (pr *ProductRepo) makeProductFlat(im *Importer) gm.ProductFlat { +func (pr *ProductRepo) makeProductFlat(productId uint) gm.ProductFlat { flat := gm.ProductFlat{ - + ProductID: productId, Status: true, VisibleIndividually: true, Name: pr.Data.Name, @@ -127,32 +140,22 @@ func (pr *ProductRepo) makeProductFlat(im *Importer) gm.ProductFlat { //UrlKey: pr.Data.ProductGroupID, Weight: pr.Weight, FavoritesCount: uint(pr.Data.FavoriteCount), + MetaKeywords: pr.Keywords, MaxPrice: 0, MinPrice: 0, Price: 0, } if pr.Data.Color != "" { - flat.Color = int(im.GetColorOption(pr.Data.Color).ID) + flat.Color = int(pr.ColorOption.ID) flat.ColorLabel = pr.Data.Color } - if pr.Data.SizeVariants != nil && len(*pr.Data.SizeVariants) > 0 { + if pr.Data.Brand != "" { + flat.BrandID = pr.Brand.ID + } - for _, variant := range *pr.Data.SizeVariants { - price := variant.Price - - if flat.MinPrice == 0 || flat.MinPrice > price.DiscountedPrice.Value { - flat.MaxPrice = price.DiscountedPrice.Value - } - - maxPrice := math.Max(price.OriginalPrice.Value, price.DiscountedPrice.Value) - if flat.MaxPrice == 0 || flat.MaxPrice < maxPrice { - flat.MaxPrice = maxPrice - } - } - - } else { + if !pr.HasSizeVariants() { flat.MinPrice = pr.Data.Price.DiscountedPrice.Value flat.MaxPrice = math.Max(pr.Data.Price.OriginalPrice.Value, pr.Data.Price.DiscountedPrice.Value) flat.Price = flat.MaxPrice @@ -162,15 +165,31 @@ func (pr *ProductRepo) makeProductFlat(im *Importer) gm.ProductFlat { } } + //else {//todo calculate price after variants inserted + // for _, variant := range *pr.Data.SizeVariants { + // price := variant.Price + // + // if flat.MinPrice == 0 || flat.MinPrice > price.DiscountedPrice.Value { + // flat.MaxPrice = price.DiscountedPrice.Value + // } + // + // maxPrice := math.Max(price.OriginalPrice.Value, price.DiscountedPrice.Value) + // if flat.MaxPrice == 0 || flat.MaxPrice < maxPrice { + // flat.MaxPrice = maxPrice + // } + // } + // + //} return flat } -func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID int) gm.ProductFlat { +func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID, parentID uint) gm.ProductFlat { maxPRice := math.Max(variant.Price.OriginalPrice.Value, variant.Price.DiscountedPrice.Value) flat := gm.ProductFlat{ + ParentID: parentID, Status: true, Name: pr.Data.Name, Sku: pr.Data.ProductGroupID, @@ -178,7 +197,7 @@ func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID int) gm.Pro Weight: pr.Weight, FavoritesCount: uint(pr.Data.FavoriteCount), SizeLabel: variant.AttributeValue, - Size: SizID, + Size: int(SizID), MaxPrice: maxPRice, MinPrice: variant.Price.DiscountedPrice.Value, Price: maxPRice, @@ -220,7 +239,7 @@ func (pr *ProductRepo) getProductAttributes(AttributesMap map[string]gm.Attribut return attributes } -func (pr *ProductRepo) getVariantAttributes(AttributesMap map[string]gm.Attribute, product *models.Variant, SizID int) []gm.ProductAttributeValue { +func (pr *ProductRepo) getVariantAttributes(AttributesMap map[string]gm.Attribute, product *models.Variant, SizID uint) []gm.ProductAttributeValue { price := math.Max(product.Price.OriginalPrice.Value, product.Price.DiscountedPrice.Value) @@ -231,7 +250,7 @@ func (pr *ProductRepo) getVariantAttributes(AttributesMap map[string]gm.Attribut {AttributeID: AttributesMap["name"].ID, TextValue: pr.Data.Name, Channel: "default", Locale: "tm"}, {AttributeID: AttributesMap["weight"].ID, TextValue: pr.Data.Weight}, {AttributeID: AttributesMap["status"].ID, BooleanValue: true}, - {AttributeID: AttributesMap["size"].ID, IntegerValue: SizID}, + {AttributeID: AttributesMap["size"].ID, IntegerValue: int(SizID)}, {AttributeID: AttributesMap["price"].ID, FloatValue: price}, }