internal static product Create(PriceItem item)
        {
            var result = new product
                             {
                                 active = Convert.ToInt32(item.Active),
                                 ean13 = item.Ean13,
                                 reference = item.Reference,
                                 supplier_reference = item.SupplierReference,
                                 price = Convert.ToDecimal(item.RetailPrice),
                                 wholesale_price = Convert.ToDecimal(item.WholesalePrice),
                                 show_price = 1,
                                 redirect_type = "404",
                                 id_shop_default = 1,
                                 available_for_order = 1,
                                 advanced_stock_management = 0,
                                 id_tax_rules_group = 1,
                                 minimal_quantity = 1,
                                 weight = !string.IsNullOrWhiteSpace(item.Weight) ? Convert.ToDecimal(item.Weight) : 0,
                                 associations = new AssociationsProduct(),
                                 name = new List<language> { new language(1, item.Name) },
                                 description = new List<language> { new language(1, item.Description) },
                                 description_short = new List<language> { new language(1, item.ShortDescription) }
                             };

            return result;
        }
 internal void FillOptions(PriceItem priceItem, product product)
 {
     foreach (var assort in priceItem.Assort)
     {
         GetOrCreateCombination(product, assort);
     }
 }
        internal category GetCategoryValue(PriceItem priceItem)
        {
            var filter = new Dictionary<string, string> { { "name", priceItem.Category } };

            var category = _apiFactory.CategoryFactory.GetByFilter(filter, null, null).FirstOrDefault();
            if (category == null)
            {
                throw new Exception(string.Format("Unknown category: {0}", priceItem.Category));
            }
            return category;
        }
 public void Update(product product, PriceItem item, PriceType processingPriceType)
 {
     _stockProcessor.UpdateStockValue(item, product);
     UpdateMetaInfo(item, product);
     if (processingPriceType == PriceType.Stock)
     {
         UpdateProductPriceAndActivity(item, product);
     }
     if (processingPriceType == PriceType.Discount)
     {
         UpdateDiscountInfo(item, product);
     }
 }
 internal void UpdateStockValue(PriceItem priceItem, product product)
 {
     foreach (var assort in priceItem.Assort)
     {
         var stock = GetStockValue(product, assort);
         if (stock.quantity != assort.Balance)
         {
             Log.Info("Balance changed from {0} to {1}. Reference: {2}", stock.quantity, assort.Balance, priceItem.Reference);
             stock.quantity = assort.Balance;
             _apiFactory.StockFactory.Update(stock);
         }
     }
 }
 private bool SameBalance(PriceItem item, PriceItem oldItem)
 {
     foreach (var assort in item.Assort)
     {
         var oldAssort = oldItem.Assort
             .FirstOrDefault(s => s.Size.Equals(assort.Size, StringComparison.OrdinalIgnoreCase) && 
                 s.Color.Equals(assort.Color, StringComparison.OrdinalIgnoreCase));
         
         if(oldAssort != null && oldAssort.Balance != assort.Balance)
         {
             return false;
         }
     }
     return true;
 }
 private void UpdateProductPriceAndActivity(PriceItem item, product product)
 {
     // price of onSale products is updated by special file
     if (product.on_sale == 0 &&
         (product.active != Convert.ToInt32(item.Active) ||
         product.price != Convert.ToDecimal(item.RetailPrice) || 
         product.wholesale_price != Convert.ToDecimal(item.WholesalePrice)))
     {
         product.active = Convert.ToInt32(item.Active);
         product.price = Convert.ToDecimal(item.RetailPrice);
         product.wholesale_price = Convert.ToDecimal(item.WholesalePrice);
         Log.Debug("Updating price. Reference: {0}", item.Reference);
         _apiFactory.ProductFactory.Update(product);
     }
 }
        internal manufacturer GetManufacturerValue(PriceItem priceItem, product product)
        {
            var filter = new Dictionary<string, string> { { "name", priceItem.Manufacturer } };
            var manufacturers = _apiFactory.ManufacturerFactory.GetByFilter(filter, null, null);

            if (manufacturers == null || !manufacturers.Any())
            {
                var manufacturer = new manufacturer
                {
                    name = priceItem.Manufacturer,
                    active = 1,
                };
                return _apiFactory.ManufacturerFactory.Add(manufacturer);
            }
            return manufacturers.First();
        }
        private void UpdateMetaInfo(PriceItem item, product product)
        {
            if (!SameMetaInfo(item, product))
            {
                product = ProductsMapper.FillMetaInfo(item, product);
				if (product.on_sale == 1) 
				{
					var specialPriceRule = GetSpecialPriceRule(product);
					if (specialPriceRule != null)
					{
						if (specialPriceRule.reduction_type != "percentage") 
						{
							throw new NotImplementedException();
						}

						product.price = product.price / specialPriceRule.reduction;
					}
				}
                Log.Debug("Updating meta info. Reference: {0}", item.Reference);
                _apiFactory.ProductFactory.Update(product);
            }
        }
        internal product_supplier GetProductSupplierValue(PriceItem priceItem, product product, supplier supplierFeature)
        {
            var filter = new Dictionary<string, string>
            {
                { "id_product", product.id.Value.ToString(CultureInfo.InvariantCulture) }
            };

            var supplier = _apiFactory.ProductSupplierFactory.GetByFilter(filter, null, null).FirstOrDefault();
            if (supplier == null)
            {
                supplier = new product_supplier
                {
                    id_currency = 1,
                    id_product = product.id,
                    id_product_attribute = 0,
                    id_supplier = supplierFeature.id,
                    product_supplier_reference = priceItem.SupplierReference,
                    product_supplier_price_te = Convert.ToDecimal(priceItem.WholesalePrice)
                };
                supplier = _apiFactory.ProductSupplierFactory.Add(supplier);
            }

            return supplier;
        }
        public void UpdateDiscountInfo(PriceItem item, product product)
        {
			specific_price specialPriceRule = null;

			if (product.on_sale == 1)
				specialPriceRule = GetSpecialPriceRule(product);

			if ((product.on_sale == 1 || item.OnSale) && product.on_sale != Convert.ToInt32(item.OnSale))
            {
                if (specialPriceRule != null)
                {
                    if (!item.OnSale && product.on_sale == 1)
                    {
                        // remove special price
                        Log.Info("Removing discount info. Reference: {0}", item.Reference);
                        _apiFactory.SpecialPriceFactory.Delete(specialPriceRule);
                    }
                    else
                    {
                        if (specialPriceRule.reduction != Convert.ToDecimal(item.DiscountValue) / 100)
                        {
                            specialPriceRule.reduction = Convert.ToDecimal(item.DiscountValue) / 100;
                            Log.Info("Updating reduction info. Reference: {0}", item.Reference);
                            _apiFactory.SpecialPriceFactory.Update(specialPriceRule);
                        }
                    }
                }
                else
                {
                    specialPriceRule = new specific_price
                    {
                        id_product = product.id,
                        reduction = Convert.ToDecimal(item.DiscountValue) / 100,
                        reduction_type = "percentage",
                        id_shop = 1,
                        id_cart = 0,
                        id_currency = 0,
                        id_country = 0,
                        id_group = 0,
                        id_customer = 0,
                        from_quantity = 1,
                        price = -1,
                    };
                    Log.Info("Adding discount price info. Reference: {0}", item.Reference);
                    _apiFactory.SpecialPriceFactory.Add(specialPriceRule);
                }
            }

			var productRetailPrice = Convert.ToDecimal(item.RetailPrice);
			if (specialPriceRule != null) 
			{
				productRetailPrice = Math.Ceiling(productRetailPrice * specialPriceRule.reduction);
			}

            if (product.on_sale != Convert.ToInt32(item.OnSale) ||
				product.price !=  productRetailPrice ||
                product.wholesale_price != Convert.ToDecimal(item.WholesalePrice))
            {
                product.on_sale = Convert.ToInt32(item.OnSale);
                product.price = Convert.ToDecimal(item.RetailPrice);
                product.wholesale_price = Convert.ToDecimal(item.WholesalePrice);
                Log.Debug("Updating discount info. Reference: {0}", item.Reference);
                _apiFactory.ProductFactory.Update(product);
            }
        }
        private bool SameMetaInfo(PriceItem priceItem, product product)
        {
            if (string.IsNullOrWhiteSpace(priceItem.Name))
                return true;

            if (product.meta_title == null ||
                !product.meta_title.Any() ||
                !product.meta_title[0].Value.Equals(priceItem.Name, StringComparison.OrdinalIgnoreCase))
                return false;

            if (product.meta_description == null ||
                !product.meta_description.Any() ||
                !product.meta_description[0].Value.Equals(string.Format("Купить {0} в Москве", priceItem.Name), StringComparison.OrdinalIgnoreCase))
                return false;

            if (product.meta_keywords == null ||
                !product.meta_keywords.Any())
                return false;


            if (!product.meta_keywords.Exists(s => s.Value.Equals(string.Format("Купить {0} в Москве", priceItem.Name), StringComparison.OrdinalIgnoreCase)))
                return false;

            return true;
        }
        internal void RemoveDiscountInfo(PriceItem item, product product)
        {
            var specialPriceRule = GetSpecialPriceRule(product);
            if(specialPriceRule != null)
            {
                Log.Info("Removing special price. Reference: {0}", item.Reference);
                _apiFactory.SpecialPriceFactory.Delete(specialPriceRule);
            }

            if (product.on_sale == 1)
            {
                product.on_sale = 0;
                product.price = Convert.ToDecimal(item.RetailPrice);
                Log.Debug("Removing discount. Reference: {0}", item.Reference);
                _apiFactory.ProductFactory.Update(product);
            }
        }
        public void Create(PriceItem priceItem)
        {
            if (string.IsNullOrWhiteSpace(priceItem.PhotoSmall) && (priceItem.Photos == null || !priceItem.Photos.Any()))
            {
                return;
            }

            var product = ProductsMapper.Create(priceItem);

            var category = _categoryProcessor.GetCategoryValue(priceItem);
            product = ProductsMapper.MapCategory(product, category);

            var supplier = _apiFactory.Suppliers.First(s => s.name.Equals(priceItem.SupplierName, StringComparison.CurrentCultureIgnoreCase));
            product = ProductsMapper.MapSupplier(product, supplier);

            var featureValue = _featureProcessor.GetFeatureValue(priceItem.Material, _apiFactory.MaterialFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            featureValue = _featureProcessor.GetFeatureValue(priceItem.Country, _apiFactory.CountryFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            featureValue = _featureProcessor.GetFeatureValue(priceItem.Packing, _apiFactory.PackingFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            featureValue = _featureProcessor.GetFeatureValue(priceItem.Length, _apiFactory.LengthFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            featureValue = _featureProcessor.GetFeatureValue(priceItem.Diameter, _apiFactory.DiameterFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            featureValue = _featureProcessor.GetFeatureValue(priceItem.Battery, _apiFactory.BatteryFeature);
            product = ProductsMapper.MapFeature(product, featureValue);

            var manufacturerValue = _manufacturerProcessor.GetManufacturerValue(priceItem, product);
            product = ProductsMapper.MapManufacturer(product, manufacturerValue);

            product = ProductsMapper.FillMetaInfo(priceItem, product);

            // Добавление продукта
            product = _apiFactory.ProductFactory.Add(product);

            if (priceItem.Photos == null || !priceItem.Photos.Any())
            {
                var image = _imageProcessor.GetImageValue(priceItem.PhotoSmall, product);
                product = ProductsMapper.MapImage(product, image);
            }
            else
            {
                foreach (var photo in priceItem.Photos)
                {
                    var image = _imageProcessor.GetImageValue(photo, product);
                    product = ProductsMapper.MapImage(product, image);
                }
            }

            if (product.associations.images == null || !product.associations.images.Any())
            {
                Log.Warn("Unable to load product photos. Product will be deleted. Product reference: {0}", priceItem.Reference);
                _apiFactory.ProductFactory.Delete(product.id.Value);
                Log.Debug("Product deleted. Reference: {0}", priceItem.Reference);
                throw new PhotoLoadException();
            }

            _supplierProcessor.GetProductSupplierValue(priceItem, product, supplier);

            _combinationsProcessor.FillOptions(priceItem, product);

            _stockProcessor.UpdateStockValue(priceItem, product);
        }
        internal static product FillMetaInfo(PriceItem priceItem, product product)
        {
            if (string.IsNullOrWhiteSpace(priceItem.Name))
                return product;

            product.meta_title = new List<language> { new language(1, priceItem.Name) };
            product.meta_description = new List<language> { new language(1, string.Format("Купить {0} в Москве", priceItem.Name)) };
            product.meta_keywords = new List<language>
            {
                new language(1, string.Format("Купить {0} в Москве", priceItem.Name))
            };
            return product;
        }
        public float Build(PriceItem priceItem)
        {
            float result;
            var elements = _multiplicators.Cast<MultiplicatorRuleElement>().ToList();
            
            var referenceElement = elements.FirstOrDefault(e => e.ProductReference.Equals(priceItem.Reference, StringComparison.OrdinalIgnoreCase));
            if(referenceElement != null)
            {
                // 0 means leave supplier recommended price
                if (referenceElement.Value == 0)
                {
                    result = priceItem.RetailPrice;
                }
                else
                {
                    result = priceItem.WholesalePrice * referenceElement.Value;
                }                
            }
            else
            {
                var categoryElement = elements.FirstOrDefault(e => e.Category.Equals(priceItem.Category, StringComparison.OrdinalIgnoreCase) || e.Category.Equals(priceItem.RootCategory, StringComparison.OrdinalIgnoreCase));
                if (categoryElement != null)
                {
                    // 0 means leave supplier recommended price
                    if (categoryElement.Value == 0)
                    {
                        result = priceItem.RetailPrice;
                    }
                    else
                    {
                        result = priceItem.WholesalePrice * categoryElement.Value;
                    }
                    
                }
                else
                {
                    var minMaxPriceElement = elements.FirstOrDefault(e => e.MinPrice <= priceItem.WholesalePrice && priceItem.WholesalePrice <= e.MaxPrice);
                    if (minMaxPriceElement != null)
                    {
                        // 0 means leave supplier recommended price
                        if (minMaxPriceElement.Value == 0)
                        {
                            result = priceItem.RetailPrice;
                        }
                        else
                        {
                            result = priceItem.WholesalePrice * minMaxPriceElement.Value;
                        }
                    }
                    else
                    {
                        // 0 means leave supplier recommended price
                        if (_multiplicators.Default == 0)
                        {
                            result = priceItem.RetailPrice;
                        }
                        else
                        {
                            result = priceItem.WholesalePrice * _multiplicators.Default;
                        }                        
                    }
                }
            }

            result = (float)Math.Ceiling(result);
            return result;
        }