private static dynamic ToDynamic(Manufacturer manufacturer, DataExporterContext ctx) { if (manufacturer == null) { return(null); } dynamic result = new DynamicEntity(manufacturer); result.Picture = null; result.Name = ctx.GetTranslation(manufacturer, nameof(manufacturer.Name), manufacturer.Name); if (!ctx.IsPreview) { result.SeName = ctx.GetUrlRecord(manufacturer); result.Description = ctx.GetTranslation(manufacturer, nameof(manufacturer.Description), manufacturer.Description); result.BottomDescription = ctx.GetTranslation(manufacturer, nameof(manufacturer.BottomDescription), manufacturer.BottomDescription); result.MetaKeywords = ctx.GetTranslation(manufacturer, nameof(manufacturer.MetaKeywords), manufacturer.MetaKeywords); result.MetaDescription = ctx.GetTranslation(manufacturer, nameof(manufacturer.MetaDescription), manufacturer.MetaDescription); result.MetaTitle = ctx.GetTranslation(manufacturer, nameof(manufacturer.MetaTitle), manufacturer.MetaTitle); result._Localized = GetLocalized(ctx, manufacturer, x => x.Name, x => x.Description, x => x.BottomDescription, x => x.MetaKeywords, x => x.MetaDescription, x => x.MetaTitle); } return(result); }
private static dynamic ToDynamic(Address address, DataExporterContext ctx) { if (address == null) { return(null); } dynamic result = new DynamicEntity(address); result.Country = ToDynamic(address.Country, ctx); if (address.StateProvinceId.GetValueOrDefault() > 0) { dynamic sp = new DynamicEntity(address.StateProvince); sp.Name = ctx.GetTranslation(address.StateProvince, nameof(address.StateProvince.Name), address.StateProvince.Name); sp._Localized = GetLocalized(ctx, address.StateProvince, x => x.Name); result.StateProvince = sp; } else { result.StateProvince = null; } return(result); }
private async Task <dynamic> ToDynamic(Order order, DataExporterContext ctx) { if (order == null) { return(null); } dynamic result = new DynamicEntity(order); result.OrderNumber = order.GetOrderNumber(); result.OrderStatus = await _services.Localization.GetLocalizedEnumAsync(order.OrderStatus, ctx.LanguageId); result.PaymentStatus = await _services.Localization.GetLocalizedEnumAsync(order.PaymentStatus, ctx.LanguageId); result.ShippingStatus = await _services.Localization.GetLocalizedEnumAsync(order.ShippingStatus, ctx.LanguageId); result.Customer = null; result.BillingAddress = null; result.ShippingAddress = null; result.Shipments = null; result.Store = ctx.Stores.ContainsKey(order.StoreId) ? ToDynamic(ctx.Stores[order.StoreId], ctx) : null; if (!ctx.IsPreview) { result.RedeemedRewardPointsEntry = CreateDynamic(order.RedeemedRewardPointsEntry); } return(result); }
public async Task <DataExportResult> ExportAsync(DataExportRequest request, CancellationToken cancellationToken) { var ctx = new DataExporterContext(request, false, cancellationToken); if (request?.Profile?.Enabled ?? false) { var lockKey = $"dataexporter:profile:{request.Profile.Id}"; if (!AsyncLock.IsLockHeld(lockKey)) { using (await AsyncLock.KeyedAsync(lockKey, cancellationToken: cancellationToken)) { // TODO: (mg) (core) start to export in ExportAsync. //await ExportCoreOuterAsync(ctx); } cancellationToken.ThrowIfCancellationRequested(); } else { ctx.Result.LastError = $"The execution of the profile \"{request.Profile.Name.NaIfEmpty()}\" (ID {request.Profile.Id}) is locked."; } } return(ctx.Result); }
private static dynamic ToDynamic(Store store, DataExporterContext ctx) { if (store == null) { return(null); } dynamic result = new DynamicEntity(store); result.PrimaryStoreCurrency = ToDynamic(store.PrimaryStoreCurrency, ctx); result.PrimaryExchangeRateCurrency = ToDynamic(store.PrimaryExchangeRateCurrency, ctx); return(result); }
private static dynamic ToDynamic(DeliveryTime deliveryTime, DataExporterContext ctx) { if (deliveryTime == null) { return(null); } dynamic result = new DynamicEntity(deliveryTime); result.Name = ctx.GetTranslation(deliveryTime, nameof(deliveryTime.Name), deliveryTime.Name); result._Localized = GetLocalized(ctx, deliveryTime, x => x.Name); return(result); }
private static dynamic ToDynamic(Country country, DataExporterContext ctx) { if (country == null) { return(null); } dynamic result = new DynamicEntity(country); result.Name = ctx.GetTranslation(country, nameof(country.Name), country.Name); result._Localized = GetLocalized(ctx, country, x => x.Name); return(result); }
private static dynamic ToDynamic(NewsletterSubscription subscription, DataExporterContext ctx) { if (subscription == null) { return(null); } dynamic result = new DynamicEntity(subscription); result.Store = ctx.Stores.ContainsKey(subscription.StoreId) ? ToDynamic(ctx.Stores[subscription.StoreId], ctx) : null; return(result); }
private async Task <dynamic> ToDynamic(OrderItem orderItem, DataExporterContext ctx) { if (orderItem == null) { return(null); } await _productAttributeMaterializer.MergeWithCombinationAsync(orderItem.Product, orderItem.AttributeSelection); dynamic result = new DynamicEntity(orderItem); result.Product = ToDynamic(orderItem.Product, ctx); return(result); }
private async Task <IEnumerable <dynamic> > Convert(Customer customer, DataExporterContext ctx) { var result = new List <dynamic>(); var genericAttributes = await ctx.CustomerBatchContext.GenericAttributes.GetOrLoadAsync(customer.Id); dynamic dynObject = ToDynamic(customer); dynObject.BillingAddress = ToDynamic(customer.BillingAddress, ctx); dynObject.ShippingAddress = ToDynamic(customer.ShippingAddress, ctx); dynObject.Addresses = customer.Addresses .Select(x => ToDynamic(x, ctx)) .ToList(); dynObject._GenericAttributes = genericAttributes .Select(x => CreateDynamic(x)) .ToList(); dynObject._HasNewsletterSubscription = ctx.NewsletterSubscriptions.Contains(customer.Email, StringComparer.CurrentCultureIgnoreCase); dynObject._FullName = customer.GetFullName(); dynObject._AvatarPictureUrl = null; if (_customerSettings.AllowCustomersToUploadAvatars) { // Reduce traffic and do not export default avatar. var fileId = genericAttributes.FirstOrDefault(x => x.Key == SystemCustomerAttributeNames.AvatarPictureId)?.Value?.ToInt() ?? 0; var file = await _mediaService.GetFileByIdAsync(fileId, MediaLoadFlags.AsNoTracking); if (file != null) { dynObject._AvatarPictureUrl = _mediaService.GetUrl(file, new ProcessImageQuery { MaxSize = _mediaSettings.AvatarPictureSize }, ctx.Store.GetHost()); } } result.Add(dynObject); await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = dynObject, EntityType = ExportEntityType.Customer, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); return(result); }
private static dynamic ToDynamic(Shipment shipment, DataExporterContext ctx) { if (shipment == null) { return(null); } dynamic result = new DynamicEntity(shipment); result.ShipmentItems = shipment.ShipmentItems .Select(x => { dynamic exp = new DynamicEntity(x); return(exp); }) .ToList(); return(result); }
private async Task <dynamic> ToDynamic(ShoppingCartItem cartItem, DataExporterContext ctx) { if (cartItem == null) { return(null); } dynamic result = new DynamicEntity(cartItem); await _productAttributeMaterializer.MergeWithCombinationAsync(cartItem.Product, cartItem.AttributeSelection); result.Store = ctx.Stores.ContainsKey(cartItem.StoreId) ? ToDynamic(ctx.Stores[cartItem.StoreId], ctx) : null; result.Customer = ToDynamic(cartItem.Customer); result.Product = await ToDynamic(cartItem.Product, ctx); return(result); }
private static dynamic ToDynamic(QuantityUnit quantityUnit, DataExporterContext ctx) { if (quantityUnit == null) { return(null); } dynamic result = new DynamicEntity(quantityUnit); result.Name = ctx.GetTranslation(quantityUnit, nameof(quantityUnit.Name), quantityUnit.Name); result.NamePlural = ctx.GetTranslation(quantityUnit, nameof(quantityUnit.NamePlural), quantityUnit.NamePlural); result.Description = ctx.GetTranslation(quantityUnit, nameof(quantityUnit.Description), quantityUnit.Description); result._Localized = GetLocalized(ctx, quantityUnit, x => x.Name, x => x.NamePlural, x => x.Description); return(result); }
private async Task <IEnumerable <dynamic> > Convert(Category category, DataExporterContext ctx) { var result = new List <dynamic>(); var productCategories = await ctx.CategoryBatchContext.ProductCategories.GetOrLoadAsync(category.Id); dynamic dynObject = ToDynamic(category, ctx); if (category.MediaFileId.HasValue) { var numberOfFiles = ctx.Projection.NumberOfMediaFiles ?? int.MaxValue; var files = (await ctx.CategoryBatchContext.MediaFiles.GetOrLoadAsync(category.MediaFileId.Value)).Take(numberOfFiles); if (files.Any()) { dynObject.Picture = ToDynamic(files.First(), _mediaSettings.CategoryThumbPictureSize, _mediaSettings.CategoryThumbPictureSize, ctx); } } dynObject.ProductCategories = productCategories .OrderBy(x => x.DisplayOrder) .Select(x => { dynamic dyn = new DynamicEntity(x); return(dyn); }) .ToList(); result.Add(dynObject); await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = dynObject, EntityType = ExportEntityType.Category, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); return(result); }
private static dynamic ToDynamic(Category category, DataExporterContext ctx) { if (category == null) { return(null); } dynamic result = new DynamicEntity(category); result.Picture = null; result.Name = ctx.GetTranslation(category, nameof(category.Name), category.Name); result.FullName = ctx.GetTranslation(category, nameof(category.FullName), category.FullName); if (!ctx.IsPreview) { result.SeName = ctx.GetUrlRecord(category); result.Description = ctx.GetTranslation(category, nameof(category.Description), category.Description); result.BottomDescription = ctx.GetTranslation(category, nameof(category.BottomDescription), category.BottomDescription); result.MetaKeywords = ctx.GetTranslation(category, nameof(category.MetaKeywords), category.MetaKeywords); result.MetaDescription = ctx.GetTranslation(category, nameof(category.MetaDescription), category.MetaDescription); result.MetaTitle = ctx.GetTranslation(category, nameof(category.MetaTitle), category.MetaTitle); result._CategoryTemplateViewPath = ctx.CategoryTemplates.ContainsKey(category.CategoryTemplateId) ? ctx.CategoryTemplates[category.CategoryTemplateId] : ""; result._Localized = GetLocalized(ctx, category, x => x.Name, x => x.FullName, x => x.Description, x => x.BottomDescription, x => x.MetaKeywords, x => x.MetaDescription, x => x.MetaTitle); } return(result); }
private static dynamic ToDynamic(ProductVariantAttribute productAttribute, DataExporterContext ctx) { if (productAttribute == null) { return(null); } var languageId = ctx.LanguageId; var attribute = productAttribute.ProductAttribute; dynamic result = new DynamicEntity(productAttribute); dynamic dynAttribute = new DynamicEntity(attribute); dynAttribute.Name = ctx.GetTranslation(attribute, nameof(attribute.Name), attribute.Name); dynAttribute.Description = ctx.GetTranslation(attribute, nameof(attribute.Description), attribute.Description); dynAttribute.Values = productAttribute.ProductVariantAttributeValues .OrderBy(x => x.DisplayOrder) .Select(x => { dynamic dyn = new DynamicEntity(x); dyn.Name = ctx.GetTranslation(x, nameof(x.Name), x.Name); dyn._Localized = GetLocalized(ctx, x, y => y.Name); return(dyn); }) .ToList(); dynAttribute._Localized = GetLocalized(ctx, attribute, x => x.Name, x => x.Description); result.Attribute = dynAttribute; return(result); }
private bool HasPermission(DataExporterContext ctx) { if (ctx.Request.HasPermission) return true; var customer = _services.WorkContext.CurrentCustomer; if (customer.SystemName == SystemCustomerNames.BackgroundTask) return true; if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Product || ctx.Request.Provider.Value.EntityType == ExportEntityType.Category || ctx.Request.Provider.Value.EntityType == ExportEntityType.Manufacturer) return _services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog, customer); if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Customer) return _services.Permissions.Authorize(StandardPermissionProvider.ManageCustomers, customer); if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Order) return _services.Permissions.Authorize(StandardPermissionProvider.ManageOrders, customer); if (ctx.Request.Provider.Value.EntityType == ExportEntityType.NewsLetterSubscription) return _services.Permissions.Authorize(StandardPermissionProvider.ManageNewsletterSubscribers, customer); return true; }
private void SetProgress(DataExporterContext ctx, string message) { try { if (!ctx.IsPreview && message.HasValue()) { ctx.Request.ProgressValueSetter.Invoke(0, 0, message); } } catch { } }
private void SendCompletionEmail(DataExporterContext ctx, string zipPath) { var emailAccount = _emailAccountService.Value.GetEmailAccountById(ctx.Request.Profile.EmailAccountId); if (emailAccount == null) emailAccount = _emailAccountService.Value.GetDefaultEmailAccount(); var downloadUrl = "{0}Admin/Export/DownloadExportFile/{1}?name=".FormatInvariant(_services.WebHelper.GetStoreLocation(ctx.Store.SslEnabled), ctx.Request.Profile.Id); var languageId = ctx.Projection.LanguageId ?? 0; var smtpContext = new SmtpContext(emailAccount); var message = new EmailMessage(); var storeInfo = "{0} ({1})".FormatInvariant(ctx.Store.Name, ctx.Store.Url); var intro =_services.Localization.GetResource("Admin.DataExchange.Export.CompletedEmail.Body", languageId).FormatInvariant(storeInfo); var body = new StringBuilder(intro); if (ctx.Result.LastError.HasValue()) { body.AppendFormat("<p style=\"color: #B94A48;\">{0}</p>", ctx.Result.LastError); } if (ctx.IsFileBasedExport && File.Exists(zipPath)) { var fileName = Path.GetFileName(zipPath); body.AppendFormat("<p><a href='{0}{1}' download>{2}</a></p>", downloadUrl, HttpUtility.UrlEncode(fileName), fileName); } if (ctx.IsFileBasedExport && ctx.Result.Files.Any()) { body.Append("<p>"); foreach (var file in ctx.Result.Files) { body.AppendFormat("<div><a href='{0}{1}' download>{2}</a></div>", downloadUrl, HttpUtility.UrlEncode(file.FileName), file.FileName); } body.Append("</p>"); } message.From = new EmailAddress(emailAccount.Email, emailAccount.DisplayName); if (ctx.Request.Profile.CompletedEmailAddresses.HasValue()) message.To.AddRange(ctx.Request.Profile.CompletedEmailAddresses.SplitSafe(",").Where(x => x.IsEmail()).Select(x => new EmailAddress(x))); if (message.To.Count == 0 && _contactDataSettings.Value.CompanyEmailAddress.HasValue()) message.To.Add(new EmailAddress(_contactDataSettings.Value.CompanyEmailAddress)); if (message.To.Count == 0) message.To.Add(new EmailAddress(emailAccount.Email, emailAccount.DisplayName)); message.Subject = _services.Localization.GetResource("Admin.DataExchange.Export.CompletedEmail.Subject", languageId) .FormatInvariant(ctx.Request.Profile.Name); message.Body = body.ToString(); _emailSender.Value.SendEmail(smtpContext, message); //_queuedEmailService.Value.InsertQueuedEmail(new QueuedEmail //{ // From = emailAccount.Email, // FromName = emailAccount.DisplayName, // To = message.To.First().Address, // Subject = message.Subject, // Body = message.Body, // CreatedOnUtc = DateTime.UtcNow, // EmailAccountId = emailAccount.Id, // SendManually = true //}); //_dbContext.SaveChanges(); }
public int GetDataCount(DataExportRequest request) { var cancellation = new CancellationTokenSource(TimeSpan.FromMinutes(5.0)); var ctx = new DataExporterContext(request, cancellation.Token, true); var unused = Init(ctx); var totalCount = ctx.RecordsPerStore.First().Value; return totalCount; }
public DataExportResult Export(DataExportRequest request, CancellationToken cancellationToken) { var ctx = new DataExporterContext(request, cancellationToken); ExportCoreOuter(ctx); cancellationToken.ThrowIfCancellationRequested(); return ctx.Result; }
private bool CallProvider(DataExporterContext ctx, string streamId, string method, string path) { if (method != "Execute" && method != "OnExecuted") throw new SmartException("Unknown export method {0}.".FormatInvariant(method.NaIfEmpty())); try { ctx.ExecuteContext.DataStreamId = streamId; using (ctx.ExecuteContext.DataStream = new MemoryStream()) { if (method == "Execute") { ctx.Request.Provider.Value.Execute(ctx.ExecuteContext); } else if (method == "OnExecuted") { ctx.Request.Provider.Value.OnExecuted(ctx.ExecuteContext); } if (ctx.IsFileBasedExport && path.HasValue() && ctx.ExecuteContext.DataStream.Length > 0) { if (!ctx.ExecuteContext.DataStream.CanSeek) { ctx.Log.Warning("Data stream seems to be closed!"); } ctx.ExecuteContext.DataStream.Seek(0, SeekOrigin.Begin); using (_rwLock.GetWriteLock()) using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { ctx.Log.Information("Creating file {0}.".FormatInvariant(path)); ctx.ExecuteContext.DataStream.CopyTo(fileStream); } } } } catch (Exception exception) { ctx.ExecuteContext.Abort = DataExchangeAbortion.Hard; ctx.Log.Error("The provider failed at the {0} method: {1}.".FormatInvariant(method, exception.ToAllMessages()), exception); ctx.Result.LastError = exception.ToString(); } finally { if (ctx.ExecuteContext.DataStream != null) { ctx.ExecuteContext.DataStream.Dispose(); ctx.ExecuteContext.DataStream = null; } if (ctx.ExecuteContext.Abort == DataExchangeAbortion.Hard && ctx.IsFileBasedExport && path.HasValue()) { FileSystemHelper.Delete(path); } } return (ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard); }
private IQueryable<Order> GetOrderQuery(DataExporterContext ctx, int skip, int take) { var query = _orderService.Value.GetOrders( ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId, ctx.Projection.CustomerId ?? 0, ctx.Filter.CreatedFrom.HasValue ? (DateTime?)_dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedFrom.Value, _dateTimeHelper.Value.CurrentTimeZone) : null, ctx.Filter.CreatedTo.HasValue ? (DateTime?)_dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedTo.Value, _dateTimeHelper.Value.CurrentTimeZone) : null, ctx.Filter.OrderStatusIds, ctx.Filter.PaymentStatusIds, ctx.Filter.ShippingStatusIds, null, null, null); if (ctx.Request.EntitiesToExport.Any()) query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id)); query = query.OrderByDescending(x => x.CreatedOnUtc); if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private List<Store> Init(DataExporterContext ctx, int? totalRecords = null) { // Init base things that are even required for preview. Init all other things (regular export) in ExportCoreOuter. List<Store> result = null; if (ctx.Projection.CurrencyId.HasValue) ctx.ContextCurrency = _currencyService.Value.GetCurrencyById(ctx.Projection.CurrencyId.Value); else ctx.ContextCurrency = _services.WorkContext.WorkingCurrency; if (ctx.Projection.CustomerId.HasValue) ctx.ContextCustomer = _customerService.GetCustomerById(ctx.Projection.CustomerId.Value); else ctx.ContextCustomer = _services.WorkContext.CurrentCustomer; if (ctx.Projection.LanguageId.HasValue) ctx.ContextLanguage = _languageService.Value.GetLanguageById(ctx.Projection.LanguageId.Value); else ctx.ContextLanguage = _services.WorkContext.WorkingLanguage; ctx.Stores = _services.StoreService.GetAllStores().ToDictionary(x => x.Id, x => x); ctx.Languages = _languageService.Value.GetAllLanguages(true).ToDictionary(x => x.Id, x => x); if (!ctx.IsPreview && ctx.Request.Profile.PerStore) { result = new List<Store>(ctx.Stores.Values.Where(x => x.Id == ctx.Filter.StoreId || ctx.Filter.StoreId == 0)); } else { int? storeId = (ctx.Filter.StoreId == 0 ? ctx.Projection.StoreId : ctx.Filter.StoreId); ctx.Store = ctx.Stores.Values.FirstOrDefault(x => x.Id == (storeId ?? _services.StoreContext.CurrentStore.Id)); result = new List<Store> { ctx.Store }; } // get total records for progress foreach (var store in result) { ctx.Store = store; int totalCount = 0; if (totalRecords.HasValue) { totalCount = totalRecords.Value; // speed up preview by not counting total at each page } else { switch (ctx.Request.Provider.Value.EntityType) { case ExportEntityType.Product: totalCount = GetProductQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; case ExportEntityType.Order: totalCount = GetOrderQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; case ExportEntityType.Manufacturer: totalCount = GetManufacturerQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; case ExportEntityType.Category: totalCount = GetCategoryQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; case ExportEntityType.Customer: totalCount = GetCustomerQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; case ExportEntityType.NewsLetterSubscription: totalCount = GetNewsLetterSubscriptionQuery(ctx, ctx.Request.Profile.Offset, int.MaxValue).Count(); break; } } ctx.RecordsPerStore.Add(store.Id, totalCount); } return result; }
private async Task <IEnumerable <dynamic> > Convert(ShoppingCartItem shoppingCartItem, DataExporterContext ctx) { var result = new List <dynamic>(); dynamic dynObject = await ToDynamic(shoppingCartItem, ctx); result.Add(dynObject); await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = dynObject, EntityType = ExportEntityType.ShoppingCartItem, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); return(result); }
private void ExportCoreInner(DataExporterContext ctx, Store store) { if (ctx.ExecuteContext.Abort != DataExchangeAbortion.None) return; var fileIndex = 0; var dataExchangeSettings = _services.Settings.LoadSetting<DataExchangeSettings>(store.Id); ctx.Store = store; { var logHead = new StringBuilder(); logHead.AppendLine(); logHead.AppendLine(new string('-', 40)); logHead.AppendLine("SmartStore.NET:\t\tv." + SmartStoreVersion.CurrentFullVersion); logHead.Append("Export profile:\t\t" + ctx.Request.Profile.Name); logHead.AppendLine(ctx.Request.Profile.Id == 0 ? " (volatile)" : " (Id {0})".FormatInvariant(ctx.Request.Profile.Id)); if (ctx.Request.Provider.Metadata.FriendlyName.HasValue()) logHead.AppendLine("Export provider:\t{0} ({1})".FormatInvariant(ctx.Request.Provider.Metadata.FriendlyName, ctx.Request.Profile.ProviderSystemName)); else logHead.AppendLine("Export provider:\t{0}".FormatInvariant(ctx.Request.Profile.ProviderSystemName)); var plugin = ctx.Request.Provider.Metadata.PluginDescriptor; logHead.Append("Plugin:\t\t\t"); logHead.AppendLine(plugin == null ? "".NaIfEmpty() : "{0} ({1}) v.{2}".FormatInvariant(plugin.FriendlyName, plugin.SystemName, plugin.Version.ToString())); logHead.AppendLine("Entity:\t\t\t" + ctx.Request.Provider.Value.EntityType.ToString()); try { var uri = new Uri(store.Url); logHead.AppendLine("Store:\t\t\t{0} (Id {1})".FormatInvariant(uri.DnsSafeHost.NaIfEmpty(), ctx.Store.Id)); } catch { } var customer = _services.WorkContext.CurrentCustomer; logHead.Append("Executed by:\t\t" + (customer.Email.HasValue() ? customer.Email : customer.SystemName)); ctx.Log.Information(logHead.ToString()); } ctx.ExecuteContext.Store = ToDynamic(ctx, ctx.Store); ctx.ExecuteContext.MaxFileNameLength = dataExchangeSettings.MaxFileNameLength; var publicDeployment = ctx.Request.Profile.Deployments.FirstOrDefault(x => x.DeploymentType == ExportDeploymentType.PublicFolder); ctx.ExecuteContext.HasPublicDeployment = (publicDeployment != null); ctx.ExecuteContext.PublicFolderPath = publicDeployment.GetDeploymentFolder(true); var fileExtension = (ctx.Request.Provider.Value.FileExtension.HasValue() ? ctx.Request.Provider.Value.FileExtension.ToLower().EnsureStartsWith(".") : ""); using (var segmenter = CreateSegmenter(ctx)) { if (segmenter == null) { throw new SmartException("Unsupported entity type '{0}'.".FormatInvariant(ctx.Request.Provider.Value.EntityType.ToString())); } if (segmenter.TotalRecords <= 0) { ctx.Log.Information("There are no records to export."); } while (ctx.ExecuteContext.Abort == DataExchangeAbortion.None && segmenter.HasData) { segmenter.RecordPerSegmentCount = 0; ctx.ExecuteContext.RecordsSucceeded = 0; string path = null; if (ctx.IsFileBasedExport) { var resolvedPattern = ctx.Request.Profile.ResolveFileNamePattern(ctx.Store, ++fileIndex, ctx.ExecuteContext.MaxFileNameLength); ctx.ExecuteContext.FileName = resolvedPattern + fileExtension; path = Path.Combine(ctx.ExecuteContext.Folder, ctx.ExecuteContext.FileName); } if (CallProvider(ctx, null, "Execute", path)) { ctx.Log.Information("Provider reports {0} successfully exported record(s).".FormatInvariant(ctx.ExecuteContext.RecordsSucceeded)); if (ctx.IsFileBasedExport && File.Exists(path)) { ctx.Result.Files.Add(new DataExportResult.ExportFileInfo { StoreId = ctx.Store.Id, FileName = ctx.ExecuteContext.FileName }); } } ctx.EntityIdsPerSegment.Clear(); if (ctx.ExecuteContext.IsMaxFailures) ctx.Log.Warning("Export aborted. The maximum number of failures has been reached."); if (ctx.CancellationToken.IsCancellationRequested) ctx.Log.Warning("Export aborted. A cancellation has been requested."); DetachAllEntitiesAndClear(ctx); } if (ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard) { // always call OnExecuted if (ctx.ExecuteContext.ExtraDataUnits.Count == 0) ctx.ExecuteContext.ExtraDataUnits.Add(new ExportDataUnit()); ctx.ExecuteContext.ExtraDataUnits.ForEach(x => { var path = (x.FileName.HasValue() ? Path.Combine(ctx.ExecuteContext.Folder, x.FileName) : null); CallProvider(ctx, x.Id, "OnExecuted", path); }); ctx.ExecuteContext.ExtraDataUnits.Clear(); } } }
private void ExportCoreOuter(DataExporterContext ctx) { if (ctx.Request.Profile == null || !ctx.Request.Profile.Enabled) return; var logPath = ctx.Request.Profile.GetExportLogPath(); var zipPath = ctx.Request.Profile.GetExportZipPath(); FileSystemHelper.Delete(logPath); FileSystemHelper.Delete(zipPath); FileSystemHelper.ClearDirectory(ctx.FolderContent, false); using (var logger = new TraceLogger(logPath)) { try { ctx.Log = logger; ctx.ExecuteContext.Log = logger; ctx.ProgressInfo = T("Admin.DataExchange.Export.ProgressInfo"); if (!ctx.Request.Provider.IsValid()) throw new SmartException("Export aborted because the export provider is not valid."); if (!HasPermission(ctx)) throw new SmartException("You do not have permission to perform the selected export."); foreach (var item in ctx.Request.CustomData) { ctx.ExecuteContext.CustomProperties.Add(item.Key, item.Value); } if (ctx.Request.Profile.ProviderConfigData.HasValue()) { var configInfo = ctx.Request.Provider.Value.ConfigurationInfo; if (configInfo != null) { ctx.ExecuteContext.ConfigurationData = XmlHelper.Deserialize(ctx.Request.Profile.ProviderConfigData, configInfo.ModelType); } } // lazyLoading: false, proxyCreation: false impossible. how to identify all properties of all data levels of all entities // that require manual resolving for now and for future? fragile, susceptible to faults (e.g. price calculation)... using (var scope = new DbContextScope(_dbContext, autoDetectChanges: false, proxyCreation: true, validateOnSave: false, forceNoTracking: true)) { ctx.DeliveryTimes = _deliveryTimeService.Value.GetAllDeliveryTimes().ToDictionary(x => x.Id); ctx.QuantityUnits = _quantityUnitService.Value.GetAllQuantityUnits().ToDictionary(x => x.Id); ctx.ProductTemplates = _productTemplateService.Value.GetAllProductTemplates().ToDictionary(x => x.Id, x => x.ViewPath); ctx.CategoryTemplates = _categoryTemplateService.Value.GetAllCategoryTemplates().ToDictionary(x => x.Id, x => x.ViewPath); if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Product) { var allCategories = _categoryService.Value.GetAllCategories(showHidden: true, applyNavigationFilters: false); ctx.Categories = allCategories.ToDictionary(x => x.Id); } if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Order) { ctx.Countries = _countryService.Value.GetAllCountries(true).ToDictionary(x => x.Id, x => x); } if (ctx.Request.Provider.Value.EntityType == ExportEntityType.Customer) { var subscriptionEmails = _subscriptionRepository.Value.TableUntracked .Where(x => x.Active) .Select(x => x.Email) .Distinct() .ToList(); ctx.NewsletterSubscriptions = new HashSet<string>(subscriptionEmails, StringComparer.OrdinalIgnoreCase); } var stores = Init(ctx); ctx.ExecuteContext.Language = ToDynamic(ctx, ctx.ContextLanguage); ctx.ExecuteContext.Customer = ToDynamic(ctx, ctx.ContextCustomer); ctx.ExecuteContext.Currency = ToDynamic(ctx, ctx.ContextCurrency); stores.ForEach(x => ExportCoreInner(ctx, x)); } if (!ctx.IsPreview && ctx.ExecuteContext.Abort != DataExchangeAbortion.Hard) { if (ctx.IsFileBasedExport) { if (ctx.Request.Profile.CreateZipArchive) { ZipFile.CreateFromDirectory(ctx.FolderContent, zipPath, CompressionLevel.Fastest, false); } if (ctx.Request.Profile.Deployments.Any(x => x.Enabled)) { SetProgress(ctx, T("Common.Publishing")); var allDeploymentsSucceeded = Deploy(ctx, zipPath); if (allDeploymentsSucceeded && ctx.Request.Profile.Cleanup) { logger.Information("Cleaning up export folder"); FileSystemHelper.ClearDirectory(ctx.FolderContent, false); } } } if (ctx.Request.Profile.EmailAccountId != 0 && ctx.Request.Profile.CompletedEmailAddresses.HasValue()) { SendCompletionEmail(ctx, zipPath); } else if (ctx.Request.Profile.IsSystemProfile && !ctx.Supports(ExportFeatures.CanOmitCompletionMail)) { SendCompletionEmail(ctx, zipPath); } } } catch (Exception exception) { logger.ErrorsAll(exception); ctx.Result.LastError = exception.ToString(); } finally { try { if (!ctx.IsPreview && ctx.Request.Profile.Id != 0) { ctx.Request.Profile.ResultInfo = XmlHelper.Serialize(ctx.Result); _exportProfileService.Value.UpdateExportProfile(ctx.Request.Profile); } } catch (Exception exception) { logger.ErrorsAll(exception); } DetachAllEntitiesAndClear(ctx); try { ctx.NewsletterSubscriptions.Clear(); ctx.ProductTemplates.Clear(); ctx.CategoryTemplates.Clear(); ctx.Countries.Clear(); ctx.Languages.Clear(); ctx.QuantityUnits.Clear(); ctx.DeliveryTimes.Clear(); ctx.CategoryPathes.Clear(); ctx.Categories.Clear(); ctx.Stores.Clear(); ctx.Request.CustomData.Clear(); ctx.ExecuteContext.CustomProperties.Clear(); ctx.ExecuteContext.Log = null; ctx.Log = null; } catch (Exception exception) { logger.ErrorsAll(exception); } } } if (ctx.IsPreview || ctx.ExecuteContext.Abort == DataExchangeAbortion.Hard) return; // post process order entities if (ctx.EntityIdsLoaded.Any() && ctx.Request.Provider.Value.EntityType == ExportEntityType.Order && ctx.Projection.OrderStatusChange != ExportOrderStatusChange.None) { using (var logger = new TraceLogger(logPath)) { try { int? orderStatusId = null; if (ctx.Projection.OrderStatusChange == ExportOrderStatusChange.Processing) orderStatusId = (int)OrderStatus.Processing; else if (ctx.Projection.OrderStatusChange == ExportOrderStatusChange.Complete) orderStatusId = (int)OrderStatus.Complete; using (var scope = new DbContextScope(_dbContext, false, null, false, false, false, false)) { foreach (var chunk in ctx.EntityIdsLoaded.Chunk()) { var entities = _orderRepository.Value.Table.Where(x => chunk.Contains(x.Id)).ToList(); entities.ForEach(x => x.OrderStatusId = (orderStatusId ?? x.OrderStatusId)); _dbContext.SaveChanges(); } } logger.Information("Updated order status for {0} order(s).".FormatInvariant(ctx.EntityIdsLoaded.Count())); } catch (Exception exception) { logger.ErrorsAll(exception); ctx.Result.LastError = exception.ToString(); } } } }
private void DetachAllEntitiesAndClear(DataExporterContext ctx) { try { _dbContext.DetachAll(); } catch (Exception exception) { ctx.Log.Warning("Detaching all entities failed.", exception); } try { // now again attach what is globally required _dbContext.Attach(ctx.Request.Profile); _dbContext.AttachRange(ctx.Stores.Values); } catch (Exception exception) { ctx.Log.Warning("Re-attaching entities failed.", exception); } try { if (ctx.ProductExportContext != null) ctx.ProductExportContext.Clear(); if (ctx.OrderExportContext != null) ctx.OrderExportContext.Clear(); if (ctx.ManufacturerExportContext != null) ctx.ManufacturerExportContext.Clear(); if (ctx.CategoryExportContext != null) ctx.CategoryExportContext.Clear(); if (ctx.CustomerExportContext != null) ctx.CustomerExportContext.Clear(); } catch { } }
private bool Deploy(DataExporterContext ctx, string zipPath) { var allSucceeded = true; var deployments = ctx.Request.Profile.Deployments.OrderBy(x => x.DeploymentTypeId).Where(x => x.Enabled); if (deployments.Count() == 0) return false; var context = new ExportDeploymentContext { T = T, Log = ctx.Log, FolderContent = ctx.FolderContent, ZipPath = zipPath, CreateZipArchive = ctx.Request.Profile.CreateZipArchive }; foreach (var deployment in deployments) { IFilePublisher publisher = null; context.Result = new DataDeploymentResult { LastExecutionUtc = DateTime.UtcNow }; try { switch (deployment.DeploymentType) { case ExportDeploymentType.Email: publisher = new EmailFilePublisher(_emailAccountService.Value, _queuedEmailService.Value); break; case ExportDeploymentType.FileSystem: publisher = new FileSystemFilePublisher(); break; case ExportDeploymentType.Ftp: publisher = new FtpFilePublisher(); break; case ExportDeploymentType.Http: publisher = new HttpFilePublisher(); break; case ExportDeploymentType.PublicFolder: publisher = new PublicFolderPublisher(); break; } if (publisher != null) { publisher.Publish(context, deployment); if (!context.Result.Succeeded) allSucceeded = false; } } catch (Exception exception) { allSucceeded = false; if (context.Result != null) { context.Result.LastError = exception.ToAllMessages(); } ctx.Log.Error("Deployment \"{0}\" of type {1} failed: {2}".FormatInvariant( deployment.Name, deployment.DeploymentType.ToString(), exception.Message), exception); } deployment.ResultInfo = XmlHelper.Serialize(context.Result); _exportProfileService.Value.UpdateExportDeployment(deployment); } return allSucceeded; }
private IExportDataSegmenterProvider CreateSegmenter(DataExporterContext ctx, int pageIndex = 0) { var offset = Math.Max(ctx.Request.Profile.Offset, 0) + (pageIndex * PageSize); var limit = (ctx.IsPreview ? PageSize : Math.Max(ctx.Request.Profile.Limit, 0)); var recordsPerSegment = (ctx.IsPreview ? 0 : Math.Max(ctx.Request.Profile.BatchSize, 0)); var totalCount = Math.Max(ctx.Request.Profile.Offset, 0) + ctx.RecordsPerStore.First(x => x.Key == ctx.Store.Id).Value; switch (ctx.Request.Provider.Value.EntityType) { case ExportEntityType.Product: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<Product> ( skip => GetProducts(ctx, skip), entities => { // load data behind navigation properties for current queue in one go ctx.ProductExportContext = new ProductExportContext(entities, x => _productAttributeService.Value.GetProductVariantAttributesByProductIds(x, null), x => _productAttributeService.Value.GetProductVariantAttributeCombinations(x), x => _productService.Value.GetTierPricesByProductIds(x, (ctx.Projection.CurrencyId ?? 0) != 0 ? ctx.ContextCustomer : null, ctx.Store.Id), x => _categoryService.Value.GetProductCategoriesByProductIds(x), x => _manufacturerService.Value.GetProductManufacturersByProductIds(x), x => _productService.Value.GetProductPicturesByProductIds(x), x => _productService.Value.GetProductTagsByProductIds(x), x => _productService.Value.GetAppliedDiscountsByProductIds(x), x => _productService.Value.GetProductSpecificationAttributesByProductIds(x), x => _productService.Value.GetBundleItemsByProductIds(x, true) ); }, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; case ExportEntityType.Order: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<Order> ( skip => GetOrders(ctx, skip), entities => { ctx.OrderExportContext = new OrderExportContext(entities, x => _customerService.GetCustomersByIds(x), x => _customerService.GetRewardPointsHistoriesByCustomerIds(x), x => _addressService.Value.GetAddressByIds(x), x => _orderService.Value.GetOrderItemsByOrderIds(x), x => _shipmentService.Value.GetShipmentsByOrderIds(x) ); }, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; case ExportEntityType.Manufacturer: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<Manufacturer> ( skip => GetManufacturers(ctx, skip), entities => { ctx.ManufacturerExportContext = new ManufacturerExportContext(entities, x => _manufacturerService.Value.GetProductManufacturersByManufacturerIds(x), x => _pictureService.Value.GetPicturesByIds(x) ); }, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; case ExportEntityType.Category: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<Category> ( skip => GetCategories(ctx, skip), entities => { ctx.CategoryExportContext = new CategoryExportContext(entities, x => _categoryService.Value.GetProductCategoriesByCategoryIds(x), x => _pictureService.Value.GetPicturesByIds(x) ); }, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; case ExportEntityType.Customer: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<Customer> ( skip => GetCustomers(ctx, skip), entities => { ctx.CustomerExportContext = new CustomerExportContext(entities, x => _genericAttributeService.Value.GetAttributesForEntity(x, "Customer") ); }, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; case ExportEntityType.NewsLetterSubscription: ctx.ExecuteContext.DataSegmenter = new ExportDataSegmenter<NewsLetterSubscription> ( skip => GetNewsLetterSubscriptions(ctx, skip), null, entity => Convert(ctx, entity), offset, PageSize, limit, recordsPerSegment, totalCount ); break; default: ctx.ExecuteContext.DataSegmenter = null; break; } return ctx.ExecuteContext.DataSegmenter as IExportDataSegmenterProvider; }
/// <summary> /// Creates an expando object with the most important general properties of a product such as the name and description. /// This method is used for entities where products are to be exported as related data, e.g. order items. /// </summary> private async Task <dynamic> ToDynamic(Product product, DataExporterContext ctx, string seName = null, Money?price = null) { if (product == null) { return(null); } dynamic result = new DynamicEntity(product); var localizedName = ctx.GetTranslation(product, nameof(product.Name), product.Name); result.AppliedDiscounts = null; result.Downloads = null; result.TierPrices = null; result.ProductAttributes = null; result.ProductAttributeCombinations = null; result.ProductPictures = null; result.ProductCategories = null; result.ProductManufacturers = null; result.ProductTags = null; result.ProductSpecificationAttributes = null; result.ProductBundleItems = null; result.Name = localizedName; if (!ctx.IsPreview) { result.SeName = seName ?? ctx.GetUrlRecord(product); result.ShortDescription = ctx.GetTranslation(product, nameof(product.ShortDescription), product.ShortDescription); result.FullDescription = ctx.GetTranslation(product, nameof(product.FullDescription), product.FullDescription); result.MetaKeywords = ctx.GetTranslation(product, nameof(product.MetaKeywords), product.MetaKeywords); result.MetaDescription = ctx.GetTranslation(product, nameof(product.MetaDescription), product.MetaDescription); result.MetaTitle = ctx.GetTranslation(product, nameof(product.MetaTitle), product.MetaTitle); result.BundleTitleText = ctx.GetTranslation(product, nameof(product.BundleTitleText), product.BundleTitleText); result._ProductTemplateViewPath = ctx.ProductTemplates.ContainsKey(product.ProductTemplateId) ? ctx.ProductTemplates[product.ProductTemplateId] : string.Empty; if (product.BasePriceHasValue && product.BasePriceAmount != 0) { if (price == null) { var calculationOptions = _priceCalculationService.CreateDefaultOptions(false, ctx.ContextCustomer, ctx.ContextCurrency, ctx.ProductBatchContext); var productPrice = await _priceCalculationService.CalculatePriceAsync(new PriceCalculationContext(product, calculationOptions)); price = productPrice.FinalPrice; } result._BasePriceInfo = _priceCalculationService.GetBasePriceInfo(product, price.Value, ctx.ContextCurrency, ctx.ContextLanguage, false); } else { result._BasePriceInfo = string.Empty; } result.DeliveryTime = ctx.DeliveryTimes.TryGetValue(product.DeliveryTimeId ?? 0, out var deliveryTime) ? ToDynamic(deliveryTime, ctx) : null; result.QuantityUnit = ctx.QuantityUnits.TryGetValue(product.QuantityUnitId ?? 0, out var quantityUnit) ? ToDynamic(quantityUnit, ctx) : null; result.CountryOfOrigin = product.CountryOfOriginId.HasValue ? ToDynamic(product.CountryOfOrigin, ctx) : null; result._Localized = GetLocalized(ctx, product, x => x.Name, x => x.ShortDescription, x => x.FullDescription, x => x.MetaKeywords, x => x.MetaDescription, x => x.MetaTitle, x => x.BundleTitleText); } return(result); }
private List<Order> GetOrders(DataExporterContext ctx, int skip) { var orders = GetOrderQuery(ctx, skip, PageSize).ToList(); if (ctx.Projection.OrderStatusChange != ExportOrderStatusChange.None) { ctx.SetLoadedEntityIds(orders.Select(x => x.Id)); } SetProgress(ctx, orders.Count); return orders; }
private List<Category> GetCategories(DataExporterContext ctx, int skip) { var categories = GetCategoryQuery(ctx, skip, PageSize).ToList(); SetProgress(ctx, categories.Count); return categories; }
public IList<dynamic> Preview(DataExportRequest request, int pageIndex, int? totalRecords = null) { var resultData = new List<dynamic>(); var cancellation = new CancellationTokenSource(TimeSpan.FromMinutes(5.0)); var ctx = new DataExporterContext(request, cancellation.Token, true); var unused = Init(ctx, totalRecords); if (!HasPermission(ctx)) throw new SmartException(T("Admin.AccessDenied")); using (var segmenter = CreateSegmenter(ctx, pageIndex)) { if (segmenter == null) { throw new SmartException(T("Admin.Common.UnsupportedEntityType", ctx.Request.Provider.Value.EntityType.ToString())); } while (segmenter.HasData) { segmenter.RecordPerSegmentCount = 0; while (segmenter.ReadNextSegment()) { resultData.AddRange(segmenter.CurrentSegment); } } DetachAllEntitiesAndClear(ctx); } if (ctx.Result.LastError.HasValue()) { _services.Notifier.Error(ctx.Result.LastError); } return resultData; }
private async Task <IEnumerable <dynamic> > Convert(NewsletterSubscription subscription, DataExporterContext ctx) { var result = new List <dynamic>(); dynamic dynObject = ToDynamic(subscription, ctx); result.Add(dynObject); await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = dynObject, EntityType = ExportEntityType.NewsLetterSubscription, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); return(result); }
private IQueryable<Category> GetCategoryQuery(DataExporterContext ctx, int skip, int take) { var showHidden = !ctx.Filter.IsPublished.HasValue; var storeId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId); var query = _categoryService.Value.GetCategories(null, showHidden, null, true, storeId); if (ctx.Request.EntitiesToExport.Any()) query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id)); query = query .OrderBy(x => x.ParentCategoryId) .ThenBy(x => x.DisplayOrder); if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private IQueryable<Product> GetProductQuery(DataExporterContext ctx, int skip, int take) { IQueryable<Product> query = null; if (ctx.Request.ProductQuery == null) { var searchContext = new ProductSearchContext { OrderBy = ProductSortingEnum.CreatedOn, ProductIds = ctx.Request.EntitiesToExport, StoreId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId), VisibleIndividuallyOnly = true, PriceMin = ctx.Filter.PriceMinimum, PriceMax = ctx.Filter.PriceMaximum, IsPublished = ctx.Filter.IsPublished, WithoutCategories = ctx.Filter.WithoutCategories, WithoutManufacturers = ctx.Filter.WithoutManufacturers, ManufacturerId = ctx.Filter.ManufacturerId ?? 0, FeaturedProducts = ctx.Filter.FeaturedProducts, ProductType = ctx.Filter.ProductType, ProductTagId = ctx.Filter.ProductTagId ?? 0, IdMin = ctx.Filter.IdMinimum ?? 0, IdMax = ctx.Filter.IdMaximum ?? 0, AvailabilityMinimum = ctx.Filter.AvailabilityMinimum, AvailabilityMaximum = ctx.Filter.AvailabilityMaximum }; if (!ctx.Filter.IsPublished.HasValue) searchContext.ShowHidden = true; if (ctx.Filter.CategoryIds != null && ctx.Filter.CategoryIds.Length > 0) searchContext.CategoryIds = ctx.Filter.CategoryIds.ToList(); if (ctx.Filter.CreatedFrom.HasValue) searchContext.CreatedFromUtc = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedFrom.Value, _dateTimeHelper.Value.CurrentTimeZone); if (ctx.Filter.CreatedTo.HasValue) searchContext.CreatedToUtc = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedTo.Value, _dateTimeHelper.Value.CurrentTimeZone); query = _productService.Value.PrepareProductSearchQuery(searchContext); query = query.OrderByDescending(x => x.CreatedOnUtc); } else { query = ctx.Request.ProductQuery; } if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private IQueryable<Customer> GetCustomerQuery(DataExporterContext ctx, int skip, int take) { var query = _customerRepository.Value.TableUntracked .Expand(x => x.BillingAddress) .Expand(x => x.ShippingAddress) .Expand(x => x.Addresses.Select(y => y.Country)) .Expand(x => x.Addresses.Select(y => y.StateProvince)) .Expand(x => x.CustomerRoles) .Where(x => !x.Deleted); if (ctx.Filter.IsActiveCustomer.HasValue) query = query.Where(x => x.Active == ctx.Filter.IsActiveCustomer.Value); if (ctx.Filter.IsTaxExempt.HasValue) query = query.Where(x => x.IsTaxExempt == ctx.Filter.IsTaxExempt.Value); if (ctx.Filter.CustomerRoleIds != null && ctx.Filter.CustomerRoleIds.Length > 0) query = query.Where(x => x.CustomerRoles.Select(y => y.Id).Intersect(ctx.Filter.CustomerRoleIds).Any()); if (ctx.Filter.BillingCountryIds != null && ctx.Filter.BillingCountryIds.Length > 0) query = query.Where(x => x.BillingAddress != null && ctx.Filter.BillingCountryIds.Contains(x.BillingAddress.Id)); if (ctx.Filter.ShippingCountryIds != null && ctx.Filter.ShippingCountryIds.Length > 0) query = query.Where(x => x.ShippingAddress != null && ctx.Filter.ShippingCountryIds.Contains(x.ShippingAddress.Id)); if (ctx.Filter.LastActivityFrom.HasValue) { var activityFrom = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.LastActivityFrom.Value, _dateTimeHelper.Value.CurrentTimeZone); query = query.Where(x => activityFrom <= x.LastActivityDateUtc); } if (ctx.Filter.LastActivityTo.HasValue) { var activityTo = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.LastActivityTo.Value, _dateTimeHelper.Value.CurrentTimeZone); query = query.Where(x => activityTo >= x.LastActivityDateUtc); } if (ctx.Filter.HasSpentAtLeastAmount.HasValue) { query = query .Join(_orderRepository.Value.Table, x => x.Id, y => y.CustomerId, (x, y) => new { Customer = x, Order = y }) .GroupBy(x => x.Customer.Id) .Select(x => new { Customer = x.FirstOrDefault().Customer, OrderTotal = x.Sum(y => y.Order.OrderTotal) }) .Where(x => x.OrderTotal >= ctx.Filter.HasSpentAtLeastAmount.Value) .Select(x => x.Customer); } if (ctx.Filter.HasPlacedAtLeastOrders.HasValue) { query = query .Join(_orderRepository.Value.Table, x => x.Id, y => y.CustomerId, (x, y) => new { Customer = x, Order = y }) .GroupBy(x => x.Customer.Id) .Select(x => new { Customer = x.FirstOrDefault().Customer, OrderCount = x.Count() }) .Where(x => x.OrderCount >= ctx.Filter.HasPlacedAtLeastOrders.Value) .Select(x => x.Customer); } if (ctx.Request.EntitiesToExport.Any()) query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id)); query = query.OrderByDescending(x => x.CreatedOnUtc); if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private async Task <IEnumerable <dynamic> > Convert(Order order, DataExporterContext ctx) { var result = new List <dynamic>(); ctx.OrderBatchContext.Addresses.Collect(order.ShippingAddressId ?? 0); await ctx.OrderBatchContext.Addresses.GetOrLoadAsync(order.BillingAddressId); var customers = await ctx.OrderBatchContext.Customers.GetOrLoadAsync(order.CustomerId); var genericAttributes = await ctx.OrderBatchContext.CustomerGenericAttributes.GetOrLoadAsync(order.CustomerId); var rewardPointsHistories = await ctx.OrderBatchContext.RewardPointsHistories.GetOrLoadAsync(order.CustomerId); var orderItems = await ctx.OrderBatchContext.OrderItems.GetOrLoadAsync(order.Id); var shipments = await ctx.OrderBatchContext.Shipments.GetOrLoadAsync(order.Id); dynamic dynObject = await ToDynamic(order, ctx); dynObject.Customer = ToDynamic(customers.FirstOrDefault(x => x.Id == order.CustomerId)); // We do not export all customer generic attributes because otherwise the export file gets too big. dynObject.Customer._GenericAttributes = genericAttributes .Where(x => x.Value.HasValue() && _orderCustomerAttributes.Contains(x.Key)) .Select(x => CreateDynamic(x)) .ToList(); dynObject.Customer.RewardPointsHistory = rewardPointsHistories .Select(x => CreateDynamic(x)) .ToList(); if (rewardPointsHistories.Any()) { dynObject.Customer._RewardPointsBalance = rewardPointsHistories .OrderByDescending(x => x.CreatedOnUtc) .ThenByDescending(x => x.Id) .FirstOrDefault() .PointsBalance; } dynObject.BillingAddress = ctx.OrderBatchContext.Addresses.TryGetValues(order.BillingAddressId, out var billingAddresses) ? ToDynamic(billingAddresses.FirstOrDefault(), ctx) : null; dynObject.ShippingAddress = order.ShippingAddressId.HasValue && ctx.OrderBatchContext.Addresses.TryGetValues(order.ShippingAddressId.Value, out var shippingAddresses) ? ToDynamic(shippingAddresses.FirstOrDefault(), ctx) : null; dynObject.OrderItems = await orderItems .SelectAsync(async x => await ToDynamic(x, ctx)) .ToListAsync(); dynObject.Shipments = shipments .Select(x => ToDynamic(x, ctx)) .ToList(); result.Add(dynObject); await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = dynObject, EntityType = ExportEntityType.Order, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); return(result); }
private List<Customer> GetCustomers(DataExporterContext ctx, int skip) { var customers = GetCustomerQuery(ctx, skip, PageSize).ToList(); SetProgress(ctx, customers.Count); return customers; }
private List<NewsLetterSubscription> GetNewsLetterSubscriptions(DataExporterContext ctx, int skip) { var subscriptions = GetNewsLetterSubscriptionQuery(ctx, skip, PageSize).ToList(); SetProgress(ctx, subscriptions.Count); return subscriptions; }
private static dynamic ToDynamic(ProductVariantAttributeCombination attributeCombination, DataExporterContext ctx) { if (attributeCombination == null) { return(null); } dynamic result = new DynamicEntity(attributeCombination); result.DeliveryTime = ctx.DeliveryTimes.TryGetValue(attributeCombination.DeliveryTimeId ?? 0, out var deliveryTime) ? ToDynamic(deliveryTime, ctx) : null; result.QuantityUnit = ctx.QuantityUnits.TryGetValue(attributeCombination.QuantityUnitId ?? 0, out var quantityUnit) ? ToDynamic(quantityUnit, ctx) : null; return(result); }
private IQueryable<NewsLetterSubscription> GetNewsLetterSubscriptionQuery(DataExporterContext ctx, int skip, int take) { var storeId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId); var query = _subscriptionRepository.Value.TableUntracked; if (storeId > 0) query = query.Where(x => x.StoreId == storeId); if (ctx.Filter.IsActiveSubscriber.HasValue) query = query.Where(x => x.Active == ctx.Filter.IsActiveSubscriber.Value); if (ctx.Filter.CreatedFrom.HasValue) { var createdFrom = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedFrom.Value, _dateTimeHelper.Value.CurrentTimeZone); query = query.Where(x => createdFrom <= x.CreatedOnUtc); } if (ctx.Filter.CreatedTo.HasValue) { var createdTo = _dateTimeHelper.Value.ConvertToUtcTime(ctx.Filter.CreatedTo.Value, _dateTimeHelper.Value.CurrentTimeZone); query = query.Where(x => createdTo >= x.CreatedOnUtc); } if (ctx.Request.EntitiesToExport.Any()) query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id)); query = query .OrderBy(x => x.StoreId) .ThenBy(x => x.Email); if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private dynamic ToDynamic(MediaFile file, int thumbPictureSize, int detailsPictureSize, DataExporterContext ctx) { return(ToDynamic(_mediaService.ConvertMediaFile(file), thumbPictureSize, detailsPictureSize, ctx)); }
private List<Manufacturer> GetManufacturers(DataExporterContext ctx, int skip) { var manus = GetManufacturerQuery(ctx, skip, PageSize).ToList(); SetProgress(ctx, manus.Count); return manus; }
private void SetProgress(DataExporterContext ctx, int loadedRecords) { try { if (!ctx.IsPreview && loadedRecords > 0) { int totalRecords = ctx.RecordsPerStore.Sum(x => x.Value); if (ctx.Request.Profile.Limit > 0 && totalRecords > ctx.Request.Profile.Limit) totalRecords = ctx.Request.Profile.Limit; ctx.RecordCount = Math.Min(ctx.RecordCount + loadedRecords, totalRecords); var msg = ctx.ProgressInfo.FormatInvariant(ctx.RecordCount, totalRecords); ctx.Request.ProgressValueSetter.Invoke(ctx.RecordCount, totalRecords, msg); } } catch { } }
private static dynamic ToDynamic(ProductSpecificationAttribute productSpecificationAttribute, DataExporterContext ctx) { if (productSpecificationAttribute == null) { return(null); } var option = productSpecificationAttribute.SpecificationAttributeOption; var attribute = option.SpecificationAttribute; dynamic result = new DynamicEntity(productSpecificationAttribute); dynamic dynAttribute = new DynamicEntity(attribute); dynAttribute.Name = ctx.GetTranslation(attribute, nameof(attribute.Name), attribute.Name); dynAttribute._Localized = GetLocalized(ctx, attribute, x => x.Name); dynAttribute.Alias = ctx.GetTranslation(attribute, nameof(attribute.Alias), attribute.Alias); dynAttribute._Localized = GetLocalized(ctx, attribute, x => x.Alias); dynamic dynOption = new DynamicEntity(option); dynOption.Name = ctx.GetTranslation(option, nameof(option.Name), option.Name); dynOption._Localized = GetLocalized(ctx, option, x => x.Name); dynOption.Alias = ctx.GetTranslation(option, nameof(option.Alias), option.Alias); dynOption._Localized = GetLocalized(ctx, option, x => x.Alias); dynOption.SpecificationAttribute = dynAttribute; result.SpecificationAttributeOption = dynOption; return(result); }
private IQueryable<Manufacturer> GetManufacturerQuery(DataExporterContext ctx, int skip, int take) { var showHidden = !ctx.Filter.IsPublished.HasValue; var storeId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId); var query = _manufacturerService.Value.GetManufacturers(showHidden, storeId); if (ctx.Request.EntitiesToExport.Any()) query = query.Where(x => ctx.Request.EntitiesToExport.Contains(x.Id)); query = query.OrderBy(x => x.DisplayOrder); if (skip > 0) query = query.Skip(skip); if (take != int.MaxValue) query = query.Take(take); return query; }
private dynamic ToDynamic(MediaFileInfo file, int thumbPictureSize, int detailsPictureSize, DataExporterContext ctx) { if (file == null) { return(null); } try { var host = ctx.Store.GetHost(); dynamic result = new DynamicEntity(file.File); result._FileName = file.Name; result._RelativeUrl = _mediaService.GetUrl(file, null, null); result._ThumbImageUrl = _mediaService.GetUrl(file, thumbPictureSize, host); result._ImageUrl = _mediaService.GetUrl(file, detailsPictureSize, host); result._FullSizeImageUrl = _mediaService.GetUrl(file, null, host); return(result); } catch (Exception ex) { ctx.Log.Error(ex, $"Failed to get details for file with ID {file.File.Id}."); return(null); } }
/// <summary> /// Applies data of media files (product pictures) to an expando object. /// </summary> private async Task <IEnumerable <ProductMediaFile> > ApplyMediaFiles(dynamic dynObject, Product product, DataExporterContext ctx, DynamicProductContext productContext) { IEnumerable <ProductMediaFile> mediaFiles = await ctx.ProductBatchContext.ProductMediaFiles.GetOrLoadAsync(product.Id); var productPictureSize = ctx.Projection.PictureSize > 0 ? ctx.Projection.PictureSize : _mediaSettings.ProductDetailsPictureSize; if (productContext.Combination != null) { var mediaIds = productContext.Combination.GetAssignedMediaIds(); if (mediaIds.Any()) { mediaFiles = mediaFiles.Where(x => mediaIds.Contains(x.MediaFileId)); } } mediaFiles = mediaFiles.Take(ctx.Projection.NumberOfMediaFiles ?? int.MaxValue); dynObject.ProductPictures = mediaFiles .OrderBy(x => x.DisplayOrder) .Select(x => { dynamic dyn = new DynamicEntity(x); dyn.Picture = ToDynamic(x.MediaFile, _mediaSettings.ProductThumbPictureSize, productPictureSize, ctx); return(dyn); }) .ToList(); return(mediaFiles); }
/// <summary> /// Applies extra data to an expando object. /// Export feature flags set by the export provider controls whether and what to be exported here. /// </summary> private async Task ApplyExportFeatures( dynamic dynObject, Product product, CalculatedPrice price, IEnumerable <ProductMediaFile> mediaFiles, DataExporterContext ctx, DynamicProductContext productContext) { if (ctx.Supports(ExportFeatures.CanProjectDescription)) { await ApplyProductDescription(dynObject, product, ctx); } if (ctx.Supports(ExportFeatures.OffersBrandFallback)) { string brand = null; var productManus = await ctx.ProductBatchContext.ProductManufacturers.GetOrLoadAsync(product.Id); if (productManus?.Any() ?? false) { var manufacturer = productManus.First().Manufacturer; brand = ctx.GetTranslation(manufacturer, nameof(manufacturer.Name), manufacturer.Name); } if (brand.IsEmpty()) { brand = ctx.Projection.Brand; } dynObject._Brand = brand; } if (ctx.Supports(ExportFeatures.CanIncludeMainPicture)) { var imageQuery = ctx.Projection.PictureSize > 0 ? new ProcessImageQuery { MaxWidth = ctx.Projection.PictureSize } : null; if (mediaFiles?.Any() ?? false) { var file = _mediaService.ConvertMediaFile(mediaFiles.Select(x => x.MediaFile).First()); dynObject._MainPictureUrl = _mediaService.GetUrl(file, imageQuery, ctx.Store.GetHost()); dynObject._MainPictureRelativeUrl = _mediaService.GetUrl(file, imageQuery); } else if (!_catalogSettings.HideProductDefaultPictures) { // Get fallback image URL. dynObject._MainPictureUrl = _mediaService.GetUrl(null, imageQuery, ctx.Store.GetHost()); dynObject._MainPictureRelativeUrl = _mediaService.GetUrl(null, imageQuery); } else { dynObject._MainPictureUrl = null; dynObject._MainPictureRelativeUrl = null; } } if (ctx.Supports(ExportFeatures.UsesSkuAsMpnFallback) && product.ManufacturerPartNumber.IsEmpty()) { dynObject.ManufacturerPartNumber = product.Sku; } if (ctx.Supports(ExportFeatures.OffersShippingTimeFallback)) { dynamic deliveryTime = dynObject.DeliveryTime; dynObject._ShippingTime = deliveryTime == null ? ctx.Projection.ShippingTime : deliveryTime.Name; } if (ctx.Supports(ExportFeatures.OffersShippingCostsFallback)) { dynObject._FreeShippingThreshold = ctx.Projection.FreeShippingThreshold; dynObject._ShippingCosts = product.IsFreeShipping || (ctx.Projection.FreeShippingThreshold.HasValue && (decimal)dynObject.Price >= ctx.Projection.FreeShippingThreshold.Value) ? decimal.Zero : ctx.Projection.ShippingCosts; } if (ctx.Supports(ExportFeatures.UsesOldPrice)) { if (product.OldPrice != decimal.Zero && product.OldPrice != (decimal)dynObject.Price && !(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing)) { if (ctx.Projection.ConvertNetToGrossPrices) { var tax = await _taxCalculator.CalculateProductTaxAsync(product, product.OldPrice, true, ctx.ContextCustomer, ctx.ContextCurrency); dynObject._OldPrice = tax.Price; } else { dynObject._OldPrice = product.OldPrice; } } else { dynObject._OldPrice = null; } } if (ctx.Supports(ExportFeatures.UsesSpecialPrice)) { dynObject._SpecialPrice = null; // Special price which is valid now. dynObject._FutureSpecialPrice = null; // Special price which is valid now and in future. dynObject._RegularPrice = null; // Price as if a special price would not exist. if (!(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing)) { if (price.OfferPrice.HasValue && product.SpecialPriceEndDateTimeUtc.HasValue) { var endDate = DateTime.SpecifyKind(product.SpecialPriceEndDateTimeUtc.Value, DateTimeKind.Utc); if (endDate > DateTime.UtcNow) { dynObject._FutureSpecialPrice = price.OfferPrice.Value.Amount; } } dynObject._SpecialPrice = price.OfferPrice?.Amount ?? null; if (price.OfferPrice.HasValue || dynObject._FutureSpecialPrice != null) { var clonedOptions = ctx.PriceCalculationOptions.Clone(); clonedOptions.IgnoreOfferPrice = true; var calculationContext = new PriceCalculationContext(product, clonedOptions); calculationContext.AddSelectedAttributes(productContext?.Combination?.AttributeSelection, product.Id); var priceWithoutOfferPrice = await _priceCalculationService.CalculatePriceAsync(calculationContext); dynObject._RegularPrice = priceWithoutOfferPrice.FinalPrice.Amount; } } } }
/// <summary> /// Applies the product description to an expando object. /// Projection settings controls in detail how the product description is to be exported here. /// </summary> private static async Task ApplyProductDescription(dynamic dynObject, Product product, DataExporterContext ctx) { try { var languageId = ctx.LanguageId; string description = ""; // Description merging. if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.None) { // Export empty description. } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.ShortDescriptionOrNameIfEmpty) { description = dynObject.FullDescription; if (description.IsEmpty()) { description = dynObject.ShortDescription; } if (description.IsEmpty()) { description = dynObject.Name; } } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.ShortDescription) { description = dynObject.ShortDescription; } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.Description) { description = dynObject.FullDescription; } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.NameAndShortDescription) { description = ((string)dynObject.Name).Grow((string)dynObject.ShortDescription, " "); } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.NameAndDescription) { description = ((string)dynObject.Name).Grow((string)dynObject.FullDescription, " "); } else if (ctx.Projection.DescriptionMerging == ExportDescriptionMerging.ManufacturerAndNameAndShortDescription || ctx.Projection.DescriptionMerging == ExportDescriptionMerging.ManufacturerAndNameAndDescription) { var productManus = await ctx.ProductBatchContext.ProductManufacturers.GetOrLoadAsync(product.Id); if (productManus != null && productManus.Any()) { var manufacturer = productManus.First().Manufacturer; description = ctx.GetTranslation(manufacturer, nameof(manufacturer.Name), manufacturer.Name); } description = description.Grow((string)dynObject.Name, " "); description = ctx.Projection.DescriptionMerging == ExportDescriptionMerging.ManufacturerAndNameAndShortDescription ? description.Grow((string)dynObject.ShortDescription, " ") : description.Grow((string)dynObject.FullDescription, " "); } // Append text. if (ctx.Projection.AppendDescriptionText.HasValue() && ((string)dynObject.ShortDescription).IsEmpty() && ((string)dynObject.FullDescription).IsEmpty()) { var appendText = ctx.Projection.AppendDescriptionText.SplitSafe(",").ToArray(); if (appendText.Any()) { var rnd = CommonHelper.GenerateRandomInteger(0, appendText.Length - 1); description = description.Grow(appendText.ElementAtOrDefault(rnd), " "); } } // Remove critical characters. if (description.HasValue() && ctx.Projection.RemoveCriticalCharacters) { foreach (var str in ctx.Projection.CriticalCharacters.SplitSafe(",")) { description = description.Replace(str, ""); } } // Convert to plain text. if (description.HasValue() && ctx.Projection.DescriptionToPlainText) { //Regex reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase); //description = HttpUtility.HtmlDecode(reg.Replace(description, "")); description = HtmlUtils.ConvertHtmlToPlainText(description); description = HtmlUtils.StripTags(HttpUtility.HtmlDecode(description)); } dynObject.FullDescription = description.TrimSafe(); } catch { } }
/// <summary> /// Creates an expando object with all product properties. /// This method is used when exporting products and when exporting variant combinations as products. /// </summary> private async Task <dynamic> ToDynamic(Product product, bool isParent, DataExporterContext ctx, DynamicProductContext productContext) { var combination = productContext.Combination; product.MergeWithCombination(combination); var productManufacturers = await ctx.ProductBatchContext.ProductManufacturers.GetOrLoadAsync(product.Id); var productCategories = await ctx.ProductBatchContext.ProductCategories.GetOrLoadAsync(product.Id); var productAttributes = await ctx.ProductBatchContext.Attributes.GetOrLoadAsync(product.Id); var productTags = await ctx.ProductBatchContext.ProductTags.GetOrLoadAsync(product.Id); var specificationAttributes = await ctx.ProductBatchContext.SpecificationAttributes.GetOrLoadAsync(product.Id); var selectedAttributes = combination?.AttributeSelection; var variantAttributeValues = combination?.AttributeSelection?.MaterializeProductVariantAttributeValues(productAttributes); // Price calculation. var calculationContext = new PriceCalculationContext(product, ctx.PriceCalculationOptions); calculationContext.AddSelectedAttributes(combination?.AttributeSelection, product.Id); var price = await _priceCalculationService.CalculatePriceAsync(calculationContext); dynamic dynObject = ToDynamic(product, ctx, productContext.SeName, price.FinalPrice); dynObject._IsParent = isParent; dynObject._CategoryName = null; dynObject._CategoryPath = null; dynObject._AttributeCombinationValues = null; dynObject._AttributeCombinationId = 0; dynObject.Price = price.FinalPrice.Amount; if (combination != null) { dynObject._AttributeCombinationId = combination.Id; dynObject._UniqueId = product.Id + "-" + combination.Id; if (ctx.Supports(ExportFeatures.UsesAttributeCombination)) { dynObject._AttributeCombinationValues = variantAttributeValues; } if (ctx.Projection.AttributeCombinationValueMerging == ExportAttributeValueMerging.AppendAllValuesToName) { var valueNames = variantAttributeValues .Select(x => ctx.GetTranslation(x, nameof(x.Name), x.Name)) .ToList(); dynObject.Name = ((string)dynObject.Name).Grow(string.Join(", ", valueNames), " "); } } else { dynObject._UniqueId = product.Id.ToString(); } if (selectedAttributes?.AttributesMap?.Any() ?? false) { var query = new ProductVariantQuery(); await _productUrlHelper.AddAttributesToQueryAsync(query, selectedAttributes, product.Id, 0, productAttributes); dynObject._DetailUrl = productContext.AbsoluteProductUrl + _productUrlHelper.ToQueryString(query); } else { dynObject._DetailUrl = productContext.AbsoluteProductUrl; } // Category path. { var categoryPath = string.Empty; var pc = productCategories.OrderBy(x => x.DisplayOrder).FirstOrDefault(); if (pc != null) { var node = await _categoryService.GetCategoryTreeAsync(pc.CategoryId, true, ctx.Store.Id); if (node != null) { categoryPath = _categoryService.GetCategoryPath(node, ctx.Projection.LanguageId, null, " > "); } } dynObject._CategoryPath = categoryPath; } dynObject.CountryOfOrigin = ctx.Countries.TryGetValue(product.CountryOfOriginId ?? 0, out var countryOfOrigin) ? ToDynamic(countryOfOrigin, ctx) : null; dynObject.ProductManufacturers = productManufacturers .OrderBy(x => x.DisplayOrder) .Select(x => { dynamic dyn = new DynamicEntity(x); dyn.Manufacturer = ToDynamic(x.Manufacturer, ctx); dyn.Manufacturer.Picture = x.Manufacturer != null && x.Manufacturer.MediaFileId.HasValue ? ToDynamic(x.Manufacturer.MediaFile, _mediaSettings.ManufacturerThumbPictureSize, _mediaSettings.ManufacturerThumbPictureSize, ctx) : null; return(dyn); }) .ToList(); dynObject.ProductCategories = productCategories .OrderBy(x => x.DisplayOrder) .Select(x => { dynamic dyn = new DynamicEntity(x); dyn.Category = ToDynamic(x.Category, ctx); dyn.Category.Picture = x.Category != null && x.Category.MediaFileId.HasValue ? ToDynamic(x.Category.MediaFile, _mediaSettings.CategoryThumbPictureSize, _mediaSettings.CategoryThumbPictureSize, ctx) : null; if (dynObject._CategoryName == null) { dynObject._CategoryName = (string)dyn.Category.Name; } return(dyn); }) .ToList(); dynObject.ProductAttributes = productAttributes .OrderBy(x => x.DisplayOrder) .Select(x => ToDynamic(x, ctx)) .ToList(); // Do not export combinations if a combination is exported as a product. if (productContext.Combinations != null && productContext.Combination == null) { var pictureSize = ctx.Projection.PictureSize > 0 ? ctx.Projection.PictureSize : _mediaSettings.ProductDetailsPictureSize; var productMediaFiles = (await ctx.ProductBatchContext.ProductMediaFiles.GetOrLoadAsync(product.Id)) .ToDictionarySafe(x => x.MediaFileId, x => x); dynObject.ProductAttributeCombinations = productContext.Combinations .Select(x => { dynamic dyn = DataExporter.ToDynamic(x, ctx); var assignedFiles = new List <dynamic>(); foreach (var fileId in x.GetAssignedMediaIds().Take(ctx.Projection.NumberOfMediaFiles ?? int.MaxValue)) { if (productMediaFiles.TryGetValue(fileId, out var assignedFile) && assignedFile.MediaFile != null) { assignedFiles.Add(ToDynamic(assignedFile.MediaFile, _mediaSettings.ProductThumbPictureSize, pictureSize, ctx)); } } dyn.Pictures = assignedFiles; return(dyn); }) .ToList(); } else { dynObject.ProductAttributeCombinations = Enumerable.Empty <ProductVariantAttributeCombination>(); } if (product.HasTierPrices) { var tierPrices = await ctx.ProductBatchContext.TierPrices.GetOrLoadAsync(product.Id); dynObject.TierPrices = tierPrices .RemoveDuplicatedQuantities() .Select(x => { dynamic dyn = new DynamicEntity(x); return(dyn); }) .ToList(); } if (product.HasDiscountsApplied) { var appliedDiscounts = await ctx.ProductBatchContext.AppliedDiscounts.GetOrLoadAsync(product.Id); dynObject.AppliedDiscounts = appliedDiscounts .Select(x => CreateDynamic(x)) .ToList(); } if (product.IsDownload) { var downloads = await ctx.ProductBatchContext.Downloads.GetOrLoadAsync(product.Id); dynObject.Downloads = downloads .Select(x => CreateDynamic(x)) .ToList(); } dynObject.ProductTags = productTags .Select(x => { var localizedName = ctx.GetTranslation(x, nameof(x.Name), x.Name); dynamic dyn = new DynamicEntity(x); dyn.Name = localizedName; dyn.SeName = SeoHelper.BuildSlug(localizedName, _seoSettings); dyn._Localized = GetLocalized(ctx, x, y => y.Name); return(dyn); }) .ToList(); dynObject.ProductSpecificationAttributes = specificationAttributes .Select(x => ToDynamic(x, ctx)) .ToList(); if (product.ProductType == ProductType.BundledProduct) { var bundleItems = await ctx.ProductBatchContext.ProductBundleItems.GetOrLoadAsync(product.Id); dynObject.ProductBundleItems = bundleItems .Select(x => { dynamic dyn = new DynamicEntity(x); dyn.Name = ctx.GetTranslation(x, nameof(x.Name), x.Name); dyn.ShortDescription = ctx.GetTranslation(x, nameof(x.ShortDescription), x.ShortDescription); dyn._Localized = GetLocalized(ctx, x, y => y.Name, y => y.ShortDescription); return(dyn); }) .ToList(); } var mediaFiles = await ApplyMediaFiles(dynObject, product, ctx, productContext); await ApplyExportFeatures(dynObject, product, price, mediaFiles, ctx, productContext); return(dynObject); }
private List<Product> GetProducts(DataExporterContext ctx, int skip) { // we use ctx.EntityIdsPerSegment to avoid exporting products multiple times per segment\file (cause of associated products). var result = new List<Product>(); var products = GetProductQuery(ctx, skip, PageSize).ToList(); foreach (var product in products) { if (product.ProductType == ProductType.SimpleProduct || product.ProductType == ProductType.BundledProduct) { if (!ctx.EntityIdsPerSegment.Contains(product.Id)) { result.Add(product); ctx.EntityIdsPerSegment.Add(product.Id); } } else if (product.ProductType == ProductType.GroupedProduct) { if (ctx.Projection.NoGroupedProducts && !ctx.IsPreview) { var associatedSearchContext = new ProductSearchContext { OrderBy = ProductSortingEnum.Position, PageSize = int.MaxValue, StoreId = (ctx.Request.Profile.PerStore ? ctx.Store.Id : ctx.Filter.StoreId), VisibleIndividuallyOnly = false, ParentGroupedProductId = product.Id }; foreach (var associatedProduct in _productService.Value.SearchProducts(associatedSearchContext)) { if (!ctx.EntityIdsPerSegment.Contains(associatedProduct.Id)) { result.Add(associatedProduct); ctx.EntityIdsPerSegment.Add(associatedProduct.Id); } } } else { if (!ctx.EntityIdsPerSegment.Contains(product.Id)) { result.Add(product); ctx.EntityIdsPerSegment.Add(product.Id); } } } } SetProgress(ctx, products.Count); return result; }
private static List <dynamic> GetLocalized <TEntity>( DataExporterContext ctx, TEntity entity, params Expression <Func <TEntity, string> >[] keySelectors) where TEntity : BaseEntity, ILocalizedEntity { if (ctx.Languages.Count <= 1) { return(null); } var translations = ctx.GetTranslations <TEntity>(); if (translations == null) { return(null); } var slugs = ctx.GetUrlRecords <TEntity>(); var result = new List <dynamic>(); foreach (var language in ctx.Languages) { var languageCulture = language.Value.LanguageCulture.EmptyNull().ToLower(); // Add slug. if (slugs != null) { var value = slugs.GetSlug(language.Value.Id, entity.Id, false); if (value.HasValue()) { dynamic exp = new HybridExpando(); exp.Culture = languageCulture; exp.LocaleKey = "SeName"; exp.LocaleValue = value; result.Add(exp); } } // Add localized property value. foreach (var keySelector in keySelectors) { var member = keySelector.Body as MemberExpression; var propInfo = member.Member as PropertyInfo; string localeKey = propInfo.Name; var value = translations.GetValue(language.Value.Id, entity.Id, localeKey); // We do not export empty values to not fill databases with it. if (value.HasValue()) { dynamic exp = new HybridExpando(); exp.Culture = languageCulture; exp.LocaleKey = localeKey; exp.LocaleValue = value; result.Add(exp); } } } return(result.Any() ? result : null); }
/// <summary> /// The main method to create expando objects for a product to be exported. /// Returns several objects if variant combinations are to be exported as products. /// </summary> private async Task <IEnumerable <dynamic> > Convert(Product product, DataExporterContext ctx) { var result = new List <dynamic>(); var seName = ctx.GetUrlRecord(product); var productContext = new DynamicProductContext { SeName = seName, Combinations = await ctx.ProductBatchContext.AttributeCombinations.GetOrLoadAsync(product.Id), AbsoluteProductUrl = await _productUrlHelper.GetAbsoluteProductUrlAsync(product.Id, seName, null, ctx.Store, ctx.ContextLanguage) }; if (ctx.Projection.AttributeCombinationAsProduct && productContext.Combinations.Where(x => x.IsActive).Any()) { if (ctx.Supports(ExportFeatures.UsesAttributeCombinationParent)) { var dynObject = await ToDynamic(product, true, ctx, productContext); result.Add(dynObject); } var dbContext = _db as DbContext; foreach (var combination in productContext.Combinations.Where(x => x.IsActive)) { var attachedProduct = _db.Attach(product); product = attachedProduct.Entity; var entry = dbContext.Entry(product); // The returned object is not the entity and is not being tracked by the context. // It also does not have any relationships set to other objects. // CurrentValues only includes database (thus primitive) values. var productClone = entry.CurrentValues.ToObject() as Product; _db.DetachEntity(product); productContext.Combination = combination; var dynObject = await ToDynamic(productClone, false, ctx, productContext); result.Add(dynObject); } } else { var dynObject = await ToDynamic(product, false, ctx, productContext); result.Add(dynObject); } if (result.Any()) { await _services.EventPublisher.PublishAsync(new RowExportingEvent { Row = result.First(), EntityType = ExportEntityType.Product, ExportRequest = ctx.Request, ExecuteContext = ctx.ExecuteContext }); } return(result); }