Skip to content

Commit 08d0a9f

Browse files
MikeAlhayekCopilot
andcommitted
Fix migration to traverse BagPart for nested PhoneNumber items
PhoneNumber content items are embedded inside a BagPart named ContactMethods on parent content items that have OmnichannelContactPart. They are not separate YesSql documents, so the previous approach of querying ContentItemIndex for PhoneNumber type would find nothing. Now the migration: - Discovers content types with OmnichannelContactPart attached - Queries those parent documents via cursor-based pagination - Navigates into ContactMethods BagPart -> ContentItems array - Migrates each inner PhoneNumber item's Number field from TextField to PhoneField format Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 40b3ab0 commit 08d0a9f

1 file changed

Lines changed: 53 additions & 12 deletions

File tree

src/Modules/CrestApps.OrchardCore.Omnichannel.Managements/Migrations/ContactMethodMigrations.cs

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private static async Task MigratePhoneNumberDataAsync(ShellScope scope)
199199
var contentDefinitionManager = scope.ServiceProvider.GetRequiredService<IContentDefinitionManager>();
200200
var logger = scope.ServiceProvider.GetRequiredService<ILogger<ContactMethodMigrations>>();
201201

202-
var contentTypes = await GetContentTypesWithPhoneNumberInfoPartAsync(contentDefinitionManager);
202+
var contentTypes = await GetContentTypesWithOmnichannelContactPartAsync(contentDefinitionManager);
203203

204204
if (contentTypes.Length == 0)
205205
{
@@ -233,21 +233,21 @@ private static async Task MigratePhoneNumberDataAsync(ShellScope scope)
233233

234234
try
235235
{
236-
if (!TryMigratePhoneNumberContent(contentItem, phoneNumberService))
236+
if (TryMigrateContactPhoneNumbers(contentItem, phoneNumberService))
237+
{
238+
await session.SaveAsync(contentItem);
239+
batchMigrated++;
240+
}
241+
else
237242
{
238243
skippedCount++;
239-
240-
continue;
241244
}
242-
243-
await session.SaveAsync(contentItem);
244-
batchMigrated++;
245245
}
246246
catch (Exception ex)
247247
{
248248
logger.LogWarning(
249249
ex,
250-
"Failed to migrate phone number for content item '{ContentItemId}' (version '{ContentItemVersionId}').",
250+
"Failed to migrate phone numbers for content item '{ContentItemId}' (version '{ContentItemVersionId}').",
251251
contentItem.ContentItemId,
252252
contentItem.ContentItemVersionId);
253253
skippedCount++;
@@ -268,20 +268,61 @@ private static async Task MigratePhoneNumberDataAsync(ShellScope scope)
268268
}
269269
}
270270

271-
private static async Task<string[]> GetContentTypesWithPhoneNumberInfoPartAsync(IContentDefinitionManager contentDefinitionManager)
271+
private static async Task<string[]> GetContentTypesWithOmnichannelContactPartAsync(IContentDefinitionManager contentDefinitionManager)
272272
{
273273
var typeDefinitions = await contentDefinitionManager.ListTypeDefinitionsAsync();
274274

275275
return typeDefinitions
276276
.Where(type => type.Parts.Any(part =>
277-
string.Equals(part.PartDefinition.Name, OmnichannelConstants.ContentParts.PhoneNumberInfo, StringComparison.Ordinal)))
277+
string.Equals(part.PartDefinition.Name, OmnichannelConstants.ContentParts.OmnichannelContact, StringComparison.Ordinal)))
278278
.Select(type => type.Name)
279279
.ToArray();
280280
}
281281

282-
private static bool TryMigratePhoneNumberContent(ContentItem contentItem, IPhoneNumberService phoneNumberService)
282+
private static bool TryMigrateContactPhoneNumbers(ContentItem contentItem, IPhoneNumberService phoneNumberService)
283+
{
284+
var bagNode = contentItem.Content[OmnichannelConstants.NamedParts.ContactMethods] as JsonObject;
285+
286+
if (bagNode is null)
287+
{
288+
return false;
289+
}
290+
291+
var contentItems = bagNode["ContentItems"] as JsonArray;
292+
293+
if (contentItems is null || contentItems.Count == 0)
294+
{
295+
return false;
296+
}
297+
298+
var anyMigrated = false;
299+
300+
foreach (var item in contentItems)
301+
{
302+
if (item is not JsonObject innerItem)
303+
{
304+
continue;
305+
}
306+
307+
var contentType = innerItem["ContentType"]?.GetValue<string>();
308+
309+
if (!string.Equals(contentType, OmnichannelConstants.ContentTypes.PhoneNumber, StringComparison.Ordinal))
310+
{
311+
continue;
312+
}
313+
314+
if (TryMigratePhoneNumberField(innerItem, phoneNumberService))
315+
{
316+
anyMigrated = true;
317+
}
318+
}
319+
320+
return anyMigrated;
321+
}
322+
323+
private static bool TryMigratePhoneNumberField(JsonObject innerContentItem, IPhoneNumberService phoneNumberService)
283324
{
284-
var partNode = contentItem.Content[OmnichannelConstants.ContentParts.PhoneNumberInfo] as JsonObject;
325+
var partNode = innerContentItem[OmnichannelConstants.ContentParts.PhoneNumberInfo] as JsonObject;
285326

286327
if (partNode is null)
287328
{

0 commit comments

Comments
 (0)