go_service/repositories/ImportRepository.go

1040 lines
27 KiB
Go
Raw Normal View History

2022-09-27 13:53:17 +00:00
package repositories
import (
gm "db_service/gorm_models"
2022-10-03 06:31:28 +00:00
"db_service/models"
helper "db_service/pkg"
"encoding/json"
2022-10-03 12:32:27 +00:00
"errors"
2022-10-03 06:31:28 +00:00
"fmt"
"gorm.io/driver/mysql"
2022-09-27 13:53:17 +00:00
"gorm.io/gorm"
2022-10-03 06:31:28 +00:00
"log"
2022-10-03 12:32:27 +00:00
"math"
2022-10-03 06:31:28 +00:00
"os"
2022-10-08 10:57:03 +00:00
"strconv"
2022-10-03 06:31:28 +00:00
"sync"
2022-10-08 11:10:57 +00:00
"time"
2022-09-27 13:53:17 +00:00
)
type Importer struct {
mainCategories []gm.Category
baza *gorm.DB
families []gm.AttributeFamily
2022-10-03 06:31:28 +00:00
sellers map[string]gm.MarketplaceSeller
2023-01-19 11:32:55 +00:00
wishlist map[string]gm.Product
2022-10-03 06:31:28 +00:00
AttributesMap map[string]gm.Attribute
Error error
ImportWGroup sync.WaitGroup
ColorOptions map[string]gm.AttributeOption
SexOptions map[string]gm.AttributeOption
2022-10-08 10:57:03 +00:00
ColorMutex sync.Mutex
SexMutex sync.Mutex
2022-09-27 13:53:17 +00:00
}
2023-02-08 05:46:03 +00:00
type GormErr struct {
Number int `json:"Number"`
Message string `json:"Message"`
}
2022-10-03 06:31:28 +00:00
func ImporterInstance() (instance *Importer, err error) {
db, err := gorm.Open(mysql.Open(os.Getenv("database_url")), &gorm.Config{SkipDefaultTransaction: true})
if err != nil {
log.Println(err)
return nil, err
}
instance = &Importer{baza: db}
2023-01-19 11:32:55 +00:00
instance.ImportWGroup.Add(5)
2022-10-03 06:31:28 +00:00
//load main categories to memory
go func(db *gorm.DB) {
defer instance.ImportWGroup.Done()
instance.mainCategories, instance.Error = gm.GetMainCategories(db)
2023-02-11 10:25:41 +00:00
2022-10-03 06:31:28 +00:00
}(db)
//load families to memory
go func() {
defer instance.ImportWGroup.Done()
instance.families, instance.Error = gm.GetFamilies(db)
}()
//load attributes to memory
go func() {
defer instance.ImportWGroup.Done()
if attributes, err := gm.GetAttributes(db); err != nil {
instance.Error = err
return
} else {
instance.AttributesMap = make(map[string]gm.Attribute, len(attributes))
for _, attribute := range attributes {
instance.AttributesMap[attribute.Code] = attribute
}
}
if colorOptions, err := gm.GetAttrOptions(db, instance.AttributesMap["color"].ID); err != nil {
instance.Error = err
return
} else {
instance.ColorOptions = make(map[string]gm.AttributeOption, len(colorOptions))
for _, option := range colorOptions {
instance.ColorOptions[option.AdminName] = option
}
}
if sexOPtions, err := gm.GetAttrOptions(db, instance.AttributesMap["cinsiyet"].ID); err != nil {
instance.Error = err
return
} else {
instance.SexOptions = make(map[string]gm.AttributeOption, len(sexOPtions))
for _, option := range sexOPtions {
instance.SexOptions[option.AdminName] = option
}
}
}()
//load sellers to memory
go func() {
defer instance.ImportWGroup.Done()
var vendors, err = gm.GetSellers(db)
if err != nil {
instance.Error = err
return
}
//init sellers map
instance.sellers = make(map[string]gm.MarketplaceSeller, len(vendors))
for _, vendor := range vendors {
instance.sellers[vendor.Url] = vendor
}
}()
2023-01-19 11:32:55 +00:00
//load wishlist to memory
go func(){
defer instance.ImportWGroup.Done()
var wishlist, err = gm.GetWishlistProducts(db)
if err != nil {
instance.Error = err
return
}
instance.wishlist = make(map[string]gm.Product, len(wishlist))
for _, product := range wishlist {
instance.wishlist[product.Sku] = product
}
}()
2022-10-03 06:31:28 +00:00
if instance.Error != nil {
log.Println(instance.Error)
return nil, instance.Error
}
return instance, nil
}
2023-02-17 08:50:31 +00:00
func ParseImporterInstance() (instance *Importer, err error) {
2023-02-17 06:58:25 +00:00
db, err := gorm.Open(mysql.Open(os.Getenv("database_url")), &gorm.Config{SkipDefaultTransaction: true})
if err != nil {
log.Println(err)
return nil, err
}
instance = &Importer{baza: db}
instance.ImportWGroup.Add(3)
//load families to memory
go func() {
defer instance.ImportWGroup.Done()
instance.families, instance.Error = gm.GetFamilies(db)
}()
//load attributes to memory
go func() {
defer instance.ImportWGroup.Done()
if attributes, err := gm.GetAttributes(db); err != nil {
instance.Error = err
return
} else {
instance.AttributesMap = make(map[string]gm.Attribute, len(attributes))
for _, attribute := range attributes {
instance.AttributesMap[attribute.Code] = attribute
}
}
if colorOptions, err := gm.GetAttrOptions(db, instance.AttributesMap["color"].ID); err != nil {
instance.Error = err
return
} else {
instance.ColorOptions = make(map[string]gm.AttributeOption, len(colorOptions))
for _, option := range colorOptions {
instance.ColorOptions[option.AdminName] = option
}
}
if sexOPtions, err := gm.GetAttrOptions(db, instance.AttributesMap["cinsiyet"].ID); err != nil {
instance.Error = err
return
} else {
instance.SexOptions = make(map[string]gm.AttributeOption, len(sexOPtions))
for _, option := range sexOPtions {
instance.SexOptions[option.AdminName] = option
}
}
}()
//load sellers to memory
go func() {
defer instance.ImportWGroup.Done()
var vendors, err = gm.GetSellers(db)
if err != nil {
instance.Error = err
return
}
//init sellers map
instance.sellers = make(map[string]gm.MarketplaceSeller, len(vendors))
for _, vendor := range vendors {
instance.sellers[vendor.Url] = vendor
}
}()
if instance.Error != nil {
log.Println(instance.Error)
return nil, instance.Error
}
return instance, nil
}
2022-10-03 06:31:28 +00:00
func (importer *Importer) Start() (instance *Importer) {
2022-10-08 11:10:57 +00:00
log.Println("Start Product delete")
deleteTime := time.Now()
importer.Error = gm.DeleteProducts(importer.baza)
deleteElapsed := time.Since(deleteTime)
log.Printf("Delete products took %s", deleteElapsed)
if importer.Error != nil {
return importer
}
2022-10-03 06:31:28 +00:00
//init wait group to main categories length
importer.ImportWGroup.Add(len(importer.mainCategories))
//start gorutines for each main category
for _, element := range importer.mainCategories {
slug := element.Translations[0].Slug
go importer.categoryRoutine("ty_db_" + slug)
}
return importer
}
func (importer *Importer) categoryRoutine(dbName string) {
defer importer.ImportWGroup.Done()
if dbExists := helper.CheckDBExists(os.Getenv("couch_db_source") + dbName); dbExists {
totalDocCount := getTotalDocumentCount(dbName)
skip := 0
limit := 200
totalImport := 0
for skip < totalDocCount {
var response models.BagistoModelResponse
url := fmt.Sprintf("%s%s/_all_docs?include_docs=true&limit=%v&skip=%v", os.Getenv("couch_db_source"), dbName, limit, skip)
fmt.Println(url)
skip += limit
body, err := helper.SendRequest("GET", url, nil, "")
if err != nil {
fmt.Println(err.Error())
continue
}
if err = json.Unmarshal(body, &response); err != nil {
log.Println(err.Error())
continue
}
//iterate 100 row products
for _, element := range response.Rows {
if err := importer.ImportProduct(element.Doc).Error; err != nil {
log.Println(err)
} else {
totalImport++
}
}
log.Printf("%s total imported documents count %d \n", dbName, totalImport)
}
} else {
log.Println(dbName + "+doesnt exist")
}
}
func getTotalDocumentCount(db string) int {
var response models.DBDocCountResponse
url := os.Getenv("couch_db_source") + db
body, err := helper.SendRequest("GET", url, nil, "")
if err != nil {
log.Println(err.Error())
return 0
}
err = json.Unmarshal(body, &response)
if err != nil {
log.Println(err.Error())
return 0
}
return response.DocCount
}
func (importer *Importer) ImportProduct(product models.Product) (instance *Importer) {
2022-10-03 12:32:27 +00:00
var linkedProducts []gm.Product
2022-10-08 10:57:03 +00:00
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 {
2022-10-03 12:32:27 +00:00
linkedProducts = append(linkedProducts, *firstProduct)
for _, colorVariant := range *product.ColorVariants {
2022-10-08 10:57:03 +00:00
if !colorVariant.IsSellable {
continue
}
2022-10-03 12:32:27 +00:00
if variant, err := importer.importVariant(colorVariant); err == nil {
linkedProducts = append(linkedProducts, *variant)
}
}
}
2022-10-03 06:31:28 +00:00
2022-10-08 10:57:03 +00:00
if len(linkedProducts) > 1 {
2022-11-01 10:27:16 +00:00
2022-10-08 10:57:03 +00:00
var relation []gm.ProductRelation
for index, variant := range linkedProducts {
//spoint := "color" + strconv.Itoa(index)
2022-10-15 10:27:56 +00:00
temp := make([]gm.Product, len(linkedProducts))
copy(temp, linkedProducts)
if index+1 <= len(temp) {
temp = append(temp[:index], temp[index+1:]...)
for _, item := range temp {
relation = append(relation, gm.ProductRelation{ParentID: variant.ID, ChildID: item.ID})
}
2022-10-08 10:57:03 +00:00
}
2022-10-15 10:27:56 +00:00
2022-10-08 10:57:03 +00:00
}
if err := importer.baza.Create(&relation).Error; err != nil {
log.Println(err)
}
2022-10-03 06:31:28 +00:00
}
2022-10-03 12:32:27 +00:00
return importer
}
func (importer *Importer) importVariant(product models.Product) (*gm.Product, error) {
2023-01-19 11:32:55 +00:00
// check if wishlisted then update if.
if _, ok := importer.wishlist[product.ProductNumber]; ok {
delete(importer.wishlist,product.ProductNumber)
return importer.updateVariant(product)
}
2022-10-03 12:32:27 +00:00
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)
}
2022-10-03 06:31:28 +00:00
2022-10-03 12:32:27 +00:00
if brand, err := gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); err != nil {
return nil, err
} else {
productRepo.Brand = brand
2022-10-03 06:31:28 +00:00
}
2022-10-03 12:32:27 +00:00
mainPorduct := productRepo.makeProduct(importer)
2022-10-03 06:31:28 +00:00
//BEGIN TRANSACTION
2022-10-08 10:57:03 +00:00
tx := importer.baza.Begin()
2022-10-03 12:32:27 +00:00
if err := tx.Omit("Categories.*", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error; err != nil {
2023-02-08 05:46:03 +00:00
//todo update categories
byteErr, _ := json.Marshal(err)
var newError GormErr
2023-02-08 06:19:04 +00:00
if err1:= json.Unmarshal((byteErr), &newError);err1!=nil{
2023-02-08 05:46:03 +00:00
tx.Rollback()
2023-02-08 06:19:04 +00:00
log.Println(err1)
2023-02-08 05:46:03 +00:00
return nil, err
}
2023-02-08 06:19:04 +00:00
if newError.Number == 1062{
2023-02-08 05:46:03 +00:00
var barProduct gm.Product
if err2 := tx.First(&barProduct,"sku = ?",mainPorduct.Sku).Error;err2 !=nil {
tx.Rollback()
2023-02-08 06:19:04 +00:00
log.Println(err2)
2023-02-08 05:46:03 +00:00
return nil, err2
}
if err3:= tx.Model(&barProduct).Association("Categories").Append(mainPorduct.Categories); err3!=nil{
tx.Rollback()
2023-02-08 06:19:04 +00:00
log.Println(err3)
2023-02-08 05:46:03 +00:00
return nil, err3
}
2023-02-08 06:42:21 +00:00
return &barProduct,tx.Commit().Error;
2023-02-08 06:19:04 +00:00
}else{
tx.Rollback()
return nil, err
2023-02-08 05:46:03 +00:00
}
2022-10-03 12:32:27 +00:00
}
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
2022-10-08 10:57:03 +00:00
for index, variant := range *product.SizeVariants {
if !variant.Sellable {
continue
}
savePoint := "size" + strconv.Itoa(index)
tx.SavePoint(savePoint)
2022-11-01 06:35:43 +00:00
var sizeOPtion gm.AttributeOption
if variant.AttributeName == "Beden" {
sizeOPtion = gm.GetAttributeOption(tx, importer.AttributesMap["size"].ID, variant.AttributeValue)
} else {
sizeOPtion = gm.GetAttributeOption(tx, importer.AttributesMap["boyut"].ID, variant.AttributeValue)
}
2022-10-03 12:32:27 +00:00
2022-10-08 10:57:03 +00:00
sku := fmt.Sprintf("%s-%d", product.ProductNumber, variant.ItemNumber)
2023-02-17 09:05:08 +00:00
2022-10-08 10:57:03 +00:00
variantProduct := productRepo.makeVariant(mainPorduct.ID, mainPorduct.AttributeFamilyID, sku)
2022-10-03 12:32:27 +00:00
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())
2022-10-08 10:57:03 +00:00
tx.RollbackTo(savePoint)
2022-10-03 12:32:27 +00:00
continue
}
2022-10-08 10:57:03 +00:00
variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, mainFlat.ID, variantProduct.ID)
2022-10-03 12:32:27 +00:00
if err := tx.Create(&variantFlat).Error; err != nil {
log.Println("Variant Flat Create Error: " + err.Error())
2022-10-08 10:57:03 +00:00
tx.RollbackTo(savePoint)
2022-10-03 12:32:27 +00:00
continue
}
sizeVariants = append(sizeVariants, variantFlat)
}
2022-10-08 10:57:03 +00:00
if len(sizeVariants) == 0 {
2022-10-03 12:32:27 +00:00
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
2022-11-13 10:56:40 +00:00
mainFlat.Variants = sizeVariants
2022-10-03 12:32:27 +00:00
if err != nil {
tx.Rollback()
return nil, err
}
}
}
2022-12-05 08:50:24 +00:00
sProduct := importer.createSellerProduct(&mainFlat, product.Vendor)
2022-11-13 10:56:40 +00:00
2022-12-05 08:50:24 +00:00
if errSProduct := tx.Create(&sProduct).Error; errSProduct != nil {
2022-11-13 10:56:40 +00:00
tx.Rollback()
return nil, errSProduct
}
2022-10-03 12:32:27 +00:00
if err := tx.Commit().Error; err != nil {
return nil, err
}
return &mainPorduct, nil
}
2022-11-13 10:56:40 +00:00
func (importer *Importer) createSellerProduct(flat *gm.ProductFlat, sellerURL string) gm.MarketplaceProduct {
sellerID := importer.sellers[sellerURL].ID
if sellerID == 0 {
sellerID = 1
}
sellerProduct := gm.MarketplaceProduct{
MarketplaceSellerID: sellerID,
IsApproved: true,
Condition: "new",
Description: "scraped",
IsOwner: true,
ProductID: flat.ProductID,
}
for _, variant := range flat.Variants {
sellerProduct.Variants = append(sellerProduct.Variants, gm.MarketplaceProduct{
ProductID: variant.ProductID,
IsOwner: true,
IsApproved: true,
MarketplaceSellerID: sellerID,
Condition: "new",
})
}
return sellerProduct
}
2022-10-03 12:32:27 +00:00
func calcPrice(variants []gm.ProductFlat, flat *gm.ProductFlat) {
for _, variant := range variants {
2022-11-01 08:10:53 +00:00
if !variant.Status {
continue
}
2022-10-03 12:32:27 +00:00
if flat.MinPrice == 0 || flat.MinPrice > variant.MinPrice {
flat.MinPrice = variant.MinPrice
}
flat.MaxPrice = math.Max(flat.MaxPrice, variant.MaxPrice)
}
2022-10-03 06:31:28 +00:00
}
func (importer *Importer) GetColorOption(optionName string) gm.AttributeOption {
if optionName == "" {
return gm.AttributeOption{}
}
2022-10-08 10:57:03 +00:00
importer.ColorMutex.Lock()
var option gm.AttributeOption
var ok bool
if option, ok = importer.ColorOptions[optionName]; !ok {
2022-10-03 06:31:28 +00:00
option := gm.GetAttributeOption(importer.baza, importer.AttributesMap["color"].ID, optionName)
importer.ColorOptions[optionName] = option
}
2022-10-08 10:57:03 +00:00
importer.ColorMutex.Unlock()
return option
2022-10-03 06:31:28 +00:00
}
func (importer *Importer) GetSexOption(optionName string) gm.AttributeOption {
if optionName == "" {
return gm.AttributeOption{}
}
2022-10-08 10:57:03 +00:00
importer.SexMutex.Lock()
var option gm.AttributeOption
var ok bool
2022-10-03 06:31:28 +00:00
2022-10-08 10:57:03 +00:00
if option, ok = importer.ColorOptions[optionName]; !ok {
option = gm.GetAttributeOption(importer.baza, importer.AttributesMap["cinsiyet"].ID, optionName)
2022-10-03 06:31:28 +00:00
importer.SexOptions[optionName] = option
}
2022-10-08 10:57:03 +00:00
importer.SexMutex.Unlock()
return option
2022-09-27 13:53:17 +00:00
}
2022-10-15 17:05:19 +00:00
func (importer *Importer) updateVariant(product models.Product) (*gm.Product, error) {
var flat gm.ProductFlat
2022-11-01 11:38:41 +00:00
err := importer.baza.Preload("Product").Preload("Variants").First(&flat, "sku = ?", product.ProductNumber).Error
2022-10-15 17:05:19 +00:00
if err != nil {
2023-02-08 06:42:21 +00:00
if errors.Is(err,gorm.ErrRecordNotFound) {
return importer.importVariant(product)
}
2023-02-08 05:46:03 +00:00
//todo not found bolsa create etmeli
2022-10-15 17:05:19 +00:00
return nil, err
}
if flat.Product.Type == "configurable" {
2022-11-01 08:10:53 +00:00
productRepo := InitProductRepo(&product, importer.GetColorOption(product.Color), importer.GetSexOption(product.Cinsiyet))
2022-11-01 12:03:25 +00:00
if brand, err := gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); err != nil {
return nil, err
} else {
productRepo.Brand = brand
}
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
for _, variant := range *product.SizeVariants {
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
found := false
for _, flatVariant := range flat.Variants {
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
if variant.AttributeValue == flatVariant.BoyutLabel || variant.AttributeValue == flatVariant.SizeLabel {
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
if !variant.Sellable {
importer.baza.Model(&flatVariant).Update("status", false)
} else {
importer.updatePrice(variant.Price, &flatVariant)
if !flatVariant.Status {
importer.baza.Model(&flatVariant).Update("status", true)
}
}
found = true
break
}
}
if variant.Sellable && !found {
// insert variant
var sizeOPtion gm.AttributeOption
if variant.AttributeName == "Beden" {
sizeOPtion = gm.GetAttributeOption(importer.baza, importer.AttributesMap["size"].ID, variant.AttributeValue)
} else {
sizeOPtion = gm.GetAttributeOption(importer.baza, importer.AttributesMap["boyut"].ID, variant.AttributeValue)
}
sku := fmt.Sprintf("%s-%d", product.ProductNumber, variant.ItemNumber)
variantProduct := productRepo.makeVariant(flat.ProductID, flat.Product.AttributeFamilyID, sku)
variantProduct.AttributeValues = productRepo.getVariantAttributes(importer.AttributesMap, &variant, sizeOPtion.ID)
if err := importer.baza.Omit("Categories.*").Create(&variantProduct).Error; err != nil {
log.Println("Variant Product Create Error: " + err.Error())
}
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, flat.ID, variantProduct.ID)
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
if err := importer.baza.Create(&variantFlat).Error; err != nil {
log.Println("Variant Flat Create Error: " + err.Error())
2022-11-01 06:35:43 +00:00
2022-11-01 08:10:53 +00:00
}
flat.Variants = append(flat.Variants, variantFlat)
}
2022-11-01 06:35:43 +00:00
}
2022-11-01 08:10:53 +00:00
calcPrice(flat.Variants, &flat)
importer.baza.Omit("ParentID", "CreatedAt", "Variants", "SpecialPrice").Save(&flat)
} else { //simple
importer.updatePrice(product.Price, &flat)
2022-10-15 17:05:19 +00:00
}
2022-11-01 11:52:39 +00:00
return &flat.Product, nil
2022-10-15 17:05:19 +00:00
}
2022-11-01 08:10:53 +00:00
func (importer *Importer) updatePrice(price models.Price, flat *gm.ProductFlat) {
if price.OriginalPrice.Value > price.DiscountedPrice.Value {
importer.baza.Model(&flat).Updates(map[string]interface{}{
"price": price.OriginalPrice.Value,
"special_price": price.DiscountedPrice.Value,
"min_price": price.DiscountedPrice.Value,
"max_price": price.OriginalPrice.Value,
})
importer.baza.Model(&gm.ProductAttributeValue{}).
Where("attribute_id = 11 and product_id = ?", flat.ProductID).
Update("float_value", price.OriginalPrice.Value)
importer.baza.Model(&gm.ProductAttributeValue{}).
Where("attribute_id = 13 and product_id = ?", flat.ProductID).
Update("float_value", price.DiscountedPrice.Value)
} else {
importer.baza.Model(&flat).Updates(map[string]interface{}{
"price": price.DiscountedPrice.Value,
"special_price": nil,
"min_price": price.DiscountedPrice.Value,
"max_price": price.DiscountedPrice.Value,
})
importer.baza.Model(&gm.ProductAttributeValue{}).
Where("attribute_id = 11 and product_id = ?", flat.ProductID).
Update("float_value", price.DiscountedPrice.Value)
importer.baza.Where("attribute_id = 13 and product_id = ?", flat.ProductID).
Delete(&gm.ProductAttributeValue{})
}
}
2022-10-15 17:05:19 +00:00
func (importer *Importer) UpdateOrCreate(product models.Product) (instance *Importer) {
firstProduct, err := importer.importVariant(product)
2022-12-08 10:37:10 +00:00
var newProducts []gm.Product
2022-10-15 17:05:19 +00:00
if err != nil {
helper.Error(err)
firstProduct, importer.Error = importer.updateVariant(product)
if importer.Error != nil {
return importer
}
2022-12-08 10:37:10 +00:00
} else if &firstProduct != nil {
2022-12-09 10:58:14 +00:00
newProducts = append(newProducts, *firstProduct)
2022-10-15 17:05:19 +00:00
}
if product.ColorVariants != nil && len(*product.ColorVariants) > 0 {
linkedProducts := []gm.Product{*firstProduct}
for _, colorVariant := range *product.ColorVariants {
var (
variant *gm.Product
err error
)
if !colorVariant.IsSellable {
if err = importer.baza.Model(&gm.ProductFlat{}).Where("sku=?", colorVariant.ProductNumber).Update("status", false).Error; err != nil {
log.Println(err)
}
continue
2022-11-01 10:27:16 +00:00
} else {
2022-10-15 17:05:19 +00:00
2022-11-01 10:27:16 +00:00
if variant, err = importer.importVariant(colorVariant); err != nil {
2022-10-15 17:05:19 +00:00
2022-11-01 10:27:16 +00:00
if variant, importer.Error = importer.updateVariant(colorVariant); importer.Error != nil {
return importer
}
linkedProducts = append(linkedProducts, *variant)
2022-10-15 17:05:19 +00:00
2022-11-01 10:27:16 +00:00
} else {
newProducts = append(newProducts, *variant)
}
2022-10-15 17:05:19 +00:00
}
}
if len(newProducts) > 0 {
2022-11-01 10:27:16 +00:00
// relation
var relation []gm.ProductRelation
for _, linkedProduct := range linkedProducts {
for _, newProd := range newProducts {
relation = append(relation, gm.ProductRelation{ParentID: linkedProduct.ID, ChildID: newProd.ID})
relation = append(relation, gm.ProductRelation{ParentID: newProd.ID, ChildID: linkedProduct.ID})
}
}
if err := importer.baza.Create(&relation).Error; err != nil {
log.Println(err)
}
2022-10-15 17:05:19 +00:00
}
}
return importer
}
2023-02-17 08:50:31 +00:00
func (importer *Importer) importParsedVariant(product models.Product)(gm.Product, error) {
//todo search if exists
productRepo := InitProductRepo(&product, importer.GetColorOption(product.Color), importer.GetSexOption(product.Cinsiyet))
productRepo.ImageType = "lcw"
if brand, err := gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); err != nil {
return gm.Product{}, err
} else {
productRepo.Brand = brand
}
mainPorduct := productRepo.makeProduct(importer)
//BEGIN TRANSACTION
tx := importer.baza.Begin()
if err := tx.Omit("Categories", "SuperAttributes.*", "ParentID").Create(&mainPorduct).Error; err != nil {
tx.Rollback()
return gm.Product{}, err
}
mainFlat := productRepo.makeProductFlat(mainPorduct.ID)
if err := tx.Create(&mainFlat).Error; err != nil {
tx.Rollback()
return gm.Product{}, err
}
if productRepo.HasSizeVariants() {
var sizeVariants []gm.ProductFlat
for index, variant := range *product.SizeVariants {
if !variant.Sellable {
continue
}
savePoint := "size" + strconv.Itoa(index)
tx.SavePoint(savePoint)
var sizeOPtion gm.AttributeOption
if variant.AttributeName == "Beden" {
sizeOPtion = gm.GetAttributeOption(tx, importer.AttributesMap["size"].ID, variant.AttributeValue)
} else {
sizeOPtion = gm.GetAttributeOption(tx, importer.AttributesMap["boyut"].ID, variant.AttributeValue)
}
sku := fmt.Sprintf("%s-%d", product.ProductNumber, variant.ItemNumber)
2023-02-17 09:05:08 +00:00
log.Println(sku)
log.Println(variant)
2023-02-17 08:50:31 +00:00
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(savePoint)
continue
}
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(savePoint)
continue
}
sizeVariants = append(sizeVariants, variantFlat)
}
if len(sizeVariants) == 0 {
tx.Rollback()
return gm.Product{}, errors.New("siz variantlary yok bolsa main productam girayenok")
} else {
calcPrice(sizeVariants, &mainFlat)
err := tx.Omit("ParentID", "CreatedAt", "Variants", "SpecialPrice").Save(&mainFlat).Error
mainFlat.Variants = sizeVariants
if err != nil {
tx.Rollback()
return gm.Product{}, err
}
}
}
sProduct := importer.createSellerProduct(&mainFlat, product.Vendor)
if errSProduct := tx.Create(&sProduct).Error; errSProduct != nil {
tx.Rollback()
return gm.Product{}, errSProduct
}
if err := tx.Commit().Error; err != nil {
return gm.Product{}, err
}
return mainPorduct, nil
}
func (importer *Importer) updateParsedVariant(product models.Product) (gm.Product, error){
var flat gm.ProductFlat
err := importer.baza.Preload("Product").Preload("Variants").First(&flat, "sku = ?", product.ProductNumber).Error
if err != nil {
if errors.Is(err,gorm.ErrRecordNotFound) {
return importer.importParsedVariant(product)
}
//todo not found bolsa create etmeli
return gm.Product{}, err
}
if flat.Product.Type == "configurable" {
productRepo := InitProductRepo(&product, importer.GetColorOption(product.Color), importer.GetSexOption(product.Cinsiyet))
productRepo.ImageType = "lcw"
if brand, err := gm.FindOrCreateBrand(importer.baza, product.Brand, productRepo.Categories); err != nil {
return gm.Product{}, err
} else {
productRepo.Brand = brand
}
for _, variant := range *product.SizeVariants {
found := false
for _, flatVariant := range flat.Variants {
if variant.AttributeValue == flatVariant.BoyutLabel || variant.AttributeValue == flatVariant.SizeLabel {
if !variant.Sellable {
importer.baza.Model(&flatVariant).Update("status", false)
} else {
importer.updatePrice(variant.Price, &flatVariant)
if !flatVariant.Status {
importer.baza.Model(&flatVariant).Update("status", true)
}
}
found = true
break
}
}
if variant.Sellable && !found {
// insert variant
var sizeOPtion gm.AttributeOption
if variant.AttributeName == "Beden" {
sizeOPtion = gm.GetAttributeOption(importer.baza, importer.AttributesMap["size"].ID, variant.AttributeValue)
} else {
sizeOPtion = gm.GetAttributeOption(importer.baza, importer.AttributesMap["boyut"].ID, variant.AttributeValue)
}
sku := fmt.Sprintf("%s-%d", product.ProductNumber, variant.ItemNumber)
variantProduct := productRepo.makeVariant(flat.ProductID, flat.Product.AttributeFamilyID, sku)
variantProduct.AttributeValues = productRepo.getVariantAttributes(importer.AttributesMap, &variant, sizeOPtion.ID)
if err := importer.baza.Omit("Categories").Create(&variantProduct).Error; err != nil {
log.Println("Variant Product Create Error: " + err.Error())
}
variantFlat := productRepo.makeVariantFlat(variant, sizeOPtion.ID, flat.ID, variantProduct.ID)
if err := importer.baza.Create(&variantFlat).Error; err != nil {
log.Println("Variant Flat Create Error: " + err.Error())
}
flat.Variants = append(flat.Variants, variantFlat)
}
}
calcPrice(flat.Variants, &flat)
importer.baza.Omit("ParentID", "CreatedAt", "Variants", "SpecialPrice").Save(&flat)
} else { //simple
importer.updatePrice(product.Price, &flat)
}
return flat.Product, nil
}
func (importer *Importer) UpdateOrCreateLCW(product models.Product) (instance *Importer){
var firstProduct gm.Product
result := importer.baza.First(&firstProduct,"sku=?",product.ProductNumber)
if errors.Is(result.Error, gorm.ErrRecordNotFound){
firstProduct, importer.Error = importer.importParsedVariant(product)
}else{
firstProduct, importer.Error = importer.updateParsedVariant(product)
}
var newProducts []gm.Product
if importer.Error != nil {
return importer
}else if &firstProduct != nil {
newProducts = append(newProducts, firstProduct)
}
if product.ColorVariants != nil && len(*product.ColorVariants) > 0 {
linkedProducts := []gm.Product{firstProduct}
for _, colorVariant := range *product.ColorVariants {
var (
variant *gm.Product
err error
)
if !colorVariant.IsSellable {
if err = importer.baza.Model(&gm.ProductFlat{}).Where("sku=?", colorVariant.ProductNumber).Update("status", false).Error; err != nil {
log.Println(err)
}
continue
} else {
//todo check parsed import variant
if variant, err = importer.importVariant(colorVariant); err != nil {
if variant, importer.Error = importer.updateVariant(colorVariant); importer.Error != nil {
return importer
}
linkedProducts = append(linkedProducts, *variant)
} else {
newProducts = append(newProducts, *variant)
}
}
}
if len(newProducts) > 0 {
// relation
var relation []gm.ProductRelation
for _, linkedProduct := range linkedProducts {
for _, newProd := range newProducts {
relation = append(relation, gm.ProductRelation{ParentID: linkedProduct.ID, ChildID: newProd.ID})
relation = append(relation, gm.ProductRelation{ParentID: newProd.ID, ChildID: linkedProduct.ID})
}
}
if err := importer.baza.Create(&relation).Error; err != nil {
log.Println(err)
}
}
}
return importer
}