/// <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 );
            }
        }
Esempio n. 3
0
        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);
                }
            }
        }
Esempio n. 4
0
        /// <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 );
        }
Esempio n. 5
0
        /// <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);
            }
        }
Esempio n. 6
0
        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 );
                }
            }
        }
Esempio n. 7
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>
        /// <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);
        }