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);
        }
示例#5
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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
                                    });
                                });
                            }
                        }
                    }
                }
            }
        }