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)); }
public async Task UpdateAsync(ConditionCompletion conditionCompletion) { using (var context = _msSqlContextFactory.CreateDataContext()) { var entity = _mapper.Map <ConditionCompletionEntity>(conditionCompletion); context.ConditionCompletionEntities.Update(entity); await context.SaveChangesAsync(); } }
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)); }
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); }
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); }
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); }
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); }); }
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]); }
public async Task UpdateAsync(ConditionCompletion conditionCompletion) { await _conditionCompletionRepository.UpdateAsync(conditionCompletion); }
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())); }
public async Task <string> InsertAsync(ConditionCompletion conditionCompletion) { var conditionCompletionId = await _conditionCompletionRepository.InsertAsync(conditionCompletion); return(conditionCompletionId.ToString("D")); }
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 }; }
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}'."); } }
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); }
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]); }