Пример #1
0
        public void StartCreatingFeeds(Func <FeedFileCreationContext, bool> createFeed, string secondFileName = null)
        {
            try
            {
                using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, forceNoTracking: true))
                {
                    _cachedPathes     = null;
                    _cachedCategories = null;

                    var storeService = _ctx.Resolve <IStoreService>();
                    var stores       = new List <Store>();

                    if (BaseSettings.StoreId != 0)
                    {
                        var storeById = storeService.GetStoreById(BaseSettings.StoreId);
                        if (storeById != null)
                        {
                            stores.Add(storeById);
                        }
                    }

                    if (stores.Count == 0)
                    {
                        stores.AddRange(storeService.GetAllStores());
                    }

                    var context = new FeedFileCreationContext()
                    {
                        StoreCount = stores.Count,
                        Progress   = new Progress <FeedFileCreationProgress>(x =>
                        {
                            AsyncState.Current.Set(x, SystemName);
                        })
                    };

                    foreach (var store in stores)
                    {
                        var feedFile = GetFeedFileByStore(store, secondFileName);
                        if (feedFile != null)
                        {
                            FileSystemHelper.Delete(feedFile.FileTempPath);

                            if (secondFileName.HasValue())
                            {
                                FileSystemHelper.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string);
                            }

                            using (var stream = new FileStream(feedFile.FileTempPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                                using (var logger = new TraceLogger(feedFile.LogPath))
                                {
                                    context.Stream      = stream;
                                    context.Logger      = logger;
                                    context.Store       = store;
                                    context.FeedFileUrl = feedFile.FileUrl;

                                    if (secondFileName.HasValue())
                                    {
                                        context.SecondFilePath = feedFile.CustomProperties["SecondFileTempPath"] as string;
                                    }

                                    if (!createFeed(context))
                                    {
                                        break;
                                    }
                                }

                            FileSystemHelper.Copy(feedFile.FileTempPath, feedFile.FilePath);

                            if (secondFileName.HasValue())
                            {
                                FileSystemHelper.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string);
                            }
                        }
                    }
                }
            }
            finally
            {
                AsyncState.Current.Remove <FeedFileCreationProgress>(SystemName);
            }
        }
Пример #2
0
        private void WriteItem(FeedFileCreationContext fileCreation, XmlWriter writer, Product product, Currency currency, string measureWeightSystemKey)
        {
            GoogleProductRecord googleProduct = null;

            try
            {
                googleProduct = GetGoogleProductRecord(product.Id);

                if (googleProduct != null && !googleProduct.Export)
                    return;
            }
            catch (Exception exc)
            {
                fileCreation.Logger.Error(exc.Message, exc);
            }

            writer.WriteStartElement("item");

            try
            {
                var manu = _manufacturerService.GetProductManufacturersByProductId(product.Id).FirstOrDefault();
                var mainImageUrl = Helper.GetMainProductImageUrl(fileCreation.Store, product);
                var category = ProductCategory(googleProduct);

                if (category.IsEmpty())
                    fileCreation.ErrorMessage = Helper.GetResource("MissingDefaultCategory");

                string manuName = (manu != null ? manu.Manufacturer.GetLocalized(x => x.Name, Settings.LanguageId, true, false) : null);
                string productName = product.GetLocalized(x => x.Name, Settings.LanguageId, true, false);
                string shortDescription = product.GetLocalized(x => x.ShortDescription, Settings.LanguageId, true, false);
                string fullDescription = product.GetLocalized(x => x.FullDescription, Settings.LanguageId, true, false);

                var brand = (manuName ?? Settings.Brand);
                var mpn = Helper.GetManufacturerPartNumber(product);

                bool identifierExists = product.Gtin.HasValue() || brand.HasValue() || mpn.HasValue();

                writer.WriteElementString("g", "id", _googleNamespace, product.Id.ToString());

                writer.WriteStartElement("title");
                writer.WriteCData(productName.Truncate(70));
                writer.WriteEndElement();

                var description = Helper.BuildProductDescription(productName, shortDescription, fullDescription, manuName, d =>
                {
                    if (fullDescription.IsEmpty() && shortDescription.IsEmpty())
                    {
                        var rnd = new Random();

                        switch (rnd.Next(1, 5))
                        {
                            case 1: return d.Grow(Settings.AppendDescriptionText1, " ");
                            case 2: return d.Grow(Settings.AppendDescriptionText2, " ");
                            case 3: return d.Grow(Settings.AppendDescriptionText3, " ");
                            case 4: return d.Grow(Settings.AppendDescriptionText4, " ");
                            case 5: return d.Grow(Settings.AppendDescriptionText5, " ");
                        }
                    }
                    return d;
                });

                writer.WriteStartElement("description");
                writer.WriteCData(description.RemoveInvalidXmlChars());
                writer.WriteEndElement();

                writer.WriteStartElement("g", "google_product_category", _googleNamespace);
                writer.WriteCData(category);
                writer.WriteFullEndElement();

                string productType = Helper.GetCategoryPath(product);
                if (productType.HasValue())
                {
                    writer.WriteStartElement("g", "product_type", _googleNamespace);
                    writer.WriteCData(productType);
                    writer.WriteFullEndElement();
                }

                writer.WriteElementString("link", Helper.GetProductDetailUrl(fileCreation.Store, product));
                writer.WriteElementString("g", "image_link", _googleNamespace, mainImageUrl);

                foreach (string additionalImageUrl in Helper.GetAdditionalProductImages(fileCreation.Store, product, mainImageUrl))
                {
                    writer.WriteElementString("g", "additional_image_link", _googleNamespace, additionalImageUrl);
                }

                writer.WriteElementString("g", "condition", _googleNamespace, Condition());
                writer.WriteElementString("g", "availability", _googleNamespace, Availability(product));

                decimal price = Helper.GetProductPrice(product, currency, fileCreation.Store);
                string specialPriceDate;

                if (SpecialPrice(product, out specialPriceDate))
                {
                    writer.WriteElementString("g", "sale_price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode);
                    writer.WriteElementString("g", "sale_price_effective_date", _googleNamespace, specialPriceDate);

                    // get regular price ignoring any special price
                    decimal specialPrice = product.SpecialPrice.Value;
                    product.SpecialPrice = null;
                    price = Helper.GetProductPrice(product, currency, fileCreation.Store);
                    product.SpecialPrice = specialPrice;

                    _dbContext.SetToUnchanged<Product>(product);
                }

                writer.WriteElementString("g", "price", _googleNamespace, price.FormatInvariant() + " " + currency.CurrencyCode);

                writer.WriteCData("gtin", product.Gtin, "g", _googleNamespace);
                writer.WriteCData("brand", brand, "g", _googleNamespace);
                writer.WriteCData("mpn", mpn, "g", _googleNamespace);

                writer.WriteCData("gender", Gender(googleProduct), "g", _googleNamespace);
                writer.WriteCData("age_group", AgeGroup(googleProduct), "g", _googleNamespace);
                writer.WriteCData("color", Color(googleProduct), "g", _googleNamespace);
                writer.WriteCData("size", Size(googleProduct), "g", _googleNamespace);
                writer.WriteCData("material", Material(googleProduct), "g", _googleNamespace);
                writer.WriteCData("pattern", Pattern(googleProduct), "g", _googleNamespace);
                writer.WriteCData("item_group_id", ItemGroupId(googleProduct), "g", _googleNamespace);

                writer.WriteElementString("g", "online_only", _googleNamespace, Settings.OnlineOnly ? "y" : "n");
                writer.WriteElementString("g", "identifier_exists", _googleNamespace, identifierExists ? "TRUE" : "FALSE");

                if (Settings.ExpirationDays > 0)
                {
                    writer.WriteElementString("g", "expiration_date", _googleNamespace, DateTime.UtcNow.AddDays(Settings.ExpirationDays).ToString("yyyy-MM-dd"));
                }

                if (Settings.ExportShipping)
                {
                    string weightInfo, weight = product.Weight.FormatInvariant();

                    if (measureWeightSystemKey.IsCaseInsensitiveEqual("gram"))
                        weightInfo = weight + " g";
                    else if (measureWeightSystemKey.IsCaseInsensitiveEqual("lb"))
                        weightInfo = weight + " lb";
                    else if (measureWeightSystemKey.IsCaseInsensitiveEqual("ounce"))
                        weightInfo = weight + " oz";
                    else
                        weightInfo = weight + " kg";

                    writer.WriteElementString("g", "shipping_weight", _googleNamespace, weightInfo);
                }

                if (Settings.ExportBasePrice && product.BasePriceHasValue)
                {
                    string measureUnit = BasePriceUnits(product.BasePriceMeasureUnit);

                    if (BasePriceSupported(product.BasePriceBaseAmount ?? 0, measureUnit))
                    {
                        string basePriceMeasure = "{0} {1}".FormatWith((product.BasePriceAmount ?? decimal.Zero).FormatInvariant(), measureUnit);
                        string basePriceBaseMeasure = "{0} {1}".FormatWith(product.BasePriceBaseAmount, measureUnit);

                        writer.WriteElementString("g", "unit_pricing_measure", _googleNamespace, basePriceMeasure);
                        writer.WriteElementString("g", "unit_pricing_base_measure", _googleNamespace, basePriceBaseMeasure);
                    }
                }
            }
            catch (Exception exc)
            {
                fileCreation.Logger.Error(exc.Message, exc);
            }

            writer.WriteEndElement(); // item
        }
        private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionContext taskContext)
        {
            var xmlSettings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CheckCharacters = false
            };

            using (var writer = XmlWriter.Create(fileCreation.Stream, xmlSettings))
            {
                try
                {
                    fileCreation.Logger.Information("Log file - Google Merchant Center feed.");

                    var searchContext = new ProductSearchContext()
                    {
                        OrderBy = ProductSortingEnum.CreatedOn,
                        PageSize = int.MaxValue,
                        StoreId = fileCreation.Store.Id,
                        VisibleIndividuallyOnly = true
                    };

                    string breakingError = null;
                    var qualifiedProducts = new List<Product>();
                    var currency = Helper.GetUsedCurrency(Settings.CurrencyId);
                    var products = _productService.SearchProducts(searchContext);
                    var measureWeightSystemKey = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword;

                    if (fileCreation.TotalRecords == 0)
                        fileCreation.TotalRecords = products.Count * fileCreation.StoreCount;

                    writer.WriteStartDocument();
                    writer.WriteStartElement("rss");
                    writer.WriteAttributeString("version", "2.0");
                    writer.WriteAttributeString("xmlns", "g", null, _googleNamespace);
                    writer.WriteStartElement("channel");
                    writer.WriteElementString("title", "{0} - Feed for Google Merchant Center".FormatWith(fileCreation.Store.Name));
                    writer.WriteElementString("link", "http://base.google.com/base/");
                    writer.WriteElementString("description", "Information about products");

                    foreach (var product in products)
                    {
                        fileCreation.Report();

                        Helper.GetQualifiedProductsByProduct(product, fileCreation.Store, qualifiedProducts);

                        foreach (var qualifiedProduct in qualifiedProducts)
                        {
                            writer.WriteStartElement("item");

                            try
                            {
                                breakingError = WriteItem(writer, fileCreation.Store, qualifiedProduct, currency, measureWeightSystemKey);
                            }
                            catch (Exception exc)
                            {
                                fileCreation.Logger.Error(exc.Message, exc);
                            }

                            writer.WriteEndElement(); // item
                        }

                        if (breakingError.HasValue())
                        {
                            fileCreation.Logger.Error(breakingError);
                            break;
                        }
                        if (taskContext.CancellationToken.IsCancellationRequested)
                        {
                            fileCreation.Logger.Warning("A cancellation has been requested");
                            break;
                        }
                    }

                    writer.WriteEndElement(); // channel
                    writer.WriteEndElement(); // rss
                    writer.WriteEndDocument();

                    if (breakingError.HasValue())
                        throw new SmartException(breakingError);
                }
                catch (Exception exc)
                {
                    fileCreation.Logger.Error(exc.Message, exc);
                }
            }
        }
Пример #4
0
        private void CreateFeed(FeedFileCreationContext fileCreation, TaskExecutionContext taskContext)
        {
            var xmlSettings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CheckCharacters = false
            };

            using (var writer = XmlWriter.Create(fileCreation.Stream, xmlSettings))
            {
                try
                {
                    fileCreation.Logger.Information("Log file - Google Merchant Center feed.");

                    var searchContext = new ProductSearchContext
                    {
                        OrderBy = ProductSortingEnum.CreatedOn,
                        PageSize = Settings.PageSize,
                        StoreId = fileCreation.Store.Id,
                        VisibleIndividuallyOnly = true
                    };

                    var currency = _currencyService.GetCurrencyById(Settings.CurrencyId);
                    var measureWeightSystemKey = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword;

                    if (currency == null || !currency.Published)
                        currency = _services.WorkContext.WorkingCurrency;

                    writer.WriteStartDocument();
                    writer.WriteStartElement("rss");
                    writer.WriteAttributeString("version", "2.0");
                    writer.WriteAttributeString("xmlns", "g", null, _googleNamespace);
                    writer.WriteStartElement("channel");
                    writer.WriteElementString("title", "{0} - Feed for Google Merchant Center".FormatWith(fileCreation.Store.Name));
                    writer.WriteElementString("link", "http://base.google.com/base/");
                    writer.WriteElementString("description", "Information about products");

                    for (int i = 0; i < 9999999; ++i)
                    {
                        searchContext.PageIndex = i;

                        // Perf
                        _dbContext.DetachAll();

                        var products = _productService.SearchProducts(searchContext);

                        if (fileCreation.TotalRecords == 0)
                            fileCreation.TotalRecords = products.TotalCount * fileCreation.StoreCount;	// approx

                        foreach (var product in products)
                        {
                            fileCreation.Report();

                            if (product.ProductType == ProductType.SimpleProduct || product.ProductType == ProductType.BundledProduct)
                            {
                                WriteItem(fileCreation, writer, product, currency, measureWeightSystemKey);
                            }
                            else if (product.ProductType == ProductType.GroupedProduct)
                            {
                                var associatedSearchContext = new ProductSearchContext
                                {
                                    OrderBy = ProductSortingEnum.CreatedOn,
                                    PageSize = int.MaxValue,
                                    StoreId = fileCreation.Store.Id,
                                    VisibleIndividuallyOnly = false,
                                    ParentGroupedProductId = product.Id
                                };

                                foreach (var associatedProduct in _productService.SearchProducts(associatedSearchContext))
                                {
                                    WriteItem(fileCreation, writer, associatedProduct, currency, measureWeightSystemKey);
                                }
                            }

                            if (taskContext.CancellationToken.IsCancellationRequested)
                            {
                                fileCreation.Logger.Warning("A cancellation has been requested");
                                break;
                            }
                        }

                        if (!products.HasNextPage || taskContext.CancellationToken.IsCancellationRequested)
                            break;
                    }

                    writer.WriteEndElement(); // channel
                    writer.WriteEndElement(); // rss
                    writer.WriteEndDocument();

                    if (fileCreation.ErrorMessage.HasValue())
                        fileCreation.Logger.Error(fileCreation.ErrorMessage);
                }
                catch (Exception exc)
                {
                    fileCreation.Logger.Error(exc.Message, exc);
                }
            }
        }
Пример #5
0
        public void StartCreatingFeeds(Func<FeedFileCreationContext, bool> createFeed, string secondFileName = null)
        {
            try
            {
                using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, forceNoTracking: true))
                {
                    _cachedPathes = null;
                    _cachedCategories = null;

                    var storeService = _ctx.Resolve<IStoreService>();
                    var stores = new List<Store>();

                    if (BaseSettings.StoreId != 0)
                    {
                        var storeById = storeService.GetStoreById(BaseSettings.StoreId);
                        if (storeById != null)
                            stores.Add(storeById);
                    }

                    if (stores.Count == 0)
                    {
                        stores.AddRange(storeService.GetAllStores());
                    }

                    var context = new FeedFileCreationContext
                    {
                        StoreCount = stores.Count,
                        Progress = new Progress<FeedFileCreationProgress>(x =>
                        {
                            AsyncState.Current.Set(x, SystemName);
                        })
                    };

                    foreach (var store in stores)
                    {
                        var feedFile = GetFeedFileByStore(store, secondFileName);
                        if (feedFile != null)
                        {
                            FileSystemHelper.Delete(feedFile.FileTempPath);

                            if (secondFileName.HasValue())
                                FileSystemHelper.Delete(feedFile.CustomProperties["SecondFileTempPath"] as string);

                            using (var stream = new FileStream(feedFile.FileTempPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                            using (var logger = new TraceLogger(feedFile.LogPath))
                            {
                                context.Stream = stream;
                                context.Logger = logger;
                                context.Store = store;
                                context.FeedFileUrl = feedFile.FileUrl;

                                if (secondFileName.HasValue())
                                    context.SecondFilePath = feedFile.CustomProperties["SecondFileTempPath"] as string;

                                if (!createFeed(context))
                                    break;
                            }

                            FileSystemHelper.Copy(feedFile.FileTempPath, feedFile.FilePath);

                            if (secondFileName.HasValue())
                                FileSystemHelper.Copy(context.SecondFilePath, feedFile.CustomProperties["SecondFilePath"] as string);
                        }
                    }
                }
            }
            finally
            {
                AsyncState.Current.Remove<FeedFileCreationProgress>(SystemName);
            }
        }