private async Task <ComposerTemplate> EnsureComposerTemplateProperty(SyncForceClientPolicy syncForcePolicy, ComposerTemplate template, CommerceContext context, EntityView childView, string name, string propertyType) { var entityViewComponent = template.GetComponent <EntityViewComponent>(); if (childView.Properties.All(p => p.Name != name)) { if (entityViewComponent.View.GetChildView( it => String.Equals(it.Name, syncForcePolicy.CommonComposerTemplateName, StringComparison.InvariantCultureIgnoreCase)) is EntityView templateView) { templateView.Properties.Add(new ViewProperty() { DisplayName = name, IsHidden = false, OriginalType = propertyType, IsRequired = false, IsReadOnly = false, Name = name }); template.SetComponent(entityViewComponent); return((await _persistEntityPipeline.Run(new PersistEntityArgument(template), context.PipelineContextOptions))?.Entity as ComposerTemplate); } } return(template); }
private async Task UpdateSyncforceComposerTemplate(SynchronizeProductArgument arg, CommercePipelineExecutionContext context, SellableItem sellableItem, ComposerTemplate commonComposerTemplate, SyncForceClientPolicy syncForcePolicy) { var sellableEntityViewComponent = sellableItem.GetComponent <EntityViewComponent>(); if (sellableEntityViewComponent != null) { EntityView tempViewHolder = new EntityView(); tempViewHolder.SetPropertyValue("Template", syncForcePolicy.CommonComposerTemplateName); tempViewHolder.GetProperty(it => String.Equals(it.Name, "Template", StringComparison.InvariantCultureIgnoreCase)).Value = syncForcePolicy.CommonComposerTemplateName; EntityView templateView = !string.IsNullOrEmpty(tempViewHolder.ItemId) ? sellableItem.GetComponent <EntityViewComponent>().ChildViewWithItemId(tempViewHolder.ItemId) : sellableItem.GetComponent <EntityViewComponent>().View.ChildViews.OfType <EntityView>().FirstOrDefault <EntityView>(); if (templateView == null || !sellableItem.GetComponent <EntityViewComponent>().HasChildViews((Func <EntityView, bool>)(p => p.Name.Equals(templateView.Name, StringComparison.OrdinalIgnoreCase)))) { await _composerCommander.AddChildViewFromTemplate(context.CommerceContext, tempViewHolder, sellableItem); } var composerView = sellableItem.GetComponent <EntityViewComponent>()?.View.ChildViews?.OfType <EntityView>() ?.FirstOrDefault(v => v.Name == syncForcePolicy.CommonComposerTemplateName); if (composerView != null) { //Add SyncForce timestamp var timestampDateTime = DateTime.SpecifyKind(arg.MasterProduct.TimeStamp, DateTimeKind.Utc); var timestampDateTimeOffset = (DateTimeOffset)timestampDateTime; var timestampRawValue = timestampDateTimeOffset.ToString("yyyy-MM-dd'T'H:mm:ss.fffffffzzz"); //Ensure timestamp field on ComposerTemplate await EnsureComposerTemplateProperty(syncForcePolicy, commonComposerTemplate, context.CommerceContext, composerView, "Timestamp", "System.DateTimeOffset"); if (composerView.ContainsProperty("Timestamp")) { composerView.SetPropertyValue("Timestamp", timestampRawValue); } else { composerView.Properties.Add(new ViewProperty() { DisplayName = "Timestamp", RawValue = timestampRawValue, IsHidden = false, IsReadOnly = false, IsRequired = false, Name = "Timestamp", OriginalType = "System.DateTimeOffset" }); } } } }
/// <summary> /// Ensures the existence of the Category. /// If it doesn't exist it creates the Category, adds DisplayNames, adds identifiers and associates the Category with the parent Category. /// </summary> /// <param name="propositionCategory"></param> /// <param name="catalogId"></param> /// <param name="catalogName"></param> /// <param name="policy"></param> /// <param name="context"></param> /// <param name="associateWithCatalog"></param> /// <returns></returns> private async Task <List <Category> > EnsureCategory(CollectionFolder propositionCategory, string catalogId, string catalogName, SyncForceClientPolicy policy, CommerceContext context, bool associateWithCatalog = false) { var result = new List <Category>(); var categoryName = propositionCategory.Values.FirstOrDefault(l => l.Language == policy.DefaultLanguage) ?.Name; //Added sort index to category name to make sure sorting is done right, instead of done on alphabetical order. var categoryId = $"{CommerceEntity.IdPrefix<Category>()}{catalogName}-{propositionCategory.SortIndex.ToString().PadLeft(3, '0') + propositionCategory.Id + categoryName.ProposeValidId()}"; Category category = null; //Get or create category if (await _doesEntityExistPipeline.Run(new FindEntityArgument(typeof(Category), categoryId), context.PipelineContextOptions)) { category = await _getCategoryPipeline.Run(new GetCategoryArgument(categoryId), context.PipelineContextOptions); } else { var createResult = await _createCategoryPipeline.Run( new CreateCategoryArgument(catalogId, propositionCategory.SortIndex.ToString().PadLeft(3, '0') + propositionCategory.Id + categoryName.ProposeValidId(), categoryName, ""), context.PipelineContextOptions); category = createResult?.Categories?.FirstOrDefault(c => c.Id == categoryId); } if (category != null) { //Localize properties var localizationEntityId = LocalizationEntity.GetIdBasedOnEntityId(category.Id); var localizationEntity = await _findEntityPipeline.Run(new FindEntityArgument(typeof(LocalizationEntity), localizationEntityId), context.PipelineContextOptions) as LocalizationEntity; if (localizationEntity != null) { var displayNames = propositionCategory.Values.Select(p => new Parameter(p.Language, p.Name)).ToList(); localizationEntity.AddOrUpdatePropertyValue("DisplayName", displayNames); var descriptions = propositionCategory.CategoryContent.Values.Select(p => new Parameter(p.Language, p.Name)).ToList(); localizationEntity.AddOrUpdatePropertyValue("Description", descriptions); await _persistEntityPipeline.Run(new PersistEntityArgument(localizationEntity), context.PipelineContextOptions); } //Add identifiers var identifiersComponent = category.GetComponent <IdentifiersComponent>(); if (!identifiersComponent.CustomId.Any(i => i.Key.Equals(policy.CustomIdentifierKey))) { identifiersComponent.CustomId.Add( new Sitecore.Commerce.Plugin.Catalogs.SyncForce.Models.CustomIdentifier( policy.CustomIdentifierKey, propositionCategory.Id.ToString())); } category.SetComponent(identifiersComponent); category = (await _persistEntityPipeline.Run(new PersistEntityArgument(category), context.PipelineContextOptions))?.Entity as Category ?? category; //Add custom properties var categoryComponent = category.GetComponent <SyncForceCategoryComponent>(); categoryComponent.Sortorder = propositionCategory.SortIndex; category.SetComponent(categoryComponent); category = (await _persistEntityPipeline.Run(new PersistEntityArgument(category), context.PipelineContextOptions))?.Entity as Category ?? category; //Create sub-categories if (propositionCategory?.ProductPropositionCategories?.Any() ?? false) { foreach (var subCategory in propositionCategory.ProductPropositionCategories) { var s = await EnsureCategory(subCategory, catalogId, catalogName, policy, context); result.AddRange(s); foreach (var createdSubCategory in s) { var persistedSubCategory = (await _persistEntityPipeline.Run(new PersistEntityArgument(createdSubCategory), context.PipelineContextOptions))?.Entity; var associateResult = await _associateCategoryToParentPipeline.Run( new CatalogReferenceArgument(catalogId, category.Id, persistedSubCategory?.Id ?? createdSubCategory.Id), context.PipelineContextOptions); category = associateResult?.Categories?.FirstOrDefault(c => c.Id == category.Id) ?? category; } } } //Associate with catalog if top level category if (associateWithCatalog) { var associateResult = await _associateCategoryToParentPipeline.Run( new CatalogReferenceArgument(catalogId, catalogId, category.Id), context.PipelineContextOptions); category = associateResult?.Categories ?.FirstOrDefault(c => c.Id == category.Id) ?? category; } result.Add(category); } return(result); }