diff --git a/src/Dynamicweb.DataIntegration.Providers.OrderProvider.csproj b/src/Dynamicweb.DataIntegration.Providers.OrderProvider.csproj index 81ae6d4..e8aef55 100644 --- a/src/Dynamicweb.DataIntegration.Providers.OrderProvider.csproj +++ b/src/Dynamicweb.DataIntegration.Providers.OrderProvider.csproj @@ -23,8 +23,12 @@ snupkg - + + + ..\..\..\Dynamicweb10\src\Features\DataIntegration\Dynamicweb.DataIntegration\bin\Debug\net8.0\Dynamicweb.DataIntegration.dll + + diff --git a/src/OrderProvider.cs b/src/OrderProvider.cs index 2da2e71..f12ee4a 100644 --- a/src/OrderProvider.cs +++ b/src/OrderProvider.cs @@ -9,6 +9,7 @@ using Dynamicweb.Logging; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Data; using System.Data.SqlClient; using System.Globalization; @@ -104,14 +105,16 @@ public override Schema GetOriginalSourceSchema() var ordersTable = result.GetTables().FirstOrDefault(obj => string.Equals(obj.Name, "EcomOrders", StringComparison.OrdinalIgnoreCase)); if (orderLinesTable != null && ordersTable != null) { - foreach (var column in ordersTable.Columns) - { - if (!column.Name.Equals(OrderCustomerAccessUserExternalId, StringComparison.OrdinalIgnoreCase)) - { - orderLinesTable.AddColumn(new SqlColumn(column.Name, typeof(string), SqlDbType.NVarChar, orderLinesTable, -1, false, false, true)); - } - } + var orderTableColumns = new ColumnCollection(); + orderTableColumns.AddRange(ordersTable.Columns); + + var orderLineTableColumns = new ColumnCollection(); + orderLineTableColumns.AddRange(orderLinesTable.Columns); + + ordersTable.AddColumn(new TableColumn(orderLinesTable.Name, orderLinesTable.Name, orderLinesTable, typeof(Collection), orderLineTableColumns)); + orderLinesTable.AddColumn(new SqlColumn(OrderLineCalculatedDiscountPercentage, typeof(double), SqlDbType.NVarChar, orderLinesTable, -1, false, false, true)); + orderLinesTable.AddColumn(new TableColumn(ordersTable.Name, ordersTable.Name, orderLinesTable, typeof(object), orderTableColumns)); } return result; @@ -313,9 +316,9 @@ public OrderProvider() public override ISourceReader GetReader(Mapping mapping) { return new OrderSourceReader(mapping, Connection, ExportNotExportedOrders, ExportOnlyOrdersWithoutExtID, DoNotExportCarts); - } + } - public override void OrderTablesInJob(Job job, bool isSource) => OrderTablesByRelations(job, isSource); + public override void OrderTablesInJob(Job job, bool isSource) => OrderTablesByRelations(job, isSource); internal static List GetMappingsByName(MappingCollection collection, string name, bool isSourceLookup) { diff --git a/src/OrderSourceReader.cs b/src/OrderSourceReader.cs index e48f95e..25e14d1 100644 --- a/src/OrderSourceReader.cs +++ b/src/OrderSourceReader.cs @@ -1,6 +1,7 @@ using Dynamicweb.DataIntegration.Integration; using Dynamicweb.Ecommerce.Orders; using System; +using System.Collections; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; @@ -12,6 +13,7 @@ internal class OrderSourceReader : BaseSqlReader private static MappingConditionalCollection _ordersConditions = null; private static List _ordersToExport = null; private ColumnMappingCollection _columnMappings = null; + private bool _skipReading; public OrderSourceReader(Mapping mapping, SqlConnection connection, bool exportNotExportedOrders, bool exportOnlyOrdersWithoutExtID, bool doNotExportCarts) : base(mapping, connection) { @@ -162,7 +164,7 @@ protected override string GetFromTables() result = result + " inner join EcomOrders on EcomOrderLines.OrderLineOrderID = EcomOrders.OrderID"; break; case "EcomOrders": - result = "[dbo].[EcomOrders] left join dbo.AccessUser on OrderCustomerAccessUserID = AccessUserID"; + result = "[dbo].[EcomOrders] left join dbo.AccessUser on OrderCustomerAccessUserID = AccessUserID inner join EcomOrderLines on EcomOrderLines.OrderLineOrderID = EcomOrders.OrderID"; break; default: break; @@ -172,7 +174,9 @@ protected override string GetFromTables() public override Dictionary GetNext() { - Dictionary row = _columnMappings.Where(columnMapping => columnMapping.SourceColumn != null).GroupBy(cm => cm.SourceColumn.Name, (key, group) => group.First()).ToDictionary(columnMapping => columnMapping.SourceColumn.Name, columnMapping => _reader[columnMapping.SourceColumn.Name]); + _skipReading = false; + var columnMappings = _columnMappings.Where(columnMapping => columnMapping.SourceColumn != null); + Dictionary row = columnMappings.Where(cm => string.IsNullOrEmpty(cm.SourceColumn.Group)).GroupBy(cm => cm.SourceColumn.Name, (key, group) => group.First()).ToDictionary(columnMapping => columnMapping.SourceColumn.Name, columnMapping => _reader[columnMapping.SourceColumn.Name]); if (mapping.SourceTable.Name == "EcomOrders") { string orderId = Core.Converter.ToString(_reader["OrderId"]); @@ -187,10 +191,60 @@ public override Dictionary GetNext() row.Add("OrderId", orderId); } } + var nestedColumnMappings = columnMappings.Where(cm => !string.IsNullOrEmpty(cm.SourceColumn.Group)); + if (nestedColumnMappings.Any()) + { + var result = new Dictionary>>(); + var nestedListValueCollection = new List>(); + var nestedGroups = columnMappings.Where(cm => !string.IsNullOrEmpty(cm.SourceColumn.Group)).Select(cm => cm.SourceColumn.Group).ToList().Distinct(); + foreach (var nestedGroup in nestedGroups) + { + var nestedValueCollection = nestedColumnMappings.Where(cm => cm.SourceColumn.Group.Equals(nestedGroup)).ToDictionary(columnMapping => columnMapping.SourceColumn.Name, columnMapping => _reader[columnMapping.SourceColumn.Name]); + var nestedValuesList = new List> { nestedValueCollection }; + result.Add(nestedGroup, nestedValuesList); + } + + while (_reader.Read()) + { + Dictionary rootRow = columnMappings.Where(cm => string.IsNullOrEmpty(cm.SourceColumn.Group)).GroupBy(cm => cm.SourceColumn.Name, (key, group) => group.First()).ToDictionary(columnMapping => columnMapping.SourceColumn.Name, columnMapping => _reader[columnMapping.SourceColumn.Name]); + if(!AreDictionariesEqual(row,rootRow)) + { + _skipReading = true; + break; + } + + foreach (var nestedGroup in nestedGroups) + { + if (result.TryGetValue(nestedGroup, out var nestedList)) + { + nestedList.Add(nestedColumnMappings.Where(cm => cm.SourceColumn.Group.Equals(nestedGroup)).ToDictionary(columnMapping => columnMapping.SourceColumn.Name, columnMapping => _reader[columnMapping.SourceColumn.Name])); + } + } + } + + foreach (var item in result) + { + row.Add(item.Key, item.Value); + } + } } + return row; } + public override bool IsDone() + { + if (_skipReading) + return false; + + if (_reader.Read()) + return false; + + _reader.Close(); + return true; + } + + public static void UpdateExportedOrdersInDb(string orderStateIDAfterExport, SqlConnection connection) { if (_ordersToExport != null && _ordersToExport.Count > 0) @@ -256,6 +310,54 @@ private static void ClearOrderCache(IEnumerable orderIds) os.RemoveOrderCache(id); } } + + private static bool AreDictionariesEqual(Dictionary dict1, Dictionary dict2) + { + if (dict1 == null || dict2 == null) + return dict1 == dict2; + + if (dict1.Count != dict2.Count) + return false; + + foreach (var key in dict1.Keys) + { + if (!dict2.ContainsKey(key)) + return false; + + if (!AreValuesEqual(dict1[key], dict2[key])) + return false; + } + + return true; + } + + private static bool AreValuesEqual(object value1, object value2) + { + if (value1 == null || value2 == null) + return value1 == value2; + + if (value1 is Dictionary dict1 && value2 is Dictionary dict2) + return AreDictionariesEqual(dict1, dict2); + + if (value1 is IList list1 && value2 is IList list2) + return AreListsEqual(list1, list2); + + return value1.Equals(value2); + } + + private static bool AreListsEqual(IList list1, IList list2) + { + if (list1.Count != list2.Count) + return false; + + for (int i = 0; i < list1.Count; i++) + { + if (!AreValuesEqual(list1[i], list2[i])) + return false; + } + + return true; + } } }