public async Task AddBonusOperationAsync(BonusOperation bonusOperation)
        {
            var campaignId = bonusOperation.CampaignId.ToGuid();

            var bonusIssuedEvent = new BonusIssuedEvent
            {
                OperationId = Guid.NewGuid(),
                Amount      = bonusOperation.Reward,
                CampaignId  = campaignId,
                ConditionId = bonusOperation.BonusOperationType == Domain.Enums.BonusOperationType.CampaignReward
                    ? Guid.Empty
                    : bonusOperation.ConditionId.ToGuid(),
                PartnerId          = bonusOperation.PartnerId,
                LocationId         = bonusOperation.LocationId,
                UnitLocationCode   = bonusOperation.UnitLocationCode,
                CustomerId         = bonusOperation.CustomerId,
                BonusOperationType = _mapper.Map <BonusOperationType>(bonusOperation.BonusOperationType),
                TimeStamp          = bonusOperation.TimeStamp,
                ReferralId         = bonusOperation.ReferralId
            };

            // Zero reward operations are not accepted by blockchain facade
            if (bonusIssuedEvent.Amount > 0)
            {
                await _bonusIssuedPublisher.PublishAsync(bonusIssuedEvent);

                _log.Info(
                    $"Bonus issued: {bonusIssuedEvent.ToJson()}",
                    bonusIssuedEvent.BonusOperationType,
                    process: nameof(AddBonusOperationAsync));
            }
        }
        private async Task ProcessCampaignForCustomerAsync(MAVN.Service.BonusEngine.Domain.Models.Campaign campaign,
                                                           CampaignCompletion campaignCompletion, Guid operationId, IReadOnlyDictionary <string, string> data)
        {
            var customerId = campaignCompletion.CustomerId;
            var campaignId = campaign.Id;

            var conditionCompletions = await _conditionCompletionService
                                       .GetConditionCompletionsAsync(customerId, campaignId);

            if (IsCampaignCompleted(conditionCompletions, campaign) == false)
            {
                return;
            }

            var reward = await _bonusCalculatorService.CalculateRewardAmountAsync(campaign, customerId, conditionCompletions);

            var bonusOperation = new BonusOperation
            {
                CustomerId          = customerId,
                CampaignId          = campaignId,
                ExternalOperationId = operationId,
                Reward             = reward,
                TimeStamp          = DateTime.UtcNow,
                BonusOperationType = BonusOperationType.CampaignReward
            };

            if (data.TryGetValue(ReferralId, out string referralId))
            {
                bonusOperation.ReferralId = referralId;
            }

            await _bonusOperationService.AddBonusOperationAsync(bonusOperation);

            _log.Info("Customer completed all condition in campaign.",
                      context: $"operationId: {operationId}; campaignId: {campaignId}; customerId: {customerId}");

            await _campaignCompletionService.IncreaseCompletionCountAsync(campaignCompletion, campaign,
                                                                          conditionCompletions);
        }
        private async Task ProcessConditionsForCustomerAsync(
            string customerId,
            string partnerId,
            string locationId,
            string campaignId,
            IEnumerable <Condition> conditions,
            IReadOnlyDictionary <string, string> data,
            Guid operationId)
        {
            // Doesn't make sense to have multiple of the same conditions in the same campaign, but just in case
            foreach (var condition in conditions)
            {
                // If condition has any partners we need to make sure we match one them, otherwise just skip the check
                if (condition.PartnerIds != null && condition.PartnerIds.Any())
                {
                    if (!Guid.TryParse(partnerId, out var partnerIdGuid) ||
                        !condition.PartnerIds.Contains(partnerIdGuid))
                    {
                        _log.Info("The partner identifier does not match campaign condition partners.",
                                  context: $"partnerId: {partnerId}'; conditionId: {condition.Id}");
                        continue;
                    }
                }

                var conditionCompletion = await _conditionCompletionService
                                          .GetConditionCompletionAsync(customerId, condition.Id);

                // ConditionCompletion being null is a valid case handled by IncreaseOrCreateAsync
                if (conditionCompletion != null && conditionCompletion.IsCompleted)
                {
                    continue;
                }

                conditionCompletion = await _conditionCompletionService
                                      .IncreaseOrCreateAsync(customerId, conditionCompletion, data, condition);

                Money18 reward = 0;

                if (condition.RewardHasRatio && condition.RewardRatio != null)
                {
                    if (data.TryGetValue(PaymentId, out string paymentId))
                    {
                        reward = await _bonusCalculatorService.CalculateConditionRewardRatioAmountAsync(condition, conditionCompletion, paymentId);
                    }
                    else
                    {
                        _log.Error("No paymentId was passed");
                    }
                }
                else
                {
                    reward = await _bonusCalculatorService.CalculateConditionRewardAmountAsync(condition, conditionCompletion);
                }

                if (reward > 0.0M)
                {
                    var bonusOperation = new BonusOperation
                    {
                        CustomerId          = customerId,
                        CampaignId          = campaignId,
                        ConditionId         = condition.Id,
                        ExternalOperationId = operationId,
                        PartnerId           = partnerId,
                        LocationId          = locationId,
                        Reward             = reward,
                        TimeStamp          = DateTime.UtcNow,
                        BonusOperationType = BonusOperationType.ConditionReward
                    };

                    if (data.TryGetValue(UnitLocationCodeKey, out string locationCode))
                    {
                        bonusOperation.UnitLocationCode = locationCode;
                    }

                    if (data.TryGetValue(ReferralId, out string referralId))
                    {
                        bonusOperation.ReferralId = referralId;
                    }
                    else if (data.TryGetValue(PaymentId, out string paymentId))
                    {
                        bonusOperation.ReferralId = paymentId;
                    }

                    await _bonusOperationService.AddBonusOperationAsync(bonusOperation);
                }

                if (conditionCompletion.CurrentCount == condition.CompletionCount && !condition.RewardHasRatio)
                {
                    await _conditionCompletionService.SetConditionCompletedAsync(conditionCompletion.Id);

                    _log.Info("Customer completed condition.",
                              context:
                              $"operationId: {operationId}; campaignId: {campaignId}; conditionId: {condition.Id}; customerId: {customerId}");
                }
                else if (condition.RewardHasRatio)
                {
                    var lastThreshold = _conditionCompletionService.SetConditionCompletionLastGivenRatioReward(data, condition, conditionCompletion, out bool allGiven);

                    if (lastThreshold >= 100m && conditionCompletion.CurrentCount == condition.CompletionCount && allGiven)
                    {
                        conditionCompletion.IsCompleted = true;

                        _log.Info("Customer completed condition.",
                                  context:
                                  $"operationId: {operationId}; campaignId: {campaignId}; conditionId: {condition.Id}; customerId: {customerId}");
                    }
                    else
                    {
                        _log.Info("Customer not complete condition.",
                                  context:
                                  $"operationId: {operationId}; campaignId: {campaignId}; conditionId: {condition.Id}; customerId: {customerId}; currentCount: {conditionCompletion.CurrentCount}; requiredCount {condition.CompletionCount ?? int.MaxValue}");
                    }

                    await _conditionCompletionService.UpdateAsync(conditionCompletion);
                }
                else
                {
                    _log.Info("Customer not complete condition.",
                              context:
                              $"operationId: {operationId}; campaignId: {campaignId}; conditionId: {condition.Id}; customerId: {customerId}; currentCount: {conditionCompletion.CurrentCount}; requiredCount {condition.CompletionCount ?? int.MaxValue}");
                }
            }
        }
示例#4
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
            };
        }