public override Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull(this.Name + ": The argument cannot be null"); EntityViewArgument request = context.CommerceContext.GetObjects <EntityViewArgument>().FirstOrDefault(); if (request == null) { return(Task.FromResult(arg)); } bool isAddAction = request.ForAction.Equals(context.GetPolicy <KnownPricingActionsPolicy>().AddPriceSnapshot, StringComparison.OrdinalIgnoreCase); bool isEditAction = request.ForAction.Equals(context.GetPolicy <KnownPricingActionsPolicy>().EditPriceSnapshot, StringComparison.OrdinalIgnoreCase); if (string.IsNullOrEmpty(request?.ViewName) || !(request.Entity is PriceCard) || !request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().Master, StringComparison.OrdinalIgnoreCase) && !request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().PriceCardSnapshots, StringComparison.OrdinalIgnoreCase) && !request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().PriceSnapshotDetails, StringComparison.OrdinalIgnoreCase) || request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().PriceSnapshotDetails, StringComparison.OrdinalIgnoreCase) && string.IsNullOrEmpty(request.ItemId) && !isAddAction) { return(Task.FromResult(arg)); } PriceCard card = (PriceCard)request.Entity; if (request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().Master, StringComparison.OrdinalIgnoreCase) || request.ViewName.Equals(context.GetPolicy <KnownPricingViewsPolicy>().PriceCardSnapshots, StringComparison.OrdinalIgnoreCase)) { List <EntityView> views = new List <EntityView>(); this.FindViews(views, arg, context.GetPolicy <KnownPricingViewsPolicy>().PriceSnapshotDetails, context.CommerceContext); views.ForEach(snapshotDetailsView => { EntityView view = snapshotDetailsView; PriceCard priceCard = card; PriceSnapshotComponent snapshot = priceCard?.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotDetailsView.ItemId, StringComparison.OrdinalIgnoreCase)); int num1 = isAddAction ? 1 : 0; int num2 = isEditAction ? 1 : 0; this.PopulateSnapshotDetails(view, snapshot, num1 != 0, num2 != 0); }); return(Task.FromResult(arg)); } PriceSnapshotComponent snapshotComponent; if (isAddAction) { snapshotComponent = null; } else { PriceCard priceCard = card; snapshotComponent = priceCard?.Snapshots.FirstOrDefault(s => s.Id.Equals(request.ItemId, StringComparison.OrdinalIgnoreCase)); } PriceSnapshotComponent snapshot1 = snapshotComponent; this.PopulateSnapshotDetails(arg, snapshot1, isAddAction, isEditAction); var rawValue = arg.Properties.FirstOrDefault((p => p.Name.Equals("BeginDate", StringComparison.OrdinalIgnoreCase))).RawValue; CultureInfo cultureInfo = CultureInfo.GetCultureInfo(context.CommerceContext.CurrentLanguage()); string str = (string.IsNullOrEmpty(card.DisplayName) ? card.Name : card.DisplayName) + " (" + rawValue + ")"; ViewProperty viewProperty1 = arg.Properties.FirstOrDefault(p => p.Name.Equals("DisplayName", StringComparison.OrdinalIgnoreCase)); if (viewProperty1 != null) { viewProperty1.RawValue = str; } else if (!isAddAction && !isEditAction) { List <ViewProperty> properties = arg.Properties; ViewProperty viewProperty2 = new ViewProperty { Name = "DisplayName", RawValue = str, IsReadOnly = true }; properties.Add(viewProperty2); } return(Task.FromResult(arg)); }
public virtual async Task <PriceCard> Process(CommerceContext commerceContext, PriceCard priceCard, PriceSnapshotComponent priceSnapshot, IEnumerable <CustomPriceTier> priceTiers) { PriceCard result = null; using (CommandActivity.Start(commerceContext, this)) { var snapshot = await GetPriceSnapshot(commerceContext, priceCard, priceSnapshot.Id).ConfigureAwait(false); if (snapshot == null) { return(null); } await PerformTransaction(commerceContext, async() => { foreach (CustomPriceTier priceTier in priceTiers) { result = await _removeCustomPriceTierPipeline.Run(new PriceCardSnapshotCustomTierArgument(priceCard, priceSnapshot, priceTier), commerceContext.GetPipelineContextOptions()) .ConfigureAwait(false); if (commerceContext.HasErrors()) { break; } } }).ConfigureAwait(false); return(result); } }
public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context) { if (string.IsNullOrEmpty(arg?.Action) || !arg.Action.Equals(context.GetPolicy <KnownCustomPricingActionsPolicy>().EditMembershipCurrency, StringComparison.OrdinalIgnoreCase) || !arg.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomRow, StringComparison.OrdinalIgnoreCase)) { return(arg); } PriceCard card = context.CommerceContext.GetObjects <PriceCard>().FirstOrDefault(p => p.Id.Equals(arg.EntityId, StringComparison.OrdinalIgnoreCase)); if (card == null) { return(arg); } KnownResultCodes errorsCodes = context.GetPolicy <KnownResultCodes>(); if (string.IsNullOrEmpty(arg.ItemId)) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { "ItemId" }, "Invalid or missing value for property 'ItemId'.") .ConfigureAwait(false); return(arg); } string snapshotId = arg.ItemId.Split('|')[0]; PriceSnapshotComponent snapshot = card.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotId, StringComparison.OrdinalIgnoreCase)); if (snapshot == null) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "PriceSnapshotNotFound", new object[] { snapshotId, card.FriendlyId }, "Price snapshot " + snapshotId + " on price card " + card.FriendlyId + " was not found.") .ConfigureAwait(false); return(arg); } ViewProperty currency = arg.Properties.FirstOrDefault(p => p.Name.Equals("Currency", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrEmpty(currency?.Value)) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { currency == null ? "Currency" : currency.DisplayName }, "Invalid or missing value for property 'Currency'.") .ConfigureAwait(false); return(arg); } List <Model> list = arg.ChildViews.Where(v => v.Name.Equals(context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomCell, StringComparison.OrdinalIgnoreCase)) .ToList(); if (!list.Any()) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { "Tiers" }, "Invalid or missing value for property 'Tiers'.") .ConfigureAwait(false); return(arg); } List <CustomPriceTier> tiersToAdd = new List <CustomPriceTier>(); List <CustomPriceTier> tiersToEdit = new List <CustomPriceTier>(); List <CustomPriceTier> tiersToDelete = new List <CustomPriceTier>(); bool hasError = false; foreach (EntityView entityView in list.Cast <EntityView>()) { ViewProperty quantityViewProperty = entityView.Properties.FirstOrDefault(p => p.Name.Equals("Quantity", StringComparison.OrdinalIgnoreCase)); decimal quantity; if (!decimal.TryParse(quantityViewProperty?.Value, out quantity)) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { quantityViewProperty == null ? "Quantity" : quantityViewProperty.DisplayName }, "Invalid or missing value for property 'Quantity'.") .ConfigureAwait(false); hasError = true; } else { ViewProperty membershipLevel = entityView.Properties.FirstOrDefault(p => p.Name.Equals("MembershipLevel", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrEmpty(currency?.Value)) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { currency == null ? "MembershipLevel" : currency.DisplayName }, "Invalid or missing value for property 'MembershipLevel'.") .ConfigureAwait(false); hasError = true; } else { ViewProperty priceViewProperty = entityView.Properties.FirstOrDefault(p => p.Name.Equals("Price", StringComparison.OrdinalIgnoreCase)); decimal result; bool isPriceParsed = decimal.TryParse(priceViewProperty?.Value, out result); var membershipTiersComponent = snapshot.GetComponent <MembershipTiersComponent>(); CustomPriceTier priceTier = membershipTiersComponent.Tiers.FirstOrDefault(t => t.Currency == currency.Value && t.Quantity == quantity && t.MembershipLevel == membershipLevel.Value); if (priceTier == null) { if (!isPriceParsed) { await context.CommerceContext.AddMessage(errorsCodes.ValidationError, "InvalidOrMissingPropertyValue", new object[] { priceViewProperty == null ? "Price" : priceViewProperty.DisplayName }, "Invalid or missing value for property 'Price'.") .ConfigureAwait(false); hasError = true; } else { tiersToAdd.Add(new CustomPriceTier(currency.Value, quantity, result, membershipLevel.Value)); } } else if (!isPriceParsed) { tiersToDelete.Add(priceTier); } else { priceTier.Price = result; priceTier.Quantity = quantity; priceTier.MembershipLevel = membershipLevel.Value; tiersToEdit.Add(priceTier); } } } } if (hasError) { return(arg); } if (tiersToAdd.Any()) { await _addPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToAdd) .ConfigureAwait(false); } if (tiersToDelete.Any() && !context.CommerceContext.HasErrors()) { await _removeCustomPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToDelete) .ConfigureAwait(false); } if (tiersToEdit.Any() && !context.CommerceContext.HasErrors()) { await _editPriceTierCommand.Process(context.CommerceContext, card, snapshot, tiersToEdit) .ConfigureAwait(false); } return(arg); }
public PriceCardSnapshotCustomTierArgument(PriceCard priceCard, PriceSnapshotComponent priceSnapshot, CustomPriceTier priceTier) : base(priceCard, priceSnapshot) { Condition.Requires(priceTier).IsNotNull("The price tier can not be null"); PriceTier = priceTier; }
public virtual async Task <PriceCard> Process(CommerceContext commerceContext, PriceCard priceCard, PriceSnapshotComponent priceSnapshot, CustomPriceTier priceTier) { PriceCard result = null; using (CommandActivity.Start(commerceContext, this)) { await PerformTransaction(commerceContext, async() => { result = await _removeCustomPriceTierPipeline.Run(new PriceCardSnapshotCustomTierArgument(priceCard, priceSnapshot, priceTier), commerceContext.GetPipelineContextOptions()) .ConfigureAwait(false); }).ConfigureAwait(false); } return(result); }
public virtual async Task <PriceCard> Process(CommerceContext commerceContext, PriceCard priceCard, PriceSnapshotComponent priceSnapshot, CustomPriceTier priceTier) { PriceCard result = null; using (CommandActivity.Start(commerceContext, this)) { var priceSnapshotById = await GetPriceSnapshot(commerceContext, priceCard, priceSnapshot.Id) .ConfigureAwait(false); if (priceSnapshotById == null) { return(null); } await PerformTransaction(commerceContext, (async() => result = await _addCustomPriceTierPipeline.Run(new PriceCardSnapshotCustomTierArgument(priceCard, priceSnapshotById, priceTier), commerceContext.GetPipelineContextOptions()).ConfigureAwait(false))) .ConfigureAwait(false); return(result); } }
public override async Task <EntityView> Run(EntityView arg, CommercePipelineExecutionContext context) { if (string.IsNullOrEmpty(arg?.Action) || !arg.Action.Equals(context.GetPolicy <KnownCustomPricingActionsPolicy>().RemoveMembershipCurrency, StringComparison.OrdinalIgnoreCase)) { return(arg); } PriceCard card = context.CommerceContext.GetObjects <PriceCard>().FirstOrDefault(p => p.Id.Equals(arg.EntityId, StringComparison.OrdinalIgnoreCase)); if (card == null) { return(arg); } if (string.IsNullOrEmpty(arg.ItemId)) { await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "InvalidOrMissingPropertyValue", new object[] { "ItemId" }, "Invalid or missing value for property 'ItemId'.") .ConfigureAwait(false); return(arg); } string[] strArray = arg.ItemId.Split('|'); if (strArray.Length != 2 || string.IsNullOrEmpty(strArray[0]) || string.IsNullOrEmpty(strArray[1])) { string str = await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "InvalidOrMissingPropertyValue", new object[] { "ItemId (Correct format is snapshotId|currency)" }, "Invalid or missing value for property 'ItemId (Correct format is snapshotId|currency)'.") .ConfigureAwait(false); return(arg); } string snapshotId = strArray[0]; string currency = strArray[1]; PriceSnapshotComponent snapshotComponent = card.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotId, StringComparison.OrdinalIgnoreCase)); if (snapshotComponent == null) { await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "PriceSnapshotNotFound", new object[] { snapshotId, card.FriendlyId }, "Price snapshot " + snapshotId + " on price card " + card.FriendlyId + " was not found.") .ConfigureAwait(false); return(arg); } var membershipTiersComponent = snapshotComponent.GetComponent <MembershipTiersComponent>(); List <CustomPriceTier> list = membershipTiersComponent.Tiers.Where(t => t.Currency.Equals(currency, StringComparison.OrdinalIgnoreCase)).ToList(); if (!list.Any()) { await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "CurrencyNotFound", new object[] { currency, snapshotId, card.FriendlyId }, "Currency '" + currency + "' for price snapshot '" + snapshotId + "' on price card '" + card.FriendlyId + "' was not found.") .ConfigureAwait(false); return(arg); } foreach (CustomPriceTier priceTier in list) { PriceCard priceCard = await _removeCustomPriceTierCommand.Process(context.CommerceContext, card.FriendlyId, snapshotId, priceTier.Id).ConfigureAwait(false); } 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 <CustomPriceTier> GetCustomPriceTier(CommerceContext context, PriceCard priceCard, PriceSnapshotComponent priceSnapshot, string priceTierId) { if (priceCard == null || priceSnapshot == null || string.IsNullOrEmpty(priceTierId)) { return(null); } var membershipTiersComponent = priceSnapshot.GetComponent <MembershipTiersComponent>(); var existingPriceTier = membershipTiersComponent.Tiers.FirstOrDefault(t => t.Id.Equals(priceTierId, StringComparison.OrdinalIgnoreCase)); if (existingPriceTier != null) { return(existingPriceTier); } await context.AddMessage(context.GetPolicy <KnownResultCodes>().ValidationError, "PriceTierNotFound", new object[] { priceTierId, priceSnapshot.Id, priceCard.FriendlyId }, "Price tier " + priceTierId + " was not found in snapshot " + priceSnapshot.Id + " for card " + priceCard.FriendlyId + ".") .ConfigureAwait(false); return(existingPriceTier); }
public override async Task <SellableItem> Run( SellableItem arg, CommercePipelineExecutionContext context) { if (arg == null) { return(null); } if (arg.HasPolicy <PurchaseOptionMoneyPolicy>() && arg.GetPolicy <PurchaseOptionMoneyPolicy>().Expires > DateTimeOffset.UtcNow && arg.GetPolicy <PurchaseOptionMoneyPolicy>().SellPrice.CurrencyCode.Equals(context.CommerceContext.CurrentCurrency(), StringComparison.OrdinalIgnoreCase)) { return(arg); } if (arg.HasComponent <PriceSnapshotComponent>()) { arg.Components.Remove(arg.GetComponent <PriceSnapshotComponent>()); } string currentCurrency = context.CommerceContext.CurrentCurrency(); MessagesComponent messagesComponent = arg.GetComponent <MessagesComponent>(); Money sellPrice = null; PriceCardPolicy priceCardPolicy = arg.Policies.OfType <PriceCardPolicy>().FirstOrDefault(); PriceSnapshotComponent snapshotComponent = null; bool pricingByTags = false; if (!string.IsNullOrEmpty(priceCardPolicy?.PriceCardName)) { snapshotComponent = await _resolveSnapshotByCardPipeline.Run(priceCardPolicy.PriceCardName, context); } else if (arg.Tags.Any()) { snapshotComponent = await _resolveSnapshotByTagsPipeline.Run(arg.Tags, context); pricingByTags = true; } PriceTier priceTier = snapshotComponent?.Tiers.FirstOrDefault(t => { return(t.Currency.Equals(currentCurrency, StringComparison.OrdinalIgnoreCase) ? t.Quantity == decimal.One : false); }); Customer customer = await _findEntityPipeline.Run(new FindEntityArgument(typeof(Customer), context.CommerceContext.CurrentCustomerId(), false), context) as Customer; bool isMembershipLevelPrice = false; if (customer != null && customer.HasComponent <MembershipSubscriptionComponent>()) { var membershipSubscriptionComponent = customer.GetComponent <MembershipSubscriptionComponent>(); var customerMemerbshipLevelName = membershipSubscriptionComponent.MemerbshipLevelName; var memerbshipLevelName = membershipSubscriptionComponent.MemerbshipLevelName; if (snapshotComponent != null && snapshotComponent.HasComponent <MembershipTiersComponent>()) { var membershipTiersComponent = snapshotComponent.GetComponent <MembershipTiersComponent>(); var membershipPriceTier = membershipTiersComponent.Tiers.FirstOrDefault(x => x.MembershipLevel == memerbshipLevelName); if (membershipPriceTier != null) { sellPrice = new Money(membershipPriceTier.Currency, membershipPriceTier.Price); isMembershipLevelPrice = true; messagesComponent.AddMessage(context.GetPolicy <KnownMessageCodePolicy>().Pricing, pricingByTags ? string.Format("SellPrice<=Tags.Snapshot: MembershipLevel={0}|Price={1}|Qty={2}|Tags='{3}'", customerMemerbshipLevelName, sellPrice.AsCurrency(false, null), membershipPriceTier.Quantity, string.Join(", ", snapshotComponent.Tags.Select(c => c.Name))) : string.Format("SellPrice<=PriceCard.Snapshot: MembershipLevel={0}|Price={1}|Qty={2}|PriceCard={3}", customerMemerbshipLevelName, sellPrice.AsCurrency(false, null), membershipPriceTier.Quantity, priceCardPolicy.PriceCardName)); } } } if (!isMembershipLevelPrice && priceTier != null) { sellPrice = new Money(priceTier.Currency, priceTier.Price); messagesComponent.AddMessage(context.GetPolicy <KnownMessageCodePolicy>().Pricing, pricingByTags ? string.Format("SellPrice<=Tags.Snapshot: Price={0}|Qty={1}|Tags='{2}'", sellPrice.AsCurrency(false, null), priceTier.Quantity, string.Join(", ", snapshotComponent.Tags.Select(c => c.Name))) : string.Format("SellPrice<=PriceCard.Snapshot: Price={0}|Qty={1}|PriceCard={2}", sellPrice.AsCurrency(false, null), priceTier.Quantity, priceCardPolicy.PriceCardName)); } if (snapshotComponent != null) { arg.SetComponent(snapshotComponent); } if (sellPrice != null) { arg.SetPolicy(new PurchaseOptionMoneyPolicy() { SellPrice = sellPrice }); } 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 }); }); } } } } } }
/// <summary> /// Creates the tags card. /// </summary> /// <param name="book">The book.</param> /// <param name="context">The context.</param> private async Task CreateTagsCard(PriceBook book, CommercePipelineExecutionContext context) { // TAGS CARD PriceCard card = await _addPriceCardPipeline .Run(new AddPriceCardArgument(book, "Habitat_TagsPriceCard"), context).ConfigureAwait(false); // TAGS CARD FIRST SNAPSHOT card = await _addPriceSnapshotPipeline .Run(new PriceCardSnapshotArgument(card, new PriceSnapshotComponent(DateTimeOffset.UtcNow)), context) .ConfigureAwait(false); PriceSnapshotComponent firstSnapshot = card.Snapshots.FirstOrDefault(); // TAGS CARD FIRST SNAPSHOT TIERS card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, firstSnapshot, new PriceTier("USD", 1, 250M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, firstSnapshot, new PriceTier("USD", 5, 200M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, firstSnapshot, new PriceTier("CAD", 1, 251M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, firstSnapshot, new PriceTier("CAD", 5, 201M)), context) .ConfigureAwait(false); // TAGS CARD FIRST SNAPSHOT TAGS card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, firstSnapshot, new Tag("Habitat")), context) .ConfigureAwait(false); card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, firstSnapshot, new Tag("Habitat 2")), context) .ConfigureAwait(false); card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, firstSnapshot, new Tag("common")), context) .ConfigureAwait(false); // TAGS CARD SECOND SNAPSHOT card = await _addPriceSnapshotPipeline .Run(new PriceCardSnapshotArgument(card, new PriceSnapshotComponent(DateTimeOffset.UtcNow.AddSeconds(1))), context).ConfigureAwait(false); PriceSnapshotComponent secondSnapshot = card.Snapshots.FirstOrDefault(s => !s.Id.Equals(firstSnapshot?.Id, StringComparison.OrdinalIgnoreCase)); // TAGS CARD SECOND SNAPSHOT TIERS card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, secondSnapshot, new PriceTier("USD", 1, 150M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, secondSnapshot, new PriceTier("USD", 5, 100M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, secondSnapshot, new PriceTier("CAD", 1, 101M)), context) .ConfigureAwait(false); card = await _addPriceTierPipeline .Run(new PriceCardSnapshotTierArgument(card, secondSnapshot, new PriceTier("CAD", 5, 151M)), context) .ConfigureAwait(false); // TAGS CARD SECOND SNAPSHOT TAGS card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, secondSnapshot, new Tag("Habitat variants")), context) .ConfigureAwait(false); card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, secondSnapshot, new Tag("Habitat variants 2")), context) .ConfigureAwait(false); card = await _addPriceSnapshotTagPipeline .Run(new PriceCardSnapshotTagArgument(card, secondSnapshot, new Tag("common")), context) .ConfigureAwait(false); // TAGS CARD APPROVAl COMPONENT card.Snapshots.ForEach(s => { s.SetComponent(new ApprovalComponent(context.GetPolicy <ApprovalStatusPolicy>().Approved)); }); await _persistEntityPipeline.Run(new PersistEntityArgument(card), context).ConfigureAwait(false); }
/// <summary> /// Creates the variants card. /// </summary> /// <param name="book">The book.</param> /// <param name="context">The context.</param> private async Task CreateVariantsCard(PriceBook book, CommercePipelineExecutionContext context) { context.CommerceContext.RemoveModels(m => m is PriceSnapshotAdded || m is PriceTierAdded); DateTimeOffset date = DateTimeOffset.UtcNow; // VARIANTS CARD PriceCard adventureVariantsCard = await _addPriceCardPipeline .Run(new AddPriceCardArgument(book, "Habitat_VariantsPriceCard"), context) .ConfigureAwait(false); // READY FOR APPROVAL SNAPSHOT adventureVariantsCard = await _addPriceSnapshotPipeline .Run( new PriceCardSnapshotArgument(adventureVariantsCard, new PriceSnapshotComponent(date.AddMinutes(-10))), context) .ConfigureAwait(false); PriceSnapshotComponent readyForApprovalSnapshot = adventureVariantsCard.Snapshots.FirstOrDefault(s => s.Id.Equals(context.CommerceContext.GetModel <PriceSnapshotAdded>()?.PriceSnapshotId, StringComparison.OrdinalIgnoreCase)); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, readyForApprovalSnapshot, new PriceTier("USD", 1, 2000M)), context).ConfigureAwait(false); context.CommerceContext.RemoveModels(m => m is PriceSnapshotAdded || m is PriceTierAdded); // FIRST APPROVED SNAPSHOT adventureVariantsCard = await _addPriceSnapshotPipeline .Run( new PriceCardSnapshotArgument(adventureVariantsCard, new PriceSnapshotComponent(date.AddHours(-1))), context).ConfigureAwait(false); PriceSnapshotComponent firstSnapshot = adventureVariantsCard.Snapshots.FirstOrDefault(s => s.Id.Equals( context.CommerceContext .GetModel <PriceSnapshotAdded>() ?.PriceSnapshotId, StringComparison.OrdinalIgnoreCase)); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("USD", 1, 9M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("USD", 5, 6M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("USD", 10, 3M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("CAD", 1, 7M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("CAD", 5, 4M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("CAD", 10, 2M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, firstSnapshot, new PriceTier("EUR", 1, 2M)), context).ConfigureAwait(false); context.CommerceContext.RemoveModels(m => m is PriceSnapshotAdded || m is PriceTierAdded); // DRAFT SNAPSHOT adventureVariantsCard = await _addPriceSnapshotPipeline .Run( new PriceCardSnapshotArgument(adventureVariantsCard, new PriceSnapshotComponent(date)), context).ConfigureAwait(false); PriceSnapshotComponent draftSnapshot = adventureVariantsCard.Snapshots.FirstOrDefault(s => s.Id.Equals( context.CommerceContext .GetModel <PriceSnapshotAdded>() ?.PriceSnapshotId, StringComparison.OrdinalIgnoreCase)); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, draftSnapshot, new PriceTier("USD", 1, 1000M)), context).ConfigureAwait(false); context.CommerceContext.RemoveModels(m => m is PriceSnapshotAdded || m is PriceTierAdded); // SECOND APPROVED SNAPSHOT adventureVariantsCard = await _addPriceSnapshotPipeline .Run( new PriceCardSnapshotArgument(adventureVariantsCard, new PriceSnapshotComponent(date.AddDays(30))), context).ConfigureAwait(false); PriceSnapshotComponent secondSnapshot = adventureVariantsCard.Snapshots.FirstOrDefault(s => s.Id.Equals( context.CommerceContext .GetModel <PriceSnapshotAdded>() ?.PriceSnapshotId, StringComparison.OrdinalIgnoreCase)); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("USD", 1, 8M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("USD", 5, 4M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("USD", 10, 2M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("CAD", 1, 7M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("CAD", 5, 3M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("CAD", 10, 1M)), context).ConfigureAwait(false); adventureVariantsCard = await _addPriceTierPipeline .Run( new PriceCardSnapshotTierArgument(adventureVariantsCard, secondSnapshot, new PriceTier("EUR", 1, 2M)), context).ConfigureAwait(false); context.CommerceContext.RemoveModels(m => m is PriceSnapshotAdded || m is PriceTierAdded); readyForApprovalSnapshot?.SetComponent( new ApprovalComponent(context.GetPolicy <ApprovalStatusPolicy>().ReadyForApproval)); firstSnapshot?.SetComponent(new ApprovalComponent(context.GetPolicy <ApprovalStatusPolicy>().Approved)); secondSnapshot?.SetComponent(new ApprovalComponent(context.GetPolicy <ApprovalStatusPolicy>().Approved)); await _persistEntityPipeline.Run(new PersistEntityArgument(adventureVariantsCard), context).ConfigureAwait(false); }