private async Task <Category> CreateOrGetCategory(CommercePipelineExecutionContext context, Catalog catalog, string categoryName, string parentCategoryId = null) { try { string categoryId = GenerateFullCategoryId(catalog.Name, categoryName); //Check if catalog with given name already exists before trying to create a new one Category category = await _findEntityCommand.Process(context.CommerceContext, typeof(Category), categoryId, false) as Category; if (category == null) { context.Logger.LogInformation($"ProductImport:Category Not Found, result is nill _getCategoryCommand:{categoryId}"); context.Logger.LogInformation($"ProductImport:Creating Category: {categoryId}"); category = await _createCategoryCommand.Process(context.CommerceContext, catalog.Id, categoryName, categoryName, categoryName) as Category; category.ParentCatalogList = catalog.SitecoreId; } else { context.Logger.LogInformation($"ProductImport: Category found _findEntityPipeline, catalog: {categoryName}"); } return(category); } catch (Exception ex) { context.Logger.LogInformation($"ProductImport: Error during catelog process" + ex.Message); return(null); } }
/// <summary> /// Runs the specified argument. /// </summary> /// <param name="arg">The argument.</param> /// <param name="context">The context.</param> /// <returns></returns> public override async Task <CommerceEntity> Run(CommerceEntity arg, CommercePipelineExecutionContext context) { if (arg == null) { return(arg); } if (!(arg is SellableItem)) { return(arg); } var sellableItem = (SellableItem)arg; var productId = arg.Id.Substring($"{CommerceEntity.IdPrefix<SellableItem>()}".Length); productId = productId.Replace("-", " "); sellableItem.Id = $"{CommerceEntity.IdPrefix<SellableItem>()}{productId}"; sellableItem.ProductId = productId; sellableItem.FriendlyId = productId; var targetSellableItem = await _findEntityCommand.Process(context.CommerceContext, typeof(SellableItem), sellableItem.Id).ConfigureAwait(false); if (targetSellableItem != null) { sellableItem.IsPersisted = true; sellableItem.Version = targetSellableItem.Version; } return(sellableItem); }
public override async Task <ImportEntityArgument> Run(ImportEntityArgument arg, CommercePipelineExecutionContext context) { string entityId = arg.ImportHandler.EntityId; var entityToUpdate = arg.ImportHandler.GetCommerceEntity() ?? await _findEntityCommand .Process(context.CommerceContext, typeof(CommerceEntity), entityId) .ConfigureAwait(false); bool createNewVersion = entityToUpdate != null && arg.CatalogImportPolicy.EntityVersioningScheme == EntityVersioningScheme.CreateNewVersion; if (entityToUpdate != null && arg.CatalogImportPolicy.EntityVersioningScheme == EntityVersioningScheme.UpdateLatestUnpublished) { VersioningEntity versioningEntity = await _findEntityCommand.Process(context.CommerceContext, typeof(VersioningEntity), VersioningEntity.GetIdBasedOnEntityId(entityToUpdate.Id), new int?()).ConfigureAwait(false) as VersioningEntity; if (versioningEntity?.Versions != null && versioningEntity.Versions.Any()) { var unpublishedVersion = versioningEntity.Versions.Where(x => !x.Published).Max(x => x.Version); if (unpublishedVersion <= 0 || entityToUpdate.EntityVersion != unpublishedVersion) { createNewVersion = true; } } } if (createNewVersion) { var newVersion = entityToUpdate.EntityVersion + 1; await _addEntityVersionCommand.Process(context.CommerceContext, entityToUpdate, newVersion).ConfigureAwait(false); entityToUpdate = await _findEntityCommand.Process(context.CommerceContext, typeof(CommerceEntity), entityId, newVersion).ConfigureAwait(false); } if (entityToUpdate != null) { arg.IsNew = false; arg.ImportHandler.SetCommerceEntity(entityToUpdate); } return(arg); }
/// <summary> /// Runs the specified argument. /// </summary> /// <param name="arg">The argument.</param> /// <param name="context">The context.</param> /// <returns></returns> public override async Task <FindEntityArgument> Run(FindEntityArgument arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull($"{this.Name}: the argument cannot be null."); context.Logger.LogInformation($"{this.Name} - Run IEntityMigrationPipeline:{arg.EntityId}"); var targetEntity = await _findEntityCommand.Process(context.CommerceContext, typeof(CommerceEntity), arg.EntityId); arg.Entity = targetEntity; return(arg); }
public override async Task <ImportEntityArgument> Run(ImportEntityArgument arg, CommercePipelineExecutionContext context) { string entityId = arg.ImportHandler.EntityId; var entityToUpdate = await _findEntityCommand.Process(context.CommerceContext, typeof(CommerceEntity), entityId) .ConfigureAwait(false); if (entityToUpdate != null) { arg.IsNew = false; arg.ImportHandler.SetCommerceEntity(entityToUpdate); } return(arg); }
/// <summary> /// Save Commmerce Entities collection into Commerce DB /// </summary> /// <param name="entityModel"></param> /// <param name="context"></param> /// <returns></returns> public async Task ImportCommerceEntities(EntityCollectionModel entityModel, CommercePipelineExecutionContext context) { try { foreach (var commerceEntity in entityModel.Entities) { var entity = Cast(commerceEntity, entityModel.EntityType); var existingEntity = await _findEntityCommand.Process(context.CommerceContext, entity.GetType(), entity.Id); if (existingEntity != null) { // Try to increase version count instead of delete DeleteEntityArgument result = await _deleteEntityCommand.Process(context.CommerceContext, existingEntity.Id); if (!result.Success) { Log.Error($"{this.GetType().Name}: Deletion of {existingEntity.Id} failed - new Entity was not imported"); } else { entity.Version = 0; } } //entity.EntityVersion = 1; //entity.Version = 0; entity.IsPersisted = false; context.CommerceContext.AddUniqueEntityByType(entity); var persistResult = await this._persistEntityCommand.Process(context.CommerceContext, entity); } if (entityModel.EntityType == typeof(Category)) { await AssociateCategoriesToParent(entityModel, context); } if (entityModel.EntityType == typeof(SellableItem)) { await AssociateSellableItemsToParent(entityModel, context); } } catch (Exception ex) { throw ex; } }
private async Task <Category> CreateOrGetCategory(CommercePipelineExecutionContext context, Catalog catalog, string categoryName, string parentCategoryId = null) { try { string categoryId = GenerateFullCategoryId(catalog.Name, categoryName); //Check if catalog with given name already exists before trying to create a new one Category category = await _findEntityCommand.Process(context.CommerceContext, typeof(Category), categoryId, false) as Category; if (category == null) { context.Logger.LogInformation($"ProductImport:Category Not Found, result is nill _getCategoryCommand:{categoryId}"); context.Logger.LogInformation($"ProductImport:Creating Category: {categoryId}"); category = await _createCategoryCommand.Process(context.CommerceContext, catalog.Id, categoryName, categoryName, categoryName) as Category; //category.ParentCatalogList = catalog.SitecoreId; //int version = category.Version; //if(category.Version != version + 1) //var newItemVersion = category.EntityVersion + 1; //await _addEntityVersionCommand.Process(context.CommerceContext, category, newItemVersion); //Save Category Result //var result = await _commander.Pipeline<IPersistEntityPipeline>() // .Run(new PersistEntityArgument(category), context.CommerceContext.GetPipelineContextOptions()); //if (string.IsNullOrWhiteSpace(parentCategoryId)) // await _associateCategoryToParentCommand.Process(context.CommerceContext, catalog.Id, catalog.Id, category.Id); //else // await _associateCategoryToParentCommand.Process(context.CommerceContext, catalog.Id, parentCategoryId, category.Id); return(category); } else { context.Logger.LogInformation($"ProductImport: Category found _findEntityPipeline, catalog: {categoryName}"); } return(category); } catch (Exception ex) { context.Logger.LogInformation($"ProductImport: Error during catelog process" + ex.Message); return(null); } }
private async Task <Catalog> GetOrCreateCatalog(string catalogName, CommercePipelineExecutionContext context) { try { //Commerce would use a add different prefixes to internal IDs of different kinds of entities. //this will get us internal commerce ID for a given catalog name var commerceCatalogId = $"{CommerceEntity.IdPrefix<Catalog>()}{catalogName}"; //Check if catalog with given name already exists before trying to create a new one Catalog catalog = await _findEntityCommand.Process(context.CommerceContext, typeof(Catalog), commerceCatalogId, null, false) as Catalog; if (catalog == null) { var catalogBaseName = catalogName.Replace("_Catalog", string.Empty); catalog = await _createCatalogCommand.Process(context.CommerceContext, catalogName, catalogDisplayName) as Catalog; //Persist changes to Catalog (Price and Promo books associations created above) into Commerce database var result = await _commander.Pipeline <IPersistEntityPipeline>() .Run(new PersistEntityArgument(catalog), context.CommerceContext.PipelineContextOptions); catalog = result.Entity as Catalog; } else { context.Logger.LogInformation($"ProductImport: catalog found _findEntityPipeline, catalog: {catalogName}"); } if (catalog == null) { context.Logger.LogInformation($"ProductImport: Error during catalog process"); } //TO DO: Need to apply Clear cache every fifth iteration: https://doc.sitecore.com/developers/91/sitecore-experience-commerce/en/optimize-the-commercecontext-cache-for-a-long-running-process.html //Refresh Commerce Cache context.CommerceContext = new CommerceContext(context.CommerceContext.Logger, context.CommerceContext.TelemetryClient) { GlobalEnvironment = context.CommerceContext.GlobalEnvironment, Environment = context.CommerceContext.Environment, Headers = context.CommerceContext.Headers }; return(catalog); } catch (Exception ex) { context.Logger.LogInformation($"ProductImport: Error during catalog process" + ex.Message); return(null); } }
private async Task <Catalog> GetOrCreateCatalog(string catalogName, CommercePipelineExecutionContext context) { try { //Commerce would use a add different prefixes to internal IDs of different kinds of entities. //this will get us internal commerce ID for a given catalog name var commerceCatalogId = $"{CommerceEntity.IdPrefix<Catalog>()}{catalogName}"; //Check if catalog with given name already exists before trying to create a new one Catalog catalog = await _findEntityCommand.Process(context.CommerceContext, typeof(Catalog), commerceCatalogId, false) as Catalog; if (catalog == null) { var catalogBaseName = catalogName.Replace("_Catalog", string.Empty); catalog = await _createCatalogCommand.Process(context.CommerceContext, catalogName, catalogDisplayName) as Catalog; //Persist changes to Catalog (Price and Promo books associations created above) into Commerce database var result = await _commander.Pipeline <IPersistEntityPipeline>() .Run(new PersistEntityArgument(catalog), context.CommerceContext.GetPipelineContextOptions()); catalog = result.Entity as Catalog; } else { context.Logger.LogInformation($"ProductImport: catalog found _findEntityPipeline, catalog: {catalogName}"); } if (catalog == null) { context.Logger.LogInformation($"ProductImport: Error during catalog process"); } return(catalog); } catch (Exception ex) { context.Logger.LogInformation($"ProductImport: Error during catalog process" + ex.Message); return(null); } }
public virtual async Task <Sitecore.Commerce.Plugin.Customers.Customer> Process(CommerceContext commerceContext, string customerID, bool subscribeEmail, string company) { try { var customerEntity = await _getCustomerCommand.Process(commerceContext, customerID); if (customerEntity != null) { var customerEntityView = await _getEntityViewCommand.Process(commerceContext, customerEntity.Id, "Master", "", ""); var composerEditView = customerEntityView.ChildViews.Where(x => x.Name == "Details").FirstOrDefault() as EntityView; if (composerEditView != null) { commerceContext.Logger.LogDebug($"Edit customer detail view loaded: {DateTime.Now}"); var updatedCustomerEntity = await _findEntityCommand.Process(commerceContext, typeof(Sitecore.Commerce.Plugin.Customers.Customer), composerEditView.EntityId) as Sitecore.Commerce.Plugin.Customers.Customer; var customDetails = new CustomerExtended(); customDetails.ReceiveEmailUpdates = Convert.ToBoolean(subscribeEmail); customDetails.Company = company; updatedCustomerEntity.SetComponent(customDetails); await this._persistEntityPipeline.Run(new PersistEntityArgument(updatedCustomerEntity), commerceContext.PipelineContext); } else { commerceContext.Logger.LogInformation($"Edit customer entityview is empty: {DateTime.Now}"); } } else { commerceContext.Logger.LogInformation($"Customer entityview is null: {DateTime.Now}"); } return(customerEntity); } catch (Exception e) { commerceContext.Logger.LogInformation($"Exception occured in getting customer { e.StackTrace} and id is {e.Message}"); return(await Task.FromException <Sitecore.Commerce.Plugin.Customers.Customer>(e)); } }
public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context) { if (string.IsNullOrEmpty(arg?.Action) || !arg.Action.Equals(context.GetPolicy <KnownCustomPricingActionsPolicy>().SelectMembershipCurrency, StringComparison.OrdinalIgnoreCase) || !arg.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomRow, StringComparison.OrdinalIgnoreCase)) { return(arg); } var card = context.CommerceContext.GetObjects <PriceCard>().FirstOrDefault(p => p.Id.Equals(arg.EntityId, StringComparison.OrdinalIgnoreCase)); if (card == null) { return(arg); } KnownResultCodes policy = context.GetPolicy <KnownResultCodes>(); if (string.IsNullOrEmpty(arg.ItemId)) { await context.CommerceContext.AddMessage(policy.ValidationError, "InvalidOrMissingPropertyValue", new object[] { "ItemId" }, "Invalid or missing value for property 'ItemId'.") .ConfigureAwait(false); return(arg); } PriceSnapshotComponent snapshot = card.Snapshots.FirstOrDefault(s => s.Id.Equals(arg.ItemId, StringComparison.OrdinalIgnoreCase)); if (snapshot == null) { await context.CommerceContext.AddMessage(policy.ValidationError, "PriceSnapshotNotFound", new object[] { arg.ItemId, card.FriendlyId }, "Price snapshot " + arg.ItemId + " on price card " + card.FriendlyId + " was not found.") .ConfigureAwait(false); return(arg); } var currencyProperty = arg.Properties.FirstOrDefault(p => p.Name.Equals("Currency", StringComparison.OrdinalIgnoreCase)); string currency = currencyProperty?.Value; if (string.IsNullOrEmpty(currency)) { await context.CommerceContext.AddMessage(policy.ValidationError, "InvalidOrMissingPropertyValue", new object[] { currencyProperty == null ? "Currency" : currencyProperty.DisplayName }, "Invalid or missing value for property 'Currency'.") .ConfigureAwait(false); return(arg); } if (snapshot.Tiers.Any(t => t.Currency.Equals(currency, StringComparison.OrdinalIgnoreCase))) { await context.CommerceContext.AddMessage(policy.ValidationError, "CurrencyAlreadyExists", new object[] { currency, snapshot.Id, card.FriendlyId }, "Currency " + currency + " already exists for snapshot " + snapshot.Id + " on price card " + card.FriendlyId + ".") .ConfigureAwait(false); return(arg); } CurrencySet currencySet = null; string entityTarget = (await _findEntityCommand.Process(context.CommerceContext, typeof(PriceBook), card.Book.EntityTarget, false).ConfigureAwait(false) as PriceBook)?.CurrencySet.EntityTarget; if (!string.IsNullOrEmpty(entityTarget)) { currencySet = await _getCurrencySetCommand.Process(context.CommerceContext, entityTarget).ConfigureAwait(false); if (currencySet != null) { var currencies = currencySet.GetComponent <CurrenciesComponent>().Currencies; string str = string.Join(", ", currencies.Select(c => c.Code)); if (!currencies.Any(c => c.Code.Equals(currency, StringComparison.OrdinalIgnoreCase))) { CommercePipelineExecutionContext executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string commerceTermKey = "InvalidCurrency"; var args = new object[] { currency, str }; string defaultMessage = "Invalid currency '" + currency + "'. Valid currencies are '" + str + "'."; executionContext.Abort(await commerceContext.AddMessage(validationError, commerceTermKey, args, defaultMessage).ConfigureAwait(false), context); executionContext = null; return(arg); } } } currencyProperty.IsReadOnly = true; currencyProperty.Policies = new List <Policy>() { new AvailableSelectionsPolicy(currencySet == null || !currencySet.HasComponent <CurrenciesComponent>() ? new List <Selection>() : currencySet.GetComponent <CurrenciesComponent>() .Currencies.Select(c => { return(new Selection() { DisplayName = c.Code, Name = c.Code }); }).ToList(), false) }; EntityView priceCustomCellEntityView = new EntityView { Name = context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomCell, EntityId = card.Id, ItemId = snapshot.Id }; var membershipLevels = context.GetPolicy <MembershipLevelPolicy>().MembershipLevels; List <Selection> selections = currencySet == null || !currencySet.HasComponent <CurrenciesComponent>() ? new List <Selection>() : membershipLevels.Select(c => { return(new Selection() { DisplayName = c.MemerbshipLevelName, Name = c.MemerbshipLevelName }); }).ToList(); AvailableSelectionsPolicy availableSelectionsPolicy = new AvailableSelectionsPolicy(selections, false); List <Policy> commercePolicies = new List <Policy>() { availableSelectionsPolicy }; ViewProperty membershipLevelViewProperty = new ViewProperty() { Name = "MembershipLevel", OriginalType = typeof(string).FullName, Policies = commercePolicies }; priceCustomCellEntityView.Properties.Add(membershipLevelViewProperty); ViewProperty quantityViewProperty = new ViewProperty(); quantityViewProperty.Name = "Quantity"; quantityViewProperty.OriginalType = typeof(decimal).FullName; priceCustomCellEntityView.Properties.Add(quantityViewProperty); ViewProperty priceViewProperty = new ViewProperty { Name = "Price", RawValue = null, OriginalType = typeof(decimal).FullName }; priceCustomCellEntityView.Properties.Add(priceViewProperty); arg.ChildViews.Add(priceCustomCellEntityView); arg.UiHint = "Grid"; context.CommerceContext.AddModel(new MultiStepActionModel(context.GetPolicy <KnownCustomPricingActionsPolicy>().AddMembershipCurrency)); return(arg); }
/// <summary> /// Runs the specified argument. /// </summary> /// <param name="arg">The argument.</param> /// <param name="context">The context.</param> /// <returns></returns> public override async Task <CommerceEntity> Run(CommerceEntity arg, CommercePipelineExecutionContext context) { if (arg == null) { return(arg); } if (!(arg is Order)) { return(arg); } var migrationPolicy = context.CommerceContext?.GetPolicy <MigrationPolicy>(); if (migrationPolicy == null) { await context.CommerceContext.AddMessage( context.CommerceContext.GetPolicy <KnownResultCodes>().Error, "InvalidOrMissingPropertyValue", new object[] { "MigrationPolicy" }, $"{this.GetType()}. Missing MigrationPolicy").ConfigureAwait(false); return(arg); } Guid id; if (!Guid.TryParse(arg.Id, out id)) { context.Logger.LogInformation($"{this.Name} - Invalid Order Id:{arg.Id}"); return(arg); } arg.Id = $"{CommerceEntity.IdPrefix<Order>()}{id:N}"; var targetOrder = await _findEntityCommand.Process(context.CommerceContext, typeof(Order), arg.Id).ConfigureAwait(false); if (targetOrder != null) { arg.IsPersisted = true; arg.Version = targetOrder.Version; return(arg); } if (arg.HasComponent <ContactComponent>()) { var indexByCustomerId = new EntityIndex { Id = $"{EntityIndex.IndexPrefix<Order>("Id")}{arg.Id}", IndexKey = arg.GetComponent <ContactComponent>()?.CustomerId, EntityId = arg.Id }; if (!migrationPolicy.ReviewOnly) { await this._persistEntityPipeline.Run(new PersistEntityArgument(indexByCustomerId), context).ConfigureAwait(false); } } var order = (Order)arg; var indexByConfirmationId = new EntityIndex { Id = $"{EntityIndex.IndexPrefix<Order>("Id")}{order?.OrderConfirmationId}", IndexKey = order?.OrderConfirmationId, EntityId = arg.Id }; if (!migrationPolicy.ReviewOnly) { await this._persistEntityPipeline.Run(new PersistEntityArgument(indexByConfirmationId), context).ConfigureAwait(false); } return(arg); }
public override async Task <CreateCouponsArgument> Run( CreateCouponsArgument arg, CommercePipelineExecutionContext context) { await this._getManagedListCommand.PerformTransaction(context.CommerceContext, async() => { var policy = context.CommerceContext.GetPolicy <LoyaltyPointsPolicy>(); LoyaltyPointsEntity loyaltyPointsEntity = await _findEntityCommand.Process(context.CommerceContext, typeof(LoyaltyPointsEntity), Constants.EntityId, shouldCreate: true) as LoyaltyPointsEntity; if (loyaltyPointsEntity == null) { await context.AbortWithError("Unable to access or create LoyaltyPointsEntity {0}", "LoyaltyPointsEntityNotReturned", Constants.EntityId); return; } // Prevent simultaneous updates, in case multiple minion instances. Since these might be on scaled servers, mutex lock uses database field. // Lock is read before count is checked, so that when first process finishes and releases row, counts will be replenished. // Notes: // 1. If this pipeline aborts, the lock should be rolled back. // 2. Assuming transactions are enabled, the second process should never see IsLocked=true, as the read won't return until the lock is released. However, // this syntax should work on a non-transactional environment, and makes the intent of the code clearer. if (loyaltyPointsEntity.IsLocked) { await context.AbortWithError("{0} is locked. If this condition persists, unset this value through the database.", "EntityLocked", Constants.EntityId); return; } var list = await EnsureList(context, Constants.AvailableCouponsList); if (list == null) { await context.AbortWithError("Unable to create list {0}", "UnableToCreateList", Constants.AvailableCouponsList); return; } long count = await _getListCountCommand.Process(context.CommerceContext, Constants.AvailableCouponsList); context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} has {count} items."); if (count <= policy.ReprovisionTriggerCount) { loyaltyPointsEntity.IsLocked = true; await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity); context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} is at or under reprovision count of {policy.ReprovisionTriggerCount}."); loyaltyPointsEntity.SequenceNumber++; string suffix = loyaltyPointsEntity.SequenceNumber.ToString(); string promotionName = string.Format(Constants.GeneratedPromotion, suffix); Promotion promotion = await GeneratePromotion(context, promotionName); if (promotion == null) { await context.AbortWithError("Unable to generate promotion {0}.", "PromotionNotFound", promotionName); return; } await AddCoupons(context, promotion, suffix); if (context.IsNullOrHasErrors()) { return; } await AllocateCoupons(context, promotion, suffix); if (context.IsNullOrHasErrors()) { return; } ApprovePromotion(context, promotion); await CopyCouponsToList(context, loyaltyPointsEntity, list); if (context.IsNullOrHasErrors()) { return; } loyaltyPointsEntity.IsLocked = false; await _persistEntityCommand.Process(context.CommerceContext, list); await _persistEntityCommand.Process(context.CommerceContext, promotion); await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity); } }); return(arg); }
protected virtual async Task PopulateRowDetails(EntityView view, PriceCard card, string itemId, bool isAddAction, bool isEditAction, CommercePipelineExecutionContext context) { if (view == null || card == null || string.IsNullOrEmpty(itemId)) { return; } if (isAddAction) { CurrencySet currencySet = null; string entityTarget = (await _findEntityCommand.Process(context.CommerceContext, typeof(PriceBook), card.Book.EntityTarget, false).ConfigureAwait(false) as PriceBook)?.CurrencySet.EntityTarget; if (!string.IsNullOrEmpty(entityTarget)) { currencySet = await _getCurrencySetCommand.Process(context.CommerceContext, entityTarget).ConfigureAwait(false); } List <Policy> commercePolicies = new List <Policy>() { new AvailableSelectionsPolicy(currencySet == null || !currencySet.HasComponent <CurrenciesComponent>() ? new List <Selection>() : currencySet.GetComponent <CurrenciesComponent>().Currencies.Select(c => { return(new Selection() { DisplayName = c.Code, Name = c.Code }); }).ToList(), false) }; ViewProperty item = new ViewProperty() { Name = "Currency", RawValue = string.Empty, Policies = commercePolicies }; view.Properties.Add(item); } else { string[] strArray = itemId.Split('|'); if (strArray.Length != 2 || string.IsNullOrEmpty(strArray[0]) || string.IsNullOrEmpty(strArray[1])) { context.Logger.LogError("Expecting a SnapshotId and Currency in the ItemId: " + itemId + ". Correct format is 'snapshotId|currency'", Array.Empty <object>()); } else { string snapshotId = strArray[0]; string currency = strArray[1]; PriceSnapshotComponent snapshotComponent = card.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotId, StringComparison.OrdinalIgnoreCase)); if (snapshotComponent == null) { context.Logger.LogError("Price snapshot " + snapshotId + " on price card " + card.FriendlyId + " was not found.", Array.Empty <object>()); } else { var list = snapshotComponent.GetComponent <MembershipTiersComponent>().Tiers; IGrouping <string, CustomPriceTier> currencyGroup = list.GroupBy(t => t.Currency) .ToList() .FirstOrDefault(g => g.Key.Equals(currency, StringComparison.OrdinalIgnoreCase)); if (currencyGroup == null) { context.Logger.LogError("Price row " + currency + " was not found in snapshot " + snapshotId + " for card " + card.FriendlyId + ".", Array.Empty <object>()); } else { view.Properties.Add(new ViewProperty { Name = "Currency", RawValue = currencyGroup.Key, IsReadOnly = true }); if (isEditAction) { view.UiHint = "Grid"; currencyGroup.ForEach(tier => { EntityView entityView = new EntityView() { Name = context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomCell, EntityId = card.Id, ItemId = itemId }; var membershipLevels = context.GetPolicy <MembershipLevelPolicy>().MembershipLevels; ViewProperty item1 = new ViewProperty() { Name = "MembershipLevel", RawValue = tier.MembershipLevel, OriginalType = typeof(string).FullName, IsReadOnly = true, Policies = new List <Policy>() { new AvailableSelectionsPolicy(membershipLevels.Select(c => { return(new Selection() { DisplayName = c.MemerbshipLevelName, Name = c.MemerbshipLevelName }); }).ToList(), false) } }; entityView.Properties.Add(item1); entityView.Properties.Add(new ViewProperty() { Name = "Quantity", RawValue = tier.Quantity, IsReadOnly = true }); entityView.Properties.Add(new ViewProperty() { Name = "Price", RawValue = tier.Price, IsRequired = false }); view.ChildViews.Add(entityView); }); } else { view.Properties.Add(new ViewProperty { Name = "ItemId", RawValue = itemId, IsReadOnly = true, IsHidden = true }); list.Select(t => t.MembershipLevel).Distinct().OrderBy(q => q).ToList().ForEach(availableMembershipLevel => { CustomPriceTier priceTier = currencyGroup.FirstOrDefault(ct => ct.MembershipLevel == availableMembershipLevel); List <ViewProperty> properties = view.Properties; properties.Add(new ViewProperty() { Name = availableMembershipLevel.ToString(CultureInfo.InvariantCulture), RawValue = priceTier?.Price, IsReadOnly = true }); }); } } } } } }