public void TestCleanup() { var service = new AchievementAttemptService(_rockContext); service.DeleteRange(service.Queryable().Where(saa => _achievementIds.Contains(saa.Id) || saa.ForeignKey == KEY)); _rockContext.SaveChanges(); }
public void TestCleanup() { var service = new AchievementAttemptService(_rockContext); service.DeleteRange(service.Queryable().Where(saa => saa.AchievementTypeId == _achievementTypeId)); _rockContext.SaveChanges(); }
/// <summary> /// Processes the specified achievement type cache for the source entity. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="achievementTypeCache">The achievement type cache.</param> /// <param name="sourceEntity">The source entity.</param> /// <returns>The set of attempts that were created or updated</returns> public override HashSet <AchievementAttempt> Process(RockContext rockContext, AchievementTypeCache achievementTypeCache, IEntity sourceEntity) { var updatedAttempts = new HashSet <AchievementAttempt>(); // If we cannot link the transaction to a person, then there is nothing to do if (!(sourceEntity is FinancialTransaction financialTransaction)) { return(updatedAttempts); } // If the achievement type is not active (or null) then there is nothing to do if (achievementTypeCache?.IsActive != true) { return(updatedAttempts); } // If there are unmet prerequisites, then there is nothing to do var achievementTypeService = new AchievementTypeService(rockContext); var unmetPrerequisites = achievementTypeService.GetUnmetPrerequisites(achievementTypeCache.Id, financialTransaction.AuthorizedPersonAliasId.Value); if (unmetPrerequisites.Any()) { return(updatedAttempts); } // If the transaction is a refund, the person is empty, or less than zero amount, then there is nothing to do. if (null != financialTransaction.RefundDetails || !financialTransaction.AuthorizedPersonAliasId.HasValue || financialTransaction.AuthorizedPersonAliasId == 0 || financialTransaction.TotalAmount <= 0M) { return(updatedAttempts); } // Get all of the attempts for this interaction and achievement combo, ordered by start date DESC so that // the most recent attempts can be found with FirstOrDefault var achievementAttemptService = new AchievementAttemptService(rockContext); var attempts = achievementAttemptService.GetOrderedAchieverAttempts(achievementAttemptService.Queryable(), achievementTypeCache, financialTransaction.AuthorizedPersonAliasId.Value); var mostRecentSuccess = attempts.FirstOrDefault(saa => saa.AchievementAttemptEndDateTime.HasValue && saa.IsSuccessful); var overachievementPossible = achievementTypeCache.AllowOverAchievement; var successfulAttemptCount = attempts.Count(saa => saa.IsSuccessful); var maxSuccessesAllowed = achievementTypeCache.MaxAccomplishmentsAllowed ?? int.MaxValue; // If the most recent success is still open and overachievement is allowed, then update it if (overachievementPossible && mostRecentSuccess != null && !mostRecentSuccess.IsClosed) { UpdateOpenAttempt(mostRecentSuccess, achievementTypeCache, financialTransaction); updatedAttempts.Add(mostRecentSuccess); if (!mostRecentSuccess.IsClosed) { // New records can only be created once the open records are all closed return(updatedAttempts); } } // If the success count limit has been reached, then no more processing should be done if (successfulAttemptCount >= maxSuccessesAllowed) { return(updatedAttempts); } // Everything after the most recent success is on the table for deletion. Successes should not be // deleted. Everything after a success might be recalculated because of data changes. // Try to reuse these attempts if they match for continuity, but if the start date is changed, they // get deleted. var attemptsToDelete = attempts; if (mostRecentSuccess != null) { attemptsToDelete = attemptsToDelete .Where(saa => saa.AchievementAttemptStartDateTime > mostRecentSuccess.AchievementAttemptStartDateTime) .ToList(); } var newAttempts = CreateNewAttempts(achievementTypeCache, financialTransaction, mostRecentSuccess); if (newAttempts != null && newAttempts.Any()) { newAttempts = newAttempts.OrderBy(saa => saa.AchievementAttemptStartDateTime).ToList(); foreach (var newAttempt in newAttempts) { // Keep the old attempt if possible, otherwise add a new one var existingAttempt = attemptsToDelete.FirstOrDefault(saa => saa.AchievementAttemptStartDateTime == newAttempt.AchievementAttemptStartDateTime); if (existingAttempt != null) { attemptsToDelete.Remove(existingAttempt); CopyAttempt(newAttempt, existingAttempt); updatedAttempts.Add(existingAttempt); } else { newAttempt.AchieverEntityId = financialTransaction.AuthorizedPersonAliasId.Value; newAttempt.AchievementTypeId = achievementTypeCache.Id; achievementAttemptService.Add(newAttempt); updatedAttempts.Add(newAttempt); } // If this attempt was successful then make re-check the max success limit if (newAttempt.IsSuccessful) { successfulAttemptCount++; if (successfulAttemptCount >= maxSuccessesAllowed && !overachievementPossible) { break; } } } } if (attemptsToDelete.Any()) { updatedAttempts.RemoveAll(attemptsToDelete); achievementAttemptService.DeleteRange(attemptsToDelete); } return(updatedAttempts); }