Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public override void OnNotify(string notification, NotificationArgs args)
if (myArgs?.Document != null)
{
var settings = SettingsManager.GetSettingsByShop(myArgs.Order.ShopId);
if (settings != null && !settings.ErpControlsShipping)
if (settings != null && settings.ShippingControlMode == Constants.ShippingControlMode.DynamicwebControlsShipping)
{
var order = myArgs.Order;
var shipping = Services.Shippings.GetShipping(order.ShippingMethodId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,24 @@ internal static class OrderConfiguration

public const string DefaultShippingItemType = "ItemCharge";
}

/// <summary>
/// Provides string constants that define the available modes for controlling shipping calculation and data
/// exchange between Dynamicweb and an ERP system.
/// </summary>
/// <remarks>Use these constants to specify how shipping fees and information are managed in
/// integrations between Dynamicweb and ERP systems. Each mode determines whether shipping is calculated by
/// Dynamicweb, by the ERP, or based on selections made in Dynamicweb and processed by the ERP.</remarks>
public static class ShippingControlMode
{
/// <summary>Dynamicweb calculates and sends the shipping fee to the ERP.</summary>
public const string DynamicwebControlsShipping = "DynamicwebControlsShipping";

/// <summary>ERP controls shipping entirely; no shipping data is sent from Dynamicweb.</summary>
public const string ErpControlsShipping = "ErpControlsShipping";

/// <summary>The customer selects a shipping method in Dynamicweb; the ERP calculates the freight cost based on the selected method's identity fields.</summary>
public const string ErpCalculatesBasedOnDwSelection = "ErpCalculatesBasedOnDwSelection";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,9 @@ public interface ISettings
string ErpShippingItemKey { get; set; }

/// <summary>
/// Gets or sets if ERP controls shipping calculations
/// Gets or sets the shipping control mode.
/// </summary>
/// <value><c>true</c> if [ERP controls shipping calculations]; otherwise, <c>false</c>.</value>
bool ErpControlsShipping { get; set; }
string ShippingControlMode { get; set; }

/// <summary>
/// Gets or sets if the orderline should be set to fixed when unitprice is set by the orderhandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public Settings()
WebServiceConnectionStatusGlobalTagName = "Global:LiveIntegration.IsWebServiceConnectionAvailable";

ErpControlsDiscount = true;
ErpControlsShipping = true;
ShippingControlMode = Constants.ShippingControlMode.ErpControlsShipping;

SetOrderlineFixed = false;

Expand Down Expand Up @@ -263,10 +263,9 @@ public string InstanceName
public bool ErpControlsDiscount { get; set; }

/// <summary>
/// Gets or sets if ERP controls shipping
/// Gets or sets the shipping control mode.
/// </summary>
/// <value><c>true</c> if [ERP controls shipping]; otherwise, <c>false</c>.</value>
public bool ErpControlsShipping { get; set; }
public string ShippingControlMode { get; set; }

/// <summary>
/// Gets or sets the key for shipping item type.
Expand Down Expand Up @@ -470,7 +469,7 @@ public static void UpdateFrom(ISettings source, ISettings target)
target.SkipLedgerOrder = source.SkipLedgerOrder;
target.ErpControlsDiscount = source.ErpControlsDiscount;
target.DisableErpDiscountsForAnonymousUsers = source.DisableErpDiscountsForAnonymousUsers;
target.ErpControlsShipping = source.ErpControlsShipping;
target.ShippingControlMode = source.ShippingControlMode;
target.ErpShippingItemType = source.ErpShippingItemType;
target.ErpShippingItemKey = source.ErpShippingItemKey;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>10.21.5</Version>
<Version>10.21.6</Version>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<Title>Live Integration</Title>
<Description>Live Integration</Description>
Expand All @@ -19,7 +19,7 @@
<IncludeSymbols>true</IncludeSymbols>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dynamicweb.Ecommerce.DynamicwebLiveIntegration", "Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj", "{5B09B2C6-8E15-A19A-AA43-E303D71A0874}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5B09B2C6-8E15-A19A-AA43-E303D71A0874}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B09B2C6-8E15-A19A-AA43-E303D71A0874}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B09B2C6-8E15-A19A-AA43-E303D71A0874}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B09B2C6-8E15-A19A-AA43-E303D71A0874}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8116CA11-5865-48E8-9C90-5CBF48FF6A82}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,13 @@ public LiveIntegrationAddIn()
public bool ErpControlsDiscount { get; set; }

/// <summary>
/// Gets or sets if ERP controls shipping calculations
/// Gets or sets the shipping control mode.
/// </summary>
/// <value><c>true</c> if [ERP controls shipping calculations]; otherwise, <c>false</c>.</value>
[AddInParameter("ERP controls shipping calculations")]
[AddInParameterEditor(typeof(YesNoParameterEditor), "")]
[AddInParameter("Shipping control")]
[AddInParameterEditor(typeof(DropDownParameterEditor), "none=false")]
[AddInParameterGroup("Orders")]
[AddInParameterOrder(157)]
public bool ErpControlsShipping { get; set; }
public string ShippingControlMode { get; set; }

/// <summary>
/// Gets or sets the key for shipping item type.
Expand Down Expand Up @@ -750,11 +749,16 @@ IEnumerable<ParameterOption> IParameterOptions.GetParameterOptions(string dropdo
options.Add(new("Fixed Asset", "FixedAsset"));
options.Add(new("Resource", "Resource"));
break;
case "Shipping control":
options.Add(new("Dynamicweb controls shipping", Constants.ShippingControlMode.DynamicwebControlsShipping));
options.Add(new("ERP controls shipping", Constants.ShippingControlMode.ErpControlsShipping));
options.Add(new("ERP calculates shipping cost based on Dynamicweb selection", Constants.ShippingControlMode.ErpCalculatesBasedOnDwSelection));
break;
case "ConnectionToType":
options.Add(new(nameof(ConnectionType.Endpoint), ConnectionType.Endpoint));
options.Add(new("Dynamicweb connector web service", ConnectionType.WebService));
break;
case "ERP Local Currency":
case "ERP Local Currency":
foreach (var currency in Services.Currencies.GetAllCurrencies())
{
options.Add(new($"{currency.GetName(Services.Languages.GetDefaultLanguageId())} - {currency.Code}", currency.Code));
Expand Down Expand Up @@ -796,7 +800,7 @@ IEnumerable<string> IParameterVisibility.GetHiddenParameterNames(string paramete
result.Add("Include variants in the product information request");
result.Add("Max products per request");
}
break;
break;
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Discounts;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Extensions;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Logging;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Shipping;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.XmlGenerators;
using Dynamicweb.Ecommerce.Orders;
using Dynamicweb.Ecommerce.Prices;
Expand Down Expand Up @@ -103,7 +104,7 @@ private static ResponseCacheLevel GetOrderCacheLevel(Settings settings)
LiveIntegrationSubmitType = liveIntegrationSubmitType,
ReferenceName = "OrdersPut",
ErpControlsDiscount = erpControlsDiscount,
ErpControlsShipping = settings.ErpControlsShipping,
ShippingControlMode = settings.ShippingControlMode,
ErpShippingItemKey = settings.ErpShippingItemKey,
ErpShippingItemType = settings.ErpShippingItemType,
CalculateOrderUsingProductNumber = settings.CalculateOrderUsingProductNumber,
Expand Down Expand Up @@ -904,7 +905,7 @@ private static bool ProcessResponse(in OrderResponseContext ctx, XmlDocument res
{
XmlNode orderNode = response.SelectSingleNode("//item [@table='EcomOrders']");
PriceInfo shippingFeeSentInRequest = null;
if (!createOrder && !ctx.Settings.ErpControlsShipping && !string.IsNullOrEmpty(order.ShippingMethodId))
if (!createOrder && ctx.Settings.ShippingControlMode == Constants.ShippingControlMode.DynamicwebControlsShipping && !string.IsNullOrEmpty(order.ShippingMethodId))
{
shippingFeeSentInRequest = order.ShippingFee;
}
Expand Down Expand Up @@ -954,8 +955,15 @@ private static bool ProcessResponse(in OrderResponseContext ctx, XmlDocument res
else
{
SetOrderPrices(order, orderNode, ctx, logger, orderId, out updatePriceBeforeFeesFromOrderPrice);
}
if (ctx.Settings.ShippingControlMode == Constants.ShippingControlMode.ErpControlsShipping)
{
LiveShippingFeeProvider.ProcessShipping(ctx.Settings, order, orderNode, logger);
}
else if (ctx.Settings.ShippingControlMode == Constants.ShippingControlMode.ErpCalculatesBasedOnDwSelection)
{
ErpShippingFeeProvider.ProcessShipping(ctx.Settings, order, orderNode, logger);
Comment thread
DWDBE marked this conversation as resolved.
Outdated
}
LiveShippingFeeProvider.ProcessShipping(ctx.Settings, order, orderNode, logger);
}
else
{
Expand All @@ -979,7 +987,7 @@ private static bool ProcessResponse(in OrderResponseContext ctx, XmlDocument res
}
else
{
if (!ctx.Settings.ErpControlsShipping && shippingFeeSentInRequest != null)
if (ctx.Settings.ShippingControlMode == Constants.ShippingControlMode.DynamicwebControlsShipping && shippingFeeSentInRequest != null)
{
UpdateDynamicwebShipping(order, orderNode, shippingFeeSentInRequest, ctx.Settings, logger, updatePriceBeforeFeesFromOrderPrice);
}
Expand Down Expand Up @@ -1174,7 +1182,7 @@ private static void SetPrices(Settings settings, Order order, XmlNode orderNode,
/// <param name="orderNode">The order node.</param>
private static void SetShippingWarning(Settings settings, Order order, XmlNode orderNode)
{
if (!settings.ErpControlsShipping)
if (settings.ShippingControlMode == Constants.ShippingControlMode.DynamicwebControlsShipping)
{
var node = orderNode.SelectSingleNode("column [@columnName='OrderShippingWarning']");
if (node != null)
Expand Down Expand Up @@ -1397,6 +1405,6 @@ internal static void SetCurrentlyProcessingOrder(Order order)
internal static void RemoveCurrentlyProcessingOrder(Order order)
{
Caching.Cache.Current.Remove(OrderCacheKey(order));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.NotificationSubscribers;
using Dynamicweb.Extensibility.Notifications;

namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Shipping
{
[Subscribe(Ecommerce.Notifications.Ecommerce.Cart.BeforeShippingCalculation)]
public class CartBeforeShippingCalculation : NotificationSubscriberBase
{
public override void OnNotify(string notification, NotificationArgs args)
{
if (args is null || Context.Current?.Items is null)
return;

var myArgs = (Ecommerce.Notifications.Ecommerce.Cart.BeforeShippingCalculationArgs)args;
if (myArgs.Shipping is null || myArgs.Order is null || Context.Current.Session?["ErpShippingFeeProvider_" + myArgs.Order.Id] is null)
Comment thread
DWDBE marked this conversation as resolved.
Outdated
{
return;
}
Context.Current.Items[$"CartBeforeShippingCalculationShippingId{myArgs.Order.Id}"] = myArgs.Shipping.Id;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Configuration;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Logging;
using Dynamicweb.Ecommerce.DynamicwebLiveIntegration.NotificationSubscribers;
using Dynamicweb.Ecommerce.Orders;
using Dynamicweb.Ecommerce.Prices;
using System.Xml;

namespace Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Shipping
{
public class ErpShippingFeeProvider : FeeProvider
{
private const string CachePrefix = "ErpShippingFeeProvider_";

private static string OrderMarkerKey(string orderId) => CachePrefix + orderId;
private static string MethodCacheKey(string orderId, string shippingMethodId) => CachePrefix + orderId + "_" + shippingMethodId;
private static string BeforeShippingItemKey(string orderId) => "CartBeforeShippingCalculationShippingId" + orderId;

public override PriceRaw FindFee(Order order)
{
if (Context.Current?.Session is null || Context.Current.Items is null)
return null;

var shippingMethodId = Core.Converter.ToString(Context.Current.Items[BeforeShippingItemKey(order.Id)]);
if (string.IsNullOrEmpty(shippingMethodId))
return null;

var cached = Context.Current.Session[MethodCacheKey(order.Id, shippingMethodId)] as PriceInfo;
if (cached is null)
return null;

return new PriceRaw(cached.PriceWithVAT, order.Currency);
}

internal static void ProcessShipping(Settings settings, Order order, XmlNode orderNode, Logger logger)
{
Diagnostics.ExecutionTable.Current.Add("DynamicwebLiveIntegration.ErpShippingFeeProvider START");

string shippingFee = orderNode.SelectSingleNode("column [@columnName='OrderShippingFee']")?.InnerText;
if (string.IsNullOrEmpty(shippingFee))
{
ClearCache(order);
return;
}

double fee = Helpers.ToDouble(settings, logger, shippingFee);

string shippingFeeWithoutVat = orderNode.SelectSingleNode("column [@columnName='OrderShippingFeeWithoutVat']")?.InnerText;
double feeWithoutVat = 0;
double vatPercent = order.Price.VATPercent;
if (!string.IsNullOrEmpty(shippingFeeWithoutVat))
{
feeWithoutVat = Helpers.ToDouble(settings, logger, shippingFeeWithoutVat);
feeWithoutVat = feeWithoutVat > fee ? fee : feeWithoutVat;
vatPercent = feeWithoutVat > 0 ? (fee / feeWithoutVat - 1) * 100 : 0;
}
if (feeWithoutVat <= 0)
{
feeWithoutVat = MinusVat(fee, vatPercent);
}
Comment thread
DWDBE marked this conversation as resolved.

var price = new PriceInfo(order.Currency);
price.PriceWithVAT = fee;
price.PriceWithoutVAT = feeWithoutVat;
price.VATPercent = vatPercent;
price.VAT = fee - feeWithoutVat;

AddToCache(order, price);

order.ShippingFee.PriceWithVAT = price.PriceWithVAT;
order.ShippingFee.VATPercent = price.VATPercent;
order.ShippingFee.PriceWithoutVAT = price.PriceWithoutVAT;
order.ShippingFee.VAT = price.VAT;

Diagnostics.ExecutionTable.Current.Add("DynamicwebLiveIntegration.ErpShippingFeeProvider END");
Comment thread
DWDBE marked this conversation as resolved.
Outdated
}

internal static double MinusVat(double price, double percent)
{
return (double)((decimal)price / ((decimal)percent / 100M + 1M));
}

private static void AddToCache(Order order, PriceInfo shippingFee)
{
if (Context.Current?.Session is null || string.IsNullOrEmpty(order.ShippingMethodId))
return;

// Existence marker lets the notification subscriber know ERP fee caching is active for this order
Context.Current.Session[OrderMarkerKey(order.Id)] = true;
Context.Current.Session[MethodCacheKey(order.Id, order.ShippingMethodId)] = shippingFee;
}

private static void ClearCache(Order order)
{
if (Context.Current?.Session is null)
return;

Context.Current.Session.Remove(OrderMarkerKey(order.Id));
if (!string.IsNullOrEmpty(order.ShippingMethodId))
Context.Current.Session.Remove(MethodCacheKey(order.Id, order.ShippingMethodId));
Comment thread
DWDBE marked this conversation as resolved.
}
}
}
Loading
Loading