protected virtual void CreateTierDetailsViews(PriceCard card, string snapshotId, EntityView pricingView, CommercePipelineExecutionContext context) { pricingView.UiHint = "Table"; if (card == null || !card.Snapshots.Any() || string.IsNullOrEmpty(snapshotId)) { return; } PriceSnapshotComponent snapshotComponent = card.Snapshots.FirstOrDefault(s => s.Id.Equals(snapshotId, StringComparison.OrdinalIgnoreCase)); if (snapshotComponent == null) { return; } var membershipTiersComponent = snapshotComponent.GetComponent <MembershipTiersComponent>(); if (membershipTiersComponent == null || !membershipTiersComponent.Tiers.Any()) { return; } List <CustomPriceTier> list = membershipTiersComponent.Tiers.ToList(); foreach (IGrouping <string, CustomPriceTier> grouping in list.GroupBy(t => t.Currency)) { pricingView.ChildViews.Add(new EntityView { EntityId = card.Id, ItemId = snapshotComponent.Id + "|" + grouping.Key, Name = context.GetPolicy <KnownCustomPricingViewsPolicy>().PriceCustomRow }); } }
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 snapshotTierArgument = context.CommerceContext.GetObject <PriceCardSnapshotCustomTierArgument>(); CommercePipelineExecutionContext executionContext; if (snapshotTierArgument == 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(snapshotTierArgument.PriceSnapshot).IsNotNull(Name + ": The price snapshot can not be null"); Condition.Requires(snapshotTierArgument.PriceSnapshot.Id).IsNotNullOrEmpty(Name + ": The price snapshot id can not be null or empty"); Condition.Requires(snapshotTierArgument.PriceTier).IsNotNull(Name + ": The price tier can not be null"); Condition.Requires(snapshotTierArgument.PriceTier.Id).IsNotNullOrEmpty(Name + ": The price tier id can not be null or empty"); Condition.Requires(snapshotTierArgument.PriceTier.Currency).IsNotNullOrEmpty(Name + ": The price tier currency can not be null or empty"); PriceSnapshotComponent snapshot = snapshotTierArgument.PriceSnapshot; var tier = snapshotTierArgument.PriceTier; PriceSnapshotComponent existingSnapshot = card.Snapshots.FirstOrDefault(n => n.Id.Equals(snapshot.Id, StringComparison.OrdinalIgnoreCase)); if (existingSnapshot == null) { return(card); } var membershipTiersComponent = existingSnapshot.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, "Removed price tier " + tier.Id + " from price snapshot " + snapshot.Id) .ConfigureAwait(false); membershipTiersComponent.Tiers.Remove(existingTier); return(card); }
public async Task <CommerceCommand> Process(CommerceContext commerceContext, string itemId, decimal price) { using (var activity = CommandActivity.Start(commerceContext, this)) { var ids = itemId.Split('|'); var catalogName = ids[0]; var productId = ids[1]; var approvalStatusPolicy = commerceContext.GetPolicy <ApprovalStatusPolicy>(); var sellableItem = await Commander.GetEntity <SellableItem>(commerceContext, productId.ToEntityId <SellableItem>()); if (sellableItem != null) { var priceCardId = $"HerderPreisbuch-{productId}".ToEntityId <PriceCard>(); var priceCard = await Commander.GetEntity <PriceCard>(commerceContext, priceCardId); if (priceCard != null) { /// Create a new snapshot... var snapshotStartDate = DateTimeOffset.Now; int quantity = 1; string currency = "EUR"; var priceSnapShot = new PriceSnapshotComponent(); priceSnapShot.BeginDate = snapshotStartDate; priceSnapShot.Tiers.Add(new PriceTier(currency, quantity, price)); // Add the snapshot to the price card priceCard = await Commander.Command <Sitecore.Commerce.Plugin.Pricing.AddPriceSnapshotCommand>().Process(commerceContext, priceCard, priceSnapShot); // Approve the snapshot var approvalComponent = priceSnapShot.GetComponent <ApprovalComponent>(); approvalComponent.ModifyStatus(approvalStatusPolicy.Approved, "Automatically approved"); // Save the price card await Commander.PersistEntity(commerceContext, priceCard); // Associate price card with sellable item (if this has not been done already) var priceCardPolicy = sellableItem.GetPolicy <PriceCardPolicy>(); priceCardPolicy.PriceCardName = priceCard.Name; await Commander.PersistEntity(commerceContext, sellableItem); } // We assume the pricecard is already attached to the sellable item so we don't save it } return(this); } }
private async Task <PriceCard> UpdateOrCreatePriceSnapshot(CommercePipelineExecutionContext context, PriceCard priceCard, DateTimeOffset beginDate, List <MembershipSnapshotPriceModel> prices) { if (priceCard == null) { return(null); } var priceSnapshotComponent = new PriceSnapshotComponent(beginDate); var membershipTiersComponent = priceSnapshotComponent.GetComponent <MembershipTiersComponent>(); if (membershipTiersComponent.Tiers != null) { foreach (var membershipPrice in prices) { if (!membershipTiersComponent.Tiers.Any(x => x.MembershipLevel == membershipPrice.MemershipLevel)) { membershipTiersComponent.Tiers.Add(new CustomPriceTier("USD", 1, membershipPrice.Price, membershipPrice.MemershipLevel)); } } } var snapshotComponent = priceCard.Snapshots.OrderByDescending(s => s.BeginDate).FirstOrDefault(s => s.IsApproved(context.CommerceContext)); if (snapshotComponent != null && snapshotComponent.BeginDate.CompareTo(priceSnapshotComponent.BeginDate) >= 0) { return(priceCard); } if (priceCard.Snapshots.Any(s => DateTimeOffset.Compare(s.BeginDate, priceSnapshotComponent.BeginDate) == 0)) { return(priceCard); } var updatedPriceCard = await _addPriceSnapshotPipeline.Run(new PriceCardSnapshotArgument(priceCard, priceSnapshotComponent), context) .ConfigureAwait(false); return(updatedPriceCard); }
public virtual async Task <PriceCard> Process(CommerceContext commerceContext, string cardFriendlyId, DateTimeOffset beginDate, DateTimeOffset endDate) { AddPriceSnapshotCommand priceSnapshotCommand = this; PriceCard result = null; using (CommandActivity.Start(commerceContext, priceSnapshotCommand)) { PriceCard priceCard = await this.GetPriceCard(commerceContext, cardFriendlyId).ConfigureAwait(false); if (priceCard == null) { return(null); } var pricingSnapshot = new PriceSnapshotComponent(beginDate); var endDateComponent = pricingSnapshot.GetComponent <SnapshotEndDateComponent>(); endDateComponent.EndDate = endDate; await priceSnapshotCommand.PerformTransaction(commerceContext, (async() => result = await this._addPriceSnapshotPipeline.Run(new PriceCardSnapshotArgument(priceCard, pricingSnapshot), commerceContext.PipelineContextOptions).ConfigureAwait(false))).ConfigureAwait(false); return(result); } }
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 <bool> Run(bool arg, CommercePipelineExecutionContext context) { SetApprovalStatusArgument argument = context.CommerceContext.GetObject <SetApprovalStatusArgument>(); if (!(argument?.Entity is PriceCard) || string.IsNullOrEmpty(argument.Status) || string.IsNullOrEmpty(argument.ItemId)) { return(arg); } PriceCard entity = (PriceCard)argument.Entity; PriceSnapshotComponent snapshot = entity.Snapshots.FirstOrDefault(s => s.Id.Equals(argument.ItemId, StringComparison.OrdinalIgnoreCase)); CommercePipelineExecutionContext executionContext; if (snapshot == null) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string commerceTermKey = "PriceSnapshotNotFound"; object[] args = new object[2] { argument.ItemId, entity.FriendlyId }; string defaultMessage = "Price snapshot '" + argument.ItemId + "' on price card '" + entity.FriendlyId + "' was not found."; executionContext.Abort(await commerceContext.AddMessage(validationError, commerceTermKey, args, defaultMessage), context); executionContext = null; return(false); } var membershipTiersComponent = snapshot.GetComponent <MembershipTiersComponent>(); if (!snapshot.Tiers.Any() && !membershipTiersComponent.Tiers.Any()) { executionContext = context; CommerceContext commerceContext = context.CommerceContext; string validationError = context.GetPolicy <KnownResultCodes>().ValidationError; string commerceTermKey = "InvalidPriceSnapshot"; object[] args = new object[2] { argument.ItemId, entity.FriendlyId }; string defaultMessage = "Price snapshot '" + argument.ItemId + "' on price card '" + entity.FriendlyId + "' has not pricing."; executionContext.Abort(await commerceContext.AddMessage(validationError, commerceTermKey, args, defaultMessage), context); executionContext = null; return(false); } string currentStatus = snapshot.GetComponent <ApprovalComponent>().Status; IEnumerable <string> strings = await _getPossibleStatusesPipeline.Run(new GetPossibleApprovalStatusesArgument(snapshot), context); if (strings == null || !strings.Any()) { return(false); } if (!strings.Any(s => s.Equals(argument.Status, StringComparison.OrdinalIgnoreCase))) { string str = string.Join(",", strings); executionContext = context; CommerceContext commerceContext = context.CommerceContext; string error = context.GetPolicy <KnownResultCodes>().Error; string commerceTermKey = "SetStatusFailed"; object[] args = new object[4] { snapshot.Id, argument.Status, str, currentStatus }; string defaultMessage = "Attempted to change status for '" + snapshot.Id + "' to '" + argument.Status + "'. Allowed status are '" + str + "' when current status is '" + currentStatus + "'."; executionContext.Abort(await commerceContext.AddMessage(error, commerceTermKey, args, defaultMessage), context); executionContext = null; return(false); } snapshot.GetComponent <ApprovalComponent>().ModifyStatus(argument.Status, argument.Comment); await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().Information, null, null, "Price snapshot '" + snapshot.Id + "' approval status has been updated."); return(true); }
protected virtual void PopulateSnapshotDetails(EntityView view, PriceSnapshotComponent snapshot, bool isAddAction, bool isEditAction) { if (view == null) { return; } var snapshotEndDateComponent = snapshot?.GetComponent <SnapshotEndDateComponent>(); List <ViewProperty> properties1 = view.Properties; ViewProperty viewPropertyEndDate = null; ViewProperty viewPropertyStartDate = null; ViewProperty viewProertyUseEndDate = null; bool isReadOnly = !isAddAction && !isEditAction; if (isReadOnly) { viewPropertyStartDate = new ViewProperty { Name = "BeginDate", RawValue = snapshot != null?snapshot.BeginDate.ToString("g") : DateTimeOffset.UtcNow.ToString("g"), IsReadOnly = true, UiType = "ItemLink" }; viewPropertyEndDate = new ViewProperty { Name = "EndDate", RawValue = snapshot != null && snapshotEndDateComponent != null && snapshotEndDateComponent.EndDate != DateTimeOffset.MinValue ? snapshotEndDateComponent.EndDate.ToString("g") : string.Empty, IsReadOnly = true, UiType = "ItemLink" }; } else { viewPropertyStartDate = new ViewProperty { Name = "BeginDate", RawValue = snapshot != null ? snapshot.BeginDate : DateTimeOffset.UtcNow, IsReadOnly = false, UiType = "ItemLink" }; viewPropertyEndDate = new ViewProperty { Name = "EndDate", RawValue = snapshot != null && snapshotEndDateComponent != null ? snapshotEndDateComponent.EndDate : DateTimeOffset.UtcNow, IsReadOnly = false, UiType = "ItemLink" }; viewProertyUseEndDate = new ViewProperty { Name = "UseEndDate", RawValue = true, IsReadOnly = false, UiType = "Checkbox" }; } if (viewPropertyStartDate != null) { properties1.Add(viewPropertyStartDate); } if (viewPropertyEndDate != null) { properties1.Add(viewPropertyEndDate); } if (viewProertyUseEndDate != null) { properties1.Add(viewProertyUseEndDate); } if (!isAddAction) { List <string> stringList = new List <string>(); if (snapshot?.Tags != null && snapshot.Tags.Any()) { stringList = snapshot?.Tags.Where((t => !t.Excluded)).Select((t => t.Name)).ToList(); } List <ViewProperty> properties2 = view.Properties; ViewProperty viewProperty2 = new ViewProperty(new List <Policy>()) { Name = "IncludedTags", RawValue = stringList.ToArray(), IsReadOnly = !isEditAction, IsRequired = false, UiType = isEditAction ? "Tags" : "List", OriginalType = "List" }; properties2.Add(viewProperty2); } if (isAddAction | isEditAction || snapshot == null) { return; } List <ViewProperty> properties3 = view.Properties; ViewProperty viewProperty3 = new ViewProperty { Name = "ItemId", RawValue = snapshot.Id, IsReadOnly = true, IsHidden = true }; properties3.Add(viewProperty3); List <ViewProperty> properties4 = view.Properties; ViewProperty viewProperty4 = new ViewProperty { Name = "Status", RawValue = snapshot.GetComponent <ApprovalComponent>().Status, IsReadOnly = true }; properties4.Add(viewProperty4); }
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 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; 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); }
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 <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 }); }); } } } } } }