From 3784c47fca56a77fe138a56db196d648f9b69256 Mon Sep 17 00:00:00 2001 From: Dmitriy Benyuk Date: Thu, 6 Aug 2026 11:30:22 +0300 Subject: [PATCH 1/2] Save parent order line before using it as ParentLineId reference OrderLine.Id can be pre-assigned a DW_NEWMULTIORDERLINEID_ placeholder for lines created as part of a multi order line request before they are actually persisted. The existing IsNullOrEmpty(Id) check missed this case, so the parent line was never saved and discount/tax lines ended up referencing a non-persisted ParentLineId. Related: https://dev.azure.com/dynamicwebsoftware/Dynamicweb/_workitems/edit/29074 Co-Authored-By: Claude Sonnet 5 --- .../OrderHandler.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs index 3a82699..5401c94 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/OrderHandler.cs @@ -33,8 +33,24 @@ public static class OrderHandler /// private static readonly string OrderXmlLogFolder = "/Files/System/Log/LiveIntegration/OrderXml"; + /// + /// Prefix used by OrderLine.Id for order lines that were created as part of a multi order line + /// request but have not actually been persisted yet. Lines with this placeholder Id still need + /// to be saved before they can be used as a ParentLineId reference. + /// + private const string NewMultiOrderLineIdPrefix = "DW_NEWMULTIORDERLINEID_"; + private readonly record struct OrderResponseContext(Settings Settings, bool ErpControlsDiscountForUser); + /// + /// Determines whether an order line has not actually been persisted yet, including lines whose + /// Id was pre-assigned a temporary multi order line placeholder before saving. + /// + private static bool IsUnsavedOrderLine(OrderLine orderLine) + { + return string.IsNullOrEmpty(orderLine.Id) || orderLine.Id.StartsWith(NewMultiOrderLineIdPrefix, StringComparison.OrdinalIgnoreCase); + } + /// /// Gets the cache level for order information. /// @@ -533,7 +549,7 @@ private static void ProcessDiscountOrderLine(in OrderResponseContext ctx, Order } parentLine = parentLineWithVariant ?? parentLine; - if (parentLine != null && string.IsNullOrEmpty(parentLine.Id)) + if (parentLine != null && IsUnsavedOrderLine(parentLine)) { Services.OrderLines.Save(parentLine); orderLineIds.Add(parentLine.Id); @@ -723,7 +739,7 @@ private static void ProcessTaxOrderLine(Settings settings, Order order, XmlNode } parentLine = parentLineWithVariant ?? parentLine; - if (parentLine != null && string.IsNullOrEmpty(parentLine.Id)) + if (parentLine != null && IsUnsavedOrderLine(parentLine)) { Services.OrderLines.Save(parentLine); orderLineIds.Add(parentLine.Id); From 21b742f8a7d1b02e2761cd25d64be0149095fdce Mon Sep 17 00:00:00 2001 From: Dmitriy Benyuk Date: Thu, 6 Aug 2026 11:30:49 +0300 Subject: [PATCH 2/2] bump --- .../Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj index 66d42dc..840a3f8 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj @@ -1,6 +1,6 @@  - 10.21.8 + 10.21.9 1.0.0.0 Live Integration Live Integration