Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        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);
        }
Esempio n. 16
0
        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;
        }
Esempio n. 25
0
        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;
        }
Esempio n. 31
0
        /// <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;
        }
Esempio n. 35
0
        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;
        }
Esempio n. 39
0
        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;
        }
Esempio n. 42
0
        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;
        }
Esempio n. 44
0
 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 { }
        }
Esempio n. 47
0
        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;
        }
Esempio n. 49
0
        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);
            }
        }
Esempio n. 50
0
        /// <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);
        }
Esempio n. 51
0
        /// <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;
                    }
                }
            }
        }
Esempio n. 52
0
        /// <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 { }
        }
Esempio n. 53
0
        /// <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;
        }
Esempio n. 55
0
        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);
        }
Esempio n. 56
0
        /// <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);
        }