Пример #1
0
        /// <summary>
        /// Handles the Click event of the btnSaveRequestNote 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 btnSaveRequestNote_Click( object sender, EventArgs e )
        {
            int? setId = PageParameter( "Set" ).AsIntegerOrNull();
            if ( setId.HasValue )
            {
                var rockContext = new RockContext();
                var entitySet = new EntitySetService( rockContext ).Get( setId.Value );
                entitySet.Note = tbEntitySetNote.Text;
                rockContext.SaveChanges();

                nbNoteSavedSuccess.Visible = true;
                tbEntitySetNote.Visible = false;
                btnSaveRequestNote.Visible = false;
            }
        }
        /// <summary>
        /// Handles the Delete event of the gList 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 gList_Delete( object sender, RowEventArgs e )
        {
            var rockContext = new RockContext();
            var entitySetService = new EntitySetService( rockContext );
            EntitySet entitySet = entitySetService.Get( e.RowKeyId );
            if ( entitySet != null )
            {
                string errorMessage;
                if ( !entitySetService.CanDelete( entitySet, out errorMessage ) )
                {
                    mdGridWarning.Show( errorMessage, ModalAlertType.Information );
                    return;
                }

                // mark it as expired and RockCleanup will delete it later
                entitySet.ExpireDateTime = RockDateTime.Now.AddMinutes( -1 );
                entitySet.EntitySetPurposeValueId = null;
                rockContext.SaveChanges();
            }

            BindGrid();
        }
Пример #3
0
        /// <summary>
        /// creates or updates the entity set on the basis of campaign connection configuration, and returns the Id of the entitySetId
        /// </summary>
        /// <param name="campaignConfiguration">The campaign configuration.</param>
        /// <returns></returns>
        public static int GetEntitySet(CampaignItem campaignConfiguration)
        {
            var rockContext = new RockContext();

            var connectionOpportunityService = new ConnectionOpportunityService(rockContext);
            var connectionRequestService     = new ConnectionRequestService(rockContext);
            var entitySetService             = new Rock.Model.EntitySetService(rockContext);

            var connectionOpportunity = connectionOpportunityService.Get(campaignConfiguration.OpportunityGuid);

            // list of person on the basis of Dataview result and optout group.
            var filteredPersonIds = GetFilteredPersonIds(campaignConfiguration, rockContext);

            // get the last connection datetime.
            var lastConnectionDateTime = RockDateTime.Now.AddDays(-campaignConfiguration.DaysBetweenConnection);

            // if DaysBetweenConnection is 0 then check for connection request for any time period.
            if (campaignConfiguration.DaysBetweenConnection == default(int))
            {
                lastConnectionDateTime = DateTime.MinValue;
            }

            // list of person that has active connection request OR has connection closed in the past number of days between connection.
            var excludedPersonIds = connectionRequestService
                                    .Queryable()
                                    .Where(a =>
                                           a.ConnectionOpportunityId == connectionOpportunity.Id && (
                                               a.ConnectionState == ConnectionState.Active ||
                                               a.ConnectionState == ConnectionState.FutureFollowUp ||
                                               ((a.ConnectionState == ConnectionState.Connected || a.ConnectionState == ConnectionState.Inactive) && a.ModifiedDateTime > lastConnectionDateTime)))
                                    .Select(a => a.PersonAlias.PersonId)
                                    .ToList();

            // filtered list of person removing all the personIds found in excludedPersonIds List
            filteredPersonIds = filteredPersonIds.Where(a => !excludedPersonIds.Contains(a)).ToList();

            // get the ordered list of personIds based on the oldest previous connection request and connection opportunity

            /* 2020-05-06 MDP
             * If there are many filteredPersonIds, we'll get a SQL Exception, so let's get *all* the Connected connection Requests first,
             * and then use C# to filter.
             */

            var orderedLastCompletedRequestForPerson = connectionRequestService
                                                       .Queryable()
                                                       .Where(a => a.ConnectionOpportunityId == connectionOpportunity.Id &&
                                                              a.ConnectionState == ConnectionState.Connected)
                                                       .GroupBy(a => a.PersonAlias.PersonId)
                                                       .Select(a => new
            {
                PersonId = a.Key,
                LastConnectionDateTime = a.OrderByDescending(b => b.ModifiedDateTime).Select(b => b.ModifiedDateTime).FirstOrDefault()
            })
                                                       .OrderBy(a => a.LastConnectionDateTime)
                                                       .Select(a => a.PersonId).ToList();

            // Use C# to filter persons so we can avoid a SQL Exception
            orderedLastCompletedRequestForPerson = orderedLastCompletedRequestForPerson.Where(a => filteredPersonIds.Contains(a)).ToList();

            var random = new Random();

            //// get the final ordered list of personIds based on the oldest previous connection request and
            //// connection opportunity otherwise order randomly for the person who don't have any previous connection request.
            var orderedPersonIds = filteredPersonIds
                                   .OrderBy(a =>
            {
                var index = orderedLastCompletedRequestForPerson.IndexOf(a);
                if (index == -1)
                {
                    return(random.Next(orderedLastCompletedRequestForPerson.Count, int.MaxValue));
                }
                else
                {
                    return(index);
                }
            }).ToList();

            EntitySet entitySet = null;

            if (campaignConfiguration.EntitySetId != default(int))
            {
                entitySet = entitySetService.Get(campaignConfiguration.EntitySetId);
            }

            List <Rock.Model.EntitySetItem> entitySetItems = new List <Rock.Model.EntitySetItem>();
            var personEntityTypeId = EntityTypeCache.Get <Rock.Model.Person>().Id;

            if (entitySet == null || entitySet.EntityTypeId != personEntityTypeId)
            {
                entitySet = new Rock.Model.EntitySet();
                entitySet.EntityTypeId   = personEntityTypeId;
                entitySet.ExpireDateTime = null;
                entitySetService.Add(entitySet);
            }
            else
            {
                var entitySetItemQry = new EntitySetItemService(rockContext)
                                       .Queryable().AsNoTracking()
                                       .Where(i => i.EntitySetId == entitySet.Id);
                rockContext.BulkDelete(entitySetItemQry);
            }

            // Update the EntitySet name
            entitySet.Name = campaignConfiguration.Name;

            var orderIndex = 0;

            foreach (var personId in orderedPersonIds)
            {
                try
                {
                    var item = new Rock.Model.EntitySetItem();
                    item.Order    = orderIndex++;
                    item.EntityId = personId;
                    entitySetItems.Add(item);
                }
                catch
                {
                    // ignore
                }
            }

            rockContext.SaveChanges();
            entitySetItems.ForEach(a =>
            {
                a.EntitySetId = entitySet.Id;
            });

            rockContext.BulkInsert(entitySetItems);

            return(entitySet.Id);
        }
        /// <summary>
        /// Gets the merge object list for the current EntitySet
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="fetchCount">The fetch count.</param>
        /// <returns></returns>
        private List<object> GetMergeObjectList( RockContext rockContext, int? fetchCount = null )
        {
            int entitySetId = hfEntitySetId.Value.AsInteger();
            var entitySetService = new EntitySetService( rockContext );
            var entitySet = entitySetService.Get( entitySetId );
            Dictionary<int, object> mergeObjectsDictionary = new Dictionary<int, object>();

            // If this EntitySet contains IEntity Items, add those first
            if ( entitySet.EntityTypeId.HasValue )
            {
                var qryEntity = entitySetService.GetEntityQuery( entitySetId );

                if ( fetchCount.HasValue )
                {
                    qryEntity = qryEntity.Take( fetchCount.Value );
                }

                var entityTypeCache = EntityTypeCache.Read( entitySet.EntityTypeId.Value );
                bool isPersonEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.PERSON.AsGuid();
                bool isGroupMemberEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.GROUP_MEMBER.AsGuid();
                bool combineFamilyMembers = cbCombineFamilyMembers.Visible && cbCombineFamilyMembers.Checked;

                if ( ( isGroupMemberEntityType || isPersonEntityType ) && combineFamilyMembers )
                {
                    IQueryable<IEntity> qryPersons;
                    if ( isGroupMemberEntityType )
                    {
                        qryPersons = qryEntity.OfType<GroupMember>().Select( a => a.Person ).Distinct();
                    }
                    else
                    {
                        qryPersons = qryEntity;
                    }

                    Guid familyGroupType = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
                    var qryFamilyGroupMembers = new GroupMemberService( rockContext ).Queryable()
                        .Where( a => a.Group.GroupType.Guid == familyGroupType )
                        .Where( a => qryPersons.Any( aa => aa.Id == a.PersonId ) );

                    var qryCombined = qryFamilyGroupMembers.Join(
                        qryPersons,
                        m => m.PersonId,
                        p => p.Id,
                        ( m, p ) => new { GroupMember = m, Person = p } )
                        .GroupBy( a => a.GroupMember.GroupId )
                        .Select( x => new
                        {
                            GroupId = x.Key,
                            Persons = x.Select( xx => xx.Person ).Distinct()
                        } );

                    foreach ( var combinedFamilyItem in qryCombined )
                    {
                        object mergeObject;

                        string commaPersonIds = combinedFamilyItem.Persons.Select( a => a.Id ).Distinct().ToList().AsDelimited( "," );

                        var primaryGroupPerson = combinedFamilyItem.Persons.FirstOrDefault() as Person;

                        if ( mergeObjectsDictionary.ContainsKey( primaryGroupPerson.Id ) )
                        {
                            foreach ( var person in combinedFamilyItem.Persons )
                            {
                                if ( !mergeObjectsDictionary.ContainsKey( person.Id ) )
                                {
                                    primaryGroupPerson = person as Person;
                                    break;
                                }
                            }
                        }

                        // if we are combining from a GroupMemberEntityType list add the GroupMember attributes of the primary person in the combined list
                        if ( isGroupMemberEntityType )
                        {
                            var groupMember = qryEntity.OfType<GroupMember>().Where( a => a.PersonId == primaryGroupPerson.Id ).FirstOrDefault();
                            primaryGroupPerson.AdditionalLavaFields = primaryGroupPerson.AdditionalLavaFields ?? new Dictionary<string, object>();
                            if ( groupMember != null )
                            {
                                primaryGroupPerson.AdditionalLavaFields.Add( "GroupMember", groupMember );
                            }
                        }

                        if ( combinedFamilyItem.Persons.Count() > 1 )
                        {
                            var combinedPerson = primaryGroupPerson.ToJson().FromJsonOrNull<MergeTemplateCombinedPerson>();

                            var familyTitle = RockUdfHelper.ufnCrm_GetFamilyTitle( rockContext, null, combinedFamilyItem.GroupId, commaPersonIds, true );
                            combinedPerson.FullName = familyTitle;

                            var firstNameList = combinedFamilyItem.Persons.Select( a => ( a as Person ).FirstName ).ToList();
                            var nickNameList = combinedFamilyItem.Persons.Select( a => ( a as Person ).NickName ).ToList();

                            combinedPerson.FirstName = firstNameList.AsDelimited( ", ", " & " );
                            combinedPerson.NickName = nickNameList.AsDelimited( ", ", " & " );
                            combinedPerson.LastName = primaryGroupPerson.LastName;
                            combinedPerson.SuffixValueId = null;
                            combinedPerson.SuffixValue = null;
                            mergeObject = combinedPerson;
                        }
                        else
                        {
                            mergeObject = primaryGroupPerson;
                        }

                        mergeObjectsDictionary.AddOrIgnore( primaryGroupPerson.Id, mergeObject );
                    }
                }
                else if ( isGroupMemberEntityType )
                {
                    foreach ( var groupMember in qryEntity.AsNoTracking().OfType<GroupMember>() )
                    {
                        var person = groupMember.Person;
                        person.AdditionalLavaFields = new Dictionary<string, object>();
                        person.AdditionalLavaFields.Add( "GroupMember", groupMember );
                        mergeObjectsDictionary.AddOrIgnore( groupMember.PersonId, person );
                    }
                }
                else
                {
                    foreach ( var item in qryEntity.AsNoTracking() )
                    {
                        mergeObjectsDictionary.AddOrIgnore( item.Id, item );
                    }
                }
            }

            var entitySetItemService = new EntitySetItemService( rockContext );
            string[] emptyJson = new string[] { string.Empty, "{}" };
            var entitySetItemMergeValuesQry = entitySetItemService.GetByEntitySetId( entitySetId, true ).Where( a => !emptyJson.Contains( a.AdditionalMergeValuesJson ) );

            if ( fetchCount.HasValue )
            {
                entitySetItemMergeValuesQry = entitySetItemMergeValuesQry.Take( fetchCount.Value );
            }

            // the entityId to use for NonEntity objects
            int nonEntityId = 1;

            // now, add the additional MergeValues regardless of if the EntitySet contains IEntity items or just Non-IEntity items
            foreach ( var additionalMergeValuesItem in entitySetItemMergeValuesQry.AsNoTracking() )
            {
                object mergeObject;
                int entityId;
                if ( additionalMergeValuesItem.EntityId > 0 )
                {
                    entityId = additionalMergeValuesItem.EntityId;
                }
                else
                {
                    // not pointing to an actual EntityId, so use the nonEntityId for ti
                    entityId = nonEntityId++;
                }

                if ( mergeObjectsDictionary.ContainsKey( entityId ) )
                {
                    mergeObject = mergeObjectsDictionary[entityId];
                }
                else
                {
                    if ( entitySet.EntityTypeId.HasValue )
                    {
                        // if already have real entities in our list, don't add additional items to the mergeObjectsDictionary
                        continue;
                    }

                    // non-Entity merge object, so just use Dictionary
                    mergeObject = new Dictionary<string, object>();
                    mergeObjectsDictionary.AddOrIgnore( entityId, mergeObject );
                }

                foreach ( var additionalMergeValue in additionalMergeValuesItem.AdditionalMergeValues )
                {
                    if ( mergeObject is IEntity )
                    {
                        // add the additional fields to AdditionalLavaFields
                        IEntity mergeEntity = ( mergeObject as IEntity );
                        mergeEntity.AdditionalLavaFields = mergeEntity.AdditionalLavaFields ?? new Dictionary<string, object>();
                        object mergeValueObject = additionalMergeValue.Value;
                        mergeEntity.AdditionalLavaFields.AddOrIgnore( additionalMergeValue.Key, mergeValueObject );
                    }
                    else if ( mergeObject is IDictionary<string, object> )
                    {
                        // anonymous object with no fields yet
                        IDictionary<string, object> nonEntityObject = mergeObject as IDictionary<string, object>;
                        nonEntityObject.AddOrIgnore( additionalMergeValue.Key, additionalMergeValue.Value );
                    }
                    else
                    {
                        throw new Exception( string.Format( "Unexpected MergeObject Type: {0}", mergeObject ) );
                    }
                }
            }

            var result = mergeObjectsDictionary.Select( a => a.Value );
            if ( fetchCount.HasValue )
            {
                // make sure the result is limited to fetchCount (even though the above queries are also limited to fetch count)
                result = result.Take( fetchCount.Value );
            }

            return result.ToList();
        }
        /// <summary>
        /// Shows the merge for entity set identifier.
        /// </summary>
        /// <param name="entitySetId">The entity set identifier.</param>
        protected void ShowMergeForEntitySetId( int entitySetId )
        {
            hfEntitySetId.Value = entitySetId.ToString();
            var rockContext = new RockContext();
            var entitySetService = new EntitySetService( rockContext );
            var entitySetItemsService = new EntitySetItemService( rockContext );
            var entitySet = entitySetService.Get( entitySetId );
            if ( entitySet == null )
            {
                nbWarningMessage.Text = "Merge Records not found";
                nbWarningMessage.Title = "Warning";
                nbWarningMessage.NotificationBoxType = NotificationBoxType.Warning;
                pnlEntry.Visible = false;
                return;
            }

            if ( entitySet.EntityTypeId.HasValue )
            {
                bool isPersonEntitySet = entitySet.EntityTypeId.Value == EntityTypeCache.GetId<Rock.Model.Person>();
                bool isGroupMemberEntitySet = entitySet.EntityTypeId.Value == EntityTypeCache.GetId<Rock.Model.GroupMember>();
                cbCombineFamilyMembers.Visible = isPersonEntitySet || isGroupMemberEntitySet;
            }
            else
            {
                cbCombineFamilyMembers.Visible = false;
            }

            int itemsCount = entitySetItemsService.Queryable().Where( a => a.EntitySetId == entitySetId ).Count();

            nbNumberOfRecords.Text = string.Format( "There are {0} {1} to merge", itemsCount, "row".PluralizeIf( itemsCount != 1 ) );
        }
        /// <summary>
        /// Handles the Click event of the btnShowDataPreview 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 btnShowDataPreview_Click( object sender, EventArgs e )
        {
            if ( pnlPreview.Visible )
            {
                pnlPreview.Visible = false;
                return;
            }

            var rockContext = new RockContext();

            int entitySetId = hfEntitySetId.Value.AsInteger();
            var entitySetService = new EntitySetService( rockContext );
            var entitySet = entitySetService.Get( entitySetId );
            if ( entitySet.EntityTypeId.HasValue )
            {
                var qry = entitySetService.GetEntityQuery( entitySetId ).Take( 15 );

                EntityTypeCache itemEntityType = EntityTypeCache.Read( entitySet.EntityTypeId ?? 0 );
                gPreview.CreatePreviewColumns( itemEntityType.GetEntityType() );

                gPreview.DataSource = qry.ToList();
                gPreview.DataBind();
            }
            else
            {
                var entitySetItemService = new EntitySetItemService( rockContext );
                var qry = entitySetItemService.GetByEntitySetId( entitySetId, true ).Take( 15 );
                var list = qry.ToList().Select( a => a.AdditionalMergeValuesJson.FromJsonOrNull<Dictionary<string, object>>() ).ToList();
                if ( list.Any() )
                {
                    gPreview.Columns.Clear();
                    foreach ( var s in list[0] )
                    {
                        var gridField = Grid.GetGridField( s.Value != null ? s.Value.GetType() : typeof( string ) );
                        gridField.HeaderText = s.Key.SplitCase();
                        gridField.DataField = s.Key;
                        gPreview.Columns.Add( gridField );
                    }

                    gPreview.DataSource = qry.ToList().Select( a => a.AdditionalMergeValuesJson.FromJsonOrNull<object>() ).ToList();
                    gPreview.DataBind();
                }
            }

            pnlPreview.Visible = true;
        }
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            RockContext rockContext = new RockContext();
            var entitySetService = new EntitySetService( rockContext );

            var entitySetPurposeGuid = Rock.SystemGuid.DefinedValue.ENTITY_SET_PURPOSE_PERSON_MERGE_REQUEST.AsGuid();

            var currentDateTime = RockDateTime.Now;
            var entitySetQry = entitySetService.Queryable()
                .Where( a => a.EntitySetPurposeValue.Guid == entitySetPurposeGuid )
                .Where( s => !s.ExpireDateTime.HasValue || s.ExpireDateTime.Value > currentDateTime );

            SortProperty sortProperty = gList.SortProperty;

            var qryPersonEntities = entitySetService.GetEntityItems<Person>();

            var joinQry = entitySetQry.GroupJoin( qryPersonEntities, n => n.Id, o => o.EntitySetId, ( a, b ) => new
            {
                a.Id,
                a.ModifiedDateTime,
                a.Note,
                a.CreatedByPersonAlias,
                MergeRecords = b.Select( x => x.Item )
            } );

            if ( sortProperty != null )
            {
                joinQry = joinQry.Sort( sortProperty );
            }
            else
            {
                joinQry = joinQry.OrderBy( s => s.ModifiedDateTime );
            }

            gList.SetLinqDataSource( joinQry );
            gList.DataBind();
        }
Пример #8
0
        /// <summary>
        /// Loads the view details.
        /// </summary>
        private void LoadViewDetails()
        {
            if ( Page.IsPostBack )
            {
                nbMergeRequestSuccess.Visible = false;
                nbMergeRequestAlreadySubmitted.Visible = false;
            }
            else
            {
                nbNotAuthorized.Visible = true;

                int? setId = PageParameter( "Set" ).AsIntegerOrNull();
                if ( setId.HasValue )
                {
                    // if the user only has View auth to the page, mark the EntitySet as a Person Merge Request and let them edit the EntitySet note
                    var rockContext = new RockContext();
                    var entitySetService = new EntitySetService( rockContext );
                    var entitySet = entitySetService.Get( setId.Value );
                    if ( entitySet != null )
                    {
                        tbEntitySetNote.Text = entitySet.Note;
                        var definedValuePurpose = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.ENTITY_SET_PURPOSE_PERSON_MERGE_REQUEST.AsGuid() );
                        if ( definedValuePurpose != null )
                        {
                            nbNotAuthorized.Visible = false;
                            tbEntitySetNote.Visible = true;
                            btnSaveRequestNote.Visible = true;

                            if ( entitySet.EntitySetPurposeValueId != definedValuePurpose.Id && entitySet.ExpireDateTime != null )
                            {
                                nbMergeRequestSuccess.Visible = true;
                                entitySet.EntitySetPurposeValueId = definedValuePurpose.Id;
                                entitySet.ExpireDateTime = null;
                                rockContext.SaveChanges();
                            }
                            else
                            {
                                nbMergeRequestAlreadySubmitted.Visible = true;
                            }
                        }
                    }
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Handles the Click event of the lbMerge 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 lbMerge_Click( object sender, EventArgs e )
        {
            if ( MergeData.People.Count < 2 )
            {
                nbPeople.Visible = true;
                return;
            }

            bool reconfirmRequired = ( MergeData.People.Select( p => p.Email ).Distinct().Count() > 1 && MergeData.People.Where( p => p.HasLogins ).Any() );

            GetValuesSelection();

            int? primaryPersonId = null;

            var oldPhotos = new List<int>();

            var rockContext = new RockContext();

            rockContext.WrapTransaction( () =>
            {
                var personService = new PersonService( rockContext );
                var userLoginService = new UserLoginService( rockContext );
                var groupService = new GroupService( rockContext );
                var groupMemberService = new GroupMemberService( rockContext );
                var binaryFileService = new BinaryFileService( rockContext );
                var phoneNumberService = new PhoneNumberService( rockContext );
                var taggedItemService = new TaggedItemService( rockContext );

                Person primaryPerson = personService.Get( MergeData.PrimaryPersonId ?? 0 );
                if ( primaryPerson != null )
                {
                    primaryPersonId = primaryPerson.Id;

                    var changes = new List<string>();

                    foreach ( var p in MergeData.People.Where( p => p.Id != primaryPerson.Id ) )
                    {
                        changes.Add( string.Format( "Merged <span class='field-value'>{0} [ID: {1}]</span> with this record.", p.FullName, p.Id ) );
                    }

                    // Photo Id
                    int? newPhotoId = MergeData.GetSelectedValue( MergeData.GetProperty( "Photo" ) ).Value.AsIntegerOrNull();
                    if ( !primaryPerson.PhotoId.Equals( newPhotoId ) )
                    {
                        changes.Add( "Modified the photo." );
                        primaryPerson.PhotoId = newPhotoId;
                    }

                    primaryPerson.TitleValueId = GetNewIntValue( "Title", changes );
                    primaryPerson.FirstName = GetNewStringValue( "FirstName", changes );
                    primaryPerson.NickName = GetNewStringValue( "NickName", changes );
                    primaryPerson.MiddleName = GetNewStringValue( "MiddleName", changes );
                    primaryPerson.LastName = GetNewStringValue( "LastName", changes );
                    primaryPerson.SuffixValueId = GetNewIntValue( "Suffix", changes );
                    primaryPerson.RecordTypeValueId = GetNewIntValue( "RecordType", changes );
                    primaryPerson.RecordStatusValueId = GetNewIntValue( "RecordStatus", changes );
                    primaryPerson.RecordStatusReasonValueId = GetNewIntValue( "RecordStatusReason", changes );
                    primaryPerson.ConnectionStatusValueId = GetNewIntValue( "ConnectionStatus", changes );
                    primaryPerson.IsDeceased = GetNewBoolValue( "Deceased", changes ) ?? false;
                    primaryPerson.Gender = (Gender)GetNewEnumValue( "Gender", typeof( Gender ), changes );
                    primaryPerson.MaritalStatusValueId = GetNewIntValue( "MaritalStatus", changes );
                    primaryPerson.SetBirthDate( GetNewDateTimeValue( "BirthDate", changes ) );
                    primaryPerson.AnniversaryDate = GetNewDateTimeValue( "AnniversaryDate", changes );
                    primaryPerson.GraduationYear = GetNewIntValue( "GraduationYear", changes );
                    primaryPerson.Email = GetNewStringValue( "Email", changes );
                    primaryPerson.IsEmailActive = GetNewBoolValue( "EmailActive", changes ) ?? true;
                    primaryPerson.EmailNote = GetNewStringValue( "EmailNote", changes );
                    primaryPerson.EmailPreference = (EmailPreference)GetNewEnumValue( "EmailPreference", typeof( EmailPreference ), changes );
                    primaryPerson.SystemNote = GetNewStringValue( "InactiveReasonNote", changes );
                    primaryPerson.SystemNote = GetNewStringValue( "SystemNote", changes );

                    // Update phone numbers
                    var phoneTypes = DefinedTypeCache.Read( Rock.SystemGuid.DefinedType.PERSON_PHONE_TYPE.AsGuid() ).DefinedValues;
                    foreach ( var phoneType in phoneTypes )
                    {
                        var phoneNumber = primaryPerson.PhoneNumbers.Where( p => p.NumberTypeValueId == phoneType.Id ).FirstOrDefault();
                        string oldValue = phoneNumber != null ? phoneNumber.Number : string.Empty;

                        string key = "phone_" + phoneType.Id.ToString();
                        string newValue = GetNewStringValue( key, changes );
                        bool phoneNumberDeleted = false;

                        if ( !oldValue.Equals( newValue, StringComparison.OrdinalIgnoreCase ) )
                        {
                            // New phone doesn't match old

                            if ( !string.IsNullOrWhiteSpace( newValue ) )
                            {
                                // New value exists
                                if ( phoneNumber == null )
                                {
                                    // Old value didn't exist... create new phone record
                                    phoneNumber = new PhoneNumber { NumberTypeValueId = phoneType.Id };
                                    primaryPerson.PhoneNumbers.Add( phoneNumber );
                                }

                                // Update phone number
                                phoneNumber.Number = newValue;
                            }
                            else
                            {
                                // New value doesn't exist
                                if ( phoneNumber != null )
                                {
                                    // old value existed.. delete it
                                    primaryPerson.PhoneNumbers.Remove( phoneNumber );
                                    phoneNumberService.Delete( phoneNumber );
                                    phoneNumberDeleted = true;
                                }
                            }
                        }

                        // check to see if IsMessagingEnabled is true for any of the merged people for this number/numbertype
                        if ( phoneNumber != null && !phoneNumberDeleted && !phoneNumber.IsMessagingEnabled )
                        {
                            var personIds = MergeData.People.Select( a => a.Id ).ToList();
                            var isMessagingEnabled = phoneNumberService.Queryable().Where( a => personIds.Contains( a.PersonId ) && a.Number == phoneNumber.Number && a.NumberTypeValueId == phoneNumber.NumberTypeValueId ).Any( a => a.IsMessagingEnabled );
                            if ( isMessagingEnabled )
                            {
                                phoneNumber.IsMessagingEnabled = true;
                            }
                        }
                    }

                    // Save the new record
                    rockContext.SaveChanges();

                    // Update the attributes
                    primaryPerson.LoadAttributes( rockContext );
                    foreach ( var property in MergeData.Properties.Where( p => p.Key.StartsWith( "attr_" ) ) )
                    {
                        string attributeKey = property.Key.Substring( 5 );
                        string oldValue = primaryPerson.GetAttributeValue( attributeKey ) ?? string.Empty;
                        string newValue = GetNewStringValue( property.Key, changes ) ?? string.Empty;

                        if ( !oldValue.Equals( newValue ) )
                        {
                            var attribute = primaryPerson.Attributes[attributeKey];
                            Rock.Attribute.Helper.SaveAttributeValue( primaryPerson, attribute, newValue, rockContext );
                        }
                    }

                    HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                        primaryPerson.Id, changes );

                    // Delete the unselected photos
                    string photoKeeper = primaryPerson.PhotoId.HasValue ? primaryPerson.PhotoId.Value.ToString() : string.Empty;
                    foreach ( var photoValue in MergeData.Properties
                        .Where( p => p.Key == "Photo" )
                        .SelectMany( p => p.Values )
                        .Where( v => v.Value != "" && v.Value != photoKeeper )
                        .Select( v => v.Value ) )
                    {
                        int photoId = 0;
                        if ( int.TryParse( photoValue, out photoId ) )
                        {
                            var photo = binaryFileService.Get( photoId );
                            if ( photo != null )
                            {
                                string errorMessages;
                                if ( binaryFileService.CanDelete( photo, out errorMessages ) )
                                {
                                    binaryFileService.Delete( photo );
                                }
                            }
                        }
                    }
                    rockContext.SaveChanges();

                    // Delete merged person's family records and any families that would be empty after merge
                    foreach ( var p in MergeData.People.Where( p => p.Id != primaryPersonId.Value ) )
                    {
                        // Delete the merged person's phone numbers (we've already updated the primary persons values)
                        foreach ( var phoneNumber in phoneNumberService.GetByPersonId( p.Id ) )
                        {
                            phoneNumberService.Delete( phoneNumber );
                        }

                        // If there was more than one email address and user has logins, then set any of the local
                        // logins ( database & AD ) to require a reconfirmation
                        if ( reconfirmRequired )
                        {
                            foreach ( var login in userLoginService.GetByPersonId( p.Id ) )
                            {
                                var component = Rock.Security.AuthenticationContainer.GetComponent( login.EntityType.Name );
                                if ( component != null && !component.RequiresRemoteAuthentication )
                                {
                                    login.IsConfirmed = false;
                                }
                            }
                        }

                        rockContext.SaveChanges();

                        // Delete the merged person's other family member records and the family if they were the only one in the family
                        Guid familyGuid = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
                        foreach ( var familyMember in groupMemberService.Queryable().Where( m => m.PersonId == p.Id && m.Group.GroupType.Guid == familyGuid ) )
                        {
                            groupMemberService.Delete( familyMember );

                            rockContext.SaveChanges();

                            // Get the family
                            var family = groupService.Queryable( "Members" ).Where( f => f.Id == familyMember.GroupId ).FirstOrDefault();
                            if ( !family.Members.Any() )
                            {
                                // If there are not any other family members, delete the family record.

                                // If theres any people that have this group as a giving group, set it to null (the person being merged should be the only one)
                                foreach ( Person gp in personService.Queryable().Where( g => g.GivingGroupId == family.Id ) )
                                {
                                    gp.GivingGroupId = null;
                                }

                                // save to the database prior to doing groupService.Delete since .Delete quietly might not delete if thinks the Family is used for a GivingGroupId
                                rockContext.SaveChanges();

                                // Delete the family
                                string errorMessage;
                                if ( groupService.CanDelete( family, out errorMessage ) )
                                {
                                    var oldFamilyChanges = new List<string>();
                                    History.EvaluateChange( oldFamilyChanges, "Family", family.Name, string.Empty );
                                    HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                                        primaryPersonId.Value, oldFamilyChanges, family.Name, typeof( Group ), family.Id );

                                    groupService.Delete( family );
                                    rockContext.SaveChanges();
                                }
                            }
                        }
                    }

                    // Flush any security roles that the merged person's other records were a part of
                    foreach ( var p in MergeData.People.Where( p => p.Id != primaryPersonId.Value ) )
                    {
                        foreach ( var groupMember in groupMemberService.Queryable().Where( m => m.PersonId == p.Id ) )
                        {
                            Group group = new GroupService( rockContext ).Get( groupMember.GroupId );
                            if ( group.IsSecurityRole || group.GroupType.Guid.Equals( Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid() ) )
                            {
                                Rock.Security.Role.Flush( group.Id );
                                Rock.Security.Authorization.Flush();
                            }
                        }
                    }

                    // now that the Merge is complete, the EntitySet can be marked to be deleted by the RockCleanup job
                    var entitySetService = new EntitySetService( rockContext );
                    var entitySet = entitySetService.Get( MergeData.EntitySetId );
                    if ( entitySet != null )
                    {
                        entitySet.ExpireDateTime = RockDateTime.Now.AddMinutes(-1);
                        entitySet.EntitySetPurposeValueId = null;
                        rockContext.SaveChanges();
                    }

                }
            } );

            foreach ( var p in MergeData.People.Where( p => p.Id != primaryPersonId.Value ) )
            {
                // Run merge proc to merge all associated data
                var parms = new Dictionary<string, object>();
                parms.Add( "OldId", p.Id );
                parms.Add( "NewId", primaryPersonId.Value );
                DbService.ExecuteCommand( "spCrm_PersonMerge", CommandType.StoredProcedure, parms );
            }

            NavigateToLinkedPage( "PersonDetailPage", "PersonId", primaryPersonId.Value );
        }
Пример #10
0
        /// <summary>
        /// Cleans up expired entity sets.
        /// </summary>
        /// <param name="dataMap">The data map.</param>
        private int CleanupExpiredEntitySets( JobDataMap dataMap )
        {
            var entitySetRockContext = new Rock.Data.RockContext();
            var currentDateTime = RockDateTime.Now;
            var entitySetService = new EntitySetService( entitySetRockContext );
            var qry = entitySetService.Queryable().Where( a => a.ExpireDateTime.HasValue && a.ExpireDateTime < currentDateTime );
            int totalRowsDeleted = 0;

            foreach ( var entitySet in qry.ToList() )
            {
                string deleteWarning;
                if ( entitySetService.CanDelete( entitySet, out deleteWarning ) )
                {
                    // delete in chunks (see http://dba.stackexchange.com/questions/1750/methods-of-speeding-up-a-huge-delete-from-table-with-no-clauses)
                    bool keepDeleting = true;
                    while ( keepDeleting )
                    {
                        var dbTransaction = entitySetRockContext.Database.BeginTransaction();
                        try
                        {
                            string sqlCommand = @"DELETE TOP (1000) FROM [EntitySetItem] WHERE [EntitySetId] = @entitySetId";

                            int rowsDeleted = entitySetRockContext.Database.ExecuteSqlCommand( sqlCommand, new SqlParameter( "entitySetId", entitySet.Id ) );
                            keepDeleting = rowsDeleted > 0;
                            totalRowsDeleted += rowsDeleted;
                        }
                        finally
                        {
                            dbTransaction.Commit();
                        }
                    }

                    entitySetService.Delete( entitySet );
                    entitySetRockContext.SaveChanges();
                }
            }

            return totalRowsDeleted;
        }
        /// <summary>
        /// Handles the Click event of the btnProcessWaitlist control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void btnProcessWaitlist_Click( object sender, EventArgs e )
        {
            // create entity set with selected individuals
            var keys = gWaitList.SelectedKeys.ToList();
            if ( keys.Any() )
            {
                var entitySet = new Rock.Model.EntitySet();
                entitySet.EntityTypeId = Rock.Web.Cache.EntityTypeCache.Read<Rock.Model.RegistrationRegistrant>().Id;
                entitySet.ExpireDateTime = RockDateTime.Now.AddMinutes( 20 );

                foreach ( var key in keys )
                {
                    try
                    {
                        var item = new Rock.Model.EntitySetItem();
                        item.EntityId = (int)key;
                        entitySet.Items.Add( item );
                    }
                    catch
                    {
                        // ignore
                    }
                }

                if ( entitySet.Items.Any() )
                {
                    var rockContext = new RockContext();
                    var service = new Rock.Model.EntitySetService( rockContext );
                    service.Add( entitySet );
                    rockContext.SaveChanges();

                    // redirect to the waitlist page
                    Dictionary<string, string> queryParms = new Dictionary<string, string>();
                    queryParms.Add( "WaitListSetId", entitySet.Id.ToString() );
                    NavigateToLinkedPage( "WaitListProcessPage", queryParms );
                }
            }
        }