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 ).ToList();
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 );
}
var groupMembers = qryGroupMembers.ToList();
// get a list of group member ids that don't meet all the requirements
List<int> qryGroupMemberIdsThatLackGroupRequirements = groupMembers
.Where( a =>
!qryGroupRequirements
.Where( r =>
!r.GroupRoleId.HasValue ||
r.GroupRoleId.Value == a.GroupRoleId )
.Select( x => x.Id )
.All( r =>
a.GroupMemberRequirements
.Where( mr => mr.RequirementMetDateTime.HasValue )
.Select( x => x.GroupRequirementId )
.Contains( r ) ) )
.Select( a => a.Id )
.ToList();
IEnumerable<GroupMember> qryMembersWithIssues;
if ( includeWarnings )
{
IQueryable<int> qryGroupMemberIdsWithRequirementWarnings = qryGroupMemberRequirements
.Where(
a =>
a.RequirementWarningDateTime != null ||
a.RequirementFailDateTime != null )
.Select( a => a.GroupMemberId )
.Distinct();
qryMembersWithIssues = groupMembers.Where( a => qryGroupMemberIdsThatLackGroupRequirements.Contains( a.Id ) || qryGroupMemberIdsWithRequirementWarnings.Contains( a.Id ) );
}
else
{
qryMembersWithIssues = groupMembers.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;
}