Example #1
0
        /// <summary>
        /// Pres the save changes.
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="state">The state.</param>
        public override void PreSaveChanges(Rock.Data.DbContext dbContext, System.Data.Entity.EntityState state)
        {
            if (state == System.Data.Entity.EntityState.Deleted)
            {
                // manually delete any grouprequirements of this group since it can't be cascade deleted
                var groupRequirementService = new GroupRequirementService(dbContext as RockContext);
                var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupId.HasValue && a.GroupId == this.Id).ToList();
                if (groupRequirements.Any())
                {
                    groupRequirementService.DeleteRange(groupRequirements);
                }

                // manually set any attendance search group ids to null
                var attendanceService = new AttendanceService(dbContext as RockContext);
                foreach (var attendance in attendanceService.Queryable()
                         .Where(a =>
                                a.SearchResultGroupId.HasValue &&
                                a.SearchResultGroupId.Value == this.Id))
                {
                    attendance.SearchResultGroupId = null;
                }
            }

            base.PreSaveChanges(dbContext, state);
        }
Example #2
0
 /// <summary>
 /// Pres the save changes.
 /// </summary>
 /// <param name="dbContext">The database context.</param>
 /// <param name="state">The state.</param>
 public override void PreSaveChanges(Rock.Data.DbContext dbContext, System.Data.Entity.EntityState state)
 {
     if (state == System.Data.Entity.EntityState.Deleted)
     {
         // manually delete any grouprequirements of this group since it can't be cascade deleted
         var groupRequirementService = new GroupRequirementService(dbContext as RockContext);
         var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupId == this.Id).ToList();
         if (groupRequirements.Any())
         {
             groupRequirementService.DeleteRange(groupRequirements);
         }
     }
 }
            /// <summary>
            /// Called before the save operation is executed.
            /// </summary>
            protected override void PreSave()
            {
                var rockContext = ( RockContext )this.RockContext;

                if (State == EntityContextState.Deleted)
                {
                    Entity.ChildGroupTypes.Clear();

                    // manually delete any grouprequirements of this grouptype since it can't be cascade deleted
                    var groupRequirementService = new GroupRequirementService(rockContext);
                    var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupTypeId.HasValue && a.GroupTypeId == Entity.Id).ToList();
                    if (groupRequirements.Any())
                    {
                        groupRequirementService.DeleteRange(groupRequirements);
                    }
                }

                // clean up the index
                if (State == EntityContextState.Deleted && Entity.IsIndexEnabled)
                {
                    Entity.DeleteIndexedDocumentsByGroupType(Entity.Id);
                }
                else if (State == EntityContextState.Modified)
                {
                    // check if indexing is enabled
                    var changeEntry = rockContext.ChangeTracker.Entries <GroupType>().Where(a => a.Entity == Entity).FirstOrDefault();
                    if (changeEntry != null)
                    {
                        var originalIndexState = ( bool )changeEntry.OriginalValues[nameof(GroupType.IsIndexEnabled)];

                        if (originalIndexState == true && Entity.IsIndexEnabled == false)
                        {
                            // clear out index items
                            Entity.DeleteIndexedDocumentsByGroupType(Entity.Id);
                        }
                        else if (Entity.IsIndexEnabled == true)
                        {
                            // if indexing is enabled then bulk index - needed as an attribute could have changed from IsIndexed
                            Entity.BulkIndexDocumentsByGroupType(Entity.Id);
                        }
                    }
                }

                base.PreSave();
            }
Example #4
0
        /// <summary>
        /// Pres the save.
        /// </summary>
        /// <param name="dbContext">The database context.</param>
        /// <param name="state">The state.</param>
        public override void PreSaveChanges(Rock.Data.DbContext dbContext, System.Data.Entity.EntityState state)
        {
            if (state == System.Data.Entity.EntityState.Deleted)
            {
                ChildGroupTypes.Clear();

                // manually delete any grouprequirements of this grouptype since it can't be cascade deleted
                var groupRequirementService = new GroupRequirementService(dbContext as RockContext);
                var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupTypeId.HasValue && a.GroupTypeId == this.Id).ToList();
                if (groupRequirements.Any())
                {
                    groupRequirementService.DeleteRange(groupRequirements);
                }
            }

            // clean up the index
            if (state == System.Data.Entity.EntityState.Deleted && IsIndexEnabled)
            {
                this.DeleteIndexedDocumentsByGroupType(this.Id);
            }
            else if (state == System.Data.Entity.EntityState.Modified)
            {
                // check if indexing is enabled
                var changeEntry = dbContext.ChangeTracker.Entries <GroupType>().Where(a => a.Entity == this).FirstOrDefault();
                if (changeEntry != null)
                {
                    var originalIndexState = (bool)changeEntry.OriginalValues["IsIndexEnabled"];

                    if (originalIndexState == true && IsIndexEnabled == false)
                    {
                        // clear out index items
                        this.DeleteIndexedDocumentsByGroupType(Id);
                    }
                    else if (IsIndexEnabled == true)
                    {
                        // if indexing is enabled then bulk index - needed as an attribute could have changed from IsIndexed
                        BulkIndexDocumentsByGroupType(Id);
                    }
                }
            }

            base.PreSaveChanges(dbContext, state);
        }
Example #5
0
        /// <summary>
        /// Method that will be called on an entity immediately before the item is saved by context
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="entry"></param>
        public override void PreSaveChanges(Data.DbContext dbContext, DbEntityEntry entry)
        {
            var rockContext = (RockContext)dbContext;

            HistoryChangeList = new History.HistoryChangeList();

            switch (entry.State)
            {
            case System.Data.Entity.EntityState.Added:
            {
                HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Group").SetNewValue(Name);

                History.EvaluateChange(HistoryChangeList, "Name", string.Empty, Name);
                History.EvaluateChange(HistoryChangeList, "Description", string.Empty, Description);
                History.EvaluateChange(HistoryChangeList, "Group Type", (int?)null, GroupType, GroupTypeId);
                History.EvaluateChange(HistoryChangeList, "Campus", (int?)null, Campus, CampusId);
                History.EvaluateChange(HistoryChangeList, "Security Role", (bool?)null, IsSecurityRole);
                History.EvaluateChange(HistoryChangeList, "Active", (bool?)null, IsActive);
                History.EvaluateChange(HistoryChangeList, "Allow Guests", (bool?)null, AllowGuests);
                History.EvaluateChange(HistoryChangeList, "Public", (bool?)null, IsPublic);
                History.EvaluateChange(HistoryChangeList, "Group Capacity", (int?)null, GroupCapacity);

                // if this is a new record, but is saved with IsActive=False, set the InactiveDateTime if it isn't set already
                if (!this.IsActive)
                {
                    this.InactiveDateTime = this.InactiveDateTime ?? RockDateTime.Now;
                }

                break;
            }

            case System.Data.Entity.EntityState.Modified:
            {
                var originalIsActive = entry.OriginalValues["IsActive"].ToStringSafe().AsBoolean();
                History.EvaluateChange(HistoryChangeList, "Name", entry.OriginalValues["Name"].ToStringSafe(), Name);
                History.EvaluateChange(HistoryChangeList, "Description", entry.OriginalValues["Description"].ToStringSafe(), Description);
                History.EvaluateChange(HistoryChangeList, "Group Type", entry.OriginalValues["GroupTypeId"].ToStringSafe().AsIntegerOrNull(), GroupType, GroupTypeId);
                History.EvaluateChange(HistoryChangeList, "Campus", entry.OriginalValues["CampusId"].ToStringSafe().AsIntegerOrNull(), Campus, CampusId);
                History.EvaluateChange(HistoryChangeList, "Security Role", entry.OriginalValues["IsSecurityRole"].ToStringSafe().AsBoolean(), IsSecurityRole);
                History.EvaluateChange(HistoryChangeList, "Active", originalIsActive, IsActive);
                History.EvaluateChange(HistoryChangeList, "Allow Guests", entry.OriginalValues["AllowGuests"].ToStringSafe().AsBooleanOrNull(), AllowGuests);
                History.EvaluateChange(HistoryChangeList, "Public", entry.OriginalValues["IsPublic"].ToStringSafe().AsBoolean(), IsPublic);
                History.EvaluateChange(HistoryChangeList, "Group Capacity", entry.OriginalValues["GroupCapacity"].ToStringSafe().AsIntegerOrNull(), GroupCapacity);
                History.EvaluateChange(HistoryChangeList, "Archived", entry.OriginalValues["IsArchived"].ToStringSafe().AsBoolean(), this.IsArchived);

                // IsActive was modified, set the InactiveDateTime if it changed to Inactive, or set it to NULL if it changed to Active
                if (originalIsActive != this.IsActive)
                {
                    if (!this.IsActive)
                    {
                        // if the caller didn't already set InactiveDateTime, set it to now
                        this.InactiveDateTime = this.InactiveDateTime ?? RockDateTime.Now;
                    }
                    else
                    {
                        this.InactiveDateTime = null;
                    }
                }

                break;
            }

            case System.Data.Entity.EntityState.Deleted:
            {
                HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, null);

                // manually delete any grouprequirements of this group since it can't be cascade deleted
                var groupRequirementService = new GroupRequirementService(rockContext);
                var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupId.HasValue && a.GroupId == this.Id).ToList();
                if (groupRequirements.Any())
                {
                    groupRequirementService.DeleteRange(groupRequirements);
                }

                // manually set any attendance search group ids to null
                var attendanceService = new AttendanceService(rockContext);
                var attendancesToNullSearchResultGroupId = attendanceService.Queryable()
                                                           .Where(a =>
                                                                  a.SearchResultGroupId.HasValue &&
                                                                  a.SearchResultGroupId.Value == this.Id);

                dbContext.BulkUpdate(attendancesToNullSearchResultGroupId, a => new Attendance {
                        SearchResultGroupId = null
                    });

                // since we can't put a CascadeDelete on both Attendance.Occurrence.GroupId and Attendance.OccurrenceId, manually delete all Attendance records associated with this GroupId
                var attendancesToDelete = attendanceService.Queryable()
                                          .Where(a =>
                                                 a.Occurrence.GroupId.HasValue &&
                                                 a.Occurrence.GroupId.Value == this.Id);
                if (attendancesToDelete.Any())
                {
                    dbContext.BulkDelete(attendancesToDelete);
                }

                break;
            }
            }

            base.PreSaveChanges(dbContext, entry);
        }
Example #6
0
        /// <summary>
        /// Method that will be called on an entity immediately before the item is saved by context
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="entry"></param>
        public override void PreSaveChanges(Data.DbContext dbContext, DbEntityEntry entry)
        {
            var rockContext = (RockContext)dbContext;

            HistoryChanges = new List <string>();

            switch (entry.State)
            {
            case System.Data.Entity.EntityState.Added:
            {
                HistoryChanges.Add("Group Created");

                History.EvaluateChange(HistoryChanges, "Name", string.Empty, Name);
                History.EvaluateChange(HistoryChanges, "Description", string.Empty, Description);
                History.EvaluateChange(HistoryChanges, "Group Type", (int?)null, GroupType, GroupTypeId);
                History.EvaluateChange(HistoryChanges, "Campus", (int?)null, Campus, CampusId);
                History.EvaluateChange(HistoryChanges, "Security Role", (bool?)null, IsSecurityRole);
                History.EvaluateChange(HistoryChanges, "Active", (bool?)null, IsActive);
                History.EvaluateChange(HistoryChanges, "Allow Guests", (bool?)null, AllowGuests);
                History.EvaluateChange(HistoryChanges, "Public", (bool?)null, IsPublic);
                History.EvaluateChange(HistoryChanges, "Group Capacity", (int?)null, GroupCapacity);

                break;
            }

            case System.Data.Entity.EntityState.Modified:
            {
                History.EvaluateChange(HistoryChanges, "Name", entry.OriginalValues["Name"].ToStringSafe(), Name);
                History.EvaluateChange(HistoryChanges, "Description", entry.OriginalValues["Description"].ToStringSafe(), Description);
                History.EvaluateChange(HistoryChanges, "Group Type", entry.OriginalValues["GroupTypeId"].ToStringSafe().AsIntegerOrNull(), GroupType, GroupTypeId);
                History.EvaluateChange(HistoryChanges, "Campus", entry.OriginalValues["CampusId"].ToStringSafe().AsIntegerOrNull(), Campus, CampusId);
                History.EvaluateChange(HistoryChanges, "Security Role", entry.OriginalValues["IsSecurityRole"].ToStringSafe().AsBoolean(), IsSecurityRole);
                History.EvaluateChange(HistoryChanges, "Active", entry.OriginalValues["IsActive"].ToStringSafe().AsBoolean(), IsActive);
                History.EvaluateChange(HistoryChanges, "Allow Guests", entry.OriginalValues["AllowGuests"].ToStringSafe().AsBooleanOrNull(), AllowGuests);
                History.EvaluateChange(HistoryChanges, "Public", entry.OriginalValues["IsPublic"].ToStringSafe().AsBoolean(), IsPublic);
                History.EvaluateChange(HistoryChanges, "Group Capacity", entry.OriginalValues["GroupCapacity"].ToStringSafe().AsIntegerOrNull(), GroupCapacity);

                break;
            }

            case System.Data.Entity.EntityState.Deleted:
            {
                HistoryChanges.Add("Deleted");

                // manually delete any grouprequirements of this group since it can't be cascade deleted
                var groupRequirementService = new GroupRequirementService(rockContext);
                var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupId.HasValue && a.GroupId == this.Id).ToList();
                if (groupRequirements.Any())
                {
                    groupRequirementService.DeleteRange(groupRequirements);
                }

                // manually set any attendance search group ids to null
                var attendanceService = new AttendanceService(rockContext);
                foreach (var attendance in attendanceService.Queryable()
                         .Where(a =>
                                a.SearchResultGroupId.HasValue &&
                                a.SearchResultGroupId.Value == this.Id))
                {
                    attendance.SearchResultGroupId = null;
                }

                break;
            }
            }

            base.PreSaveChanges(dbContext, entry);
        }
Example #7
0
            /// <summary>
            /// Called before the save operation is executed.
            /// </summary>
            protected override void PreSave()
            {
                HistoryChangeList = new History.HistoryChangeList();

                var rockContext = ( RockContext )this.RockContext;

                _FamilyCampusIsChanged = false;

                switch (State)
                {
                case EntityContextState.Added:
                {
                    HistoryChangeList.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "Group").SetNewValue(Entity.Name);

                    History.EvaluateChange(HistoryChangeList, "Name", string.Empty, Entity.Name);
                    History.EvaluateChange(HistoryChangeList, "Description", string.Empty, Entity.Description);
                    History.EvaluateChange(HistoryChangeList, "Group Type", ( int? )null, Entity.GroupType, Entity.GroupTypeId);
                    History.EvaluateChange(HistoryChangeList, "Campus", ( int? )null, Entity.Campus, Entity.CampusId);
                    History.EvaluateChange(HistoryChangeList, "Security Role", ( bool? )null, Entity.IsSecurityRole);
                    History.EvaluateChange(HistoryChangeList, "Active", ( bool? )null, Entity.IsActive);
                    History.EvaluateChange(HistoryChangeList, "Allow Guests", ( bool? )null, Entity.AllowGuests);
                    History.EvaluateChange(HistoryChangeList, "Public", ( bool? )null, Entity.IsPublic);
                    History.EvaluateChange(HistoryChangeList, "Group Capacity", ( int? )null, Entity.GroupCapacity);

                    // if this is a new record, but is saved with IsActive=False, set the InactiveDateTime if it isn't set already
                    if (!Entity.IsActive)
                    {
                        Entity.InactiveDateTime = Entity.InactiveDateTime ?? RockDateTime.Now;
                    }

                    break;
                }

                case EntityContextState.Modified:
                {
                    var      originalIsActive         = OriginalValues[nameof(Group.IsActive)].ToStringSafe().AsBoolean();
                    DateTime?originalInactiveDateTime = OriginalValues["InactiveDateTime"].ToStringSafe().AsDateTime();

                    var      originalIsArchived       = OriginalValues[nameof(Group.IsArchived)].ToStringSafe().AsBoolean();
                    DateTime?originalArchivedDateTime = OriginalValues[nameof(Group.ArchivedDateTime)].ToStringSafe().AsDateTime();

                    History.EvaluateChange(HistoryChangeList, "Name", OriginalValues[nameof(Group.Name)].ToStringSafe(), Entity.Name);
                    History.EvaluateChange(HistoryChangeList, "Description", OriginalValues[nameof(Group.Description)].ToStringSafe(), Entity.Description);
                    History.EvaluateChange(HistoryChangeList, "Group Type", OriginalValues[nameof(Group.GroupTypeId)].ToStringSafe().AsIntegerOrNull(), Entity.GroupType, Entity.GroupTypeId);
                    History.EvaluateChange(HistoryChangeList, "Campus", OriginalValues[nameof(Group.CampusId)].ToStringSafe().AsIntegerOrNull(), Entity.Campus, Entity.CampusId);
                    History.EvaluateChange(HistoryChangeList, "Security Role", OriginalValues[nameof(Group.IsSecurityRole)].ToStringSafe().AsBoolean(), Entity.IsSecurityRole);
                    History.EvaluateChange(HistoryChangeList, "Active", originalIsActive, Entity.IsActive);
                    History.EvaluateChange(HistoryChangeList, "Allow Guests", OriginalValues[nameof(Group.AllowGuests)].ToStringSafe().AsBooleanOrNull(), Entity.AllowGuests);
                    History.EvaluateChange(HistoryChangeList, "Public", OriginalValues[nameof(Group.IsPublic)].ToStringSafe().AsBoolean(), Entity.IsPublic);
                    History.EvaluateChange(HistoryChangeList, "Group Capacity", OriginalValues[nameof(Group.GroupCapacity)].ToStringSafe().AsIntegerOrNull(), Entity.GroupCapacity);
                    History.EvaluateChange(HistoryChangeList, "Archived", OriginalValues[nameof(Group.IsArchived)].ToStringSafe().AsBoolean(), Entity.IsArchived);

                    // IsActive was modified, set the InactiveDateTime if it changed to Inactive, or set it to NULL if it changed to Active
                    if (originalIsActive != Entity.IsActive)
                    {
                        if (!Entity.IsActive)
                        {
                            // if the caller didn't already set InactiveDateTime, set it to now
                            Entity.InactiveDateTime = Entity.InactiveDateTime ?? RockDateTime.Now;
                        }
                        else
                        {
                            Entity.InactiveDateTime = null;
                        }

                        DateTime?newInactiveDateTime = Entity.InactiveDateTime;

                        UpdateGroupMembersActiveStatusFromGroupStatus(rockContext, originalIsActive, originalInactiveDateTime, Entity.IsActive, newInactiveDateTime);
                    }


                    // IsArchived was modified, set the ArchivedDateTime if it changed to IsArchived, or set it to NULL if IsArchived was changed to false
                    if (originalIsArchived != Entity.IsArchived)
                    {
                        if (Entity.IsArchived)
                        {
                            // if the caller didn't already set ArchivedDateTime, set it to now
                            Entity.ArchivedDateTime = Entity.ArchivedDateTime ?? RockDateTime.Now;
                        }
                        else
                        {
                            Entity.ArchivedDateTime = null;
                        }

                        DateTime?newArchivedDateTime = Entity.ArchivedDateTime;

                        UpdateGroupMembersArchivedValueFromGroupArchivedValue(rockContext, originalIsArchived, originalArchivedDateTime, Entity.IsArchived, newArchivedDateTime);
                    }

                    // If Campus is modified for an existing Family Group, set a flag to trigger updates for calculated field Person.PrimaryCampusId.
                    var group = Entity as Group;

                    var familyGroupTypeId = GroupTypeCache.GetFamilyGroupType().Id;

                    _FamilyCampusIsChanged = (group.GroupTypeId == familyGroupTypeId &&
                                              group.CampusId.GetValueOrDefault(0) != OriginalValues["CampusId"].ToStringSafe().AsInteger());

                    break;
                }

                case EntityContextState.Deleted:
                {
                    HistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, null);

                    // manually delete any grouprequirements of this group since it can't be cascade deleted
                    var groupRequirementService = new GroupRequirementService(rockContext);
                    var groupRequirements       = groupRequirementService.Queryable().Where(a => a.GroupId.HasValue && a.GroupId == Entity.Id).ToList();
                    if (groupRequirements.Any())
                    {
                        groupRequirementService.DeleteRange(groupRequirements);
                    }

                    // manually set any attendance search group ids to null
                    var attendanceService = new AttendanceService(rockContext);
                    var attendancesToNullSearchResultGroupId = attendanceService.Queryable()
                                                               .Where(a =>
                                                                      a.SearchResultGroupId.HasValue &&
                                                                      a.SearchResultGroupId.Value == Entity.Id);

                    rockContext.BulkUpdate(attendancesToNullSearchResultGroupId, a => new Attendance {
                            SearchResultGroupId = null
                        });

                    // since we can't put a CascadeDelete on both Attendance.Occurrence.GroupId and Attendance.OccurrenceId, manually delete all Attendance records associated with this GroupId
                    var attendancesToDelete = attendanceService.Queryable()
                                              .Where(a =>
                                                     a.Occurrence.GroupId.HasValue &&
                                                     a.Occurrence.GroupId.Value == Entity.Id);
                    if (attendancesToDelete.Any())
                    {
                        rockContext.BulkDelete(attendancesToDelete);
                    }

                    break;
                }
                }

                base.PreSave();
            }
Example #8
0
        /// <summary>
        /// Groups the members not meeting requirements.
        /// </summary>
        /// <param name="groupId">The group identifier.</param>
        /// <param name="includeWarnings">if set to <c>true</c> [include warnings].</param>
        /// <param name="includeInactive">if set to <c>true</c> [include inactive].</param>
        /// <returns></returns>
        public Dictionary <GroupMember, Dictionary <PersonGroupRequirementStatus, DateTime> > GroupMembersNotMeetingRequirements(int groupId, bool includeWarnings, bool includeInactive = false)
        {
            Dictionary <GroupMember, Dictionary <PersonGroupRequirementStatus, DateTime> > results = new Dictionary <GroupMember, Dictionary <PersonGroupRequirementStatus, DateTime> >();

            var rockContext                   = this.Context as RockContext;
            var groupRequirementService       = new GroupRequirementService(rockContext);
            var groupMemberService            = new GroupMemberService(rockContext);
            var groupMemberRequirementService = new GroupMemberRequirementService(rockContext);

            var  qryGroupRequirements = groupRequirementService.Queryable().Where(a => a.GroupId == groupId);
            bool hasGroupRequirements = qryGroupRequirements.Any();

            if (!hasGroupRequirements)
            {
                // if no group requirements, then there are no members that don't meet the requirements, so return an empty dictionary
                return(new Dictionary <GroupMember, Dictionary <PersonGroupRequirementStatus, DateTime> >());
            }

            var qryGroupMembers            = groupMemberService.Queryable().Where(a => a.GroupId == groupId);
            var qryGroupMemberRequirements = groupMemberRequirementService.Queryable().Where(a => a.GroupMember.GroupId == groupId);

            if (!includeInactive)
            {
                qryGroupMembers = qryGroupMembers.Where(a => a.GroupMemberStatus == GroupMemberStatus.Active);
            }

            // get a list of group member ids that don't meet all the requirements
            IQueryable <int> qryGroupMemberIdsThatLackGroupRequirements = qryGroupMembers.Where(
                a => !qryGroupRequirements.Select(x => x.Id).All(
                    r => a.GroupMemberRequirements.Where(mr => mr.RequirementMetDateTime.HasValue).Select(x => x.GroupRequirementId).Contains(r))).Select(a => a.Id);

            IQueryable <GroupMember> qryMembersWithIssues;

            if (includeWarnings)
            {
                IQueryable <int> qryGroupMemberIdsWithRequirementWarnings = qryGroupMemberRequirements.Where(a => a.RequirementWarningDateTime != null || a.RequirementFailDateTime != null).Select(a => a.GroupMemberId).Distinct();
                qryMembersWithIssues = qryGroupMembers.Where(a => qryGroupMemberIdsThatLackGroupRequirements.Contains(a.Id) || qryGroupMemberIdsWithRequirementWarnings.Contains(a.Id));
            }
            else
            {
                qryMembersWithIssues = qryGroupMembers.Where(a => qryGroupMemberIdsThatLackGroupRequirements.Contains(a.Id));
            }

            var qry = qryMembersWithIssues.Select(a => new
            {
                GroupMember = a,
                GroupRequirementStatuses = qryGroupMemberRequirements.Where(x => x.GroupMemberId == a.Id)
            });

            var currentDateTime = RockDateTime.Now;

            foreach (var groupMemberWithIssues in qry)
            {
                Dictionary <PersonGroupRequirementStatus, DateTime> statuses = new Dictionary <PersonGroupRequirementStatus, DateTime>();

                // populate where the status is known
                foreach (var requirementStatus in groupMemberWithIssues.GroupRequirementStatuses)
                {
                    PersonGroupRequirementStatus status = new PersonGroupRequirementStatus();
                    status.GroupRequirement = requirementStatus.GroupRequirement;
                    status.PersonId         = groupMemberWithIssues.GroupMember.PersonId;

                    DateTime occuranceDate = new DateTime();

                    if (requirementStatus.RequirementMetDateTime == null)
                    {
                        status.MeetsGroupRequirement = MeetsGroupRequirement.NotMet;
                        occuranceDate = requirementStatus.RequirementFailDateTime ?? currentDateTime;
                    }
                    else if (requirementStatus.RequirementWarningDateTime.HasValue)
                    {
                        status.MeetsGroupRequirement = MeetsGroupRequirement.MeetsWithWarning;
                        occuranceDate = requirementStatus.RequirementWarningDateTime.Value;
                    }
                    else
                    {
                        status.MeetsGroupRequirement = MeetsGroupRequirement.Meets;
                        occuranceDate = requirementStatus.RequirementMetDateTime.Value;
                    }

                    statuses.Add(status, occuranceDate);
                }

                // also add any groupRequirements that they don't have statuses for (and therefore haven't met)
                foreach (var groupRequirement in qryGroupRequirements)
                {
                    if (!statuses.Any(x => x.Key.GroupRequirement.Id == groupRequirement.Id))
                    {
                        PersonGroupRequirementStatus status = new PersonGroupRequirementStatus();
                        status.GroupRequirement      = groupRequirement;
                        status.PersonId              = groupMemberWithIssues.GroupMember.PersonId;
                        status.MeetsGroupRequirement = MeetsGroupRequirement.NotMet;
                        statuses.Add(status, currentDateTime);
                    }
                }

                var statusesWithIssues = statuses.Where(a => a.Key.MeetsGroupRequirement != MeetsGroupRequirement.Meets).ToDictionary(k => k.Key, v => v.Value);

                if (statusesWithIssues.Any())
                {
                    results.Add(groupMemberWithIssues.GroupMember, statusesWithIssues);
                }
            }

            return(results);
        }