From 6a15c0ff690c8924e026a105d4f16b29c208c953 Mon Sep 17 00:00:00 2001 From: merdan Date: Sat, 8 Oct 2022 15:57:03 +0500 Subject: [PATCH] finish before delete && flush --- gorm_models/product.go | 6 +++ repositories/ImportRepository.go | 78 ++++++++++++++++++++----------- repositories/ProductRepository.go | 21 +++++---- 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/gorm_models/product.go b/gorm_models/product.go index 1cea3b5..bd88456 100644 --- a/gorm_models/product.go +++ b/gorm_models/product.go @@ -23,6 +23,12 @@ type Product struct { Categories []Category `gorm:"many2many:product_categories;"` AttributeValues []ProductAttributeValue SuperAttributes []Attribute `gorm:"many2many:product_super_attributes;"` + //Variants []*Product `gorm:"many2many:product_relations;foreignKey:child_id;primaryKey:parent_id;"` +} + +type ProductRelation struct { + ParentID uint + ChildID uint } type ProductFlat struct { diff --git a/repositories/ImportRepository.go b/repositories/ImportRepository.go index e8fa836..e01e90e 100644 --- a/repositories/ImportRepository.go +++ b/repositories/ImportRepository.go @@ -12,6 +12,7 @@ import ( "log" "math" "os" + "strconv" "sync" ) @@ -25,6 +26,8 @@ type Importer struct { ImportWGroup sync.WaitGroup ColorOptions map[string]gm.AttributeOption SexOptions map[string]gm.AttributeOption + ColorMutex sync.Mutex + SexMutex sync.Mutex } func ImporterInstance() (instance *Importer, err error) { @@ -205,21 +208,37 @@ func getTotalDocumentCount(db string) int { func (importer *Importer) ImportProduct(product models.Product) (instance *Importer) { var linkedProducts []gm.Product - if firstProduct, err := importer.importVariant(product); err == nil { + var firstProduct *gm.Product + if firstProduct, importer.Error = importer.importVariant(product); importer.Error != nil { + return importer + } else if product.ColorVariants != nil && len(*product.ColorVariants) > 0 { linkedProducts = append(linkedProducts, *firstProduct) - } - - if product.ColorVariants != nil && len(*product.ColorVariants) > 0 { for _, colorVariant := range *product.ColorVariants { + if !colorVariant.IsSellable { + continue + } + if variant, err := importer.importVariant(colorVariant); err == nil { linkedProducts = append(linkedProducts, *variant) } } } - if len(linkedProducts) > 0 { + if len(linkedProducts) > 1 { //todo link products + var relation []gm.ProductRelation + for index, variant := range linkedProducts { + //spoint := "color" + strconv.Itoa(index) + for _, item := range append(linkedProducts[:index], linkedProducts[index+1:]...) { + relation = append(relation, gm.ProductRelation{ParentID: variant.ID, ChildID: item.ID}) + } + } + + if err := importer.baza.Create(&relation).Error; err != nil { + log.Println(err) + } + } return importer @@ -243,9 +262,7 @@ func (importer *Importer) importVariant(product models.Product) (*gm.Product, er mainPorduct := productRepo.makeProduct(importer) //BEGIN TRANSACTION - tx := *importer.baza.Begin() - - importer.Error = tx.Omit("Categories.*", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error + tx := importer.baza.Begin() if err := tx.Omit("Categories.*", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error; err != nil { tx.Rollback() @@ -261,32 +278,37 @@ func (importer *Importer) importVariant(product models.Product) (*gm.Product, er 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) + for index, variant := range *product.SizeVariants { + if !variant.Sellable { + continue + } + savePoint := "size" + strconv.Itoa(index) + tx.SavePoint(savePoint) + sizeOPtion := gm.GetAttributeOption(tx, importer.AttributesMap["size"].ID, variant.AttributeValue) - variantProduct := productRepo.makeVariant(mainPorduct.ID, mainPorduct.AttributeFamilyID) + sku := fmt.Sprintf("%s-%d", product.ProductNumber, variant.ItemNumber) + variantProduct := productRepo.makeVariant(mainPorduct.ID, mainPorduct.AttributeFamilyID, sku) 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) + tx.RollbackTo(savePoint) continue } - variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, mainFlat.ID) + variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, mainFlat.ID, variantProduct.ID) if err := tx.Create(&variantFlat).Error; err != nil { log.Println("Variant Flat Create Error: " + err.Error()) - tx.RollbackTo(variant.ListingID) + tx.RollbackTo(savePoint) continue } sizeVariants = append(sizeVariants, variantFlat) } - if len(sizeVariants) > 0 { + if len(sizeVariants) == 0 { tx.Rollback() return nil, errors.New("siz variantlary yok bolsa main productam girayenok") } else { @@ -324,27 +346,31 @@ func (importer *Importer) GetColorOption(optionName string) gm.AttributeOption { return gm.AttributeOption{} } - if option, ok := importer.ColorOptions[optionName]; ok { - return option - } else { + importer.ColorMutex.Lock() + var option gm.AttributeOption + var ok bool + + if option, ok = importer.ColorOptions[optionName]; !ok { option := gm.GetAttributeOption(importer.baza, importer.AttributesMap["color"].ID, optionName) importer.ColorOptions[optionName] = option - return option } + importer.ColorMutex.Unlock() + return option } func (importer *Importer) GetSexOption(optionName string) gm.AttributeOption { if optionName == "" { return gm.AttributeOption{} } + importer.SexMutex.Lock() + var option gm.AttributeOption + var ok bool - if option, ok := importer.ColorOptions[optionName]; ok { - return option - } else { - option := gm.GetAttributeOption(importer.baza, importer.AttributesMap["cinsiyet"].ID, optionName) - + if option, ok = importer.ColorOptions[optionName]; !ok { + option = gm.GetAttributeOption(importer.baza, importer.AttributesMap["cinsiyet"].ID, optionName) importer.SexOptions[optionName] = option - return option } + importer.SexMutex.Unlock() + return option } diff --git a/repositories/ProductRepository.go b/repositories/ProductRepository.go index 40d60da..e9632e3 100644 --- a/repositories/ProductRepository.go +++ b/repositories/ProductRepository.go @@ -3,6 +3,7 @@ package repositories import ( gm "db_service/gorm_models" "db_service/models" + "fmt" "math" "strconv" ) @@ -110,10 +111,10 @@ func (pr *ProductRepo) makeProduct(imp *Importer) gm.Product { return product } -func (pr *ProductRepo) makeVariant(parentID, famID uint) gm.Product { +func (pr *ProductRepo) makeVariant(parentID, famID uint, sku string) gm.Product { product := gm.Product{ - Sku: pr.Data.ProductNumber, + Sku: sku, Type: "simple", AttributeFamilyID: famID, Categories: pr.Categories, @@ -134,7 +135,7 @@ func (pr *ProductRepo) makeProductFlat(productId uint) gm.ProductFlat { Status: true, VisibleIndividually: true, Name: pr.Data.Name, - Sku: pr.Data.ProductGroupID, + Sku: pr.Data.ProductNumber, //ProductNumber: pr.Data.ProductNumber, Description: pr.Description, //UrlKey: pr.Data.ProductGroupID, @@ -184,16 +185,17 @@ func (pr *ProductRepo) makeProductFlat(productId uint) gm.ProductFlat { return flat } -func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID, parentID uint) gm.ProductFlat { +func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID, parentID, productID uint) gm.ProductFlat { maxPRice := math.Max(variant.Price.OriginalPrice.Value, variant.Price.DiscountedPrice.Value) + sku := fmt.Sprintf("%s-%d", pr.Data.ProductNumber, variant.ItemNumber) flat := gm.ProductFlat{ ParentID: parentID, Status: true, Name: pr.Data.Name, - Sku: pr.Data.ProductGroupID, - ProductNumber: pr.Data.ProductNumber, + Sku: sku, + ProductNumber: fmt.Sprintf("%d", variant.ItemNumber), Weight: pr.Weight, FavoritesCount: uint(pr.Data.FavoriteCount), SizeLabel: variant.AttributeValue, @@ -201,6 +203,7 @@ func (pr *ProductRepo) makeVariantFlat(variant models.Variant, SizID, parentID u MaxPrice: maxPRice, MinPrice: variant.Price.DiscountedPrice.Value, Price: maxPRice, + ProductID: productID, } if flat.MaxPrice > flat.MinPrice { @@ -242,11 +245,11 @@ func (pr *ProductRepo) getProductAttributes(AttributesMap map[string]gm.Attribut 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) - + sku := fmt.Sprintf("%s-%d", pr.Data.ProductNumber, product.ItemNumber) attributes := []gm.ProductAttributeValue{ {AttributeID: AttributesMap["source"].ID, TextValue: pr.Data.URLKey}, - {AttributeID: AttributesMap["sku"].ID, TextValue: string(rune(product.ItemNumber))}, //todo unique - {AttributeID: AttributesMap["product_number"].ID, TextValue: string(rune(product.ItemNumber))}, //todo unique + {AttributeID: AttributesMap["sku"].ID, TextValue: sku}, //todo unique + {AttributeID: AttributesMap["product_number"].ID, TextValue: fmt.Sprintf("%d", product.ItemNumber)}, //todo unique {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},