Esempio n. 1
0
        public async Task ShouldIncreaseCompletionCount_WhenValidGuidInConditionCompletionObjectIsPassed()
        {
            // Arrange
            var conditionCompletionId             = Guid.NewGuid().ToString("D");
            var emptyData                         = new Dictionary <string, string>();
            var conditionCompletionRepositoryMock = new Mock <IConditionCompletionRepository>(MockBehavior.Strict);

            var conditionCompletion = new ConditionCompletion
            {
                Id = conditionCompletionId
            };

            conditionCompletionRepositoryMock
            .Setup(c => c.IncreaseCompletionCountAsync(Guid.Parse(conditionCompletionId), emptyData, 1))
            .Returns(Task.CompletedTask);

            conditionCompletionRepositoryMock
            .Setup(c => c.GetConditionCompletion(Guid.Parse(conditionCompletionId)))
            .ReturnsAsync(conditionCompletion);

            var service = new ConditionCompletionService(conditionCompletionRepositoryMock.Object);

            // Act
            await service.IncreaseCompletionCountAsync(conditionCompletion, emptyData, 1);

            // Assert
            conditionCompletionRepositoryMock.Verify(c => c.IncreaseCompletionCountAsync(Guid.Parse(conditionCompletionId), emptyData, 1), Times.Once);
            conditionCompletionRepositoryMock.Verify(c => c.GetConditionCompletion(Guid.Parse(conditionCompletionId)), Times.Once);
        }
        private async Task <Money18> CalculateConditionRewardByPercentageAsync(Money18 percentage,
                                                                               ConditionCompletion conditionCompletion, string paymentId = null)
        {
            Money18 rewardsAmount = 0;

            foreach (var completionData in conditionCompletion.Data)
            {
                if (paymentId != null && completionData.ContainsKey(paymentId))
                {
                    var rewardDictionary = completionData[paymentId];

                    var paymentDictionary = JsonConvert.DeserializeObject <Dictionary <string, string> >(rewardDictionary);

                    rewardsAmount += Money18.Parse(paymentDictionary[AmountName]);
                }
                else if (paymentId == null && completionData != null && completionData.ContainsKey(AmountName))
                {
                    rewardsAmount += Money18.Parse(completionData[AmountName]);
                }
            }

            var amountInCurrency = rewardsAmount * (percentage / 100m);

            return(await GetEligibilityEngineAmountByCondition(conditionCompletion, amountInCurrency));
        }
Esempio n. 3
0
 public async Task UpdateAsync(ConditionCompletion conditionCompletion)
 {
     using (var context = _msSqlContextFactory.CreateDataContext())
     {
         var entity = _mapper.Map <ConditionCompletionEntity>(conditionCompletion);
         context.ConditionCompletionEntities.Update(entity);
         await context.SaveChangesAsync();
     }
 }
Esempio n. 4
0
        public async Task <Guid> InsertAsync(ConditionCompletion conditionCompletion)
        {
            using (var context = _msSqlContextFactory.CreateDataContext())
            {
                var entity = _mapper.Map <ConditionCompletionEntity>(conditionCompletion);

                context.Add(entity);

                await context.SaveChangesAsync();

                return(entity.Id);
            }
        }
        private async Task <Money18> CalculateConditionRewardByConversionRate(ConditionCompletion conditionCompletion)
        {
            Money18 rewardsAmount = 0;

            foreach (var completionData in conditionCompletion.Data)
            {
                if (completionData != null && completionData.ContainsKey(AmountName))
                {
                    rewardsAmount += Money18.Parse(completionData[AmountName]);
                }
            }

            return(await GetEligibilityEngineAmountByCondition(conditionCompletion, rewardsAmount));
        }
Esempio n. 6
0
        private async Task UpdatePaymentRatioDataAsync(ConditionCompletion conditionCompletion, Dictionary <string, string> oldData,
                                                       Dictionary <string, string> dataToInsert, string paymentId)
        {
            var given = JsonConvert.DeserializeObject <Dictionary <string, string> >(oldData.Values.FirstOrDefault());

            var givenBonus = given[GivenRatioBonusPercent];

            if (givenBonus != null)
            {
                dataToInsert.Add(GivenRatioBonusPercent, givenBonus);
            }

            oldData[paymentId] = JsonConvert.SerializeObject(dataToInsert);

            await _conditionCompletionRepository.UpdateAsync(conditionCompletion);
        }
Esempio n. 7
0
        public void Calculate_Ratio_Reward_Give_Reward_Only_For_20_Threshold_When_Already_Given_For_10()
        {
            // Arrange
            var purchaseCompletionPercentage = 40m;

            var paymentId = Guid.NewGuid().ToString();

            var ratioData = new Dictionary <string, string> {
                { "PurchaseCompletionPercentage", purchaseCompletionPercentage.ToString() },
                { "GivenRatioBonusPercent", "10" }
            };

            var conditionCompletionData = new Dictionary <string, string> {
                {
                    paymentId, JsonConvert.SerializeObject(ratioData)
                }
            };

            var conditionCompletion = new ConditionCompletion
            {
                Id           = Guid.NewGuid().ToString(),
                CurrentCount = 1,
                Data         = new[] { conditionCompletionData }
            };

            var ratios = new List <RatioAttribute>()
            {
                new RatioAttribute()
                {
                    Order = 1, PaymentRatio = 10m, RewardRatio = 20m, Threshold = 10m
                },
                new RatioAttribute()
                {
                    Order = 2, PaymentRatio = 10m, RewardRatio = 20m, Threshold = 20m
                },
                new RatioAttribute()
                {
                    Order = 3, PaymentRatio = 80m, RewardRatio = 70m, Threshold = 100m
                },
            };

            //Act
            var result = _service.CalculateRatioReward(ratios, conditionCompletionData, 1000);

            //Assert
            Assert.Equal(200, result);
        }
Esempio n. 8
0
        public async Task ShouldIncreaseCompletionCount_WhenPassedConditionCompletionIsNotCompletedYet()
        {
            // Arrange
            var customerId  = Guid.NewGuid().ToString("D");
            var campaignId  = Guid.NewGuid().ToString("D");
            var conditionId = Guid.NewGuid().ToString("D");
            var data        = new Dictionary <string, string>
            {
                { "key", "value" }
            };
            var conditionCompletion = new ConditionCompletion
            {
                Id           = Guid.NewGuid().ToString(),
                CurrentCount = 1
            };

            var conditionCompletionRepositoryMock = new Mock <IConditionCompletionRepository>(MockBehavior.Strict);

            conditionCompletionRepositoryMock
            .Setup(c => c.IncreaseCompletionCountAsync(It.IsAny <Guid>(), It.IsAny <Dictionary <string, string> >(), It.IsAny <int>()))
            .Returns(Task.CompletedTask);
            conditionCompletionRepositoryMock
            .Setup(c => c.GetConditionCompletion(It.IsAny <Guid>()))
            .ReturnsAsync(conditionCompletion);

            var service = new ConditionCompletionService(conditionCompletionRepositoryMock.Object);

            // Act
            await service.IncreaseOrCreateAsync(
                customerId,
                conditionCompletion,
                data,
                new Condition { CampaignId = campaignId, Id = conditionId.ToString(), CompletionCount = 2 });

            // Assert
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.IncreaseCompletionCountAsync(It.IsAny <Guid>(), It.IsAny <Dictionary <string, string> >(), It.IsAny <int>()), Times.Once);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.GetConditionCompletion(It.IsAny <Guid>()), Times.Once);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.InsertAsync(It.IsAny <ConditionCompletion>()), Times.Never);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.SetConditionCompletedAsync(It.IsAny <Guid>()), Times.Never);
        }
        private async Task <Money18> GetEligibilityEngineAmountByCondition(ConditionCompletion conditionCompletion, Money18 rewardsAmount)
        {
            var response = await _eligibilityEngine.ConversionRate.GetAmountByConditionAsync(
                new ConvertAmountByConditionRequest()
            {
                CustomerId   = Guid.Parse(conditionCompletion.CustomerId),
                ConditionId  = Guid.Parse(conditionCompletion.ConditionId),
                Amount       = rewardsAmount,
                FromCurrency = _baseCurrencyCode,
                ToCurrency   = _tokenName
            });

            if (response.ErrorCode != EligibilityEngineErrors.None)
            {
                _log.Error(message: "An error occured while converting currency amount",
                           context: $"from: {_baseCurrencyCode}; to: {_tokenName}; error: {response.ErrorCode}");

                return(0);
            }

            return(response.Amount);
        }
Esempio n. 10
0
        public async Task ShouldThrowArgumentException_WhenInvalidGuidInConditionCompletionObjectIsPassed()
        {
            // Arrange
            var conditionCompletionId             = "Not a valid guid";
            var emptyData                         = new Dictionary <string, string>();
            var conditionCompletionRepositoryMock = new Mock <IConditionCompletionRepository>(MockBehavior.Strict);

            var conditionCompletion = new ConditionCompletion
            {
                Id = conditionCompletionId
            };

            var service = new ConditionCompletionService(conditionCompletionRepositoryMock.Object);

            // Act

            // Assert
            await Assert.ThrowsAsync <ArgumentException>(async() =>
            {
                await service.IncreaseCompletionCountAsync(conditionCompletion, emptyData, 1);
            });
        }
Esempio n. 11
0
        public async Task ShouldNotCompleteConditionCompletion_WhenConditionRewardRatioIsPassed()
        {
            // Arrange
            var customerId  = Guid.NewGuid().ToString("D");
            var campaignId  = Guid.NewGuid().ToString("D");
            var conditionId = Guid.NewGuid().ToString("D");
            var paymentId   = Guid.NewGuid().ToString();

            var ratioData = new Dictionary <string, string> {
                { PurchaseCompletionPercentage, "20" },
                { "GivenRatioBonusPercent", "10" }
            };

            var conditionCompletionData = new Dictionary <string, string> {
                {
                    paymentId, JsonConvert.SerializeObject(ratioData)
                }
            };

            var newData = new Dictionary <string, string>
            {
                { PurchaseCompletionPercentage, "40" },
                { "PaymentId", paymentId }
            };

            var conditionCompletion = new ConditionCompletion
            {
                Id           = Guid.NewGuid().ToString(),
                CurrentCount = 1,
                Data         = new[] { conditionCompletionData }
            };

            var condition = new Condition
            {
                CampaignId      = campaignId,
                Id              = conditionId,
                CompletionCount = 1,
                RewardHasRatio  = true,
                RewardRatio     = new RewardRatioAttribute()
                {
                    Ratios = new List <RatioAttribute>()
                    {
                        new RatioAttribute()
                        {
                            Order        = 1,
                            RewardRatio  = 20m,
                            PaymentRatio = 10m,
                            Threshold    = 10m
                        },
                        new RatioAttribute()
                        {
                            Order        = 2,
                            PaymentRatio = 10m,
                            RewardRatio  = 20m,
                            Threshold    = 20m
                        },
                        new RatioAttribute()
                        {
                            Order        = 3,
                            PaymentRatio = 70m,
                            RewardRatio  = 70m,
                            Threshold    = 100m
                        },
                    }
                }
            };
            var conditionCompletionRepositoryMock = new Mock <IConditionCompletionRepository>(MockBehavior.Strict);

            conditionCompletionRepositoryMock
            .Setup(c => c.SetConditionCompletedAsync(It.IsAny <Guid>()))
            .Returns(Task.CompletedTask);

            conditionCompletionRepositoryMock
            .Setup(c => c.UpdateAsync(It.IsAny <ConditionCompletion>()))
            .Returns(Task.CompletedTask);

            var service = new ConditionCompletionService(conditionCompletionRepositoryMock.Object);

            // Act
            var conditionUpdated = await service.IncreaseOrCreateAsync(
                customerId,
                conditionCompletion,
                newData,
                condition);

            var updatedData = conditionUpdated.Data.FirstOrDefault();

            var result = JsonConvert.DeserializeObject <Dictionary <string, string> >(updatedData.Values.FirstOrDefault());

            // Assert
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.IncreaseCompletionCountAsync(It.IsAny <Guid>(), It.IsAny <Dictionary <string, string> >(), It.IsAny <int>()), Times.Never);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.GetConditionCompletion(It.IsAny <Guid>()), Times.Never);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.SetConditionCompletedAsync(It.IsAny <Guid>()), Times.Never);
            conditionCompletionRepositoryMock.Verify(c =>
                                                     c.UpdateAsync(It.IsAny <ConditionCompletion>()), Times.Once);

            Assert.NotNull(updatedData);
            Assert.Equal("40", result[PurchaseCompletionPercentage]);
        }
Esempio n. 12
0
 public async Task UpdateAsync(ConditionCompletion conditionCompletion)
 {
     await _conditionCompletionRepository.UpdateAsync(conditionCompletion);
 }
Esempio n. 13
0
        public async Task <ConditionCompletion> IncreaseCompletionCountAsync(ConditionCompletion conditionCompletion, Dictionary <string, string> data, int count)
        {
            await _conditionCompletionRepository.IncreaseCompletionCountAsync(conditionCompletion.Id.ToGuid(), data, count);

            return(await _conditionCompletionRepository.GetConditionCompletion(conditionCompletion.Id.ToGuid()));
        }
Esempio n. 14
0
        public async Task <string> InsertAsync(ConditionCompletion conditionCompletion)
        {
            var conditionCompletionId = await _conditionCompletionRepository.InsertAsync(conditionCompletion);

            return(conditionCompletionId.ToString("D"));
        }
Esempio n. 15
0
        private void CreateConditionTestData()
        {
            BonusType = new BonusType
            {
                Type        = BonusTypeName,
                DisplayName = BonusTypeName
            };

            ConditionModel = new Condition()
            {
                CampaignId      = CampaignId,
                CompletionCount = 1,
                BonusType       = BonusType,
                Id = ConditionId,
                ImmediateReward = 10
            };

            ConditionModels = new List <Condition>()
            {
                ConditionModel
            };

            NewConditionCompletion = new ConditionCompletion
            {
                CustomerId   = CustomerId,
                ConditionId  = ConditionId,
                Id           = ConditionCompletionsId,
                CurrentCount = 0,
                IsCompleted  = false
            };

            ConditionCompletions = new List <ConditionCompletion>();

            NewConditionBonusOperation = new BonusOperation
            {
                CustomerId         = CustomerId,
                Reward             = ConditionModel.ImmediateReward,
                BonusOperationType = BonusOperationType.CampaignReward
            };

            CampaignModel = new CampaignModel()
            {
                Name            = "SignUp Campaign",
                Reward          = 20,
                Id              = CampaignId,
                CompletionCount = 1,
                Conditions      = new List <Condition>()
                {
                    ConditionModel
                }
            };

            CampaignModels = new List <CampaignModel>()
            {
                CampaignModel
            };

            CampaignCompletion = new CampaignCompletion()
            {
                CustomerId = CustomerId,
                CampaignId = CampaignId,
                CampaignCompletionCount = 0
            };

            CampaignCompletions = new List <CampaignCompletion>()
            {
                CampaignCompletion
            };

            NewCampaignBonusOperation = new BonusOperation
            {
                CustomerId         = CustomerId,
                Reward             = CampaignModel.Reward,
                BonusOperationType = BonusOperationType.CampaignReward
            };
        }
Esempio n. 16
0
        public decimal SetConditionCompletionLastGivenRatioReward(IReadOnlyDictionary <string, string> data, Condition condition,
                                                                  ConditionCompletion conditionCompletion, out bool allThresholdGiven)
        {
            allThresholdGiven = true;

            if (condition.RewardRatio == null)
            {
                return(0);
            }

            var paymentId = data["PaymentId"];

            var paymentIdData = conditionCompletion.Data.FirstOrDefault(d => d.ContainsKey(paymentId));

            var lastThreshold = 0m;

            if (paymentIdData != null)
            {
                foreach (var d in conditionCompletion.Data)
                {
                    var dataDictionary =
                        JsonConvert.DeserializeObject <Dictionary <string, string> >(d.Values
                                                                                     .FirstOrDefault());
                    var dataToUpdate = dataDictionary.ToDictionary(o => o.Key, o => o.Value);

                    if (d.ContainsKey(paymentId))
                    {
                        if (dataToUpdate.TryGetValue(PurchaseCompletionPercentage, out string percentage))
                        {
                            var value = Convert.ToDecimal(percentage);

                            foreach (var ratio in condition.RewardRatio.Ratios.OrderBy(r => r.Order))
                            {
                                if (value >= ratio.Threshold)
                                {
                                    lastThreshold = ratio.Threshold;
                                }
                            }

                            //check if we have GivenRatioBonusPercent and update value
                            if (lastThreshold != 0m)
                            {
                                dataToUpdate[GivenRatioBonusPercent] = lastThreshold.ToString();
                            }
                        }

                        paymentIdData[paymentId] = JsonConvert.SerializeObject(dataToUpdate);
                    }
                    else
                    {
                        dataToUpdate.TryGetValue(GivenRatioBonusPercent, out string percentage);

                        if (Convert.ToDecimal(percentage) < 100)
                        {
                            allThresholdGiven = false;
                        }
                    }
                }

                return(lastThreshold);
            }

            return(0);
        }
        public async Task <Money18> CalculateConditionRewardAmountAsync(Condition condition, ConditionCompletion conditionCompletion)
        {
            switch (condition.RewardType)
            {
            case RewardType.Fixed:
                return(condition.ImmediateReward);

            case RewardType.Percentage:
                return(await CalculateConditionRewardByPercentageAsync(condition.ImmediateReward, conditionCompletion));

            case RewardType.ConversionRate:
                return(await CalculateConditionRewardByConversionRate(conditionCompletion));

            default:
                throw new ArgumentOutOfRangeException($"Unknown reward type '{condition.RewardType}'.");
            }
        }
Esempio n. 18
0
        public async Task <ConditionCompletion> IncreaseOrCreateAsync(string customerId, ConditionCompletion conditionCompletion, IReadOnlyDictionary <string, string> data, Condition condition)
        {
            var dataToInsert = data.ToDictionary(o => o.Key, o => o.Value);

            // if the condition completion is not null user has not started the condition
            if (conditionCompletion == null)
            {
                if (condition.RewardHasRatio)
                {
                    dataToInsert.Add(GivenRatioBonusPercent, "0");

                    dataToInsert = PrepareDataForRewardRatio(dataToInsert);
                }

                conditionCompletion = new ConditionCompletion
                {
                    ConditionId  = condition.Id,
                    CurrentCount = 1,
                    CustomerId   = customerId,
                    CampaignId   = condition.CampaignId,
                    Data         = new[] { dataToInsert }
                };

                conditionCompletion.Id = await InsertAsync(conditionCompletion);

                return(conditionCompletion);
            }

            // completion count is null when conditionCompletionCount can be infinity
            if (condition.CompletionCount == null || conditionCompletion.CurrentCount < condition.CompletionCount)
            {
                if (condition.RewardHasRatio)
                {
                    var paymentId = dataToInsert[PaymentId];

                    var oldData = conditionCompletion.Data.FirstOrDefault(c => c.ContainsKey(paymentId));

                    //this is the case that we have payment for new paymentId
                    if (oldData == null)
                    {
                        if (condition.CompletionCount == null || conditionCompletion.Data.Count() < condition.CompletionCount)
                        {
                            dataToInsert.Add(GivenRatioBonusPercent, "0");

                            dataToInsert = PrepareDataForRewardRatio(dataToInsert);

                            conditionCompletion = await IncreaseCompletionCountAsync(conditionCompletion,
                                                                                     dataToInsert.ToDictionary(o => o.Key, o => o.Value), 1);
                        }
                    }
                    else
                    {
                        await UpdatePaymentRatioDataAsync(conditionCompletion, oldData, dataToInsert, paymentId);
                    }
                }
                else
                {
                    conditionCompletion = await IncreaseCompletionCountAsync(conditionCompletion,
                                                                             dataToInsert.ToDictionary(o => o.Key, o => o.Value), 1);
                }
            }
            else
            {
                if (condition.RewardHasRatio)
                {
                    var paymentId = dataToInsert[PaymentId];

                    var oldData = conditionCompletion.Data.FirstOrDefault(c => c.ContainsKey(paymentId));

                    if (oldData != null)
                    {
                        await UpdatePaymentRatioDataAsync(conditionCompletion, oldData, dataToInsert, paymentId);
                    }
                }
                else
                {
                    await SetConditionCompletedAsync(conditionCompletion.Id);
                }
            }

            return(conditionCompletion);
        }
        public async Task <Money18> CalculateConditionRewardRatioAmountAsync(Condition condition, ConditionCompletion conditionCompletion, string paymentId)
        {
            var dictionary = conditionCompletion.Data.FirstOrDefault(c => c.ContainsKey(paymentId));

            if (dictionary != null)
            {
                switch (condition.RewardType)
                {
                case RewardType.Fixed:
                {
                    return(CalculateRatioReward(condition.RewardRatio.Ratios, dictionary,
                                                condition.ImmediateReward));
                }

                case RewardType.Percentage:
                {
                    var conditionReward =
                        await CalculateConditionRewardByPercentageAsync(condition.ImmediateReward,
                                                                        conditionCompletion, paymentId);

                    return(CalculateRatioReward(condition.RewardRatio.Ratios, dictionary, conditionReward));
                }

                case RewardType.ConversionRate:
                {
                    var reward = await CalculateConditionRewardByConversionRate(conditionCompletion);

                    return(CalculateRatioReward(condition.RewardRatio.Ratios, dictionary, reward));
                }

                default:
                    throw new ArgumentOutOfRangeException($"Unknown reward type '{condition.RewardType}'.");
                }
            }

            return(0);
        }
Esempio n. 20
0
        public void ShouldSrtLastGivenThresholdBonus_WhenSetConditionCompletionLastGivenRatioRewardIsCalled()
        {
            // Arrange
            var campaignId  = Guid.NewGuid().ToString("D");
            var conditionId = Guid.NewGuid().ToString("D");
            var paymentId   = Guid.NewGuid().ToString();

            var ratioData = new Dictionary <string, string> {
                { "PurchaseCompletionPercentage", "20" },
                { "GivenRatioBonusPercent", "10" }
            };

            var conditionCompletionData = new Dictionary <string, string> {
                {
                    paymentId, JsonConvert.SerializeObject(ratioData)
                }
            };

            var newData = new Dictionary <string, string>
            {
                { PurchaseCompletionPercentage, "40" },
                { "PaymentId", paymentId }
            };

            var conditionCompletion = new ConditionCompletion
            {
                Id           = Guid.NewGuid().ToString(),
                CurrentCount = 1,
                Data         = new[] { conditionCompletionData }
            };

            var condition = new Condition
            {
                CampaignId      = campaignId,
                Id              = conditionId,
                CompletionCount = 1,
                RewardHasRatio  = true,
                RewardRatio     = new RewardRatioAttribute()
                {
                    Ratios = new List <RatioAttribute>()
                    {
                        new RatioAttribute()
                        {
                            Order        = 1,
                            PaymentRatio = 10m,
                            RewardRatio  = 20m,
                            Threshold    = 10m
                        },
                        new RatioAttribute()
                        {
                            Order        = 2,
                            PaymentRatio = 10m,
                            RewardRatio  = 20m,
                            Threshold    = 20m
                        },
                        new RatioAttribute()
                        {
                            Order        = 3,
                            PaymentRatio = 80m,
                            RewardRatio  = 70m,
                            Threshold    = 100m
                        },
                    }
                }
            };

            var conditionCompletionRepositoryMock = new Mock <IConditionCompletionRepository>(MockBehavior.Strict);

            var service = new ConditionCompletionService(conditionCompletionRepositoryMock.Object);

            // Act
            var threshold = service.SetConditionCompletionLastGivenRatioReward(newData, condition, conditionCompletion, out bool test);

            var updatedData = conditionCompletion.Data.FirstOrDefault(c => c.ContainsKey(paymentId));

            var result = JsonConvert.DeserializeObject <Dictionary <string, string> >(updatedData.Values.FirstOrDefault());

            Assert.Equal(20, threshold);
            Assert.NotNull(updatedData);
            Assert.Single(updatedData);

            Assert.Equal(2, result.Count);
            Assert.Equal("20", result[GivenRatioBonusPercent]);
        }