/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public void Execute(IJobExecutionContext context) { var rockContext = new RockContext(); var groupRequirementService = new GroupRequirementService(rockContext); var groupMemberRequirementService = new GroupMemberRequirementService(rockContext); var groupMemberService = new GroupMemberService(rockContext); // we only need to consider group requirements that are based on a DataView or SQL var groupRequirementQry = groupRequirementService.Queryable() .Where(a => a.GroupRequirementType.RequirementCheckType != RequirementCheckType.Manual) .AsNoTracking(); var calculationExceptions = new List <Exception>(); int groupRequirementsCalculatedMemberCount = 0; foreach (var groupRequirement in groupRequirementQry.Include(i => i.GroupRequirementType).AsNoTracking().ToList()) { try { var currentDateTime = RockDateTime.Now; var qryGroupMemberRequirementsAlreadyOK = groupMemberRequirementService.Queryable().Where(a => a.GroupRequirementId == groupRequirement.Id); if (groupRequirement.GroupRequirementType.CanExpire && groupRequirement.GroupRequirementType.ExpireInDays.HasValue) { // Expirable: don't recalculate members that already met the requirement within the expiredays (unless they are flagged with a warning) var expireDaysCount = groupRequirement.GroupRequirementType.ExpireInDays.Value; qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where(a => !a.RequirementWarningDateTime.HasValue && a.RequirementMetDateTime.HasValue && SqlFunctions.DateDiff("day", a.RequirementMetDateTime, currentDateTime) < expireDaysCount); } else { // No Expiration: don't recalculate members that already met the requirement qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where(a => a.RequirementMetDateTime.HasValue); } var groupMemberQry = groupMemberService.Queryable().Where(a => a.GroupId == groupRequirement.GroupId).AsNoTracking(); var personQry = groupMemberQry.Where(a => !qryGroupMemberRequirementsAlreadyOK.Any(r => r.GroupMemberId == a.Id)).Select(a => a.Person); var results = groupRequirement.PersonQueryableMeetsGroupRequirement(rockContext, personQry, groupRequirement.GroupRoleId).ToList(); groupRequirementsCalculatedMemberCount += results.Select(a => a.PersonId).Distinct().Count(); foreach (var result in results) { // use a fresh rockContext per Update so that ChangeTracker doesn't get bogged down var rockContextUpdate = new RockContext(); groupRequirement.UpdateGroupMemberRequirementResult(rockContextUpdate, result.PersonId, result.MeetsGroupRequirement); rockContextUpdate.SaveChanges(); } } catch (Exception ex) { calculationExceptions.Add(new Exception(string.Format("Exception when calculating group requirement: {0} ", groupRequirement), ex)); } } context.Result = string.Format("Group member requirements re-calculated for {0} group members", groupRequirementsCalculatedMemberCount); if (calculationExceptions.Any()) { throw new AggregateException("One or more group requirement calculations failed ", calculationExceptions); } }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public void Execute( IJobExecutionContext context ) { var rockContext = new RockContext(); var groupRequirementService = new GroupRequirementService( rockContext ); var groupMemberRequirementService = new GroupMemberRequirementService( rockContext ); var groupMemberService = new GroupMemberService( rockContext ); // we only need to consider group requirements that are based on a DataView or SQL var groupRequirementQry = groupRequirementService.Queryable() .Where( a => a.GroupRequirementType.RequirementCheckType != RequirementCheckType.Manual ) .AsNoTracking(); var calculationExceptions = new List<Exception>(); int groupRequirementsCalculatedMemberCount = 0; foreach ( var groupRequirement in groupRequirementQry.Include( i => i.GroupRequirementType ).AsNoTracking().ToList() ) { try { var currentDateTime = RockDateTime.Now; var qryGroupMemberRequirementsAlreadyOK = groupMemberRequirementService.Queryable().Where( a => a.GroupRequirementId == groupRequirement.Id ); if ( groupRequirement.GroupRequirementType.CanExpire && groupRequirement.GroupRequirementType.ExpireInDays.HasValue ) { // Expirable: don't recalculate members that already met the requirement within the expiredays (unless they are flagged with a warning) var expireDaysCount = groupRequirement.GroupRequirementType.ExpireInDays.Value; qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where( a => !a.RequirementWarningDateTime.HasValue && a.RequirementMetDateTime.HasValue && SqlFunctions.DateDiff( "day", a.RequirementMetDateTime, currentDateTime ) < expireDaysCount ); } else { // No Expiration: don't recalculate members that already met the requirement qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where( a => a.RequirementMetDateTime.HasValue ); } var groupMemberQry = groupMemberService.Queryable().Where( a => a.GroupId == groupRequirement.GroupId ).AsNoTracking(); var personQry = groupMemberQry.Where( a => !qryGroupMemberRequirementsAlreadyOK.Any( r => r.GroupMemberId == a.Id ) ).Select( a => a.Person ); var results = groupRequirement.PersonQueryableMeetsGroupRequirement( rockContext, personQry, groupRequirement.GroupRoleId ).ToList(); groupRequirementsCalculatedMemberCount += results.Select( a => a.PersonId ).Distinct().Count(); foreach ( var result in results ) { // use a fresh rockContext per Update so that ChangeTracker doesn't get bogged down var rockContextUpdate = new RockContext(); groupRequirement.UpdateGroupMemberRequirementResult( rockContextUpdate, result.PersonId, result.MeetsGroupRequirement ); rockContextUpdate.SaveChanges(); } } catch ( Exception ex ) { calculationExceptions.Add( new Exception( string.Format( "Exception when calculating group requirement: {0} ", groupRequirement ), ex ) ); } } context.Result = string.Format( "Group member requirements re-calculated for {0} group members", groupRequirementsCalculatedMemberCount ); if ( calculationExceptions.Any() ) { throw new AggregateException( "One or more group requirement calculations failed ", calculationExceptions ); } }
private void SaveGroupMember() { if (Page.IsValid) { var rockContext = new RockContext(); // Verify valid group var groupService = new GroupService(rockContext); var group = groupService.Get(hfGroupId.ValueAsInt()); if (group == null) { nbErrorMessage.Title = "Please select a Role"; return; } // Check to see if a person was selected int?personId = ppGroupMemberPerson.PersonId; int?personAliasId = ppGroupMemberPerson.PersonAliasId; if (!personId.HasValue || !personAliasId.HasValue) { nbErrorMessage.Title = "Please select a Person"; return; } // check to see if the user selected a role var role = new GroupTypeRoleService(rockContext).Get(ddlGroupRole.SelectedValueAsInt() ?? 0); if (role == null) { nbErrorMessage.Title = "Please select a Role"; return; } var groupMemberService = new GroupMemberService(rockContext); var groupMemberRequirementService = new GroupMemberRequirementService(rockContext); GroupMember groupMember; int groupMemberId = int.Parse(hfGroupMemberId.Value); // if adding a new group member if (groupMemberId.Equals(0)) { groupMember = new GroupMember { Id = 0 }; groupMember.GroupId = group.Id; } else { // load existing group member groupMember = groupMemberService.Get(groupMemberId); } groupMember.PersonId = personId.Value; groupMember.GroupRoleId = role.Id; groupMember.Note = tbNote.Text; groupMember.GroupMemberStatus = rblStatus.SelectedValueAsEnum <GroupMemberStatus>(); if (cbIsNotified.Visible) { groupMember.IsNotified = cbIsNotified.Checked; } if (pnlRequirements.Visible) { foreach (var checkboxItem in cblManualRequirements.Items.OfType <ListItem>()) { int groupRequirementId = checkboxItem.Value.AsInteger(); var groupMemberRequirement = groupMember.GroupMemberRequirements.FirstOrDefault(a => a.GroupRequirementId == groupRequirementId); bool metRequirement = checkboxItem.Selected; if (metRequirement) { if (groupMemberRequirement == null) { groupMemberRequirement = new GroupMemberRequirement(); groupMemberRequirement.GroupRequirementId = groupRequirementId; groupMember.GroupMemberRequirements.Add(groupMemberRequirement); } // set the RequirementMetDateTime if it hasn't been set already groupMemberRequirement.RequirementMetDateTime = groupMemberRequirement.RequirementMetDateTime ?? RockDateTime.Now; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } else { if (groupMemberRequirement != null) { // doesn't meets the requirement groupMemberRequirement.RequirementMetDateTime = null; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } } } } if (group.RequiredSignatureDocumentTemplate != null) { var person = new PersonService(rockContext).Get(personId.Value); var documentService = new SignatureDocumentService(rockContext); var binaryFileService = new BinaryFileService(rockContext); SignatureDocument document = null; int?signatureDocumentId = hfSignedDocumentId.Value.AsIntegerOrNull(); int?binaryFileId = fuSignedDocument.BinaryFileId; if (signatureDocumentId.HasValue) { document = documentService.Get(signatureDocumentId.Value); } if (document == null && binaryFileId.HasValue) { document = new SignatureDocument(); document.SignatureDocumentTemplateId = group.RequiredSignatureDocumentTemplate.Id; document.AppliesToPersonAliasId = personAliasId.Value; document.AssignedToPersonAliasId = personAliasId.Value; document.Name = string.Format("{0}_{1}", group.Name.RemoveSpecialCharacters(), (person != null ? person.FullName.RemoveSpecialCharacters() : string.Empty)); document.Status = SignatureDocumentStatus.Signed; document.LastStatusDate = RockDateTime.Now; documentService.Add(document); } if (document != null) { int?origBinaryFileId = document.BinaryFileId; document.BinaryFileId = binaryFileId; if (origBinaryFileId.HasValue && origBinaryFileId.Value != document.BinaryFileId) { // if a new the binaryFile was uploaded, mark the old one as Temporary so that it gets cleaned up var oldBinaryFile = binaryFileService.Get(origBinaryFileId.Value); if (oldBinaryFile != null && !oldBinaryFile.IsTemporary) { oldBinaryFile.IsTemporary = true; } } // ensure the IsTemporary is set to false on binaryFile associated with this document if (document.BinaryFileId.HasValue) { var binaryFile = binaryFileService.Get(document.BinaryFileId.Value); if (binaryFile != null && binaryFile.IsTemporary) { binaryFile.IsTemporary = false; } } } } groupMember.LoadAttributes(); Rock.Attribute.Helper.GetEditValues(phAttributes, groupMember); if (!Page.IsValid) { return; } // if the groupMember IsValid is false, and the UI controls didn't report any errors, it is probably because the custom rules of GroupMember didn't pass. // So, make sure a message is displayed in the validation summary cvGroupMember.IsValid = groupMember.IsValidGroupMember(rockContext); if (!cvGroupMember.IsValid) { cvGroupMember.ErrorMessage = groupMember.ValidationResults.Select(a => a.ErrorMessage).ToList().AsDelimited("<br />"); return; } // using WrapTransaction because there are three Saves rockContext.WrapTransaction(() => { if (groupMember.Id.Equals(0)) { groupMemberService.Add(groupMember); } rockContext.SaveChanges(); groupMember.SaveAttributeValues(rockContext); }); groupMember.CalculateRequirements(rockContext, true); if (group.IsSecurityRole || group.GroupType.Guid.Equals(Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid())) { Rock.Security.Role.Flush(group.Id); } } }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { if ( Page.IsValid ) { var rockContext = new RockContext(); GroupMemberService groupMemberService = new GroupMemberService( rockContext ); GroupMemberRequirementService groupMemberRequirementService = new GroupMemberRequirementService( rockContext ); GroupMember groupMember; int groupMemberId = int.Parse( hfGroupMemberId.Value ); GroupTypeRole role = new GroupTypeRoleService( rockContext ).Get( ddlGroupRole.SelectedValueAsInt() ?? 0 ); // check to see if the user selected a role if ( role == null ) { nbErrorMessage.Title = "Please select a Role"; return; } // if adding a new group member if ( groupMemberId.Equals( 0 ) ) { groupMember = new GroupMember { Id = 0 }; groupMember.GroupId = hfGroupId.ValueAsInt(); } else { // load existing group member groupMember = groupMemberService.Get( groupMemberId ); } groupMember.PersonId = ppGroupMemberPerson.PersonId.Value; groupMember.GroupRoleId = role.Id; groupMember.Note = tbNote.Text; groupMember.GroupMemberStatus = rblStatus.SelectedValueAsEnum<GroupMemberStatus>(); if ( cbIsNotified.Visible ) { groupMember.IsNotified = cbIsNotified.Checked; } if ( pnlRequirements.Visible ) { foreach ( var checkboxItem in cblManualRequirements.Items.OfType<ListItem>() ) { int groupRequirementId = checkboxItem.Value.AsInteger(); var groupMemberRequirement = groupMember.GroupMemberRequirements.FirstOrDefault( a => a.GroupRequirementId == groupRequirementId ); bool metRequirement = checkboxItem.Selected; if ( metRequirement ) { if ( groupMemberRequirement == null ) { groupMemberRequirement = new GroupMemberRequirement(); groupMemberRequirement.GroupRequirementId = groupRequirementId; groupMember.GroupMemberRequirements.Add( groupMemberRequirement ); } // set the RequirementMetDateTime if it hasn't been set already groupMemberRequirement.RequirementMetDateTime = groupMemberRequirement.RequirementMetDateTime ?? RockDateTime.Now; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } else { if ( groupMemberRequirement != null ) { // doesn't meets the requirement groupMemberRequirement.RequirementMetDateTime = null; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } } } } groupMember.LoadAttributes(); Rock.Attribute.Helper.GetEditValues( phAttributes, groupMember ); if ( !Page.IsValid ) { return; } // if the groupMember IsValue is false, and the UI controls didn't report any errors, it is probably because the custom rules of GroupMember didn't pass. // So, make sure a message is displayed in the validation summary cvGroupMember.IsValid = groupMember.IsValid; if ( !cvGroupMember.IsValid ) { cvGroupMember.ErrorMessage = groupMember.ValidationResults.Select( a => a.ErrorMessage ).ToList().AsDelimited( "<br />" ); return; } // using WrapTransaction because there are three Saves rockContext.WrapTransaction( () => { if ( groupMember.Id.Equals( 0 ) ) { groupMemberService.Add( groupMember ); } rockContext.SaveChanges(); groupMember.SaveAttributeValues( rockContext ); } ); groupMember.CalculateRequirements( rockContext, true ); Group group = new GroupService( rockContext ).Get( groupMember.GroupId ); if ( group.IsSecurityRole || group.GroupType.Guid.Equals( Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid() ) ) { Rock.Security.Role.Flush( group.Id ); Rock.Security.Authorization.Flush(); } } Dictionary<string, string> qryString = new Dictionary<string, string>(); qryString["GroupId"] = hfGroupId.Value; NavigateToParentPage( qryString ); }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public void Execute(IJobExecutionContext context) { var rockContext = new RockContext(); var groupRequirementService = new GroupRequirementService(rockContext); var groupMemberRequirementService = new GroupMemberRequirementService(rockContext); var groupMemberService = new GroupMemberService(rockContext); var groupService = new GroupService(rockContext); // we only need to consider group requirements that are based on a DataView or SQL var groupRequirementQry = groupRequirementService.Queryable() .Where(a => a.GroupRequirementType.RequirementCheckType != RequirementCheckType.Manual) .AsNoTracking(); var calculationExceptions = new List <Exception>(); List <int> groupRequirementsCalculatedPersonIds = new List <int>(); foreach (var groupRequirement in groupRequirementQry.Include(i => i.GroupRequirementType).Include(a => a.GroupRequirementType.DataView).Include(a => a.GroupRequirementType.WarningDataView).AsNoTracking().ToList()) { // Only calculate group requirements for Active groups (if an inactive group becomes active again, this job will take care of re-calculating the requirements again) var groupQuery = groupService.Queryable().Where(a => a.IsActive); if (groupRequirement.GroupId.HasValue) { groupQuery = groupQuery.Where(g => g.Id == groupRequirement.GroupId); } else if (groupRequirement.GroupTypeId.HasValue) { groupQuery = groupQuery.Where(g => g.GroupTypeId == groupRequirement.GroupTypeId); } else { // shouldn't happen, but Group Requirement doesn't have a groupId or a GroupTypeId break; } var groupList = groupQuery.Select(a => new { a.Id, a.Name }).ToList(); var groupCount = groupList.Count(); foreach (var group in groupList) { context.UpdateLastStatusMessage($"Calculating group requirement '{groupRequirement.GroupRequirementType.Name}' for {group.Name}"); try { var currentDateTime = RockDateTime.Now; var qryGroupMemberRequirementsAlreadyOK = groupMemberRequirementService.Queryable().Where(a => a.GroupRequirementId == groupRequirement.Id && a.GroupMember.GroupId == group.Id); if (groupRequirement.GroupRequirementType.CanExpire && groupRequirement.GroupRequirementType.ExpireInDays.HasValue) { // Group requirement can expire: don't recalculate members that already met the requirement within the expire days (unless they are flagged with a warning) var expireDaysCount = groupRequirement.GroupRequirementType.ExpireInDays.Value; qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where(a => !a.RequirementWarningDateTime.HasValue && a.RequirementMetDateTime.HasValue && SqlFunctions.DateDiff("day", a.RequirementMetDateTime, currentDateTime) < expireDaysCount); } else { // No Expiration: don't recalculate members that already met the requirement qryGroupMemberRequirementsAlreadyOK = qryGroupMemberRequirementsAlreadyOK.Where(a => a.RequirementMetDateTime.HasValue); } var groupMemberQry = groupMemberService.Queryable(); if (groupRequirement.GroupId.HasValue) { groupMemberQry = groupMemberQry.Where(g => g.GroupId == groupRequirement.GroupId); } else if (groupRequirement.GroupTypeId.HasValue) { groupMemberQry = groupMemberQry.Where(g => (g.Group.GroupTypeId == groupRequirement.GroupTypeId) && g.GroupId == group.Id); } else { // shouldn't happen, but Group Requirement doesn't have a groupId or a GroupTypeId break; } var personQry = groupMemberQry.Where(a => !qryGroupMemberRequirementsAlreadyOK.Any(r => r.GroupMemberId == a.Id)).Select(a => a.Person); var results = groupRequirement.PersonQueryableMeetsGroupRequirement(rockContext, personQry, group.Id, groupRequirement.GroupRoleId).ToList(); groupRequirementsCalculatedPersonIds.AddRange(results.Select(a => a.PersonId).Distinct()); foreach (var result in results) { try { // use a fresh rockContext per result so that ChangeTracker doesn't get bogged down using (var rockContextUpdate = new RockContext()) { groupRequirement.UpdateGroupMemberRequirementResult(rockContextUpdate, result.PersonId, group.Id, result.MeetsGroupRequirement); rockContextUpdate.SaveChanges(); } } catch (Exception ex) { calculationExceptions.Add(new Exception($"Exception when updating group requirement result: {groupRequirement} for person.Id { result.PersonId }", ex)); } } } catch (Exception ex) { calculationExceptions.Add(new Exception(string.Format("Exception when calculating group requirement: {0} ", groupRequirement), ex)); } } } context.UpdateLastStatusMessage($"{groupRequirementQry.Count()} group member requirements re-calculated for {groupRequirementsCalculatedPersonIds.Distinct().Count()} people"); if (calculationExceptions.Any()) { throw new AggregateException("One or more group requirement calculations failed ", calculationExceptions); } }
private void SaveGroupMember() { if ( Page.IsValid ) { var rockContext = new RockContext(); // Verify valid group var groupService = new GroupService( rockContext ); var group = groupService.Get( hfGroupId.ValueAsInt() ); if ( group == null ) { nbErrorMessage.Title = "Please select a Role"; return; } // Check to see if a person was selected int? personId = ppGroupMemberPerson.PersonId; int? personAliasId = ppGroupMemberPerson.PersonAliasId; if ( !personId.HasValue || !personAliasId.HasValue ) { nbErrorMessage.Title = "Please select a Person"; return; } // check to see if the user selected a role var role = new GroupTypeRoleService( rockContext ).Get( ddlGroupRole.SelectedValueAsInt() ?? 0 ); if ( role == null ) { nbErrorMessage.Title = "Please select a Role"; return; } var groupMemberService = new GroupMemberService( rockContext ); var groupMemberRequirementService = new GroupMemberRequirementService( rockContext ); GroupMember groupMember; int groupMemberId = int.Parse( hfGroupMemberId.Value ); // if adding a new group member if ( groupMemberId.Equals( 0 ) ) { groupMember = new GroupMember { Id = 0 }; groupMember.GroupId = group.Id; } else { // load existing group member groupMember = groupMemberService.Get( groupMemberId ); } groupMember.PersonId = personId.Value; groupMember.GroupRoleId = role.Id; groupMember.Note = tbNote.Text; groupMember.GroupMemberStatus = rblStatus.SelectedValueAsEnum<GroupMemberStatus>(); if ( cbIsNotified.Visible ) { groupMember.IsNotified = cbIsNotified.Checked; } if ( pnlRequirements.Visible ) { foreach ( var checkboxItem in cblManualRequirements.Items.OfType<ListItem>() ) { int groupRequirementId = checkboxItem.Value.AsInteger(); var groupMemberRequirement = groupMember.GroupMemberRequirements.FirstOrDefault( a => a.GroupRequirementId == groupRequirementId ); bool metRequirement = checkboxItem.Selected; if ( metRequirement ) { if ( groupMemberRequirement == null ) { groupMemberRequirement = new GroupMemberRequirement(); groupMemberRequirement.GroupRequirementId = groupRequirementId; groupMember.GroupMemberRequirements.Add( groupMemberRequirement ); } // set the RequirementMetDateTime if it hasn't been set already groupMemberRequirement.RequirementMetDateTime = groupMemberRequirement.RequirementMetDateTime ?? RockDateTime.Now; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } else { if ( groupMemberRequirement != null ) { // doesn't meets the requirement groupMemberRequirement.RequirementMetDateTime = null; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } } } } if ( group.RequiredSignatureDocumentTemplate != null ) { var person = new PersonService( rockContext ).Get( personId.Value ); var documentService = new SignatureDocumentService( rockContext ); var binaryFileService = new BinaryFileService( rockContext ); SignatureDocument document = null; int? signatureDocumentId = hfSignedDocumentId.Value.AsIntegerOrNull(); int? binaryFileId = fuSignedDocument.BinaryFileId; if ( signatureDocumentId.HasValue ) { document = documentService.Get( signatureDocumentId.Value ); } if ( document == null && binaryFileId.HasValue ) { document = new SignatureDocument(); document.SignatureDocumentTemplateId = group.RequiredSignatureDocumentTemplate.Id; document.AppliesToPersonAliasId = personAliasId.Value; document.AssignedToPersonAliasId = personAliasId.Value; document.Name = string.Format( "{0}_{1}", group.Name.RemoveSpecialCharacters(), ( person != null ? person.FullName.RemoveSpecialCharacters() : string.Empty ) ); document.Status = SignatureDocumentStatus.Signed; document.LastStatusDate = RockDateTime.Now; documentService.Add( document ); } if ( document != null ) { int? origBinaryFileId = document.BinaryFileId; document.BinaryFileId = binaryFileId; if ( origBinaryFileId.HasValue && origBinaryFileId.Value != document.BinaryFileId ) { // if a new the binaryFile was uploaded, mark the old one as Temporary so that it gets cleaned up var oldBinaryFile = binaryFileService.Get( origBinaryFileId.Value ); if ( oldBinaryFile != null && !oldBinaryFile.IsTemporary ) { oldBinaryFile.IsTemporary = true; } } // ensure the IsTemporary is set to false on binaryFile associated with this document if ( document.BinaryFileId.HasValue ) { var binaryFile = binaryFileService.Get( document.BinaryFileId.Value ); if ( binaryFile != null && binaryFile.IsTemporary ) { binaryFile.IsTemporary = false; } } } } groupMember.LoadAttributes(); Rock.Attribute.Helper.GetEditValues( phAttributes, groupMember ); if ( !Page.IsValid ) { return; } // if the groupMember IsValid is false, and the UI controls didn't report any errors, it is probably because the custom rules of GroupMember didn't pass. // So, make sure a message is displayed in the validation summary cvGroupMember.IsValid = groupMember.IsValid; if ( !cvGroupMember.IsValid ) { cvGroupMember.ErrorMessage = groupMember.ValidationResults.Select( a => a.ErrorMessage ).ToList().AsDelimited( "<br />" ); return; } // using WrapTransaction because there are three Saves rockContext.WrapTransaction( () => { if ( groupMember.Id.Equals( 0 ) ) { groupMemberService.Add( groupMember ); } rockContext.SaveChanges(); groupMember.SaveAttributeValues( rockContext ); } ); groupMember.CalculateRequirements( rockContext, true ); if ( group.IsSecurityRole || group.GroupType.Guid.Equals( Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid() ) ) { Rock.Security.Role.Flush( group.Id ); } } }
/// <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> /// <returns></returns> public Dictionary<GroupMember, Dictionary<PersonGroupRequirementStatus, DateTime>> GroupMembersNotMeetingRequirements( int groupId, bool includeWarnings ) { 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 ); // 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; }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { if (Page.IsValid) { var rockContext = new RockContext(); GroupMemberService groupMemberService = new GroupMemberService(rockContext); GroupMemberRequirementService groupMemberRequirementService = new GroupMemberRequirementService(rockContext); GroupMember groupMember; int groupMemberId = int.Parse(hfGroupMemberId.Value); GroupTypeRole role = new GroupTypeRoleService(rockContext).Get(ddlGroupRole.SelectedValueAsInt() ?? 0); // check to see if the user selected a role if (role == null) { nbErrorMessage.Title = "Please select a Role"; return; } // if adding a new group member if (groupMemberId.Equals(0)) { groupMember = new GroupMember { Id = 0 }; groupMember.GroupId = hfGroupId.ValueAsInt(); } else { // load existing group member groupMember = groupMemberService.Get(groupMemberId); } groupMember.PersonId = ppGroupMemberPerson.PersonId.Value; groupMember.GroupRoleId = role.Id; groupMember.Note = tbNote.Text; groupMember.GroupMemberStatus = rblStatus.SelectedValueAsEnum <GroupMemberStatus>(); if (cbIsNotified.Visible) { groupMember.IsNotified = cbIsNotified.Checked; } if (pnlRequirements.Visible) { foreach (var checkboxItem in cblManualRequirements.Items.OfType <ListItem>()) { int groupRequirementId = checkboxItem.Value.AsInteger(); var groupMemberRequirement = groupMember.GroupMemberRequirements.FirstOrDefault(a => a.GroupRequirementId == groupRequirementId); bool metRequirement = checkboxItem.Selected; if (metRequirement) { if (groupMemberRequirement == null) { groupMemberRequirement = new GroupMemberRequirement(); groupMemberRequirement.GroupRequirementId = groupRequirementId; groupMember.GroupMemberRequirements.Add(groupMemberRequirement); } // set the RequirementMetDateTime if it hasn't been set already groupMemberRequirement.RequirementMetDateTime = groupMemberRequirement.RequirementMetDateTime ?? RockDateTime.Now; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } else { if (groupMemberRequirement != null) { // doesn't meets the requirement groupMemberRequirement.RequirementMetDateTime = null; groupMemberRequirement.LastRequirementCheckDateTime = RockDateTime.Now; } } } } groupMember.LoadAttributes(); Rock.Attribute.Helper.GetEditValues(phAttributes, groupMember); if (!Page.IsValid) { return; } // if the groupMember IsValue is false, and the UI controls didn't report any errors, it is probably because the custom rules of GroupMember didn't pass. // So, make sure a message is displayed in the validation summary cvGroupMember.IsValid = groupMember.IsValid; if (!cvGroupMember.IsValid) { cvGroupMember.ErrorMessage = groupMember.ValidationResults.Select(a => a.ErrorMessage).ToList().AsDelimited("<br />"); return; } // using WrapTransaction because there are three Saves rockContext.WrapTransaction(() => { if (groupMember.Id.Equals(0)) { groupMemberService.Add(groupMember); } rockContext.SaveChanges(); groupMember.SaveAttributeValues(rockContext); }); groupMember.CalculateRequirements(rockContext, true); Group group = new GroupService(rockContext).Get(groupMember.GroupId); if (group.IsSecurityRole || group.GroupType.Guid.Equals(Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid())) { Rock.Security.Role.Flush(group.Id); Rock.Security.Authorization.Flush(); } } Dictionary <string, string> qryString = new Dictionary <string, string>(); qryString["GroupId"] = hfGroupId.Value; NavigateToParentPage(qryString); }