private void SaveProduct(coreModel.Catalog catalog, FulfillmentCenter defaultFulfillmentCenter, CsvProduct csvProduct)
        {
            var defaultLanguge = catalog.DefaultLanguage != null ? catalog.DefaultLanguage.LanguageCode : "EN-US";

            coreModel.CatalogProduct alreadyExistProduct = null;
            //For new product try to find them by code
            if (csvProduct.IsTransient() && !String.IsNullOrEmpty(csvProduct.Code))
            {
                var criteria = new SearchCriteria
                {
                    CatalogId     = catalog.Id,
                    CategoryId    = csvProduct.CategoryId,
                    Code          = csvProduct.Code,
                    ResponseGroup = SearchResponseGroup.WithProducts | SearchResponseGroup.WithVariations
                };
                var result = _searchService.Search(criteria);
                alreadyExistProduct = result.Products.FirstOrDefault();
                csvProduct.Id       = alreadyExistProduct != null ? alreadyExistProduct.Id : csvProduct.Id;
            }
            else if (!csvProduct.IsTransient())
            {
                //If id specified need check that product really exist
                alreadyExistProduct = _productService.GetById(csvProduct.Id, ItemResponseGroup.ItemInfo);
            }
            var isNewProduct = alreadyExistProduct == null;

            csvProduct.CatalogId = catalog.Id;

            if (String.IsNullOrEmpty(csvProduct.Code))
            {
                csvProduct.Code = _skuGenerator.GenerateSku(csvProduct);
            }
            //Set a parent relations
            if (csvProduct.MainProductId == null && csvProduct.MainProduct != null)
            {
                csvProduct.MainProductId = csvProduct.MainProduct.Id;
            }
            csvProduct.EditorialReview.LanguageCode = defaultLanguge;
            csvProduct.SeoInfo.LanguageCode         = defaultLanguge;
            csvProduct.SeoInfo.SemanticUrl          = String.IsNullOrEmpty(csvProduct.SeoInfo.SemanticUrl) ? csvProduct.Code : csvProduct.SeoInfo.SemanticUrl;

            var properties = !String.IsNullOrEmpty(csvProduct.CategoryId) ? _categoryService.GetById(csvProduct.CategoryId, CategoryResponseGroup.WithProperties).Properties : _catalogService.GetById(csvProduct.CatalogId).Properties;

            if (csvProduct.PropertyValues != null)
            {
                //Try to fill properties meta information for values
                foreach (var propertyValue in csvProduct.PropertyValues)
                {
                    if (propertyValue.Value != null)
                    {
                        var property = properties.FirstOrDefault(x => String.Equals(x.Name, propertyValue.PropertyName));
                        if (property != null)
                        {
                            propertyValue.ValueType = property.ValueType;
                            if (property.Dictionary)
                            {
                                property = _propertyService.GetById(property.Id);
                                var dicValue = property.DictionaryValues.FirstOrDefault(x => String.Equals(x.Value, propertyValue.Value));
                                propertyValue.ValueId = dicValue != null ? dicValue.Id : null;
                            }
                        }
                    }
                }
            }

            if (!isNewProduct)
            {
                _productService.Update(new coreModel.CatalogProduct[] { csvProduct });
            }
            else
            {
                var newProduct = _productService.Create(csvProduct);
                csvProduct.Id = newProduct.Id;
            }

            //Create price in default price list

            if (csvProduct.Price.EffectiveValue > 0)
            {
                csvProduct.Price.ProductId = csvProduct.Id;

                if (csvProduct.Price.IsTransient() || _pricingService.GetPriceById(csvProduct.Price.Id) == null)
                {
                    _pricingService.CreatePrice(csvProduct.Price);
                }
                else
                {
                    _pricingService.UpdatePrices(new Price[] { csvProduct.Price });
                }
            }

            //Create inventory
            csvProduct.Inventory.ProductId           = csvProduct.Id;
            csvProduct.Inventory.FulfillmentCenterId = csvProduct.Inventory.FulfillmentCenterId ?? defaultFulfillmentCenter.Id;
            _inventoryService.UpsertInventory(csvProduct.Inventory);
        }
        private void SaveProducts(VirtoData virtoData, ShopifyImportParams importParams, ShopifyImportNotification notification)
        {
            var productProgress = notification.Progresses[ProductsKey];

            if (importParams.ImportCollections)
            {
                //Update categories references
                foreach (var product in virtoData.Products)
                {
                    if (product.Category != null)
                    {
                        product.Category   = virtoData.Categories.First(category => category.Code == product.Category.Code);
                        product.CategoryId = product.Category.Id;
                    }
                }
            }

            notification.Description = "Checking existing products";
            _notifier.Upsert(notification);


            notification.Description = "Saving products";
            _notifier.Upsert(notification);

            var productsToCreate = new List <coreModel.CatalogProduct>();
            var productsToUpdate = new List <coreModel.CatalogProduct>();

            foreach (var product in virtoData.Products)
            {
                var existingProduct = _searchService.Search(new coreModel.SearchCriteria()
                {
                    CatalogId        = importParams.VirtoCatalogId,
                    GetAllCategories = true,
                    ResponseGroup    = coreModel.ResponseGroup.WithProducts,
                    Count            = int.MaxValue,
                    Code             = product.Code
                }).Products.FirstOrDefault();

                if (existingProduct != null)
                {
                    product.Id = existingProduct.Id;
                    productsToUpdate.Add(product);
                }
                else
                {
                    productsToCreate.Add(product);
                }
            }

            foreach (var product in productsToCreate)
            {
                try
                {
                    _productService.Create(product);

                    //Create price in default price list
                    if (product.Prices != null && product.Prices.Any())
                    {
                        var price = product.Prices.First();
                        price.ProductId = product.Id;
                        _pricingService.CreatePrice(price);
                    }
                }
                catch (Exception ex)
                {
                    productProgress.ErrorCount++;
                    notification.ErrorCount++;
                    notification.Errors.Add(ex.ToString());
                    _notifier.Upsert(notification);
                }
                finally
                {
                    //Raise notification each notifyProductSizeLimit category

                    productProgress.ProcessedCount++;
                    notification.Description = string.Format("Creating products: {0} of {1} created",
                                                             productProgress.ProcessedCount, productProgress.TotalCount);
                    if (productProgress.ProcessedCount % NotifySizeLimit == 0 || productProgress.ProcessedCount + productProgress.ErrorCount == productProgress.TotalCount)
                    {
                        _notifier.Upsert(notification);
                    }
                }
            }


            if (productsToUpdate.Count > 0)
            {
                try
                {
                    _productService.Update(productsToUpdate.ToArray());
                }
                catch (Exception ex)
                {
                    productProgress.ErrorCount++;
                    notification.ErrorCount++;
                    notification.Errors.Add(ex.ToString());
                    _notifier.Upsert(notification);
                }
                finally
                {
                    notification.Description = string.Format("Updating products: {0} updated",
                                                             productProgress.ProcessedCount = productProgress.ProcessedCount + productsToUpdate.Count);
                    _notifier.Upsert(notification);
                }
            }

            virtoData.Products.Clear();
            virtoData.Products.AddRange(productsToCreate);
            virtoData.Products.AddRange(productsToUpdate);
        }
        private void SaveProducts(VirtoData virtoData, ShopifyImportParams importParams, ShopifyImportNotification notification)
        {
            var productProgress = notification.Progresses[ProductsKey];

            if (importParams.ImportCollections)
            {
                //Update categories references
                foreach (var product in virtoData.Products)
                {
                    if (product.Category != null)
                    {
                        product.Category   = virtoData.Categories.First(category => category.Code == product.Category.Code);
                        product.CategoryId = product.Category.Id;
                    }
                }
            }

            notification.Description = "Checking existing products";
            _notifier.Upsert(notification);


            notification.Description = "Saving products";
            _notifier.Upsert(notification);

            var productsToCreate = new List <coreModel.CatalogProduct>();
            var productsToUpdate = new List <coreModel.CatalogProduct>();

            var alreadyExistProducts = _productService.GetByIds(virtoData.Products.Select(x => x.Id).Where(x => x != null).ToArray(), coreModel.ItemResponseGroup.ItemInfo);

            foreach (var product in virtoData.Products)
            {
                if (alreadyExistProducts.Any(x => x.Id == product.Id))
                {
                    productsToUpdate.Add(product);
                }
                else
                {
                    productsToCreate.Add(product);
                }
            }

            foreach (var product in productsToCreate)
            {
                try
                {
                    _productService.Create(product);

                    //Create price in default price list
                    if (product.Prices != null && product.Prices.Any())
                    {
                        var price = product.Prices.First();
                        price.ProductId = product.Id;
                        _pricingService.CreatePrice(price);
                    }
                }
                catch (Exception ex)
                {
                    productProgress.ErrorCount++;
                    notification.ErrorCount++;
                    notification.Errors.Add(ex.ToString());
                    _notifier.Upsert(notification);
                }
                finally
                {
                    //Raise notification each notifyProductSizeLimit category

                    productProgress.ProcessedCount++;
                    notification.Description = string.Format("Creating products: {0} of {1} created",
                                                             productProgress.ProcessedCount, productProgress.TotalCount);
                    if (productProgress.ProcessedCount % NotifySizeLimit == 0 || productProgress.ProcessedCount + productProgress.ErrorCount == productProgress.TotalCount)
                    {
                        _notifier.Upsert(notification);
                    }
                }
            }


            if (productsToUpdate.Count > 0)
            {
                try
                {
                    _productService.Update(productsToUpdate.ToArray());
                }
                catch (Exception ex)
                {
                    productProgress.ErrorCount++;
                    notification.ErrorCount++;
                    notification.Errors.Add(ex.ToString());
                    _notifier.Upsert(notification);
                }
                finally
                {
                    notification.Description = string.Format("Updating products: {0} updated",
                                                             productProgress.ProcessedCount = productProgress.ProcessedCount + productsToUpdate.Count);
                    _notifier.Upsert(notification);
                }
            }

            virtoData.Products.Clear();
            virtoData.Products.AddRange(productsToCreate);
            virtoData.Products.AddRange(productsToUpdate);
        }