Esempio n. 1
0
        public override async Task <CreateCouponsArgument> Run(
            CreateCouponsArgument arg,
            CommercePipelineExecutionContext context)
        {
            await this._getManagedListCommand.PerformTransaction(context.CommerceContext, async() =>
            {
                var policy = context.CommerceContext.GetPolicy <LoyaltyPointsPolicy>();

                LoyaltyPointsEntity loyaltyPointsEntity = await _findEntityCommand.Process(context.CommerceContext, typeof(LoyaltyPointsEntity),
                                                                                           Constants.EntityId, shouldCreate: true) as LoyaltyPointsEntity;
                if (loyaltyPointsEntity == null)
                {
                    await context.AbortWithError("Unable to access or create LoyaltyPointsEntity {0}",
                                                 "LoyaltyPointsEntityNotReturned", Constants.EntityId);
                    return;
                }

                // Prevent simultaneous updates, in case multiple minion instances. Since these might be on scaled servers, mutex lock uses database field.
                // Lock is read before count is checked, so that when first process finishes and releases row, counts will be replenished.
                // Notes:
                // 1. If this pipeline aborts, the lock should be rolled back.
                // 2. Assuming transactions are enabled, the second process should never see IsLocked=true, as the read won't return until the lock is released. However,
                //    this syntax should work on a non-transactional environment, and makes the intent of the code clearer.
                if (loyaltyPointsEntity.IsLocked)
                {
                    await context.AbortWithError("{0} is locked. If this condition persists, unset this value through the database.", "EntityLocked", Constants.EntityId);
                    return;
                }

                var list = await EnsureList(context, Constants.AvailableCouponsList);
                if (list == null)
                {
                    await context.AbortWithError("Unable to create list {0}", "UnableToCreateList", Constants.AvailableCouponsList);
                    return;
                }

                long count = await _getListCountCommand.Process(context.CommerceContext, Constants.AvailableCouponsList);
                context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} has {count} items.");



                if (count <= policy.ReprovisionTriggerCount)
                {
                    loyaltyPointsEntity.IsLocked = true;
                    await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity);

                    context.Logger.LogDebug($"{this.Name}: List {Constants.AvailableCouponsList} is at or under reprovision count of {policy.ReprovisionTriggerCount}.");

                    loyaltyPointsEntity.SequenceNumber++;
                    string suffix = loyaltyPointsEntity.SequenceNumber.ToString();

                    string promotionName = string.Format(Constants.GeneratedPromotion, suffix);
                    Promotion promotion  = await GeneratePromotion(context, promotionName);
                    if (promotion == null)
                    {
                        await context.AbortWithError("Unable to generate promotion {0}.", "PromotionNotFound",
                                                     promotionName);
                        return;
                    }

                    await AddCoupons(context, promotion, suffix);
                    if (context.IsNullOrHasErrors())
                    {
                        return;
                    }

                    await AllocateCoupons(context, promotion, suffix);
                    if (context.IsNullOrHasErrors())
                    {
                        return;
                    }

                    ApprovePromotion(context, promotion);

                    await CopyCouponsToList(context, loyaltyPointsEntity, list);
                    if (context.IsNullOrHasErrors())
                    {
                        return;
                    }

                    loyaltyPointsEntity.IsLocked = false;
                    await _persistEntityCommand.Process(context.CommerceContext, list);
                    await _persistEntityCommand.Process(context.CommerceContext, promotion);
                    await _persistEntityCommand.Process(context.CommerceContext, loyaltyPointsEntity);
                }
            });


            return(arg);
        }
Esempio n. 2
0
        private async Task CopyCouponsToList(CommercePipelineExecutionContext context, LoyaltyPointsEntity entity, ManagedList targetList)
        {
            var    policy         = context.GetPolicy <LoyaltyPointsPolicy>();
            string sourceListName = $"promotion-{policy.CouponPrefix}-{entity.SequenceNumber}-allocatedcoupons";
            var    coupons        = await _getEntitiesInListCommand.Process(context.CommerceContext,
                                                                            sourceListName, 0,
                                                                            policy.CouponBlockSize);

            await _addListEntitiesPipeline.Run(new ListEntitiesArgument(coupons, targetList.Name), context);
        }