Esempio n. 1
0
        /// <summary>
        /// Configures a control to display and toggle following for the specified entity
        /// </summary>
        /// <param name="followEntity">The follow entity. NOTE: Make sure to use PersonAlias instead of Person when following a Person</param>
        /// <param name="followControl">The follow control.</param>
        /// <param name="follower">The follower.</param>
        public static void SetFollowing( IEntity followEntity, WebControl followControl, Person follower )
        {
            var followingEntityType = EntityTypeCache.Read( followEntity.GetType() );
            if ( follower != null && follower.PrimaryAliasId.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    var personAliasService = new PersonAliasService( rockContext );
                    var followingService = new FollowingService( rockContext );

                    var followingQry = followingService.Queryable()
                        .Where( f =>
                            f.EntityTypeId == followingEntityType.Id &&
                            f.PersonAlias.PersonId == follower.Id );

                    followingQry = followingQry.Where( f => f.EntityId == followEntity.Id );

                    if ( followingQry.Any() )
                    {
                        followControl.AddCssClass( "following" );
                    }
                    else
                    {
                        followControl.RemoveCssClass( "following" );
                    }
                }

                int entityId = followEntity.Id;

                // only show the following control if the entity has been saved to the database
                followControl.Visible = entityId > 0;

                string script = string.Format(
                    @"Rock.controls.followingsToggler.initialize($('#{0}'), {1}, {2}, {3}, {4});",
                        followControl.ClientID,
                        followingEntityType.Id,
                        entityId,
                        follower.Id,
                        follower.PrimaryAliasId );

                ScriptManager.RegisterStartupScript( followControl, followControl.GetType(), "following", script, true );
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Handles the Delete event of the gFollowings control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gFollowings_Delete( object sender, RowEventArgs e )
        {
            var rockContext = new RockContext();
            var service = new FollowingService( rockContext );

            int personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id;
            foreach (var following in service.Queryable()
                .Where( f =>
                    f.EntityTypeId == personEntityTypeId &&
                    f.EntityId == e.RowKeyId &&
                    f.PersonAliasId == CurrentPersonAlias.Id ) )
            {
                service.Delete( following );
            }

            rockContext.SaveChanges();

            BindGrid();
        }
        /// <summary>
        /// Handles the Click event of the btnConfirm 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 btnConfirm_Click( object sender, EventArgs e )
        {
            if ( Page.IsValid )
            {
                var rockContext = new RockContext();
                var personService = new PersonService( rockContext );
                var ids = Individuals.Select( i => i.PersonId ).ToList();

                #region Individual Details Updates

                int? newTitleId = ddlTitle.SelectedValueAsInt();
                int? newSuffixId = ddlSuffix.SelectedValueAsInt();
                int? newConnectionStatusId = ddlStatus.SelectedValueAsInt();
                int? newRecordStatusId = ddlRecordStatus.SelectedValueAsInt();
                int? newInactiveReasonId = ddlInactiveReason.SelectedValueAsInt();
                string newInactiveReasonNote = tbInactiveReasonNote.Text;
                Gender newGender = ddlGender.SelectedValue.ConvertToEnum<Gender>();
                int? newMaritalStatusId = ddlMaritalStatus.SelectedValueAsInt();

                int? newGraduationYear = null;
                if ( ypGraduation.SelectedYear.HasValue )
                {
                    newGraduationYear = ypGraduation.SelectedYear.Value;
                }

                int? newCampusId = cpCampus.SelectedCampusId;

                bool? newEmailActive = null;
                if ( !string.IsNullOrWhiteSpace( ddlIsEmailActive.SelectedValue ) )
                {
                    newEmailActive = ddlIsEmailActive.SelectedValue == "Active";
                }

                EmailPreference? newEmailPreference = ddlEmailPreference.SelectedValue.ConvertToEnumOrNull<EmailPreference>();

                string newEmailNote = tbEmailNote.Text;

                int? newReviewReason = ddlReviewReason.SelectedValueAsInt();
                string newSystemNote = tbSystemNote.Text;
                string newReviewReasonNote = tbReviewReasonNote.Text;

                int inactiveStatusId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE ).Id;

                var allChanges = new Dictionary<int, List<string>>();

                var people = personService.Queryable().Where( p => ids.Contains( p.Id ) ).ToList();
                foreach ( var person in people )
                {
                    var changes = new List<string>();
                    allChanges.Add( person.Id, changes );

                    if ( SelectedFields.Contains( ddlTitle.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Title", DefinedValueCache.GetName( person.TitleValueId ), DefinedValueCache.GetName( newTitleId ) );
                        person.TitleValueId = newTitleId;
                    }

                    if ( SelectedFields.Contains( ddlSuffix.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Suffix", DefinedValueCache.GetName( person.SuffixValueId ), DefinedValueCache.GetName( newSuffixId ) );
                        person.SuffixValueId = newSuffixId;
                    }

                    if ( SelectedFields.Contains( ddlStatus.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Connection Status", DefinedValueCache.GetName( person.ConnectionStatusValueId ), DefinedValueCache.GetName( newConnectionStatusId ) );
                        person.ConnectionStatusValueId = newConnectionStatusId;
                    }

                    if ( SelectedFields.Contains( ddlRecordStatus.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Record Status", DefinedValueCache.GetName( person.RecordStatusValueId ), DefinedValueCache.GetName( newRecordStatusId ) );
                        person.RecordStatusValueId = newRecordStatusId;

                        if ( newRecordStatusId.HasValue && newRecordStatusId.Value == inactiveStatusId )
                        {
                            History.EvaluateChange( changes, "Inactive Reason", DefinedValueCache.GetName( person.RecordStatusReasonValueId ), DefinedValueCache.GetName( newInactiveReasonId ) );
                            person.RecordStatusReasonValueId = newInactiveReasonId;

                            if ( !string.IsNullOrWhiteSpace( newInactiveReasonNote ) )
                            {
                                History.EvaluateChange( changes, "Inactive Reason Note", person.InactiveReasonNote, newInactiveReasonNote );
                                person.InactiveReasonNote = newInactiveReasonNote;
                            }
                        }
                    }

                    if ( SelectedFields.Contains( ddlGender.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Gender", person.Gender, newGender );
                        person.Gender = newGender;
                    }

                    if ( SelectedFields.Contains( ddlMaritalStatus.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Marital Status", DefinedValueCache.GetName( person.MaritalStatusValueId ), DefinedValueCache.GetName( newMaritalStatusId ) );
                        person.MaritalStatusValueId = newMaritalStatusId;
                    }

                    if ( SelectedFields.Contains( ddlGradePicker.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Graduation Year", person.GraduationYear, newGraduationYear );
                        person.GraduationYear = newGraduationYear;
                    }

                    if ( SelectedFields.Contains( ddlIsEmailActive.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Email Is Active", person.IsEmailActive ?? true, newEmailActive.Value );
                        person.IsEmailActive = newEmailActive;
                    }

                    if ( SelectedFields.Contains( ddlEmailPreference.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Email Preference", person.EmailPreference, newEmailPreference );
                        person.EmailPreference = newEmailPreference.Value;
                    }

                    if ( SelectedFields.Contains( tbEmailNote.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Email Note", person.EmailNote, newEmailNote );
                        person.EmailNote = newEmailNote;
                    }

                    if ( SelectedFields.Contains( tbSystemNote.ClientID ) )
                    {
                        History.EvaluateChange( changes, "System Note", person.SystemNote, newSystemNote );
                        person.SystemNote = newSystemNote;
                    }

                    if ( SelectedFields.Contains( ddlReviewReason.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Review Reason", DefinedValueCache.GetName( person.ReviewReasonValueId ), DefinedValueCache.GetName( newReviewReason ) );
                        person.ReviewReasonValueId = newReviewReason;
                    }

                    if ( SelectedFields.Contains( tbReviewReasonNote.ClientID ) )
                    {
                        History.EvaluateChange( changes, "Review Reason Note", person.ReviewReasonNote, newReviewReasonNote );
                        person.ReviewReasonNote = newReviewReasonNote;
                    }
                }

                if ( SelectedFields.Contains( cpCampus.ClientID ) && cpCampus.SelectedCampusId.HasValue )
                {
                    int campusId = cpCampus.SelectedCampusId.Value;

                    Guid familyGuid = new Guid( Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY );

                    var familyMembers = new GroupMemberService( rockContext ).Queryable()
                        .Where( m => ids.Contains( m.PersonId ) && m.Group.GroupType.Guid == familyGuid )
                        .Select( m => new { m.PersonId, m.GroupId } )
                        .Distinct()
                        .ToList();

                    var families = new GroupMemberService( rockContext ).Queryable()
                        .Where( m => ids.Contains( m.PersonId ) && m.Group.GroupType.Guid == familyGuid )
                        .Select( m => m.Group )
                        .Distinct()
                        .ToList();

                    foreach ( int personId in ids )
                    {
                        var familyIds = familyMembers.Where( m => m.PersonId == personId ).Select( m => m.GroupId ).ToList();
                        if ( familyIds.Count == 1 )
                        {
                            int familyId = familyIds.FirstOrDefault();
                            var family = families.Where( g => g.Id == familyId ).FirstOrDefault();
                            {
                                if ( family != null )
                                {
                                    family.CampusId = campusId;
                                }
                                familyMembers.RemoveAll( m => m.GroupId == familyId );
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }

                // Update following
                if ( SelectedFields.Contains( ddlFollow.ClientID ) )
                {
                    var personAliasEntityType = EntityTypeCache.Read( "Rock.Model.PersonAlias" );
                    if ( personAliasEntityType != null )
                    {
                        int personAliasEntityTypeId = personAliasEntityType.Id;

                        bool follow = true;
                        if ( !string.IsNullOrWhiteSpace( ddlFollow.SelectedValue ) )
                        {
                            follow = ddlFollow.SelectedValue == "Add";
                        }

                        var personAliasService = new PersonAliasService( rockContext );
                        var followingService = new FollowingService( rockContext );
                        if ( follow )
                        {
                            var paQry = personAliasService.Queryable();

                            var alreadyFollowingIds = followingService.Queryable()
                                .Where( f =>
                                    f.EntityTypeId == personAliasEntityTypeId &&
                                    f.PersonAlias.Id == CurrentPersonAlias.Id )
                                .Join( paQry, f => f.EntityId, p => p.Id, ( f, p ) => new { PersonAlias = p } )
                                .Select( p => p.PersonAlias.PersonId )
                                .Distinct()
                                .ToList();

                            foreach ( int id in ids.Where( id => !alreadyFollowingIds.Contains( id ) ) )
                            {
                                var following = new Following
                                {
                                    EntityTypeId = personAliasEntityTypeId,
                                    EntityId = ( people.FirstOrDefault( p => p.Id == id ).PrimaryAliasId ) ?? 0,
                                    PersonAliasId = CurrentPersonAlias.Id
                                };
                                followingService.Add( following );
                            }
                        }
                        else
                        {
                            var paQry = personAliasService.Queryable()
                                .Where( p => ids.Contains( p.PersonId ) )
                                .Select( p => p.Id );

                            foreach ( var following in followingService.Queryable()
                                .Where( f =>
                                    f.EntityTypeId == personAliasEntityTypeId &&
                                    paQry.Contains( f.EntityId ) &&
                                    f.PersonAlias.Id == CurrentPersonAlias.Id ) )
                            {
                                followingService.Delete( following );
                            }
                        }
                    }
                }

                rockContext.SaveChanges();

                #endregion

                #region Attributes

                var selectedCategories = new List<CategoryCache>();
                foreach ( string categoryGuid in GetAttributeValue( "AttributeCategories" ).SplitDelimitedValues() )
                {
                    var category = CategoryCache.Read( categoryGuid.AsGuid(), rockContext );
                    if ( category != null )
                    {
                        selectedCategories.Add( category );
                    }
                }

                var attributes = new List<AttributeCache>();
                var attributeValues = new Dictionary<int, string>();

                int categoryIndex = 0;
                foreach ( var category in selectedCategories.OrderBy( c => c.Name ) )
                {
                    PanelWidget pw = null;
                    string controlId = "pwAttributes_" + category.Id.ToString();
                    if ( categoryIndex % 2 == 0 )
                    {
                        pw = phAttributesCol1.FindControl( controlId ) as PanelWidget;
                    }
                    else
                    {
                        pw = phAttributesCol2.FindControl( controlId ) as PanelWidget;
                    }
                    categoryIndex++;

                    if ( pw != null )
                    {
                        var orderedAttributeList = new AttributeService( rockContext ).GetByCategoryId( category.Id )
                            .OrderBy( a => a.Order ).ThenBy( a => a.Name );
                        foreach ( var attribute in orderedAttributeList )
                        {
                            if ( attribute.IsAuthorized( Authorization.EDIT, CurrentPerson ) )
                            {
                                var attributeCache = AttributeCache.Read( attribute.Id );

                                Control attributeControl = pw.FindControl( string.Format( "attribute_field_{0}", attribute.Id ) );

                                if ( attributeControl != null && SelectedFields.Contains( attributeControl.ClientID ) )
                                {
                                    string newValue = attributeCache.FieldType.Field.GetEditValue( attributeControl, attributeCache.QualifierValues );
                                    attributes.Add( attributeCache );
                                    attributeValues.Add( attributeCache.Id, newValue );
                                }
                            }
                        }
                    }
                }

                if ( attributes.Any() )
                {
                    foreach ( var person in people )
                    {
                        person.LoadAttributes();
                        foreach ( var attribute in attributes )
                        {
                            string originalValue = person.GetAttributeValue( attribute.Key );
                            string newValue = attributeValues[attribute.Id];
                            if ( ( originalValue ?? string.Empty ).Trim() != ( newValue ?? string.Empty ).Trim() )
                            {
                                Rock.Attribute.Helper.SaveAttributeValue( person, attribute, newValue, rockContext );

                                string formattedOriginalValue = string.Empty;
                                if ( !string.IsNullOrWhiteSpace( originalValue ) )
                                {
                                    formattedOriginalValue = attribute.FieldType.Field.FormatValue( null, originalValue, attribute.QualifierValues, false );
                                }

                                string formattedNewValue = string.Empty;
                                if ( !string.IsNullOrWhiteSpace( newValue ) )
                                {
                                    formattedNewValue = attribute.FieldType.Field.FormatValue( null, newValue, attribute.QualifierValues, false );
                                }

                                History.EvaluateChange( allChanges[person.Id], attribute.Name, formattedOriginalValue, formattedNewValue );
                            }
                        }
                    }
                }

                // Create the history records
                foreach ( var changes in allChanges )
                {
                    if ( changes.Value.Any() )
                    {
                        HistoryService.AddChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                            changes.Key, changes.Value );
                    }
                }
                rockContext.SaveChanges();

                #endregion

                #region Add Note

                if ( !string.IsNullOrWhiteSpace( tbNote.Text ) && CurrentPerson != null )
                {
                    string text = tbNote.Text;
                    bool isAlert = cbIsAlert.Checked;
                    bool isPrivate = cbIsPrivate.Checked;

                    var noteTypeService = new NoteTypeService( rockContext );
                    var noteType = noteTypeService.Get( Rock.SystemGuid.NoteType.PERSON_TIMELINE.AsGuid() );
                    if ( noteType != null )
                    {
                        var notes = new List<Note>();
                        var noteService = new NoteService( rockContext );

                        foreach ( int id in ids )
                        {
                            var note = new Note();
                            note.IsSystem = false;
                            note.EntityId = id;
                            note.Caption = isPrivate ? "You - Personal Note" : string.Empty;
                            note.Text = tbNote.Text;
                            note.IsAlert = cbIsAlert.Checked;
                            note.NoteType = noteType;
                            notes.Add( note );
                            noteService.Add( note );
                        }

                        rockContext.WrapTransaction( () =>
                        {
                            rockContext.SaveChanges();
                            foreach ( var note in notes )
                            {
                                note.AllowPerson( Authorization.EDIT, CurrentPerson, rockContext );
                                if ( isPrivate )
                                {
                                    note.MakePrivate( Authorization.VIEW, CurrentPerson, rockContext );
                                }
                            }
                        } );

                    }
                }

                #endregion

                #region Group

                int? groupId = gpGroup.SelectedValue.AsIntegerOrNull();
                if ( groupId.HasValue )
                {
                    var group = new GroupService( rockContext ).Get( groupId.Value );
                    if ( group != null )
                    {
                        var groupMemberService = new GroupMemberService( rockContext );

                        var existingMembers = groupMemberService.Queryable( "Group" )
                            .Where( m =>
                                m.GroupId == group.Id &&
                                ids.Contains( m.PersonId ) )
                            .ToList();

                        string action = ddlGroupAction.SelectedValue;
                        if ( action == "Remove" )
                        {
                            groupMemberService.DeleteRange( existingMembers );
                            rockContext.SaveChanges();
                        }
                        else
                        {
                            var roleId = ddlGroupRole.SelectedValueAsInt();
                            var status = ddlGroupMemberStatus.SelectedValueAsEnum<GroupMemberStatus>();

                            // Get the attribute values updated
                            var gm = new GroupMember();
                            gm.Group = group;
                            gm.GroupId = group.Id;
                            gm.LoadAttributes( rockContext );
                            var selectedGroupAttributes = new List<AttributeCache>();
                            var selectedGroupAttributeValues = new Dictionary<string, string>();
                            foreach ( var attributeCache in gm.Attributes.Select( a => a.Value ) )
                            {
                                Control attributeControl = phAttributes.FindControl( string.Format( "attribute_field_{0}", attributeCache.Id ) );
                                if ( attributeControl != null && ( action == "Add" || SelectedFields.Contains( attributeControl.ClientID ) ) )
                                {
                                    string newValue = attributeCache.FieldType.Field.GetEditValue( attributeControl, attributeCache.QualifierValues );
                                    selectedGroupAttributes.Add( attributeCache );
                                    selectedGroupAttributeValues.Add( attributeCache.Key, newValue );
                                }
                            }

                            if ( action == "Add" )
                            {
                                if ( roleId.HasValue )
                                {
                                    var newGroupMembers = new List<GroupMember>();

                                    var existingIds = existingMembers.Select( m => m.PersonId ).Distinct().ToList();
                                    foreach ( int id in ids.Where( id => !existingIds.Contains( id ) ) )
                                    {
                                        var groupMember = new GroupMember();
                                        groupMember.GroupId = group.Id;
                                        groupMember.GroupRoleId = roleId.Value;
                                        groupMember.GroupMemberStatus = status;
                                        groupMember.PersonId = id;
                                        groupMemberService.Add( groupMember );
                                        newGroupMembers.Add( groupMember );
                                    }

                                    rockContext.SaveChanges();

                                    if ( selectedGroupAttributes.Any() )
                                    {
                                        foreach ( var groupMember in newGroupMembers )
                                        {
                                            foreach ( var attribute in selectedGroupAttributes )
                                            {
                                                Rock.Attribute.Helper.SaveAttributeValue( groupMember, attribute, selectedGroupAttributeValues[attribute.Key], rockContext );
                                            }
                                        }
                                    }
                                }
                            }
                            else // Update
                            {
                                if ( SelectedFields.Contains( ddlGroupRole.ClientID ) && roleId.HasValue )
                                {
                                    foreach ( var member in existingMembers.Where( m => m.GroupRoleId != roleId.Value ) )
                                    {
                                        if ( !existingMembers.Where( m => m.PersonId == member.PersonId && m.GroupRoleId == roleId.Value ).Any() )
                                        {
                                            member.GroupRoleId = roleId.Value;
                                        }
                                    }
                                }

                                if ( SelectedFields.Contains( ddlGroupMemberStatus.ClientID ) )
                                {
                                    foreach ( var member in existingMembers )
                                    {
                                        member.GroupMemberStatus = status;
                                    }
                                }

                                rockContext.SaveChanges();

                                if ( selectedGroupAttributes.Any() )
                                {
                                    foreach ( var groupMember in existingMembers )
                                    {
                                        foreach ( var attribute in selectedGroupAttributes )
                                        {
                                            Rock.Attribute.Helper.SaveAttributeValue( groupMember, attribute, selectedGroupAttributeValues[attribute.Key], rockContext );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                #endregion

                pnlEntry.Visible = false;
                pnlConfirm.Visible = false;

                nbResult.Text = string.Format( "{0} {1} succesfully updated.",
                    ids.Count().ToString( "N0" ), ( ids.Count() > 1 ? "people were" : "person was" ) ); ;
                pnlResult.Visible = true;
            }
        }
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute( IJobExecutionContext context )
        {
            JobDataMap dataMap = context.JobDetail.JobDataMap;
            Guid? groupGuid = dataMap.GetString( "EligibleFollowers" ).AsGuidOrNull();
            Guid? systemEmailGuid = dataMap.GetString( "EmailTemplate" ).AsGuidOrNull();
            int followingEventsSent = 0;

            if ( groupGuid.HasValue && systemEmailGuid.HasValue )
            {
                var exceptionMsgs = new List<string>();

                using ( var rockContext = new RockContext() )
                {
                    var followingService = new FollowingService( rockContext );
                    var followingEventTypeService = new FollowingEventTypeService( rockContext );
                    var followingEventNotificationService = new FollowingEventNotificationService( rockContext );

                    // Get all the active event types
                    var eventTypes = followingEventTypeService
                        .Queryable().AsNoTracking()
                        .Where( e =>
                            e.EntityTypeId.HasValue &&
                            e.IsActive )
                        .OrderBy( e => e.Order )
                        .ToList();

                    // Get the required event types
                    var requiredEventTypes = eventTypes
                        .Where( e => e.IsNoticeRequired )
                        .ToList();

                    // The people who are eligible to get following event notices 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()
                        .ToList();

                    // Get all the subscriptions for the eligible people
                    var eventSubscriptions = new FollowingEventSubscriptionService( rockContext )
                        .Queryable( "PersonAlias" ).AsNoTracking()
                        .Where( f => eligiblePersonIds.Contains( f.PersonAlias.PersonId ) )
                        .ToList();

                    // Dictionaries used to store information that will be used to create notification
                    var personSubscriptions = new Dictionary<int, List<int>>();                     // Key: personId, Value: list of event type ids that person subscribes to
                    var personFollowings = new Dictionary<int, List<int>>();                        // Key: personId, Value: list of following ids that person follows
                    var eventsThatHappened = new Dictionary<int, Dictionary<int, string>>();        // Key: event type id Value: Dictionary of entity id and formatted event notice for the entity

                    //Get the subscriptions for each person
                    foreach ( int personId in eligiblePersonIds )
                    {
                        var personEventTypes = eventSubscriptions
                            .Where( s => s.PersonAlias.PersonId == personId )
                            .Select( s => s.EventType )
                            .ToList();
                        personEventTypes.AddRange( requiredEventTypes );
                        if ( personEventTypes.Any() )
                        {
                            personSubscriptions.AddOrIgnore( personId, personEventTypes
                                .OrderBy( e => e.Order )
                                .ThenBy( e => e.Name )
                                .Select( e => e.Id )
                                .Distinct()
                                .ToList() );
                        }
                    }

                    // Get a distinct list of each entitytype/entity that is being followed by anyone that subscribes to events
                    var followings = followingService
                        .Queryable( "PersonAlias" ).AsNoTracking()
                        .Where( f => personSubscriptions.Keys.Contains( f.PersonAlias.PersonId ) )
                        .ToList();

                    // group the followings by their type
                    var followedEntityIds = new Dictionary<int, List<int>>();
                    foreach ( var followedEntity in followings
                        .Select( f => new
                        {
                            f.EntityTypeId,
                            f.EntityId
                        } )
                        .Distinct() )
                    {
                        followedEntityIds.AddOrIgnore( followedEntity.EntityTypeId, new List<int>() );
                        followedEntityIds[followedEntity.EntityTypeId].Add( followedEntity.EntityId );
                    }

                    // group the followings by the follower
                    foreach ( int personId in personSubscriptions.Select( s => s.Key ) )
                    {
                        var personFollowing = followings
                            .Where( f => f.PersonAlias.PersonId == personId )
                            .Select( f => f.Id )
                            .ToList();

                        personFollowings.Add( personId, personFollowing );
                    }

                    var timestamp = RockDateTime.Now;

                    // foreach followed entitytype
                    foreach ( var keyVal in followedEntityIds )
                    {
                        // Get the entitytype
                        EntityTypeCache itemEntityType = EntityTypeCache.Read( keyVal.Key );
                        if ( itemEntityType.AssemblyName != null )
                        {
                            // get the actual type of what is being followed
                            Type entityType = itemEntityType.GetEntityType();
                            if ( entityType != null )
                            {
                                var dbContext = Reflection.GetDbContextForEntityType( entityType );
                                if ( dbContext != null )
                                {
                                    var serviceInstance = Reflection.GetServiceForEntityType( entityType, dbContext );
                                    if ( serviceInstance != null )
                                    {
                                        MethodInfo qryMethod = serviceInstance.GetType().GetMethod( "Queryable", new Type[] { } );
                                        var entityQry = qryMethod.Invoke( serviceInstance, new object[] { } ) as IQueryable<IEntity>;

                                        // If looking at person alias following, make sure to exclude deceased people
                                        if ( entityType == typeof( Rock.Model.PersonAlias ) )
                                        {
                                            var personAliasQry = entityQry as IQueryable<PersonAlias>;
                                            if ( personAliasQry != null )
                                            {
                                                entityQry = personAliasQry.Where( p => !p.Person.IsDeceased );
                                            }
                                        }

                                        var entityList = entityQry.Where( q => keyVal.Value.Contains( q.Id ) ).ToList();

                                        // If there are any followed entities of this type
                                        if ( entityList.Any() )
                                        {
                                            // Get the active event types for this entity type
                                            foreach ( var eventType in eventTypes.Where( e => e.FollowedEntityTypeId == keyVal.Key ) )
                                            {
                                                try
                                                {
                                                    // Get the component
                                                    var eventComponent = eventType.GetEventComponent();
                                                    if ( eventComponent != null )
                                                    {
                                                        // Get the previous notificatoins for this event type
                                                        var previousNotifications = followingEventNotificationService
                                                            .Queryable()
                                                            .Where( n => n.FollowingEventTypeId == eventType.Id )
                                                            .ToList();

                                                        // check each entity that is followed (by anyone)
                                                        foreach ( IEntity entity in entityList )
                                                        {
                                                            var previousNotification = previousNotifications
                                                                .Where( n => n.EntityId == entity.Id )
                                                                .FirstOrDefault();
                                                            DateTime? lastNotification = previousNotification != null ? previousNotification.LastNotified : (DateTime?)null;

                                                            // if the event happened
                                                            if ( eventComponent.HasEventHappened( eventType, entity, lastNotification ) )
                                                            {
                                                                // Store the event type id and the entity for later processing of notifications
                                                                eventsThatHappened.AddOrIgnore( eventType.Id, new Dictionary<int, string>() );
                                                                eventsThatHappened[eventType.Id].Add( entity.Id, eventComponent.FormatEntityNotification( eventType, entity ) );

                                                                if ( previousNotification == null )
                                                                {
                                                                    previousNotification = new FollowingEventNotification();
                                                                    previousNotification.FollowingEventTypeId = eventType.Id;
                                                                    previousNotification.EntityId = entity.Id;
                                                                    followingEventNotificationService.Add( previousNotification );
                                                                }
                                                                previousNotification.LastNotified = timestamp;
                                                            }
                                                        }

                                                        rockContext.SaveChanges();
                                                    }

                                                    eventType.LastCheckDateTime = RockDateTime.Now;
                                                }

                                                catch ( Exception ex )
                                                {
                                                    exceptionMsgs.Add( string.Format( "An exception occurred calculating events for the '{0}' suggestion type:{1}    {2}", eventType.Name, Environment.NewLine, ex.Messages().AsDelimited( Environment.NewLine + "   " ) ) );
                                                    ExceptionLogService.LogException( ex, System.Web.HttpContext.Current );
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // send notificatons
                    var appRoot = Rock.Web.Cache.GlobalAttributesCache.Read( rockContext ).GetValue( "ExternalApplicationRoot" );

                    var possibleRecipients = new PersonService( rockContext )
                        .Queryable().AsNoTracking()
                        .Where( p => personSubscriptions.Keys.Contains( p.Id ) )
                        .ToList();

                    // Loop through the possible recipients that actually subscribe to events
                    foreach ( var personSubscription in personSubscriptions )
                    {
                        // Get the recipient person
                        int personId = personSubscription.Key;
                        var person = possibleRecipients.Where( p => p.Id == personId ).FirstOrDefault();
                        if ( person != null )
                        {
                            try
                            {

                                // Make sure person is actually following anything
                                if ( personFollowings.ContainsKey( personId ) )
                                {
                                    // Dictionary to store the entities that had an event for each event type
                                    var personEventTypeNotices = new List<FollowingEventTypeNotices>();

                                    // Get the event types that person subscribes to
                                    foreach ( var eventType in eventsThatHappened.Where( e => personSubscription.Value.Contains( e.Key ) ) )
                                    {
                                        // Get the EntityTypeId for this event type
                                        int entityTypeId = eventTypes
                                            .Where( e => e.Id == eventType.Key )
                                            .Select( e => e.FollowedEntityTypeId.Value )
                                            .FirstOrDefault();

                                        // Find all the entities with this event type that the person follows
                                        var personFollowedEntityIds = followings
                                            .Where( f =>
                                                personFollowings[personId].Contains( f.Id ) &&
                                                f.EntityTypeId == entityTypeId )
                                            .Select( f => f.EntityId )
                                            .ToList();

                                        // Get any of those entities that had an event happen
                                        var personFollowedEntities = eventType.Value
                                            .Where( e => personFollowedEntityIds.Contains( e.Key ) )
                                            .ToList();

                                        // If any were found
                                        if ( personFollowedEntities.Any() )
                                        {
                                            // Add the entry
                                            var eventTypeObj = eventTypes.Where( e => e.Id == eventType.Key ).FirstOrDefault();
                                            if ( eventTypeObj != null )
                                            {
                                                personEventTypeNotices.Add( new FollowingEventTypeNotices( eventTypeObj, personFollowedEntities.Select( e => e.Value ).ToList() ) );
                                            }
                                        }
                                    }

                                    // If there are any events for any of the entities that this person follows, send a notification
                                    if ( personEventTypeNotices.Any() )
                                    {
                                        // Send the notice
                                        var recipients = new List<RecipientData>();
                                        var mergeFields = new Dictionary<string, object>();
                                        mergeFields.Add( "Person", person );
                                        mergeFields.Add( "EventTypes", personEventTypeNotices.OrderBy( e => e.EventType.Order ).ToList() );
                                        recipients.Add( new RecipientData( person.Email, mergeFields ) );
                                        Email.Send( systemEmailGuid.Value, recipients, appRoot );
                                        followingEventsSent++;
                                    }
                                }
                            }
                            catch ( Exception ex )
                            {
                                exceptionMsgs.Add( string.Format( "An exception occurred sending event notice to '{0}':{1}    {2}", person.FullName, Environment.NewLine, ex.Messages().AsDelimited( Environment.NewLine + "   " ) ) );
                                ExceptionLogService.LogException( ex, System.Web.HttpContext.Current );
                            }
                        }
                    }
                }

                context.Result = string.Format( "{0} following events emails sent", followingEventsSent );

                if ( exceptionMsgs.Any() )
                {
                    throw new Exception( "One or more exceptions occurred calculating following events..." + Environment.NewLine + exceptionMsgs.AsDelimited( Environment.NewLine ) );
                }
            }
        }
        /// <summary>
        /// Handles the Click event of the lbUnfollow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        void lbUnfollow_Click( object sender, EventArgs e )
        {
            var itemsSelected = new List<int>();
            gFollowings.SelectedKeys.ToList().ForEach( f => itemsSelected.Add( f.ToString().AsInteger() ) );

            if ( itemsSelected.Any() )
            {
                var rockContext = new RockContext();
                var personAliasService = new PersonAliasService( rockContext );
                var followingService = new FollowingService( rockContext );

                var paQry = personAliasService.Queryable()
                    .Where( p => itemsSelected.Contains( p.PersonId ) )
                    .Select( p => p.Id );

                int personAliasEntityTypeId = EntityTypeCache.Read( "Rock.Model.PersonAlias" ).Id;
                foreach ( var following in followingService.Queryable()
                    .Where( f =>
                        f.EntityTypeId == personAliasEntityTypeId &&
                        paQry.Contains( f.EntityId ) &&
                        f.PersonAliasId == CurrentPersonAlias.Id ) )
                {
                    followingService.Delete( following );
                }

                rockContext.SaveChanges();
            }

            BindGrid();
        }
Esempio n. 6
0
        /// <summary>
        /// Gets the suggestions.
        /// </summary>
        /// <param name="followingSuggestionType">Type of the following suggestion.</param>
        /// <param name="followerPersonIds">The follower person ids.</param>
        /// <returns></returns>
        public override List<PersonEntitySuggestion> GetSuggestions( FollowingSuggestionType followingSuggestionType, List<int> followerPersonIds )
        {
            var suggestions = new List<PersonEntitySuggestion>();
            var personAliasEntityType = EntityTypeCache.Read( typeof( Rock.Model.PersonAlias ) );

            bool isAutoFollow = GetAttributeValue( followingSuggestionType, "AutoFollow" ).AsBoolean();

            // Get the grouptype guid
            Guid? groupTypeGuid = GetAttributeValue( followingSuggestionType, "GroupType" ).AsGuidOrNull();
            if ( groupTypeGuid.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    var groupMemberService = new GroupMemberService( rockContext );
                    var personAliasService = new PersonAliasService( rockContext );

                    // Get all the groupmember records for any follower and the selected group type
                    var followers = groupMemberService.Queryable().AsNoTracking()
                        .Where( m =>
                            m.GroupMemberStatus == GroupMemberStatus.Active &&
                            m.Group != null &&
                            m.Group.IsActive &&
                            m.Group.GroupType.Guid.Equals( groupTypeGuid.Value ) &&
                            followerPersonIds.Contains( m.PersonId ) );

                    // If a specific group or security role was specifed, limit groupmembers to only those of the selected group
                    Guid? groupGuid = GetAttributeValue( followingSuggestionType, "Group" ).AsGuidOrNull();
                    if ( !groupGuid.HasValue )
                    {
                        groupGuid = GetAttributeValue( followingSuggestionType, "SecurityRole" ).AsGuidOrNull();
                    }
                    if ( groupGuid.HasValue )
                    {
                        followers = followers.Where( m => m.Group.Guid.Equals( groupGuid.Value ) );
                    }

                    // If a specific role for the follower was specified, limit groupmembers to only those with the selected role
                    Guid? followerRoleGuid = GetAttributeValue( followingSuggestionType, "FollowerGroupType" ).AsGuidOrNull();
                    if ( followerRoleGuid.HasValue )
                    {
                        followers = followers.Where( m => m.GroupRole.Guid.Equals( followerRoleGuid.Value ) );
                    }

                    // Run the query to get all the groups that follower is a member of with selected filters
                    var followerPersonGroup = followers
                        .Select( f => new
                        {
                            f.PersonId,
                            f.GroupId
                        } )
                        .ToList();

                    // Get a unique list of any of the groups that followers belong to
                    var followedGroupIds = followerPersonGroup
                        .Select( f => f.GroupId )
                        .Distinct()
                        .ToList();

                    // Start building query to get the people to follow from any group that contains a follower
                    var followed = groupMemberService
                        .Queryable().AsNoTracking()
                        .Where( m => followedGroupIds.Contains( m.GroupId ) );

                    // If a specific role for the people being followed was specified, limit the query to only those with the selected role
                    Guid? followedRoleGuid = GetAttributeValue( followingSuggestionType, "FollowedGroupType" ).AsGuidOrNull();
                    if ( followedRoleGuid.HasValue )
                    {
                        followed = followed.Where( m => m.GroupRole.Guid.Equals( followedRoleGuid.Value ) );
                    }

                    // Get all the people in any of the groups that contain a follower
                    var followedPersonGroup = followed
                        .Select( f => new
                        {
                            f.PersonId,
                            f.GroupId
                        } )
                        .ToList();

                    // Get distinct list of people
                    var followedPersonIds = followedPersonGroup
                        .Select( f => f.PersonId )
                        .Distinct()
                        .ToList();

                    // Build a dictionary of the personid->personaliasid
                    var personAliasIds = new Dictionary<int, int>();
                    personAliasService.Queryable().AsNoTracking()
                        .Where( a =>
                            followedPersonIds.Contains( a.PersonId ) &&
                            a.PersonId == a.AliasPersonId )
                        .ToList()
                        .ForEach( a => personAliasIds.AddOrIgnore( a.PersonId, a.Id ) );

                    // Loop through each follower/group combination
                    foreach ( var followedGroup in followerPersonGroup )
                    {
                        // Loop through the other people in that group
                        foreach ( int followedPersonId in followedPersonGroup
                            .Where( f =>
                                f.GroupId == followedGroup.GroupId &&
                                f.PersonId != followedGroup.PersonId )
                            .Select( f => f.PersonId ) )
                        {
                            // If the person has a valid personalias id
                            if ( personAliasIds.ContainsKey( followedPersonId ) )
                            {
                                if ( !isAutoFollow )
                                {
                                    // add them to the list of suggestions
                                    suggestions.Add( new PersonEntitySuggestion( followedGroup.PersonId, personAliasIds[followedPersonId] ) );
                                }
                                else
                                {
                                    // auto-add the follow

                                    var followingService = new FollowingService( rockContext );

                                    int followerPersonAliasId = personAliasIds[followedGroup.PersonId];
                                    int followeePersonAliasId = personAliasIds[followedPersonId];

                                    // if person is not already following the person
                                    bool isFollowing = followingService.Queryable().Where( f =>
                                                            f.EntityTypeId == personAliasEntityType.Id
                                                            && f.EntityId == followeePersonAliasId
                                                            && f.PersonAliasId == followerPersonAliasId ).Any();
                                    if ( !isFollowing )
                                    {
                                        var following = new Following();
                                        following.EntityTypeId = personAliasEntityType.Id;
                                        following.EntityId = personAliasIds[followedPersonId];
                                        following.PersonAliasId = personAliasIds[followedGroup.PersonId];
                                        followingService.Add( following );
                                        rockContext.SaveChanges();
                                    }
                                }
                            }
                        }

                    }
                }
            }

            return suggestions;
        }
Esempio n. 7
0
        private void SetFollowing()
        {
            var personAliasEntityType = EntityTypeCache.Read( "Rock.Model.PersonAlias" );
            if ( Person != null && CurrentPersonId.HasValue && CurrentPersonAlias != null && personAliasEntityType != null )
            {
                using ( var rockContext = new RockContext() )
                {
                    var personAliasService = new PersonAliasService( rockContext );
                    var followingService = new FollowingService( rockContext );

                    var paQry = personAliasService.Queryable()
                        .Where( p => p.PersonId == Person.Id )
                        .Select( p => p.Id );

                    if ( followingService.Queryable()
                        .Where( f =>
                            f.EntityTypeId == personAliasEntityType.Id &&
                            paQry.Contains( f.EntityId ) &&
                            f.PersonAlias.PersonId == CurrentPersonId )
                        .Any() )
                    {
                        pnlFollow.AddCssClass( "following" );
                    }
                    else
                    {
                        pnlFollow.RemoveCssClass( "following" );
                    }
                }

                string script = string.Format( @"
            $('.following-status').click(function () {{
            var $followingDiv = $(this);
            if ($followingDiv.hasClass('following')) {{
                $.ajax({{
                    type: 'DELETE',
                    url: Rock.settings.get('baseUrl') + 'api/followings/{0}/{1}/{2}',
                    success: function(data, status, xhr){{
                        $followingDiv.removeClass('following');
                    }},
                }});
            }} else {{
                var following = {{ EntityTypeId:{0}, EntityId:{1}, PersonAliasId:{3} }};
                $.ajax({{
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(following),
                    url: Rock.settings.get('baseUrl') + 'api/followings',
                    statusCode: {{
                        201: function () {{
                            $followingDiv.addClass('following');
                        }}
                    }}
                }});
            }}
            }});
            ", personAliasEntityType.Id, Person.PrimaryAliasId, CurrentPersonId.Value, CurrentPersonAlias.Id );
                ScriptManager.RegisterStartupScript( lImage, lImage.GetType(), "following", script, true );
            }
        }
Esempio n. 8
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. 9
0
        /// <summary>
        /// Handles the Click event of the btnComplete control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void btnComplete_Click( object sender, EventArgs e )
        {
            if ( Page.IsValid )
            {
                var rockContext = new RockContext();
                var personService = new PersonService( rockContext );
                var ids = Individuals.Select( i => i.PersonId ).ToList();

                var personEntityType = EntityTypeCache.Read( "Rock.Model.Person" );
                if ( personEntityType != null )
                {
                    int personEntityTypeId = personEntityType.Id;

                    var people = personService.Queryable().Where( p => ids.Contains( p.Id ) ).ToList();

                    #region Individual Details Updates

                    int? newTitleId = ddlTitle.SelectedValueAsInt();
                    int? newSuffixId = ddlSuffix.SelectedValueAsInt();
                    int? newConnectionStatusId = ddlStatus.SelectedValueAsInt();
                    int? newRecordStatusId = ddlRecordStatus.SelectedValueAsInt();
                    int? newInactiveReasonId = ddlInactiveReason.SelectedValueAsInt();
                    string newInactiveReasonNote = tbInactiveReasonNote.Text;
                    Gender? newGender = ddlGender.SelectedValue.ConvertToEnumOrNull<Gender>();

                    int? newMaritalStatusId = ddlMaritalStatus.SelectedValueAsInt();

                    DateTime? newGraduationDate = null;
                    if ( ypGraduation.SelectedYear.HasValue )
                    {
                        newGraduationDate = new DateTime( ypGraduation.SelectedYear.Value, _gradeTransitionDate.Month, _gradeTransitionDate.Day );
                    }

                    int? newCampusId = cpCampus.SelectedCampusId;
                    bool? newEmailActive = null;
                    if ( !string.IsNullOrWhiteSpace( ddlIsEmailActive.SelectedValue ) )
                    {
                        newEmailActive = ddlIsEmailActive.SelectedValue == "Active";
                    }
                    EmailPreference? newEmailPreference = ddlEmailPreference.SelectedValue.ConvertToEnumOrNull<EmailPreference>();
                    string newEmailNote = tbEmailNote.Text;
                    bool? newFollow = null;
                    if ( !string.IsNullOrWhiteSpace( ddlFollow.SelectedValue ) )
                    {
                        newFollow = ddlFollow.SelectedValue == "Add";
                    }
                    int? newReviewReason = ddlReviewReason.SelectedValueAsInt();
                    string newSystemNote = tbSystemNote.Text;
                    string newReviewReasonNote = tbReviewReasonNote.Text;

                    var allChanges = new Dictionary<int, List<string>>();

                    foreach ( var person in people )
                    {
                        var changes = new List<string>();
                        allChanges.Add( person.Id, changes );

                        if ( newTitleId.HasValue )
                        {
                            History.EvaluateChange( changes, "Title", DefinedValueCache.GetName( person.TitleValueId ), DefinedValueCache.GetName( newTitleId ) );
                            person.TitleValueId = newTitleId;
                        }

                        if ( newSuffixId.HasValue )
                        {
                            History.EvaluateChange( changes, "Suffix", DefinedValueCache.GetName( person.SuffixValueId ), DefinedValueCache.GetName( newSuffixId ) );
                            person.SuffixValueId = newSuffixId;
                        }

                        if ( newConnectionStatusId.HasValue )
                        {
                            History.EvaluateChange( changes, "Connection Status", DefinedValueCache.GetName( person.ConnectionStatusValueId ), DefinedValueCache.GetName( newConnectionStatusId ) );
                            person.ConnectionStatusValueId = newConnectionStatusId;
                        }

                        if ( newRecordStatusId.HasValue )
                        {
                            History.EvaluateChange( changes, "Record Status", DefinedValueCache.GetName( person.RecordStatusValueId ), DefinedValueCache.GetName( newRecordStatusId ) );
                            person.RecordStatusValueId = newRecordStatusId;
                        }

                        if ( newInactiveReasonId.HasValue )
                        {
                            History.EvaluateChange( changes, "Inactive Reason", DefinedValueCache.GetName( person.RecordStatusReasonValueId ), DefinedValueCache.GetName( newInactiveReasonId ) );
                            person.RecordStatusReasonValueId = newInactiveReasonId;
                        }

                        if ( !string.IsNullOrWhiteSpace( newInactiveReasonNote ) )
                        {
                            History.EvaluateChange( changes, "Inactive Reason Note", person.InactiveReasonNote, newInactiveReasonNote );
                            person.InactiveReasonNote = newInactiveReasonNote;
                        }

                        if ( newGender.HasValue )
                        {
                            History.EvaluateChange( changes, "Gender", person.Gender, newGender.Value );
                            person.Gender = newGender.Value;
                        }

                        if ( newMaritalStatusId.HasValue )
                        {
                            History.EvaluateChange( changes, "Marital Status", DefinedValueCache.GetName( person.MaritalStatusValueId ), DefinedValueCache.GetName( newMaritalStatusId ) );
                            person.MaritalStatusValueId = newMaritalStatusId;
                        }

                        if ( newGraduationDate.HasValue )
                        {
                            History.EvaluateChange( changes, "Graduation Date", person.GraduationDate, newGraduationDate );
                            person.GraduationDate = newGraduationDate;
                        }

                        if ( newEmailActive.HasValue )
                        {
                            History.EvaluateChange( changes, "Email Is Active", person.IsEmailActive ?? true, newEmailActive.Value );
                            person.IsEmailActive = newEmailActive;
                        }

                        if ( newEmailPreference.HasValue )
                        {
                            History.EvaluateChange( changes, "Email Preference", person.EmailPreference, newEmailPreference );
                            person.EmailPreference = newEmailPreference.Value;
                        }

                        if ( !string.IsNullOrWhiteSpace( newEmailNote ) )
                        {
                            History.EvaluateChange( changes, "Email Note", person.EmailNote, newEmailNote );
                            person.EmailNote = newEmailNote;
                        }

                        if ( !string.IsNullOrWhiteSpace( newSystemNote ) )
                        {
                            History.EvaluateChange( changes, "System Note", person.SystemNote, newSystemNote );
                            person.SystemNote = newSystemNote;
                        }

                        if ( newReviewReason.HasValue )
                        {
                            History.EvaluateChange( changes, "Review Reason", DefinedValueCache.GetName( person.ReviewReasonValueId ), DefinedValueCache.GetName( newReviewReason ) );
                            person.ReviewReasonValueId = newReviewReason;
                        }

                        if ( !string.IsNullOrWhiteSpace( newReviewReasonNote ) )
                        {
                            History.EvaluateChange( changes, "Review Reason Note", person.ReviewReasonNote, newReviewReasonNote );
                            person.ReviewReasonNote = newReviewReasonNote;
                        }
                    }

                    // Update following
                    if ( newFollow.HasValue && CurrentPersonAlias != null )
                    {
                        var followingService = new FollowingService( rockContext );
                        if ( newFollow.Value )
                        {
                            var alreadyFollingIds = followingService.Queryable()
                                .Where( f =>
                                    f.EntityTypeId == personEntityTypeId &&
                                    f.PersonAlias.Id == CurrentPersonAlias.Id )
                                .Select( f => f.EntityId )
                                .Distinct()
                                .ToList();
                            foreach ( int id in ids.Where( id => !alreadyFollingIds.Contains( id ) ) )
                            {
                                var following = new Following
                                {
                                    EntityTypeId = personEntityTypeId,
                                    EntityId = id,
                                    PersonAliasId = CurrentPersonAlias.Id
                                };
                                followingService.Add( following );
                            }
                        }
                        else
                        {
                            foreach ( var following in followingService.Queryable()
                                .Where( f =>
                                    f.EntityTypeId == personEntityTypeId &&
                                    ids.Contains( f.EntityId ) &&
                                    f.PersonAlias.Id == CurrentPersonAlias.Id ) )
                            {
                                followingService.Delete( following );
                            }
                        }
                    }

                    rockContext.SaveChanges();

                    #endregion

                    #region Attributes

                    var selectedCategories = new List<CategoryCache>();
                    foreach ( string categoryGuid in GetAttributeValue( "AttributeCategories" ).SplitDelimitedValues() )
                    {
                        var category = CategoryCache.Read( categoryGuid.AsGuid(), rockContext );
                        if ( category != null )
                        {
                            selectedCategories.Add( category );
                        }
                    }

                    var attributes = new List<AttributeCache>();
                    var attributeValues = new Dictionary<int, string>();

                    int categoryIndex = 0;
                    foreach ( var category in selectedCategories.OrderBy( c => c.Name ) )
                    {
                        PanelWidget pw = null;
                        string controlId = "pwAttributes_" + category.Id.ToString();
                        if ( categoryIndex % 2 == 0 )
                        {
                            pw = phAttributesCol1.FindControl( controlId ) as PanelWidget;
                        }
                        else
                        {
                            pw = phAttributesCol2.FindControl( controlId) as PanelWidget;
                        }
                        categoryIndex++;

                        if ( pw != null )
                        {
                            var orderedAttributeList = new AttributeService( rockContext ).GetByCategoryId( category.Id )
                                .OrderBy( a => a.Order ).ThenBy( a => a.Name );
                            foreach ( var attribute in orderedAttributeList )
                            {
                                if ( attribute.IsAuthorized( Authorization.EDIT, CurrentPerson ) )
                                {
                                    var attributeCache = AttributeCache.Read( attribute.Id );

                                    Control attributeControl = pw.FindControl( string.Format( "attribute_field_{0}", attribute.Id ) );
                                    if ( attributeControl != null )
                                    {
                                        string newValue = attributeCache.FieldType.Field.GetEditValue( attributeControl, attributeCache.QualifierValues );
                                        if (!string.IsNullOrWhiteSpace(newValue))
                                        {
                                            attributes.Add( attributeCache);
                                            attributeValues.Add( attributeCache.Id, newValue );
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (attributes.Any())
                    {
                        foreach ( var person in people )
                        {
                            person.LoadAttributes();
                            foreach ( var attribute in attributes )
                            {
                                string originalValue = person.GetAttributeValue( attribute.Key );
                                string newValue = attributeValues[attribute.Id];
                                if ( ( originalValue ?? string.Empty ).Trim() != ( newValue ?? string.Empty ).Trim() )
                                {
                                    Rock.Attribute.Helper.SaveAttributeValue( person, attribute, newValue, rockContext );

                                    string formattedOriginalValue = string.Empty;
                                    if ( !string.IsNullOrWhiteSpace( originalValue ) )
                                    {
                                        formattedOriginalValue = attribute.FieldType.Field.FormatValue( null, originalValue, attribute.QualifierValues, false );
                                    }

                                    string formattedNewValue = string.Empty;
                                    if ( !string.IsNullOrWhiteSpace( newValue ) )
                                    {
                                        formattedNewValue = attribute.FieldType.Field.FormatValue( null, newValue, attribute.QualifierValues, false );
                                    }

                                    History.EvaluateChange( allChanges[person.Id], attribute.Name, formattedOriginalValue, formattedNewValue );
                                }
                            }
                        }
                    }

                    // Create the history records
                    foreach ( var changes in allChanges )
                    {
                        if ( changes.Value.Any() )
                        {
                            HistoryService.AddChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                changes.Key, changes.Value );
                        }
                    }
                    rockContext.SaveChanges();

                    #endregion

                    #region Add Note

                    if ( !string.IsNullOrWhiteSpace( tbNote.Text ) && CurrentPerson != null )
                    {
                        string text = tbNote.Text;
                        bool isAlert = cbIsAlert.Checked;
                        bool isPrivate = cbIsPrivate.Checked;

                        var noteTypeService = new NoteTypeService( rockContext );
                        var noteService = new NoteService( rockContext );

                        string noteTypeName = GetAttributeValue( "NoteType" );
                        var noteType = noteTypeService.Get( personEntityTypeId, noteTypeName );

                        if ( noteType != null )
                        {
                            var notes = new List<Note>();

                            foreach ( int id in ids )
                            {
                                var note = new Note();
                                note.IsSystem = false;
                                note.EntityId = id;
                                note.Caption = isPrivate ? "You - Personal Note" : string.Empty;
                                note.Text = tbNote.Text;
                                note.IsAlert = cbIsAlert.Checked;
                                note.NoteType = noteType;

                                notes.Add( note );
                                noteService.Add( note );
                            }

                            rockContext.WrapTransaction( () =>
                            {
                                rockContext.SaveChanges();
                                foreach( var note in notes)
                                {
                                    note.AllowPerson( Authorization.EDIT, CurrentPerson, rockContext );
                                    if ( isPrivate)
                                    {
                                        note.MakePrivate( Authorization.VIEW, CurrentPerson, rockContext );
                                    }
                                }
                            } );

                        }
                    }

                    #endregion

                }

                string message = string.Format("{0} {1} succesfully updated!",
                    ids.Count().ToString("N0"), (ids.Count() > 1 ? "people were" : "person was") );
                ShowResult( message );
            }
        }
        /// <summary>
        /// Handles the Click event of the lbUnfollow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        void lbFollow_Click( object sender, EventArgs e )
        {
            // Get the suggestion ids that were selected
            var itemsSelected = new List<int>();
            gSuggestions.SelectedKeys.ToList().ForEach( f => itemsSelected.Add( f.ToString().AsInteger() ) );

            // Get the personAlias entity type
            var personAliasEntityType = EntityTypeCache.Read( typeof( Rock.Model.PersonAlias ));

            // If we have a valid current person and items were selected
            if ( personAliasEntityType != null && CurrentPersonAliasId.HasValue && itemsSelected.Any() )
            {
                using ( var rockContext = new RockContext() )
                {

                    // Get all the person alias id's that were selected
                    var followingSuggestedService = new FollowingSuggestedService( rockContext );
                    var selectedPersonAliasIds = followingSuggestedService
                        .Queryable()
                        .Where( f => itemsSelected.Contains( f.Id ) )
                        .Select( f => f.EntityId )
                        .Distinct()
                        .ToList();

                    // Find any of the selected person alias ids that current person is already following
                    var followingService = new FollowingService( rockContext );
                    var alreadyFollowing = followingService
                        .Queryable()
                        .Where( f =>
                            f.EntityTypeId == personAliasEntityType.Id &&
                            f.PersonAliasId == CurrentPersonAliasId.Value &&
                            selectedPersonAliasIds.Contains( f.EntityId ) )
                        .Select( f => f.EntityId )
                        .Distinct()
                        .ToList();

                    // For each selected person alias id that the current person is not already following
                    foreach ( var personAliasId in selectedPersonAliasIds.Where( p => !alreadyFollowing.Contains( p ) ) )
                    {
                        // Add a following record
                        var following = new Following();
                        following.EntityTypeId = personAliasEntityType.Id;
                        following.EntityId = personAliasId;
                        following.PersonAliasId = CurrentPersonAliasId.Value;
                        followingService.Add( following );
                    }

                    rockContext.SaveChanges();
                }
            }

            BindGrid();
        }