/// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute( IJobExecutionContext context )
        {
            var rockContext = new RockContext();

            JobDataMap dataMap = context.JobDetail.JobDataMap;
            Guid? systemEmailGuid = dataMap.GetString( "NotificationEmailTemplate" ).AsGuidOrNull();

            if ( systemEmailGuid.HasValue )
            {

                var selectedGroupTypes = new List<Guid>();
                if ( !string.IsNullOrWhiteSpace( dataMap.GetString( "GroupTypes" ) ) )
                {
                    selectedGroupTypes = dataMap.GetString( "GroupTypes" ).Split( ',' ).Select( Guid.Parse ).ToList();
                }

                var excludedGroupRoleIds = new List<int>();
                if ( !string.IsNullOrWhiteSpace( dataMap.GetString( "ExcludedGroupRoleIds" ) ) )
                {
                    excludedGroupRoleIds = dataMap.GetString( "ExcludedGroupRoleIds" ).Split( ',' ).Select( int.Parse ).ToList();
                }

                var notificationOption = dataMap.GetString( "NotifyParentLeaders" ).ConvertToEnum<NotificationOption>( NotificationOption.None );

                var accountAbilityGroupGuid = dataMap.GetString( "AccountabilityGroup" ).AsGuid();

                // get groups matching of the types provided
                GroupService groupService = new GroupService( rockContext );
                var groups = groupService.Queryable().AsNoTracking()
                                .Where( g => selectedGroupTypes.Contains( g.GroupType.Guid )
                                    && g.IsActive == true
                                    && g.GroupRequirements.Any() );

                foreach ( var group in groups )
                {
                    // check for members that don't meet requirements
                    var groupMembersWithIssues = groupService.GroupMembersNotMeetingRequirements( group.Id, true );

                    if ( groupMembersWithIssues.Count > 0 )
                    {
                        // add issues to issue list
                        GroupsMissingRequirements groupMissingRequirements = new GroupsMissingRequirements();
                        groupMissingRequirements.Id = group.Id;
                        groupMissingRequirements.Name = group.Name;
                        if ( group.GroupType != null )
                        {
                            groupMissingRequirements.GroupTypeId = group.GroupTypeId;
                            groupMissingRequirements.GroupTypeName = group.GroupType.Name;
                        }
                        groupMissingRequirements.AncestorPathName = groupService.GroupAncestorPathName( group.Id );

                        // get list of the group leaders
                        groupMissingRequirements.Leaders = group.Members
                                                            .Where( m => m.GroupRole.IsLeader == true && !excludedGroupRoleIds.Contains( m.GroupRoleId ) )
                                                            .Select( m => new GroupMemberResult
                                                            {
                                                                Id = m.Id,
                                                                PersonId = m.PersonId,
                                                                FullName = m.Person.FullName
                                                            } )
                                                              .ToList();

                        List<GroupMembersMissingRequirements> groupMembers = new List<GroupMembersMissingRequirements>();

                        foreach ( var groupMemberIssue in groupMembersWithIssues )
                        {
                            GroupMembersMissingRequirements groupMember = new GroupMembersMissingRequirements();
                            groupMember.FullName = groupMemberIssue.Key.Person.FullName;
                            groupMember.Id = groupMemberIssue.Key.Id;
                            groupMember.PersonId = groupMemberIssue.Key.PersonId;
                            groupMember.GroupMemberRole = groupMemberIssue.Key.GroupRole.Name;

                            List<MissingRequirement> missingRequirements = new List<MissingRequirement>();
                            foreach ( var issue in groupMemberIssue.Value )
                            {
                                MissingRequirement missingRequirement = new MissingRequirement();
                                missingRequirement.Id = issue.Key.GroupRequirement.GroupRequirementType.Id;
                                missingRequirement.Name = issue.Key.GroupRequirement.GroupRequirementType.Name;
                                missingRequirement.Status = issue.Key.MeetsGroupRequirement;
                                missingRequirement.OccurrenceDate = issue.Value;

                                switch ( issue.Key.MeetsGroupRequirement )
                                {
                                    case MeetsGroupRequirement.Meets:
                                        missingRequirement.Message = issue.Key.GroupRequirement.GroupRequirementType.PositiveLabel;
                                        break;
                                    case MeetsGroupRequirement.MeetsWithWarning:
                                        missingRequirement.Message = issue.Key.GroupRequirement.GroupRequirementType.WarningLabel;
                                        break;
                                    case MeetsGroupRequirement.NotMet:
                                        missingRequirement.Message = issue.Key.GroupRequirement.GroupRequirementType.NegativeLabel;
                                        break;
                                }

                                missingRequirements.Add( missingRequirement );
                            }

                            groupMember.MissingRequirements = missingRequirements;

                            groupMembers.Add( groupMember );
                        }
                        groupMissingRequirements.GroupMembersMissingRequirements = groupMembers;

                        _groupsMissingRequriements.Add( groupMissingRequirements );

                        // add leaders as people to notify
                        foreach ( var leader in group.Members.Where( m => m.GroupRole.IsLeader == true && !excludedGroupRoleIds.Contains( m.GroupRoleId ) ) )
                        {
                            NotificationItem notification = new NotificationItem();
                            notification.GroupId = group.Id;
                            notification.Person = leader.Person;
                            _notificationList.Add( notification );
                        }

                        // notify parents
                        if ( notificationOption != NotificationOption.None )
                        {
                            var parentLeaders = new GroupMemberService( rockContext ).Queryable( "Person" ).AsNoTracking()
                                                    .Where( m => m.GroupRole.IsLeader && !excludedGroupRoleIds.Contains( m.GroupRoleId ) );

                            if ( notificationOption == NotificationOption.DirectParent )
                            {
                                // just the parent group
                                parentLeaders = parentLeaders.Where( m => m.GroupId == group.ParentGroupId );
                            }
                            else
                            {
                                // all parents in the heirarchy
                                var parentIds = groupService.GetAllAncestorIds( group.Id );
                                parentLeaders = parentLeaders.Where( m => parentIds.Contains( m.GroupId ) );
                            }

                            foreach ( var parentLeader in parentLeaders.ToList() )
                            {
                                NotificationItem parentNotification = new NotificationItem();
                                parentNotification.Person = parentLeader.Person;
                                parentNotification.GroupId = group.Id;
                                _notificationList.Add( parentNotification );
                            }
                        }
                    }
                }

                // send out notificatons
                var appRoot = Rock.Web.Cache.GlobalAttributesCache.Read( rockContext ).GetValue( "PublicApplicationRoot" );
                var recipients = new List<RecipientData>();

                var notificationRecipients = _notificationList.GroupBy( p => p.Person.Id ).ToList();
                foreach ( var recipientId in notificationRecipients )
                {
                    var recipient = _notificationList.Where( n => n.Person.Id == recipientId.Key ).Select( n => n.Person ).FirstOrDefault();

                    var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields( null );
                    mergeFields.Add( "Person", recipient );

                    var notificationGroupIds = _notificationList
                                                    .Where( n => n.Person.Id == recipient.Id )
                                                    .Select( n => n.GroupId )
                                                    .ToList();

                    var missingRequirements = _groupsMissingRequriements.Where( g => notificationGroupIds.Contains( g.Id ) ).ToList();

                    mergeFields.Add( "GroupsMissingRequirements", missingRequirements );

                    recipients.Add( new RecipientData( recipient.Email, mergeFields ) );
                    Email.Send( systemEmailGuid.Value, recipients, appRoot );

                    recipients.Clear();
                }

                // add accountability group members
                if ( !accountAbilityGroupGuid.IsEmpty() )
                {
                    var accountabilityGroupMembers = new GroupMemberService( rockContext ).Queryable().AsNoTracking()
                                                        .Where( m => m.Group.Guid == accountAbilityGroupGuid )
                                                        .Select( m => m.Person );

                    foreach ( var person in accountabilityGroupMembers )
                    {
                        var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields( null );
                        mergeFields.Add( "Person", person );
                        mergeFields.Add( "GroupsMissingRequirements", _groupsMissingRequriements );

                        recipients.Add( new RecipientData( person.Email, mergeFields ) );
                    }
                }

                Email.Send( systemEmailGuid.Value, recipients, appRoot );

                context.Result = string.Format( "{0} requirement notification {1} sent", recipients.Count, "email".PluralizeIf( recipients.Count() != 1 ) );

            }
            else
            {
                context.Result = "Warning: No NotificationEmailTemplate found";
            }
        }
        private void ListGroups()
        {
            RockContext rockContext = new RockContext();

            var qry = new GroupMemberService( rockContext )
                        .Queryable( "Group" );

            var parentGroupGuid = GetAttributeValue( "ParentGroup" ).AsGuidOrNull();
            if ( parentGroupGuid!=null )
            {
                var availableGroupIds = ( List<int> ) GetCacheItem( "GroupListPersonalizedLava:" + parentGroupGuid.ToString() );

                if ( availableGroupIds == null )
                {
                    var parentGroup = new GroupService( rockContext ).Get( parentGroupGuid ?? new Guid() );
                    if ( parentGroup != null )
                    {
                        availableGroupIds = GetChildGroups( parentGroup ).Select( g => g.Id ).ToList();
                    }
                    else
                    {
                        availableGroupIds = new List<int>();
                    }
                    var cacheLength = GetAttributeValue( "CacheDuration" ).AsInteger();
                    AddCacheItem( "GroupListPersonalizedLava:" + parentGroupGuid.ToString(), availableGroupIds, cacheLength );
                }
                qry = qry.Where( m => availableGroupIds.Contains( m.GroupId ) );
            }

            qry = qry.Where( m => m.PersonId == CurrentPersonId
                        && m.GroupMemberStatus == GroupMemberStatus.Active
                        && m.Group.IsActive == true );

            List<Guid> includeGroupTypeGuids = GetAttributeValue( "IncludeGroupTypes" ).SplitDelimitedValues().Select( a => Guid.Parse( a ) ).ToList();
            if ( includeGroupTypeGuids.Count > 0 )
            {
                qry = qry.Where( t => includeGroupTypeGuids.Contains( t.Group.GroupType.Guid ) );
            }

            List<Guid> excludeGroupTypeGuids = GetAttributeValue( "ExcludeGroupTypes" ).SplitDelimitedValues().Select( a => Guid.Parse( a ) ).ToList();
            if ( excludeGroupTypeGuids.Count > 0 )
            {
                qry = qry.Where( t => !excludeGroupTypeGuids.Contains( t.Group.GroupType.Guid ) );
            }

            var groups = new List<GroupInvolvementSummary>();

            foreach ( var groupMember in qry.ToList() )
            {
                if ( groupMember.Group.IsAuthorized( Authorization.VIEW, CurrentPerson ) )
                {
                    groups.Add( new GroupInvolvementSummary
                    {
                        Group = groupMember.Group,
                        Role = groupMember.GroupRole.Name,
                        IsLeader = groupMember.GroupRole.IsLeader,
                        GroupType = groupMember.Group.GroupType.Name
                    } );
                }
            }

            var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields( this.RockPage, this.CurrentPerson );
            mergeFields.Add( "Groups", groups );

            Dictionary<string, object> linkedPages = new Dictionary<string, object>();
            linkedPages.Add( "DetailPage", LinkedPageRoute( "DetailPage" ) );
            mergeFields.Add( "LinkedPages", linkedPages );

            string template = GetAttributeValue( "LavaTemplate" );

            // show debug info
            bool enableDebug = GetAttributeValue( "EnableDebug" ).AsBoolean();
            if ( enableDebug && IsUserAuthorized( Authorization.EDIT ) )
            {
                lDebug.Visible = true;
                lDebug.Text = mergeFields.lavaDebugInfo();
            }

            lContent.Text = template.ResolveMergeFields( mergeFields );
        }
        /// <summary>
        /// Job that will sync groups.
        /// 
        /// Called by the <see cref="IScheduler" /> when a
        /// <see cref="ITrigger" /> fires that is associated with
        /// the <see cref="IJob" />.
        /// </summary>
        public virtual void Execute( IJobExecutionContext context )
        {
            JobDataMap dataMap = context.JobDetail.JobDataMap;

            try
            {
                int notificationsSent = 0;
                int pendingMembersCount = 0;

                // get groups set to sync
                RockContext rockContext = new RockContext();

                Guid? groupTypeGuid = dataMap.GetString( "GroupType" ).AsGuidOrNull();
                Guid? systemEmailGuid = dataMap.GetString( "NotificationEmail" ).AsGuidOrNull();
                Guid? groupRoleFilterGuid = dataMap.GetString( "GroupRoleFilter" ).AsGuidOrNull();
                int? pendingAge = dataMap.GetString( "PendingAge" ).AsIntegerOrNull();

                bool includePreviouslyNotificed = dataMap.GetString( "IncludePreviouslyNotified" ).AsBoolean();

                // get system email
                SystemEmailService emailService = new SystemEmailService( rockContext );

                SystemEmail systemEmail = null;
                if ( systemEmailGuid.HasValue )
                {
                    systemEmail = emailService.Get( systemEmailGuid.Value );
                }

                if ( systemEmail == null )
                {
                    // no email specified, so nothing to do
                    return;
                }

                // get group members
                if ( groupTypeGuid.HasValue && groupTypeGuid != Guid.Empty )
                {
                    var qry = new GroupMemberService( rockContext ).Queryable( "Person, Group, Group.Members.GroupRole" )
                                            .Where( m => m.Group.GroupType.Guid == groupTypeGuid.Value
                                                && m.GroupMemberStatus == GroupMemberStatus.Pending );

                    if ( !includePreviouslyNotificed )
                    {
                        qry = qry.Where( m => m.IsNotified == false );
                    }

                    if ( groupRoleFilterGuid.HasValue )
                    {
                        qry = qry.Where( m => m.GroupRole.Guid == groupRoleFilterGuid.Value );
                    }

                    if ( pendingAge.HasValue )
                    {
                        var ageDate = RockDateTime.Now.AddDays( pendingAge.Value * -1 );
                        qry = qry.Where( m => m.ModifiedDateTime > ageDate );
                    }

                    var pendingGroupMembers = qry.ToList();

                    var groups = pendingGroupMembers.GroupBy( m => m.Group );

                    foreach ( var groupKey in groups )
                    {
                        var group = groupKey.Key;

                        // get list of pending people
                        var qryPendingIndividuals = group.Members.Where( m => m.GroupMemberStatus == GroupMemberStatus.Pending );

                        if ( !includePreviouslyNotificed )
                        {
                            qryPendingIndividuals = qryPendingIndividuals.Where( m => m.IsNotified == false );
                        }

                        if ( groupRoleFilterGuid.HasValue )
                        {
                            qryPendingIndividuals = qryPendingIndividuals.Where( m => m.GroupRole.Guid == groupRoleFilterGuid.Value );
                        }

                        var pendingIndividuals = qryPendingIndividuals.Select( m => m.Person ).ToList();

                        // get list of leaders
                        var groupLeaders = group.Members.Where( m => m.GroupRole.IsLeader == true );

                        var appRoot = Rock.Web.Cache.GlobalAttributesCache.Read( rockContext ).GetValue( "PublicApplicationRoot" );

                        var recipients = new List<RecipientData>();
                        foreach ( var leader in groupLeaders )
                        {
                            // create merge object
                            var mergeFields = new Dictionary<string, object>();
                            mergeFields.Add( "PendingIndividuals", pendingIndividuals );
                            mergeFields.Add( "Group", group );
                            mergeFields.Add( "ParentGroup", group.ParentGroup );
                            mergeFields.Add( "Person", leader.Person );
                            recipients.Add( new RecipientData( leader.Person.Email, mergeFields ) );
                        }

                        if ( pendingIndividuals.Count() > 0 )
                        {
                            Email.Send( systemEmail.Guid, recipients, appRoot );
                            pendingMembersCount += pendingIndividuals.Count();
                            notificationsSent += recipients.Count();
                        }

                        // mark pending members as notified as we go in case the job fails
                        var notifiedPersonIds = pendingIndividuals.Select( p => p.Id );
                        foreach ( var pendingGroupMember in pendingGroupMembers.Where( m => m.IsNotified == false && notifiedPersonIds.Contains( m.PersonId ) ) )
                        {
                            pendingGroupMember.IsNotified = true;
                        }

                        rockContext.SaveChanges();

                    }
                }

                context.Result = string.Format( "Sent {0} emails to leaders for {1} pending individuals", notificationsSent, pendingMembersCount );
            }
            catch ( System.Exception ex )
            {
                HttpContext context2 = HttpContext.Current;
                ExceptionLogService.LogException( ex, context2 );
                throw;
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute( RockContext rockContext, WorkflowAction action, Object entity, out List<string> errorMessages )
        {
            errorMessages = new List<string>();

            Guid? groupGuid = null;
            Person person = null;
            string attributeValue = string.Empty;
            Guid groupRoleGuid = Guid.Empty;
            string attributeKey = string.Empty;

            // get the group attribute
            Guid groupAttributeGuid = GetAttributeValue(action, "Group").AsGuid();

            if ( !groupAttributeGuid.IsEmpty() )
            {
                groupGuid = action.GetWorklowAttributeValue(groupAttributeGuid).AsGuidOrNull();

                if ( !groupGuid.HasValue )
                {
                    errorMessages.Add("The group could not be found!");
                }
            }

            // get person alias guid
            Guid personAliasGuid = Guid.Empty;
            string personAttribute = GetAttributeValue( action, "Person" );

            Guid guid = personAttribute.AsGuid();
            if (!guid.IsEmpty())
            {
                var attribute = AttributeCache.Read( guid, rockContext );
                if ( attribute != null )
                {
                    string value = action.GetWorklowAttributeValue(guid);
                    personAliasGuid = value.AsGuid();
                }

                if ( personAliasGuid != Guid.Empty )
                {
                    person = new PersonAliasService(rockContext).Queryable().AsNoTracking()
                                    .Where(p => p.Guid.Equals(personAliasGuid))
                                    .Select(p => p.Person)
                                    .FirstOrDefault();
                }
                else {
                    errorMessages.Add("The person could not be found in the attribute!");
                }
            }

            // get group member attribute value
            attributeValue = GetAttributeValue(action, "AttributeValue");
            guid = attributeValue.AsGuid();
            if ( guid.IsEmpty() )
            {
                attributeValue = attributeValue.ResolveMergeFields(GetMergeFields(action));
            }
            else
            {
                var workflowAttributeValue = action.GetWorklowAttributeValue(guid);

                if ( workflowAttributeValue != null )
                {
                    attributeValue = workflowAttributeValue;
                }
            }

            // get optional role filter
            groupRoleGuid = GetAttributeValue(action, "GroupRoleFilter").AsGuid();

            // get attribute key
            attributeKey = GetAttributeValue(action, "GroupMemberAttributeKey").Replace(" ", "");

            // set attribute
            if ( groupGuid.HasValue && person != null )
            {
                var qry = new GroupMemberService(rockContext).Queryable()
                                .Where(m => m.Group.Guid == groupGuid && m.PersonId == person.Id);

                if ( groupRoleGuid != Guid.Empty )
                {
                    qry = qry.Where(m => m.GroupRole.Guid == groupRoleGuid);
                }

                foreach ( var groupMember in qry.ToList() )
                {
                    groupMember.LoadAttributes(rockContext);
                    if ( groupMember.Attributes.ContainsKey(attributeKey) )
                    {
                        var attribute = groupMember.Attributes[attributeKey];
                        Rock.Attribute.Helper.SaveAttributeValue(groupMember, attribute, attributeValue, rockContext);
                    }
                    else
                    {
                        action.AddLogEntry(string.Format("The group member attribute {0} does not exist!", attributeKey));
                        break;
                    }
                }
            }

            errorMessages.ForEach( m => action.AddLogEntry( m, true ) );

            return true;
        }
Esempio n. 5
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute( IJobExecutionContext context )
        {
            var exceptionMsgs = new List<string>();

            JobDataMap dataMap = context.JobDetail.JobDataMap;
            Guid? groupGuid = dataMap.GetString( "EligibleFollowers" ).AsGuidOrNull();
            Guid? systemEmailGuid = dataMap.GetString( "EmailTemplate" ).AsGuidOrNull();
            int followingSuggestionsEmailsSent = 0;
            int followingSuggestionsSuggestionsTotal = 0;

            if ( groupGuid.HasValue && systemEmailGuid.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    var followingService = new FollowingService( rockContext );

                    // The people who are eligible to get following suggestions based on the group type setting for this job
                    var eligiblePersonIds = new GroupMemberService( rockContext )
                        .Queryable().AsNoTracking()
                        .Where( m =>
                            m.Group != null &&
                            m.Group.Guid.Equals( groupGuid.Value ) &&
                            m.GroupMemberStatus == GroupMemberStatus.Active &&
                            m.Person != null &&
                            m.Person.Email != null &&
                            m.Person.Email != "" )
                        .Select( m => m.PersonId )
                        .Distinct();

                    // check to see if there are any event types that require notification
                    var followerPersonIds = new List<int>();
                    if ( new FollowingEventTypeService( rockContext )
                        .Queryable().AsNoTracking()
                        .Any( e => e.IsNoticeRequired ) )
                    {
                        // if so, include all eligible people
                        followerPersonIds = eligiblePersonIds.ToList();
                    }
                    else
                    {
                        // if not, filter the list of eligible people down to only those that actually have subscribed to one or more following events
                        followerPersonIds = new FollowingEventSubscriptionService( rockContext )
                            .Queryable().AsNoTracking()
                            .Where( f => eligiblePersonIds.Contains( f.PersonAlias.PersonId ) )
                            .Select( f => f.PersonAlias.PersonId )
                            .Distinct()
                            .ToList();
                    }

                    if ( followerPersonIds.Any() )
                    {
                        // Get the primary person alias id for each of the followers
                        var primaryAliasIds = new Dictionary<int, int>();
                        new PersonAliasService( rockContext )
                            .Queryable().AsNoTracking()
                            .Where( a =>
                                followerPersonIds.Contains( a.PersonId ) &&
                                a.PersonId == a.AliasPersonId )
                            .ToList()
                            .ForEach( a => primaryAliasIds.AddOrIgnore( a.PersonId, a.Id ) );

                        // Get current date/time.
                        var timestamp = RockDateTime.Now;

                        var suggestionTypes = new FollowingSuggestionTypeService( rockContext )
                            .Queryable().AsNoTracking()
                            .Where( s => s.IsActive )
                            .OrderBy( s => s.Name )
                            .ToList();

                        var components = new Dictionary<int, SuggestionComponent>();
                        var suggestedEntities = new Dictionary<int, Dictionary<int, IEntity>>();

                        foreach ( var suggestionType in suggestionTypes )
                        {
                            try
                            {
                                // Get the suggestion type component
                                var suggestionComponent = suggestionType.GetSuggestionComponent();
                                if ( suggestionComponent != null )
                                {
                                    components.Add( suggestionType.Id, suggestionComponent );

                                    // Get the entitytype for this suggestion type
                                    var suggestionEntityType = EntityTypeCache.Read( suggestionComponent.FollowedType );
                                    if ( suggestionEntityType != null )
                                    {
                                        var entityIds = new List<int>();

                                        // Call the components method to return all of it's suggestions
                                        var personEntitySuggestions = suggestionComponent.GetSuggestions( suggestionType, followerPersonIds );

                                        // If any suggestions were returned by the component
                                        if ( personEntitySuggestions.Any() )
                                        {
                                            int entityTypeId = suggestionEntityType.Id;
                                            string reasonNote = suggestionType.ReasonNote;

                                            // Get the existing followings for any of the followers
                                            var existingFollowings = new Dictionary<int, List<int>>();
                                            foreach( var following in followingService.Queryable( "PersonAlias" ).AsNoTracking()
                                                .Where( f =>
                                                    f.EntityTypeId == entityTypeId &&
                                                    followerPersonIds.Contains( f.PersonAlias.PersonId ) ) )
                                            {
                                                existingFollowings.AddOrIgnore( following.PersonAlias.PersonId, new List<int>() );
                                                existingFollowings[ following.PersonAlias.PersonId].Add( following.EntityId );
                                            }

                                            // Loop through each follower
                                            foreach ( var followerPersonId in personEntitySuggestions
                                                .Select( s => s.PersonId )
                                                .Distinct() )
                                            {

                                                using ( var suggestionContext = new RockContext() )
                                                {
                                                    var followingSuggestedService = new FollowingSuggestedService( suggestionContext );

                                                    // Read all the existing suggestions for this type and the returned followers
                                                    var existingSuggestions = followingSuggestedService
                                                        .Queryable( "PersonAlias" )
                                                        .Where( s =>
                                                            s.SuggestionTypeId == suggestionType.Id &&
                                                            s.PersonAlias.PersonId == followerPersonId )
                                                        .ToList();

                                                    // Look  through the returned suggestions
                                                    foreach ( var followedEntityId in personEntitySuggestions
                                                        .Where( s => s.PersonId == followerPersonId )
                                                        .Select( s => s.EntityId ) )
                                                    {
                                                        // Make sure person isn't already following this entity
                                                        if ( !existingFollowings.ContainsKey( followerPersonId )
                                                            || !existingFollowings[followerPersonId].Contains( followedEntityId ) )
                                                        {
                                                            // If this person had a primary alias id
                                                            if ( primaryAliasIds.ContainsKey( followerPersonId ) )
                                                            {
                                                                entityIds.Add( followedEntityId );

                                                                // Look for existing suggestion for this person and entity
                                                                var suggestion = existingSuggestions
                                                                    .Where( s => s.EntityId == followedEntityId )
                                                                    .OrderByDescending( s => s.StatusChangedDateTime )
                                                                    .FirstOrDefault();

                                                                // If not found, add one
                                                                if ( suggestion == null )
                                                                {
                                                                    suggestion = new FollowingSuggested();
                                                                    suggestion.EntityTypeId = entityTypeId;
                                                                    suggestion.EntityId = followedEntityId;
                                                                    suggestion.PersonAliasId = primaryAliasIds[followerPersonId];
                                                                    suggestion.SuggestionTypeId = suggestionType.Id;
                                                                    suggestion.Status = FollowingSuggestedStatus.PendingNotification;
                                                                    suggestion.StatusChangedDateTime = timestamp;
                                                                    followingSuggestedService.Add( suggestion );
                                                                }
                                                                else
                                                                {
                                                                    // If found, and it has not been ignored, and it's time to promote again, update the promote date
                                                                    if ( suggestion.Status != FollowingSuggestedStatus.Ignored &&
                                                                        (
                                                                            !suggestionType.ReminderDays.HasValue ||
                                                                            !suggestion.LastPromotedDateTime.HasValue ||
                                                                            suggestion.LastPromotedDateTime.Value.AddDays( suggestionType.ReminderDays.Value ) <= timestamp
                                                                        ) )
                                                                    {
                                                                        if ( suggestion.Status != FollowingSuggestedStatus.PendingNotification )
                                                                        {
                                                                            suggestion.StatusChangedDateTime = timestamp;
                                                                            suggestion.Status = FollowingSuggestedStatus.PendingNotification;
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                                    // Save the suggestions for this type
                                                    suggestionContext.SaveChanges();
                                                }
                                            }
                                        }

                                        // If any entities are being suggested for this type, query database for them and save to dictionary
                                        if ( entityIds.Any() )
                                        {
                                            if ( suggestionEntityType.AssemblyName != null )
                                            {
                                                // get the actual type of what is being followed
                                                Type entityType = suggestionEntityType.GetEntityType();
                                                if ( entityType != null )
                                                {
                                                    // Get generic queryable method and query all the entities that are being followed
                                                    Type[] modelType = { entityType };
                                                    Type genericServiceType = typeof( Rock.Data.Service<> );
                                                    Type modelServiceType = genericServiceType.MakeGenericType( modelType );
                                                    Rock.Data.IService serviceInstance = Activator.CreateInstance( modelServiceType, new object[] { rockContext } ) as IService;
                                                    MethodInfo qryMethod = serviceInstance.GetType().GetMethod( "Queryable", new Type[] { } );
                                                    var entityQry = qryMethod.Invoke( serviceInstance, new object[] { } ) as IQueryable<IEntity>;
                                                    var entityList = entityQry.AsNoTracking().Where( q => entityIds.Contains( q.Id ) ).ToList();
                                                    if ( entityList != null && entityList.Any() )
                                                    {
                                                        var entities = new Dictionary<int, IEntity>();
                                                        entityList.ForEach( e => entities.Add( e.Id, e ) );
                                                        suggestedEntities.Add( suggestionType.Id, entities );
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            catch ( Exception ex )
                            {
                                exceptionMsgs.Add( string.Format( "An exception occurred calculating suggestions for the '{0}' suggestion type:{1}    {2}", suggestionType.Name, Environment.NewLine, ex.Messages().AsDelimited( Environment.NewLine + "   " ) ) );
                                ExceptionLogService.LogException( ex, System.Web.HttpContext.Current );
                            }
                        }

                        var allSuggestions = new FollowingSuggestedService( rockContext )
                            .Queryable( "PersonAlias" )
                            .Where( s => s.Status == FollowingSuggestedStatus.PendingNotification )
                            .ToList();

                        var suggestionPersonIds = allSuggestions
                            .Where( s => followerPersonIds.Contains( s.PersonAlias.PersonId ) )
                            .Select( s => s.PersonAlias.PersonId )
                            .Distinct()
                            .ToList();

                        var appRoot = Rock.Web.Cache.GlobalAttributesCache.Read( rockContext ).GetValue( "PublicApplicationRoot" );

                        foreach ( var person in new PersonService( rockContext )
                            .Queryable().AsNoTracking()
                            .Where( p => suggestionPersonIds.Contains( p.Id ) )
                            .ToList() )
                        {
                            try
                            {
                                var personSuggestionNotices = new List<FollowingSuggestionNotices>();

                                foreach ( var suggestionType in suggestionTypes )
                                {
                                    var component = components.ContainsKey( suggestionType.Id ) ? components[suggestionType.Id] : null;
                                    if ( component != null && suggestedEntities.ContainsKey( suggestionType.Id ) )
                                    {

                                        var entities = new List<IEntity>();
                                        foreach ( var suggestion in allSuggestions
                                            .Where( s =>
                                                s.PersonAlias.PersonId == person.Id &&
                                                s.SuggestionTypeId == suggestionType.Id )
                                            .ToList() )
                                        {
                                            if ( suggestedEntities[suggestionType.Id].ContainsKey( suggestion.EntityId ) )
                                            {
                                                entities.Add( suggestedEntities[suggestionType.Id][suggestion.EntityId] );
                                                suggestion.LastPromotedDateTime = timestamp;
                                                suggestion.Status = FollowingSuggestedStatus.Suggested;
                                            }
                                        }

                                        var notices = new List<string>();
                                        foreach ( var entity in component.SortEntities( entities ) )
                                        {
                                            notices.Add( component.FormatEntityNotification( suggestionType, entity ) );
                                        }

                                        if ( notices.Any() )
                                        {
                                            personSuggestionNotices.Add( new FollowingSuggestionNotices( suggestionType, notices ) );
                                        }
                                    }
                                }

                                if ( personSuggestionNotices.Any() )
                                {
                                    // Send the notice
                                    var recipients = new List<RecipientData>();
                                    var mergeFields = new Dictionary<string, object>();
                                    mergeFields.Add( "Person", person );
                                    mergeFields.Add( "Suggestions", personSuggestionNotices.OrderBy( s => s.SuggestionType.Order ).ToList() );
                                    recipients.Add( new RecipientData( person.Email, mergeFields ) );
                                    Email.Send( systemEmailGuid.Value, recipients, appRoot );
                                    followingSuggestionsEmailsSent += recipients.Count();
                                    followingSuggestionsSuggestionsTotal += personSuggestionNotices.Count();
                                }

                                rockContext.SaveChanges();
                            }
                            catch ( Exception ex )
                            {
                                exceptionMsgs.Add( string.Format( "An exception occurred sending suggestions to '{0}':{1}    {2}", person.FullName, Environment.NewLine, ex.Messages().AsDelimited( Environment.NewLine + "   " ) ) );
                                ExceptionLogService.LogException( ex, System.Web.HttpContext.Current );
                            }
                        }

                    }
                }
            }

            context.Result = string.Format( "A total of {0} following suggestions sent to {1} people", followingSuggestionsSuggestionsTotal, followingSuggestionsEmailsSent );

            if ( exceptionMsgs.Any() )
            {
                throw new Exception( "One or more exceptions occurred calculating suggestions..." + Environment.NewLine + exceptionMsgs.AsDelimited( Environment.NewLine ) );
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Gets the groups of selected type that person is a member of
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="input">The input.</param>
        /// <param name="groupTypeId">The group type identifier.</param>
        /// <param name="status">The status.</param>
        /// <returns></returns>
        public static List<Rock.Model.GroupMember> Groups( DotLiquid.Context context, object input, string groupTypeId, string status = "Active" )
        {
            var person = GetPerson( input );
            int? numericalGroupTypeId = groupTypeId.AsIntegerOrNull();

            if ( person != null && numericalGroupTypeId.HasValue )
            {
                var groupQuery =  new GroupMemberService( GetRockContext( context ) )
                    .Queryable("Group, GroupRole").AsNoTracking()
                    .Where( m =>
                        m.PersonId == person.Id &&
                        m.Group.GroupTypeId == numericalGroupTypeId.Value &&
                        m.Group.IsActive );

                if ( status != "All" )
                {
                    GroupMemberStatus queryStatus = GroupMemberStatus.Active;
                    queryStatus = (GroupMemberStatus)Enum.Parse( typeof( GroupMemberStatus ), status, true );

                    groupQuery = groupQuery.Where( m => m.GroupMemberStatus == queryStatus );
                }

                return groupQuery.ToList();
            }

            return new List<Model.GroupMember>();
        }