Skip to content

Commit c87211f

Browse files
petrinecpCopilotJosef PohrompohromjJan Slezar
authored
Add support for commerce entities migration (#567)
* KX-21564 Ensure migration of customer and address entities * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * KX-21564 Cleanup * KX-21564 Fix analyzer warning * KX-21808 Ensure system fields prefixing (#556) Ensure system fields prefixing * KX-21565 MIgrate orders * KX-21565 addressing review notes * KX-21565 remove Kentico.Xperience.Admin package * KX-21565 review changes * KX-21565 remove comment * KX-21565 fix net format * initial wip * copilot review changes, formatting * update * wording * review update * last dev review fix * tw review changes * missing comma * add full migration example * last update * KX-21233 review changes and bum UMT package version (#574) Co-authored-by: Josef Pohrom <josefp@kentico.com> * add API comments for methods --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Josef Pohrom <josefp@kentico.com> Co-authored-by: Josef Pohrom <j.pohrom@seznam.cz> Co-authored-by: Jan Slezar <jans3@kentico.com> Co-authored-by: jslezar <149673967+Honzaless@users.noreply.github.com>
1 parent 90abe89 commit c87211f

25 files changed

+1675
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ appsettings.local.json
88
.vs/
99
*.sln.DotSettings.user
1010
Migration.Tool.CLI/appsettings.local.json_
11+
.nuget/nuget.exe

Migration.Tool.CLI/ConfigurationValidator.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,40 @@ public static IEnumerable<ValidationMessage> GetValidationErrors(IConfigurationR
157157
}
158158

159159
#endregion
160+
161+
#region Commerce configuration validation
162+
163+
var commerceConfiguration = settings?.GetSection(ConfigurationNames.CommerceConfiguration);
164+
if (commerceConfiguration is not null)
165+
{
166+
var commerceSiteNames = commerceConfiguration.GetSection(ConfigurationNames.CommerceSiteNames).Get<List<string>?>();
167+
if (commerceSiteNames is null || commerceSiteNames.Count == 0)
168+
{
169+
yield return new ValidationMessage(ValidationMessageType.Error,
170+
$"'{ConfigurationNames.CommerceConfiguration}:{ConfigurationNames.CommerceSiteNames}' must contain at least one site name when '{ConfigurationNames.CommerceConfiguration}' is specified.");
171+
}
172+
else if (commerceSiteNames.Any(string.IsNullOrWhiteSpace))
173+
{
174+
yield return new ValidationMessage(ValidationMessageType.Error,
175+
$"'{ConfigurationNames.CommerceConfiguration}:{ConfigurationNames.CommerceSiteNames}' cannot contain empty or whitespace values.");
176+
}
177+
178+
var systemFieldPrefix = commerceConfiguration.GetValue<string?>(ConfigurationNames.SystemFieldPrefix);
179+
if (systemFieldPrefix is not null && string.IsNullOrWhiteSpace(systemFieldPrefix))
180+
{
181+
yield return new ValidationMessage(ValidationMessageType.Error,
182+
$"'{ConfigurationNames.CommerceConfiguration}:{ConfigurationNames.SystemFieldPrefix}' cannot be empty or whitespace when specified. Either provide a valid prefix value or remove the configuration to use the default.");
183+
}
184+
185+
var orderStatuses = commerceConfiguration.GetValue<Dictionary<string, string[]>>(ConfigurationNames.OrderStatuses);
186+
if (orderStatuses is not null && orderStatuses.Count == 0)
187+
{
188+
yield return new ValidationMessage(ValidationMessageType.Error,
189+
$"'{ConfigurationNames.CommerceConfiguration}:{ConfigurationNames.OrderStatuses}' must contain at least one order status from XbK counterpart.");
190+
}
191+
}
192+
193+
#endregion
160194
}
161195

162196
#region "Helper methods"

Migration.Tool.CLI/README.md

Lines changed: 132 additions & 1 deletion
Large diffs are not rendered by default.

Migration.Tool.Common/Commands.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,24 @@ public record MigrateContentTypeRestrictionsCommand : IRequest<CommandResult>, I
153153

154154
public Type[] Dependencies => [typeof(MigrateSitesCommand), typeof(MigratePageTypesCommand), typeof(MigratePagesCommand)];
155155
}
156+
157+
public record MigrateCustomersCommand : IRequest<CommandResult>, ICommand
158+
{
159+
public static readonly int Rank = 1 + MigrateSitesCommand.Rank + MigrateCustomModulesCommand.Rank + MigrateUsersCommand.Rank + MigrateMembersCommand.Rank;
160+
161+
public static string Moniker => "customers";
162+
public static string MonikerFriendly => "Customers and addresses";
163+
164+
public Type[] Dependencies => [typeof(MigrateSitesCommand), typeof(MigrateCustomModulesCommand), typeof(MigrateUsersCommand), typeof(MigrateMembersCommand)];
165+
}
166+
167+
public record MigrateOrdersCommand : IRequest<CommandResult>, ICommand
168+
{
169+
public static readonly int Rank = 1 + MigrateSitesCommand.Rank + MigrateCustomModulesCommand.Rank + MigrateUsersCommand.Rank + MigrateMembersCommand.Rank + MigrateCustomersCommand.Rank;
170+
171+
public static string Moniker => "orders";
172+
173+
public static string MonikerFriendly => "Orders";
174+
175+
public Type[] Dependencies => [typeof(MigrateSitesCommand), typeof(MigrateCustomModulesCommand), typeof(MigrateUsersCommand), typeof(MigrateMembersCommand), typeof(MigrateCustomersCommand)];
176+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Migration.Tool.Common;
4+
5+
/// <summary>
6+
/// Configuration for commerce data migration.
7+
/// </summary>
8+
public class CommerceConfiguration
9+
{
10+
[JsonPropertyName(ConfigurationNames.CommerceSiteNames)]
11+
public List<string>? CommerceSiteNames { get; set; }
12+
13+
[JsonPropertyName(ConfigurationNames.IncludeCustomerSystemFields)]
14+
public List<string>? IncludeCustomerSystemFields { get; set; }
15+
16+
[JsonPropertyName(ConfigurationNames.IncludeAddressSystemFields)]
17+
public List<string>? IncludeAddressSystemFields { get; set; }
18+
19+
[JsonPropertyName(ConfigurationNames.SystemFieldPrefix)]
20+
public string? SystemFieldPrefix { get; set; }
21+
22+
[JsonPropertyName(ConfigurationNames.IncludeOrderSystemFields)]
23+
public List<string>? IncludeOrderSystemFields { get; set; }
24+
25+
[JsonPropertyName(ConfigurationNames.IncludeOrderItemsSystemFields)]
26+
public List<string>? IncludeOrderItemsSystemFields { get; set; }
27+
28+
[JsonPropertyName(ConfigurationNames.IncludeOrderAddressSystemFields)]
29+
public List<string>? IncludeOrderAddressSystemFields { get; set; }
30+
31+
[JsonPropertyName(ConfigurationNames.OrderStatuses)]
32+
public Dictionary<string, string[]> OrderStatuses { get; set; } = new(StringComparer.OrdinalIgnoreCase);
33+
34+
[JsonPropertyName(ConfigurationNames.KX13OrderFilter)]
35+
public CommerceOrderFilterConfiguration? KX13OrderFilter { get; set; }
36+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Migration.Tool.Common;
4+
/// <summary>
5+
/// Configuration for filtering orders from KX13.
6+
/// </summary>
7+
public class CommerceOrderFilterConfiguration
8+
{
9+
[JsonPropertyName(ConfigurationNames.OrderFromDate)]
10+
public DateTime? OrderFromDate { get; set; }
11+
12+
[JsonPropertyName(ConfigurationNames.OrderToDate)]
13+
public DateTime? OrderToDate { get; set; }
14+
15+
[JsonPropertyName(ConfigurationNames.OrderStatusCodeNames)]
16+
public List<string> OrderStatusCodeNames { get; set; } = [];
17+
}

Migration.Tool.Common/ConfigurationNames.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,25 @@ public class ConfigurationNames
7474
public const string XbyKApiSettings = "XbyKApiSettings";
7575

7676
#endregion
77+
78+
#region Commerce Configuration
79+
80+
public const string CommerceConfiguration = "CommerceConfiguration";
81+
public const string CommerceSiteNames = "CommerceSiteNames";
82+
public const string IncludeCustomerSystemFields = "IncludeCustomerSystemFields";
83+
public const string IncludeAddressSystemFields = "IncludeAddressSystemFields";
84+
public const string SystemFieldPrefix = "SystemFieldPrefix";
85+
public const string IncludeOrderSystemFields = "IncludeOrderSystemFields";
86+
public const string IncludeOrderItemsSystemFields = "IncludeOrderItemsSystemFields";
87+
public const string IncludeOrderAddressSystemFields = "IncludeOrderAddressSystemFields";
88+
public const string OrderStatuses = "OrderStatuses";
89+
public const string KX13OrderFilter = "KX13OrderFilter";
90+
91+
#region KX13 Order Filter Configuration
92+
public const string OrderFromDate = "OrderFromDate";
93+
public const string OrderToDate = "OrderToDate";
94+
public const string OrderStatusCodeNames = "OrderStatusCodeNames";
95+
#endregion
96+
97+
#endregion
7798
}

Migration.Tool.Common/Migration.Tool.Common.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<ItemGroup>
1919
<PackageReference Include="HtmlAgilityPack.NetCore" Version="1.5.0.1" />
20-
<PackageReference Include="Kentico.Xperience.UMT" Version="4.0.1" />
20+
<PackageReference Include="Kentico.Xperience.UMT" Version="4.1.0" />
2121
<PackageReference Include="MediatR" Version="12.4.1" />
2222
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
2323
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />

Migration.Tool.Common/Services/CommandParser.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ public class CommandParser : ICommandParser
130130
continue;
131131
}
132132

133+
if (arg == $"--{MigrateCustomersCommand.Moniker}")
134+
{
135+
subcommands.Add(new MigrateCustomersCommand());
136+
continue;
137+
}
138+
139+
if (arg == $"--{MigrateOrdersCommand.Moniker}")
140+
{
141+
subcommands.Add(new MigrateOrdersCommand());
142+
continue;
143+
}
144+
133145
throw new InvalidOperationException($"Unknown command '{arg}'");
134146
}
135147

@@ -153,6 +165,8 @@ private void PrintCommandDescriptions()
153165
WriteCommandDesc($"starts migration of {Green(MigrateMembersCommand.MonikerFriendly)}", $"migrate --{MigrateMembersCommand.Moniker}");
154166
WriteCommandDesc($"starts migration of {Green(MigrateAttachmentsCommand.MonikerFriendly)}", $"migrate --{MigrateAttachmentsCommand.Moniker}");
155167
WriteCommandDesc($"starts migration of {Green(MigrateCustomModulesCommand.MonikerFriendly)}", $"migrate --{MigrateCustomModulesCommand.Moniker}");
168+
WriteCommandDesc($"starts migration of {Green(MigrateCustomersCommand.MonikerFriendly)}", $"migrate --{MigrateCustomersCommand.Moniker}");
169+
WriteCommandDesc($"starts migration of {Green(MigrateOrdersCommand.MonikerFriendly)}", $"migrate --{MigrateOrdersCommand.Moniker}");
156170
Console.WriteLine();
157171
Console.WriteLine($"Command {Green("patch")}: Applies migration patches to XbyK database. Patches are also applied at each run of {Green("migrate")}. Use this command to run patches without migration. " +
158172
$"Migration patches fix data problems caused by bugs in previous versions of Migration Tool. This command is idempotent - i.e. tolerant to multiple runs.");

Migration.Tool.Common/ToolConfiguration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public class ToolConfiguration
2525
[ConfigurationKeyName(ConfigurationNames.EntityConfigurations)]
2626
public EntityConfigurations EntityConfigurations { get; set; } = [];
2727

28+
[ConfigurationKeyName(ConfigurationNames.CommerceConfiguration)]
29+
public CommerceConfiguration? CommerceConfiguration { get; set; }
30+
2831
[ConfigurationKeyName(ConfigurationNames.MigrateOnlyMediaFileInfo)]
2932
public bool? MigrateOnlyMediaFileInfo { get; set; } = false;
3033

0 commit comments

Comments
 (0)