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); } }
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); } } }
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); } } }
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); } }