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); }
public override async Task <PriceCard> Run(PriceCard arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull(Name + ": The price card can not be null"); PriceCard card = arg; var argument = context.CommerceContext.GetObjects <PriceCardSnapshotCustomTierArgument>().FirstOrDefault(); CommercePipelineExecutionContext executionContext; if (argument == null) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = "Argument of type " + typeof(PriceCardSnapshotCustomTierArgument).Name + " was not found in context."; executionContext.Abort(await commerceContext.AddMessage(error, "ArgumentNotFound", new object[] { typeof(PriceCardSnapshotCustomTierArgument).Name }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } Condition.Requires(argument.PriceSnapshot).IsNotNull(Name + ": The price snapshot can not be null"); Condition.Requires(argument.PriceSnapshot.Id).IsNotNullOrEmpty(Name + ": The price snapshot id can not be null or empty"); Condition.Requires(argument.PriceTier).IsNotNull(Name + ": The price tier can not be null"); Condition.Requires(argument.PriceTier.Currency).IsNotNullOrEmpty(Name + ": The price tier currency can not be null or empty"); PriceBook book = await _findEntityPipeline.Run(new FindEntityArgument(typeof(PriceBook), card.Book.EntityTarget, false), context) .ConfigureAwait(false) as PriceBook; CurrencySet currencySet = await _getCurrencySetPipeline.Run(book?.CurrencySet?.EntityTarget, context) .ConfigureAwait(false); if (!(currencySet != null && currencySet.HasComponent <CurrenciesComponent>() && currencySet.GetComponent <CurrenciesComponent>().Currencies.Any(c => c.Code.Equals(argument.PriceTier.Currency, StringComparison.OrdinalIgnoreCase)))) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = "Currency '" + argument.PriceTier.Currency + "' is no longer valid for book '" + book?.FriendlyId + "'. Either remove the tier or modify the book to include the currency."; executionContext.Abort(await commerceContext.AddMessage(error, "CurrencyNotLongerValid", new object[] { argument.PriceTier.Currency, book?.FriendlyId }, defaultMessage).ConfigureAwait(false), (object)context); executionContext = null; return(card); } GlobalPricingPolicy policy = context.GetPolicy <GlobalPricingPolicy>(); if (argument.PriceTier.Price < policy.MinimumPrice) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = string.Format("Invalid price. Minimum price allowed is '{0}'.", (object)policy.MinimumPrice); executionContext.Abort(await commerceContext.AddMessage(error, "InvalidPrice", new object[] { policy.MinimumPrice }, defaultMessage).ConfigureAwait(false), context); executionContext = null; return(card); } PriceSnapshotComponent snapshot = argument.PriceSnapshot; PriceSnapshotComponent snapshotComponent = card.Snapshots.FirstOrDefault(n => n.Id.Equals(snapshot.Id, StringComparison.OrdinalIgnoreCase)); if (snapshotComponent == null) { await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "PriceSnapshotNotFound", new object[] { snapshot.Id, card.FriendlyId }, "Price snapshot '" + snapshot.Id + "' on price card '" + card.FriendlyId + "' was not found.") .ConfigureAwait(false); return(card); } var tier = argument.PriceTier; if (string.IsNullOrEmpty(tier.Id)) { tier.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); } var membershipTiersComponent = snapshotComponent.GetComponent <MembershipTiersComponent>(); var existingTier = membershipTiersComponent?.Tiers.FirstOrDefault(t => t.Id.Equals(tier.Id, StringComparison.OrdinalIgnoreCase)); if (existingTier == null) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string defaultMessage = "Price tier '" + tier.Id + "' was not found in snapshot '" + snapshot.Id + "' for card '" + card.FriendlyId + "."; executionContext.Abort(await commerceContext.AddMessage(validationError, "PriceTierNotFound", new object[] { tier.Id, snapshot.Id, card.FriendlyId }, defaultMessage).ConfigureAwait(false), context); executionContext = null; return(card); } await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().Information, null, null, "Edited price tier '" + tier.Id + "' from price snapshot '" + snapshot.Id + "'").ConfigureAwait(false); existingTier.Price = tier.Price; return(card); }
public override async Task <PriceCard> Run(PriceCard arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull(Name + ": The price card can not be null"); PriceCard card = arg; PriceCardSnapshotCustomTierArgument argument = context.CommerceContext.GetObjects <PriceCardSnapshotCustomTierArgument>().FirstOrDefault(); CommercePipelineExecutionContext executionContext; if (argument == null) { executionContext = context; var commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = "Argument of type " + typeof(PriceCardSnapshotCustomTierArgument).Name + " was not found in context."; executionContext.Abort(await commerceContext.AddMessage(error, "ArgumentNotFound", new object[] { typeof(PriceCardSnapshotCustomTierArgument).Name }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } Condition.Requires(argument.PriceSnapshot).IsNotNull(Name + ": The price snapshot cannot be null."); Condition.Requires(argument.PriceSnapshot.Id).IsNotNullOrEmpty(Name + ": The price snapshot id cannot be null or empty."); Condition.Requires(argument.PriceTier).IsNotNull(Name + ": The price tier cannot be null."); Condition.Requires(argument.PriceTier.Currency).IsNotNullOrEmpty(Name + ": The price tier currency cannot be null or empty."); Condition.Requires(argument.PriceTier.Quantity).IsNotNull(Name + ": The price tier quantity cannot be null."); Condition.Requires(argument.PriceTier.Price).IsNotNull(Name + ": The price tier price cannot be null."); var snapshot = argument.PriceSnapshot; var tier = argument.PriceTier; var membershipTiersComponent = snapshot.GetComponent <MembershipTiersComponent>(); if (membershipTiersComponent.Tiers.Any(x => x.Currency == tier.Currency && x.MembershipLevel == tier.MembershipLevel && x.Quantity == tier.Quantity)) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string defaultMessage = "A tier for specified Currency, Membership Level and Quantity already exists for price snapshot '" + snapshot.Id + "' in price card '" + card.FriendlyId + "'."; executionContext.Abort(await commerceContext.AddMessage(validationError, "PriceTierAlreadyExists", new object[] { snapshot.Id, card.FriendlyId }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } GlobalPricingPolicy policy = context.GetPolicy <GlobalPricingPolicy>(); if (argument.PriceTier.Quantity <= policy.MinimumPricingQuantity) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = string.Format("Invalid quantity. Quantity must be greater than '{0}'.", policy.MinimumPricingQuantity); executionContext.Abort(await commerceContext.AddMessage(error, "InvalidQuantity", new object[] { policy.MinimumPricingQuantity }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } if (argument.PriceTier.Price < policy.MinimumPrice) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string defaultMessage = string.Format("Invalid price. Minimum price allowed is '{0}'.", policy.MinimumPrice); executionContext.Abort(await commerceContext.AddMessage(error, "InvalidPrice", new object[] { policy.MinimumPrice }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } PriceBook priceBook = await _findEntityPipeline.Run(new FindEntityArgument(typeof(PriceBook), card.Book.EntityTarget, false), context) .ConfigureAwait(false) as PriceBook; CurrencySet currencySet = await _getCurrencySetPipeline.Run(priceBook?.CurrencySet?.EntityTarget, context) .ConfigureAwait(false); bool flag = false; string str = string.Empty; if (currencySet != null && currencySet.HasComponent <CurrenciesComponent>()) { CurrenciesComponent component = currencySet.GetComponent <CurrenciesComponent>(); str = string.Join(", ", component.Currencies.Select(c => c.Code)); if (component.Currencies.Any(c => c.Code.Equals(argument.PriceTier.Currency, StringComparison.OrdinalIgnoreCase))) { flag = true; } } if (!flag) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string defaultMessage = "Invalid currency '" + argument.PriceTier.Currency + "'. Valid currencies are '" + str + "'."; executionContext.Abort(await commerceContext.AddMessage(validationError, "InvalidCurrency", new object[] { argument.PriceTier.Currency, str }, defaultMessage) .ConfigureAwait(false), context); executionContext = null; return(card); } tier.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); PriceSnapshotComponent snapshotComponent = card.Snapshots.FirstOrDefault(n => n.Id.Equals(snapshot.Id, StringComparison.OrdinalIgnoreCase)); if (snapshotComponent != null) { var component = snapshotComponent.GetComponent <MembershipTiersComponent>(); if (component != null) { component.Tiers.Add(tier); } } PriceTierAdded priceTierAdded = new PriceTierAdded(tier.Id) { Name = tier.Name }; context.CommerceContext.AddModel(priceTierAdded); return(card); }
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 }); }); } } } } } }