diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples.csproj b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples.csproj index 70a173d..bfdd9cb 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples.csproj +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Examples.csproj @@ -23,8 +23,8 @@ snupkg - - + + diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Global.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Global.cs index 111a0c2..a3b1bd1 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Global.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Global.cs @@ -1,5 +1,6 @@ using Dynamicweb.Core; using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Connectors; +using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Extensions; using Dynamicweb.Frontend; namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Configuration @@ -105,7 +106,7 @@ public static bool IsLazyLoadingForProductInfoEnabled(Settings settings) { return Global.IsIntegrationActive(settings) && settings.EnableLivePrices && Connector.IsWebServiceConnectionAvailable(settings, SubmitType.Live) && (settings.LiveProductInfoForAnonymousUsers || Helpers.GetCurrentExtranetUser() != null) - && (Helpers.GetCurrentExtranetUser() == null || !Helpers.GetCurrentExtranetUser().IsLivePricesDisabled) + && (Helpers.GetCurrentExtranetUser() == null || !Helpers.GetCurrentExtranetUser().IsLiveIntegrationPricesDisabled()) && settings.LazyLoadProductInfo; } } diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/ISettings.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/ISettings.cs index 7636cda..44bf014 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/ISettings.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/ISettings.cs @@ -1,4 +1,7 @@ -namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Configuration +using Dynamicweb.Extensibility.AddIns; +using Dynamicweb.Extensibility.Editors; + +namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Configuration { /// /// Interface to define settings for the Live Integration. @@ -327,5 +330,11 @@ public interface ISettings /// Gets or sets a value that determines the max number of products on each live request. /// int MaxProductsPerRequest { get; set; } + + /// + /// When enabled anonymous users will receive discounts calculated by DynamicWeb instead of retrieving them from the ERP via Live Integration + /// + /// true if [disable ERP discounts calculation for anonymous users]; otherwise, false. + public bool DisableErpDiscountsForAnonymousUsers { get; set; } } } \ No newline at end of file diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Settings.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Settings.cs index 47253fd..55aee08 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Settings.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Configuration/Settings.cs @@ -1,6 +1,8 @@ using Dynamicweb.Core; using Dynamicweb.Core.Helpers; using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Cache; +using Dynamicweb.Extensibility.AddIns; +using Dynamicweb.Extensibility.Editors; using Dynamicweb.Security.UserManagement; using System; using System.Collections.Generic; @@ -329,6 +331,12 @@ public string InstanceName /// public bool MakeRetryForLiveProductInformation { get; set; } + /// + /// When enabled anonymous users will receive discounts calculated by DynamicWeb instead of retrieving them from the ERP via Live Integration + /// + /// true if [disable ERP discounts calculation for anonymous users]; otherwise, false. + public bool DisableErpDiscountsForAnonymousUsers { get; set; } + #endregion Users parameters #region Notifications parameters @@ -456,6 +464,7 @@ public static void UpdateFrom(ISettings source, ISettings target) target.OrderStateAfterExportFailed = source.OrderStateAfterExportFailed; target.SkipLedgerOrder = source.SkipLedgerOrder; target.ErpControlsDiscount = source.ErpControlsDiscount; + target.DisableErpDiscountsForAnonymousUsers = source.DisableErpDiscountsForAnonymousUsers; target.ErpControlsShipping = source.ErpControlsShipping; target.ErpShippingItemType = source.ErpShippingItemType; target.ErpShippingItemKey = source.ErpShippingItemKey; diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj index d2c7dde..e46edb6 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj @@ -1,6 +1,6 @@  - 10.4.31 + 10.20.0 1.0.0.0 Live Integration Live Integration @@ -23,7 +23,7 @@ snupkg - + diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Extensions/UserExtensions.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Extensions/UserExtensions.cs new file mode 100644 index 0000000..ee04d05 --- /dev/null +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Extensions/UserExtensions.cs @@ -0,0 +1,32 @@ +using Dynamicweb.Core; +using Dynamicweb.Security.UserManagement; +using System.Linq; + +namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Extensions +{ + public static class UserExtensions + { + internal static bool IsLiveIntegrationPricesDisabled(this User user) + { + if (user.IsLivePricesDisabled) + return true; + + var key = $"DynamicwebLiveIntegrationIsLivePricesDisabled{user.ID}"; + var cacheValue = Context.Current?.Items?[key]; + if (cacheValue is not null) + { + return Converter.ToBoolean(cacheValue); + } + else + { + var groups = user.GetAncestorGroups(); + bool result = groups.Any(g => g.IsLivePricesDisabled); + if (Context.Current?.Items is not null) + { + Context.Current.Items[key] = result; + } + return result; + } + } + } +} diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Helpers.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Helpers.cs index 5e2aa28..3a30b85 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Helpers.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Helpers.cs @@ -304,7 +304,7 @@ internal static bool CanCheckPrice(Settings settings, Product product, User user || !settings.EnableLivePrices || Global.IsProductLazyLoad(settings) || (user == null && !settings.LiveProductInfoForAnonymousUsers) - || (user != null && user.IsLivePricesDisabled) + || (user != null && user.IsLiveIntegrationPricesDisabled()) || !Connector.IsWebServiceConnectionAvailable(settings, SubmitType.Live) || product == null || string.IsNullOrEmpty(product.Id) diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/LiveIntegrationAddIn.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/LiveIntegrationAddIn.cs index 398d97f..33ae9f2 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/LiveIntegrationAddIn.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/LiveIntegrationAddIn.cs @@ -465,6 +465,16 @@ public LiveIntegrationAddIn() [AddInParameterOrder(210)] public bool EnableCartCommunicationForAnonymousUsers { get; set; } + /// + /// When enabled anonymous users will receive discounts calculated by DynamicWeb instead of retrieving them from the ERP via Live Integration + /// + /// /// true if [disable ERP discounts calculation for anonymous users]; otherwise, false. + [AddInParameter("Disable ERP discounts for anonymous users")] + [AddInParameterEditor(typeof(YesNoParameterEditor), "explanation=When enabled anonymous users will receive discounts calculated by DynamicWeb instead of retrieving them from the ERP via Live Integration;")] + [AddInParameterGroup("Users")] + [AddInParameterOrder(220)] + public bool DisableErpDiscountsForAnonymousUsers { get; set; } + /// /// Gets or sets the customer name used in integration scenarios with anonymous users. /// @@ -494,7 +504,7 @@ public LiveIntegrationAddIn() /// /// The notification email. [AddInParameter("Notification recipient groups")] - [AddInParameterEditor(typeof(UserGroupParameterEditor), "Multiple=true;")] + [AddInParameterEditor(typeof(UserGroupParameterEditor), "Multiple=true;")] [AddInParameterGroup("Notifications")] [AddInParameterOrder(235)] public string RecipientGroups { get; set; } @@ -807,7 +817,7 @@ public override void SaveSettings() { AutoPingInterval = Constants.MinPingInterval; } - if(ConnectionTimeout < Constants.DefaultConnectionTimeout) + if (ConnectionTimeout < Constants.DefaultConnectionTimeout) { ConnectionTimeout = Constants.DefaultConnectionTimeout; } diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/NotificationSubscribers/VariantListBeforeRender.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/NotificationSubscribers/VariantListBeforeRender.cs index d1ba415..7fee5eb 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/NotificationSubscribers/VariantListBeforeRender.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/NotificationSubscribers/VariantListBeforeRender.cs @@ -1,4 +1,5 @@ using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Configuration; +using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Extensions; using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Products; using Dynamicweb.Ecommerce.Products; using Dynamicweb.Extensibility.Notifications; @@ -50,7 +51,7 @@ private static bool CanCheckPrice(Settings settings) { return EnabledAndActive(settings, SubmitType.Live) && settings.EnableLivePrices && (settings.LiveProductInfoForAnonymousUsers || Helpers.GetCurrentExtranetUser() != null) && - (Helpers.GetCurrentExtranetUser() == null || !Helpers.GetCurrentExtranetUser().IsLivePricesDisabled) && + (Helpers.GetCurrentExtranetUser() == null || !Helpers.GetCurrentExtranetUser().IsLiveIntegrationPricesDisabled()) && !Global.IsProductLazyLoad(settings); } } diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs index f1ab29e..f61466e 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs @@ -88,6 +88,8 @@ private static ResponseCacheLevel GetOrderCacheLevel(Settings settings) return null; } + bool erpControlsDiscount = IsUserErpDiscountAllowed(settings, user); + // default states successOrderStateId ??= settings.OrderStateAfterExportSucceeded; @@ -99,11 +101,11 @@ private static ResponseCacheLevel GetOrderCacheLevel(Settings settings) CreateOrder = createOrder, LiveIntegrationSubmitType = liveIntegrationSubmitType, ReferenceName = "OrdersPut", - ErpControlsDiscount = settings.ErpControlsDiscount, + ErpControlsDiscount = erpControlsDiscount, ErpControlsShipping = settings.ErpControlsShipping, ErpShippingItemKey = settings.ErpShippingItemKey, ErpShippingItemType = settings.ErpShippingItemType, - CalculateOrderUsingProductNumber = settings.CalculateOrderUsingProductNumber + CalculateOrderUsingProductNumber = settings.CalculateOrderUsingProductNumber, }; var requestXml = new OrderXmlGenerator().GenerateOrderXml(settings, order, xmlGeneratorSettings, logger); xmlGeneratorSettings.GenerateXmlForHash = true; @@ -135,7 +137,7 @@ private static ResponseCacheLevel GetOrderCacheLevel(Settings settings) XmlDocument response = GetResponse(settings, requestXml, order, createOrder, logger, out bool? requestCancelled, liveIntegrationSubmitType); if (response != null && !string.IsNullOrWhiteSpace(response.InnerXml)) { - bool processResponseResult = ProcessResponse(settings, response, order, createOrder, successOrderStateId, failedOrderStateId, logger); + bool processResponseResult = ProcessResponse(settings, response, order, createOrder, successOrderStateId, failedOrderStateId, logger, erpControlsDiscount); Diagnostics.ExecutionTable.Current.Add("DynamicwebLiveIntegration.OrderHandler.UpdateOrder END"); return processResponseResult; } @@ -465,7 +467,8 @@ private static void OrderPriceCalculation(Settings settings, Order order, XmlNod /// The discount order lines. /// The order line node. /// Type of the order line. - private static void ProcessDiscountOrderLine(Settings settings, Order order, OrderLineCollection discountOrderLines, XmlNode orderLineNode, string orderLineType, Logger logger, List orderLineIds, OrderLineFieldCollection allOrderLineFields) + private static void ProcessDiscountOrderLine(Settings settings, Order order, OrderLineCollection discountOrderLines, XmlNode orderLineNode, string orderLineType, Logger logger, List orderLineIds, OrderLineFieldCollection allOrderLineFields, + bool erpControlsDiscount) { string orderLineId = orderLineNode.SelectSingleNode("column [@columnName='OrderLineId']")?.InnerText; @@ -476,7 +479,7 @@ private static void ProcessDiscountOrderLine(Settings settings, Order order, Ord OrderLineType = Services.OrderLines.GetOrderLineType(orderLineType) }; - if (!settings.ErpControlsDiscount) + if (erpControlsDiscount) { orderLine.DiscountId = orderLineNode.SelectSingleNode("column [@columnName='OrderLineDiscountId']")?.InnerText; } @@ -538,7 +541,7 @@ private static void ProcessDiscountOrderLine(Settings settings, Order order, Ord } orderLine.ProductName = DiscountTranslation.GetDiscountName(settings, orderLineNode, orderLine); - if (settings.ErpControlsDiscount) + if (erpControlsDiscount) { orderLine.AllowOverridePrices = true; } @@ -598,7 +601,7 @@ private static void ProcessDiscountOrderLine(Settings settings, Order order, Ord /// The response. /// The order. /// The discount order lines. - private static void ProcessOrderLines(Settings settings, XmlDocument response, Order order, OrderLineCollection discountOrderLines, Logger logger) + private static void ProcessOrderLines(Settings settings, XmlDocument response, Order order, OrderLineCollection discountOrderLines, Logger logger, bool erpControlsDiscount) { XmlNodeList orderLinesNodes = response.SelectNodes("//item [@table='EcomOrderLines']"); @@ -612,7 +615,7 @@ private static void ProcessOrderLines(Settings settings, XmlDocument response, O { allOrderLineFields = Services.OrderLineFields.GetOrderLineFields(); } - bool processDiscounts = (settings.ErpControlsDiscount || !order.Complete); + bool processDiscounts = erpControlsDiscount || !order.Complete; Dictionary responseIdOrderLineDictionary = new Dictionary(); foreach (XmlNode orderLineNode in orderLinesNodes) @@ -627,7 +630,7 @@ private static void ProcessOrderLines(Settings settings, XmlDocument response, O // 1=order discount, 3=Product Discount if (processDiscounts && (orderLineType == "1" || orderLineType == "3")) { - ProcessDiscountOrderLine(settings, order, discountOrderLines, orderLineNode, orderLineType, logger, orderLineIds, allOrderLineFields); + ProcessDiscountOrderLine(settings, order, discountOrderLines, orderLineNode, orderLineType, logger, orderLineIds, allOrderLineFields, erpControlsDiscount); } // 4=Product Tax @@ -637,7 +640,7 @@ private static void ProcessOrderLines(Settings settings, XmlDocument response, O } } - bool keepDiscountOrderLines = !settings.ErpControlsDiscount && order.Complete; + bool keepDiscountOrderLines = !erpControlsDiscount && order.Complete; // Remove deleted OrderLines List linesToRemove = new List(); for (int i = order.OrderLines.Count - 1; i >= 0; i--) @@ -659,7 +662,7 @@ private static void ProcessOrderLines(Settings settings, XmlDocument response, O order.OrderLines.Remove(orderLine); Services.OrderLines.Delete(orderLine.Id); } - MergeOrderLines(settings, order); + MergeOrderLines(settings, order, erpControlsDiscount); } } @@ -879,7 +882,7 @@ private static void ProcessProductOrderLine(Settings settings, Order order, List /// State of the success. /// State of the failed. /// true if response was processed successfully, false otherwise. - private static bool ProcessResponse(Settings settings, XmlDocument response, Order order, bool createOrder, string successState, string failedState, Logger logger) + private static bool ProcessResponse(Settings settings, XmlDocument response, Order order, bool createOrder, string successState, string failedState, Logger logger, bool erpControlsDiscount) { var orderId = order == null ? "is null" : order.Id ?? "ID is null"; if (response == null || order == null) @@ -903,7 +906,7 @@ private static bool ProcessResponse(Settings settings, XmlDocument response, Ord { shippingFeeSentInRequest = order.ShippingFee; } - if (!createOrder && settings.ErpControlsDiscount) + if (!createOrder && erpControlsDiscount) order.IsPriceCalculatedByProvider = true; SetCustomOrderFields(settings, order, orderNode); @@ -914,16 +917,16 @@ private static bool ProcessResponse(Settings settings, XmlDocument response, Ord if (enableCartCommunication) { - ProcessOrderLines(settings, response, order, discountOrderLines, logger); + ProcessOrderLines(settings, response, order, discountOrderLines, logger, erpControlsDiscount); - if (!order.Complete || settings.ErpControlsDiscount) + if (!order.Complete || erpControlsDiscount) { - if (settings.ErpControlsDiscount) + if (erpControlsDiscount) { foreach (var discountLine in discountOrderLines) order.OrderLines.Add(discountLine, false); - SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice); + SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice, erpControlsDiscount); SetTotalOrderDiscount(order); // When GetCart DwApi request is executed and ERP controls discounts: @@ -938,23 +941,23 @@ private static bool ProcessResponse(Settings settings, XmlDocument response, Ord } else if (!order.Complete) { - SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice); + SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice, erpControlsDiscount); Services.Orders.CalculateDiscounts(order); } else { - SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice); + SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice, erpControlsDiscount); } } else { - SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice); + SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice, erpControlsDiscount); } LiveShippingFeeProvider.ProcessShipping(settings, order, orderNode, logger); } else { - SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice); + SetOrderPrices(order, orderNode, settings, logger, orderId, out updatePriceBeforeFeesFromOrderPrice, erpControlsDiscount); } if (createOrder) @@ -1003,12 +1006,12 @@ private static bool ProcessResponse(Settings settings, XmlDocument response, Ord return true; } - private static void SetOrderPrices(Order order, XmlNode orderNode, Settings settings, Logger logger, string orderId, out bool updatePriceBeforeFeesFromOrderPrice) + private static void SetOrderPrices(Order order, XmlNode orderNode, Settings settings, Logger logger, string orderId, out bool updatePriceBeforeFeesFromOrderPrice, bool erpControlsDiscount) { updatePriceBeforeFeesFromOrderPrice = false; // Set Order prices - order.AllowOverridePrices = settings.ErpControlsDiscount; - order.DisableDiscountCalculation = settings.ErpControlsDiscount; + order.AllowOverridePrices = erpControlsDiscount; + order.DisableDiscountCalculation = erpControlsDiscount; try { SetPrices(settings, order, orderNode, logger, out updatePriceBeforeFeesFromOrderPrice); @@ -1233,9 +1236,9 @@ private static OrderLine GetBomOrderLine(XmlNode orderLineNode, Dictionary g.IsLiveDiscountsDisabled)) + return false; + + return true; + } } } \ No newline at end of file diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductManager.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductManager.cs index 5f26f52..b037f01 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductManager.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductManager.cs @@ -149,7 +149,7 @@ internal static bool FetchProductInfos(List products, Liv return false; } - if (context.User != null && context.User.IsLivePricesDisabled) + if (context.User != null && context.User.IsLiveIntegrationPricesDisabled()) { logger.Log(ErrorLevel.DebugInfo, $"Calculated prices are not allowed for the user '{context.User.UserName}'."); return false; diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductPriceProvider.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductPriceProvider.cs index 313bd85..71278b1 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductPriceProvider.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Products/ProductPriceProvider.cs @@ -66,7 +66,7 @@ public override void PreparePrices(PriceContext context, IEnumerable