/// <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(); }