/// <summary> /// Maps the activity ministry data. /// </summary> /// <param name="tableData">The table data.</param> /// <param name="totalRows">The total rows.</param> private void MapActivityMinistry(IQueryable <Row> tableData, long totalRows = 0) { var lookupContext = new RockContext(); var newGroups = new List <Group>(); const string attendanceTypeName = "Attendance History"; var groupTypeHistory = ImportedGroupTypes.FirstOrDefault(t => t.ForeignKey.Equals(attendanceTypeName)); if (groupTypeHistory == null) { groupTypeHistory = AddGroupType(lookupContext, attendanceTypeName, string.Format("{0} imported {1}", attendanceTypeName, ImportDateTime), null, null, GroupTypeCheckinTemplateId, true, true, true, true, typeForeignKey: attendanceTypeName); ImportedGroupTypes.Add(groupTypeHistory); } const string groupsParentName = "Archived Groups"; var archivedGroupsParent = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(groupsParentName.RemoveWhitespace())); if (archivedGroupsParent == null) { archivedGroupsParent = AddGroup(lookupContext, GeneralGroupTypeId, null, groupsParentName, true, null, ImportDateTime, groupsParentName.RemoveWhitespace(), true, ImportPersonAliasId); ImportedGroups.Add(archivedGroupsParent); } if (totalRows == 0) { totalRows = tableData.Count(); } var completedItems = 0; var percentage = (totalRows - 1) / 100 + 1; ReportProgress(0, string.Format("Verifying ministry import ({0:N0} found, {1:N0} already exist).", totalRows, ImportedGroupTypes.Count)); foreach (var row in tableData.OrderBy(r => r["Ministry_ID"] as int?).ThenBy(r => r["Activity_ID"] as int?)) { // get the ministry data var ministryId = row["Ministry_ID"] as int?; var activityId = row["Activity_ID"] as int?; var ministryName = row["Ministry_Name"] as string; var activityName = row["Activity_Name"] as string; var ministryActive = row["Ministry_Active"] as string; var activityActive = row["Activity_Active"] as string; int?campusId = null; if (ministryId.HasValue && !string.IsNullOrWhiteSpace(ministryName) && !ministryName.Equals("Delete", StringComparison.OrdinalIgnoreCase)) { // check for a ministry group campus context if (ministryName.Any(n => ValidDelimiters.Contains(n))) { campusId = campusId ?? GetCampusId(ministryName); if (campusId.HasValue) { // strip the campus from the ministry name to use for grouptype (use the original name on groups though) ministryName = StripPrefix(ministryName, campusId); } } // add the new grouptype if it doesn't exist var currentGroupType = ImportedGroupTypes.FirstOrDefault(t => t.ForeignKey.Equals(ministryName)); if (currentGroupType == null) { // save immediately so we can use the grouptype for a group currentGroupType = AddGroupType(lookupContext, ministryName, string.Format("{0} imported {1}", ministryName, ImportDateTime), groupTypeHistory.Id, null, null, true, true, true, true, typeForeignKey: ministryName); ImportedGroupTypes.Add(currentGroupType); } // create a campus level parent for the ministry group var parentGroupId = archivedGroupsParent.Id; if (campusId.HasValue) { var campus = CampusList.FirstOrDefault(c => c.Id == campusId); var campusGroup = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(campus.ShortCode) && g.ParentGroupId == parentGroupId); if (campusGroup == null) { campusGroup = AddGroup(lookupContext, GeneralGroupTypeId, parentGroupId, campus.Name, true, campus.Id, ImportDateTime, campus.ShortCode, true, ImportPersonAliasId); ImportedGroups.Add(campusGroup); } parentGroupId = campusGroup.Id; } // add a ministry group level if it doesn't exist var ministryGroup = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(ministryId.ToString())); if (ministryGroup == null) { // save immediately so we can use the group as a parent ministryGroup = AddGroup(lookupContext, currentGroupType.Id, parentGroupId, ministryName, ministryActive.AsBoolean(), campusId, null, ministryId.ToString(), true, ImportPersonAliasId); ImportedGroups.Add(ministryGroup); } // check for an activity group campus context if (!string.IsNullOrWhiteSpace(activityName) && activityName.Any(n => ValidDelimiters.Contains(n))) { campusId = campusId ?? GetCampusId(activityName); if (campusId.HasValue) { activityName = StripPrefix(activityName, campusId); } } // add the child activity group if it doesn't exist var activityGroup = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(activityId.ToString())); if (activityGroup == null && activityId.HasValue && !string.IsNullOrWhiteSpace(activityName) && !activityName.Equals("Delete", StringComparison.OrdinalIgnoreCase)) { // don't save immediately, we'll batch add later activityGroup = AddGroup(lookupContext, currentGroupType.Id, ministryGroup.Id, activityName, activityActive.AsBoolean(), campusId, null, activityId.ToString(), false, ImportPersonAliasId); newGroups.Add(activityGroup); } completedItems++; if (completedItems % percentage < 1) { var percentComplete = completedItems / percentage; ReportProgress(percentComplete, string.Format("{0:N0} ministries imported ({1}% complete).", completedItems, percentComplete)); } if (completedItems % ReportingNumber < 1) { SaveGroups(newGroups); ReportPartialProgress(); ImportedGroups.AddRange(newGroups); // Reset lists and context lookupContext = new RockContext(); newGroups.Clear(); } } } if (newGroups.Any()) { SaveGroups(newGroups); ImportedGroups.AddRange(newGroups); } lookupContext.Dispose(); ReportProgress(100, string.Format("Finished ministry import: {0:N0} ministries imported.", completedItems)); }
/// <summary> /// Maps the home group membership data. /// </summary> /// <param name="tableData">The table data.</param> /// <param name="totalRows">The total rows.</param> private void MapGroups(IQueryable <Row> tableData, long totalRows = 0) { var lookupContext = new RockContext(); var newGroupMembers = new List <GroupMember>(); var importedGroupMembers = lookupContext.GroupMembers.Count(gm => gm.ForeignKey != null && gm.Group.GroupTypeId == GeneralGroupTypeId); var groupRoleMember = GroupTypeCache.Get(GeneralGroupTypeId).Roles.FirstOrDefault(r => r.Name.Equals("Member")); var archivedScheduleName = "Archived Attendance"; var archivedScheduleId = new ScheduleService(lookupContext).Queryable() .Where(s => s.Name.Equals(archivedScheduleName, StringComparison.OrdinalIgnoreCase)) .Select(s => ( int? )s.Id).FirstOrDefault(); if (!archivedScheduleId.HasValue) { var archivedSchedule = AddNamedSchedule(lookupContext, archivedScheduleName, null, null, null, ImportDateTime, archivedScheduleName.RemoveSpecialCharacters(), true, ImportPersonAliasId); archivedScheduleId = archivedSchedule.Id; } var groupsParentName = "Archived Groups"; var archivedGroups = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(groupsParentName.RemoveWhitespace())); if (archivedGroups == null) { archivedGroups = AddGroup(lookupContext, GeneralGroupTypeId, null, groupsParentName, true, null, ImportDateTime, groupsParentName.RemoveWhitespace(), true, ImportPersonAliasId); ImportedGroups.Add(archivedGroups); } if (totalRows == 0) { totalRows = tableData.Count(); } var completedItems = 0; var percentage = (totalRows - 1) / 100 + 1; ReportProgress(0, string.Format("Verifying people groups import ({0:N0} found, {1:N0} already exist).", totalRows, importedGroupMembers)); foreach (var row in tableData.Where(r => r != null)) { var groupId = row["Group_ID"] as int?; var groupName = row["Group_Name"] as string; var individualId = row["Individual_ID"] as int?; var groupCreated = row["Created_Date"] as DateTime?; var groupType = row["Group_Type_Name"] as string; // require at least a group id and name if (groupId.HasValue && !string.IsNullOrWhiteSpace(groupName) && !groupName.Equals("Delete", StringComparison.OrdinalIgnoreCase)) { var peopleGroup = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(groupId.ToString())); if (peopleGroup == null) { int?campusId = null; var parentGroupId = archivedGroups.Id; var currentGroupTypeId = GeneralGroupTypeId; if (!string.IsNullOrWhiteSpace(groupType)) { // check for a campus on the grouptype campusId = GetCampusId(groupType, true, SearchDirection.Ends); if (campusId.HasValue) { groupType = StripSuffix(groupType, campusId); } // add the grouptype if it doesn't exist var currentGroupType = ImportedGroupTypes.FirstOrDefault(t => t.ForeignKey.Equals(groupType, StringComparison.OrdinalIgnoreCase)); if (currentGroupType == null) { // save immediately so we can use the grouptype for a group currentGroupType = AddGroupType(lookupContext, groupType, string.Format("{0} imported {1}", groupType, ImportDateTime), null, null, null, true, true, true, true, typeForeignKey: groupType); ImportedGroupTypes.Add(currentGroupType); } // create a placeholder group for the grouptype if it doesn't exist var groupTypePlaceholder = ImportedGroups.FirstOrDefault(g => g.GroupTypeId == currentGroupType.Id && g.ForeignKey.Equals(groupType.RemoveWhitespace())); if (groupTypePlaceholder == null) { groupTypePlaceholder = AddGroup(lookupContext, currentGroupType.Id, archivedGroups.Id, groupType, true, null, ImportDateTime, groupType.RemoveWhitespace(), true, ImportPersonAliasId); ImportedGroups.Add(groupTypePlaceholder); } parentGroupId = groupTypePlaceholder.Id; currentGroupTypeId = currentGroupType.Id; } // put the current group under a campus parent if it exists campusId = campusId ?? GetCampusId(groupName); if (campusId.HasValue) { // create a campus level parent for the home group var campus = CampusList.FirstOrDefault(c => c.Id == campusId); var campusGroup = ImportedGroups.FirstOrDefault(g => g.ForeignKey.Equals(campus.ShortCode) && g.ParentGroupId == parentGroupId); if (campusGroup == null) { campusGroup = AddGroup(lookupContext, currentGroupTypeId, parentGroupId, campus.Name, true, campus.Id, ImportDateTime, campus.ShortCode, true, ImportPersonAliasId); ImportedGroups.Add(campusGroup); } parentGroupId = campusGroup.Id; } // add the group, finally peopleGroup = AddGroup(lookupContext, currentGroupTypeId, parentGroupId, groupName, true, campusId, null, groupId.ToString(), true, ImportPersonAliasId, archivedScheduleId); ImportedGroups.Add(peopleGroup); } // add the group member var personKeys = GetPersonKeys(individualId, null); if (personKeys != null) { newGroupMembers.Add(new GroupMember { IsSystem = false, GroupId = peopleGroup.Id, PersonId = personKeys.PersonId, GroupRoleId = groupRoleMember.Id, GroupMemberStatus = GroupMemberStatus.Active, ForeignKey = string.Format("Membership imported {0}", ImportDateTime) }); completedItems++; } if (completedItems % percentage < 1) { var percentComplete = completedItems / percentage; ReportProgress(percentComplete, string.Format("{0:N0} group members imported ({1}% complete).", completedItems, percentComplete)); } if (completedItems % ReportingNumber < 1) { SaveGroupMembers(newGroupMembers); ReportPartialProgress(); // Reset lists and context lookupContext = new RockContext(); newGroupMembers.Clear(); } } } if (newGroupMembers.Any()) { SaveGroupMembers(newGroupMembers); } lookupContext.Dispose(); ReportProgress(100, string.Format("Finished people groups import: {0:N0} members imported.", completedItems)); }
/// <summary> /// Loads the group type data. /// </summary> /// <param name="csvData">The CSV data.</param> private int LoadGroupType(CSVInstance csvData) { // Required variables var lookupContext = new RockContext(); var newGroupTypeList = new List <GroupType>(); var purposeTypeValues = DefinedTypeCache.Get(new Guid(Rock.SystemGuid.DefinedType.GROUPTYPE_PURPOSE), lookupContext).DefinedValues; var locationMeetingId = DefinedValueCache.Get(new Guid(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_MEETING_LOCATION), lookupContext).Id; var numImportedGroupTypes = ImportedGroupTypes.Count(); var completed = 0; ReportProgress(0, $"Starting group type import ({numImportedGroupTypes:N0} already exist)."); string[] row; // Uses a look-ahead enumerator: this call will move to the next record immediately while ((row = csvData.Database.FirstOrDefault()) != null) { var rowGroupTypeName = row[GroupTypeName].Left(100); var rowGroupTypeDescription = row[GroupTypeDescription]; var rowGroupTypeKey = row[GroupTypeId]; var groupTypeForeignId = rowGroupTypeKey.AsType <int?>(); // Check that this group type isn't already in our data var groupTypeExists = false; if (numImportedGroupTypes > 0) { groupTypeExists = ImportedGroupTypes.Any(t => t.ForeignKey == rowGroupTypeKey); } // Check if this was an existing group type that needs foreign id added if (!groupTypeExists) { var groupType = new GroupTypeService(lookupContext).Queryable().FirstOrDefault(t => (t.ForeignKey == null || t.ForeignKey.Trim() == "") && t.Name.Equals(rowGroupTypeName, StringComparison.OrdinalIgnoreCase)); if (groupType != null) { groupType.ForeignKey = rowGroupTypeKey; groupType.ForeignGuid = rowGroupTypeKey.AsGuidOrNull(); groupType.ForeignId = rowGroupTypeKey.AsIntegerOrNull(); lookupContext.SaveChanges(); groupTypeExists = true; ImportedGroupTypes.Add(groupType); completed++; } } if (!groupTypeExists) { var newGroupType = new GroupType { // set required properties (terms set by default) IsSystem = false, Name = rowGroupTypeName, Description = rowGroupTypeDescription, Order = 1000 + completed, // set optional properties CreatedDateTime = ParseDateOrDefault(row[GroupTypeCreatedDate], ImportDateTime), ModifiedDateTime = ImportDateTime, CreatedByPersonAliasId = ImportPersonAliasId, ModifiedByPersonAliasId = ImportPersonAliasId, ForeignKey = rowGroupTypeKey, ForeignId = groupTypeForeignId }; // set meeting location var definedValueService = new DefinedValueService(lookupContext); newGroupType.LocationTypes = new List <GroupTypeLocationType>(); newGroupType.LocationTypes.Clear(); var meetingLocationType = definedValueService.Get(locationMeetingId); if (meetingLocationType != null) { newGroupType.LocationTypes.Add(new GroupTypeLocationType { LocationTypeValueId = meetingLocationType.Id }); } // set provided optional properties newGroupType.TakesAttendance = ( bool )ParseBoolOrDefault(row[GroupTypeTakesAttendance], false); newGroupType.AttendanceCountsAsWeekendService = ( bool )ParseBoolOrDefault(row[GroupTypeWeekendService], false); newGroupType.ShowInGroupList = ( bool )ParseBoolOrDefault(row[GroupTypeShowInGroupList], false); newGroupType.ShowInNavigation = ( bool )ParseBoolOrDefault(row[GroupTypeShowInNav], false); // set schedule var allowGroupScheduleWeekly = ( bool )ParseBoolOrDefault(row[GroupTypeWeeklySchedule], false); if (allowGroupScheduleWeekly) { newGroupType.AllowedScheduleTypes = ScheduleType.Weekly; } var rowGroupTypePurpose = row[GroupTypePurpose]; if (!string.IsNullOrWhiteSpace(rowGroupTypePurpose)) { var purposeId = purposeTypeValues.Where(v => v.Value.Equals(rowGroupTypePurpose) || v.Id.Equals(rowGroupTypePurpose.AsInteger()) || v.Guid.ToString().ToLower().Equals(rowGroupTypePurpose.ToLower())) .Select(v => ( int? )v.Id).FirstOrDefault(); newGroupType.GroupTypePurposeValueId = purposeId; } var inheritedGroupType = GroupTypeCache.Get(LoadGroupTypeId(lookupContext, row[GroupTypeInheritedGroupType])); if (inheritedGroupType.Id != GroupTypeCache.Get(new Guid("8400497B-C52F-40AE-A529-3FCCB9587101"), lookupContext).Id) { newGroupType.InheritedGroupTypeId = inheritedGroupType.Id; } // add default role of member var defaultRoleGuid = Guid.NewGuid(); var memberRole = new GroupTypeRole { Guid = defaultRoleGuid, Name = "Member" }; newGroupType.Roles.Add(memberRole); // save changes each loop newGroupTypeList.Add(newGroupType); lookupContext.WrapTransaction(() => { lookupContext.GroupTypes.AddRange(newGroupTypeList); lookupContext.SaveChanges(DisableAuditing); }); // Set Parent Group Type var rowGroupTypeParentId = row[GroupTypeParentId]; if (!string.IsNullOrWhiteSpace(rowGroupTypeParentId)) { var parentGroupType = ImportedGroupTypes.FirstOrDefault(t => t.ForeignKey.Equals(rowGroupTypeParentId)); var parentGroupTypeList = new List <GroupType>(); parentGroupTypeList.Add(parentGroupType); newGroupType.ParentGroupTypes = parentGroupTypeList; } // Set Self Reference bool selfRef; TryParseBool(row[GroupTypeSelfReference], out selfRef); if (selfRef) { var selfReferenceList = new List <GroupType>(); selfReferenceList.Add(newGroupType); newGroupType.ChildGroupTypes = selfReferenceList; } // set default role newGroupType.DefaultGroupRole = newGroupType.Roles.FirstOrDefault(); // save changes lookupContext.SaveChanges(); // add these new groups to the global list ImportedGroupTypes.AddRange(newGroupTypeList); newGroupTypeList.Clear(); // // Keep the user informed as to what is going on and save in batches. // completed++; if (completed % (ReportingNumber * 10) < 1) { ReportProgress(0, $"{completed:N0} groups imported."); } if (completed % ReportingNumber < 1) { ReportPartialProgress(); } } } ReportProgress(0, $"Finished group type import: {completed:N0} group types added or updated."); return(completed); }