/// <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 people attributes to date/text attributes. /// Also converts attribute comments to person notes. /// </summary> /// <param name="tableData">The table data.</param> /// <param name="totalRows">The total rows.</param> private void MapAttribute(IQueryable <Row> tableData, long totalRows = 0) { var lookupContext = new RockContext(); var personService = new PersonService(lookupContext); var personAttributes = new AttributeService(lookupContext).GetByEntityTypeId(PersonEntityTypeId).Include("Categories").AsNoTracking().ToList(); var importedAttributeCount = lookupContext.AttributeValues.Count(v => v.Attribute.EntityTypeId == PersonEntityTypeId && v.ForeignKey != null); var baptizedHereAttribute = personAttributes.FirstOrDefault(a => a.Key.Equals("BaptizedHere", StringComparison.InvariantCultureIgnoreCase)); var newBenevolences = new List <BenevolenceRequest>(); var peopleToUpdate = new Dictionary <int, Person>(); if (totalRows == 0) { totalRows = tableData.Count(); } var completedItems = 0; var percentage = (totalRows - 1) / 100 + 1; ReportProgress(0, $"Verifying attribute import ({totalRows:N0} found, {importedAttributeCount:N0} already exist)."); foreach (var row in tableData.OrderBy(r => r["Attribute_Name"]).ThenByDescending(r => r["Start_Date"] != null).ThenBy(r => r["Start_Date"]).ThenBy(r => r["End_Date"]).Where(r => r != null)) { // add the new attribute var attributeGroupName = row["Attribute_Group_Name"] as string; var attributeName = row["Attribute_Name"] as string; var attributeDate = row["Start_Date"] as DateTime?; attributeDate = attributeDate ?? row["End_Date"] as DateTime?; var attributeComment = row["Comment"] as string; var attributeCreator = row["Staff_Individual_ID"] as int?; int?campusId = null; if (attributeGroupName.IsNullOrWhiteSpace() && attributeName.IsNullOrWhiteSpace()) { continue; } // strip attribute group name (will become a category) if (attributeGroupName.Any(n => ValidDelimiters.Contains(n))) { campusId = campusId ?? GetCampusId(attributeGroupName); if (campusId.HasValue) { attributeGroupName = StripPrefix(attributeGroupName, campusId); } } // strip attribute name if (attributeName.Any(n => ValidDelimiters.Contains(n))) { campusId = campusId ?? GetCampusId(attributeName); if (campusId.HasValue) { attributeName = StripPrefix(attributeName, campusId); } } var personBaptizedHere = false; var isBenevolenceAttribute = false; if (attributeName.StartsWith("Baptism", StringComparison.CurrentCultureIgnoreCase)) { // match the core Baptism attribute attributeName = "Baptism Date"; personBaptizedHere = attributeCreator.HasValue; } else if (attributeName.StartsWith("Benevolence", StringComparison.CurrentCultureIgnoreCase)) { // set a flag to create benevolence items isBenevolenceAttribute = true; attributeName = attributeName.Replace("Benevolence", string.Empty).Trim(); } else if (string.IsNullOrWhiteSpace(attributeName)) { attributeName = attributeGroupName; } Attribute primaryAttribute = null, campusAttribute = null; // don't create custom attributes for benevolence items if (!isBenevolenceAttribute) { // create attributes if they don't exist var attributeKey = attributeName.RemoveSpecialCharacters(); primaryAttribute = personAttributes.FirstOrDefault(a => a.Key.Equals(attributeKey, StringComparison.CurrentCultureIgnoreCase)); if (primaryAttribute == null) { primaryAttribute = AddEntityAttribute(lookupContext, PersonEntityTypeId, string.Empty, string.Empty, $"{attributeKey} imported {ImportDateTime}", attributeGroupName, attributeName, attributeKey, attributeDate.HasValue ? DateFieldTypeId : TextFieldTypeId, importPersonAliasId: ImportPersonAliasId ); personAttributes.Add(primaryAttribute); } // attribute already exists, add the new category else if (!primaryAttribute.Categories.Any(c => c.Name.Equals(attributeGroupName))) { var attributeCategory = GetCategory(lookupContext, AttributeEntityTypeId, null, attributeGroupName, false, "EntityTypeId", PersonEntityTypeId.ToString()); primaryAttribute.Categories.Add(attributeCategory); } // only create a campus attribute if there was a campus prefix campusAttribute = personAttributes.FirstOrDefault(a => a.Key.Equals($"{attributeKey}Campus", StringComparison.CurrentCultureIgnoreCase)); if (campusAttribute == null && campusId.HasValue) { campusAttribute = AddEntityAttribute(lookupContext, PersonEntityTypeId, string.Empty, string.Empty, $"{attributeKey}Campus imported {ImportDateTime}", attributeGroupName, $"{attributeName} Campus", $"{attributeKey}Campus", CampusFieldTypeId ); personAttributes.Add(campusAttribute); } } // make sure we have a valid person to assign to var individualId = row["Individual_Id"] as int?; var matchingPerson = GetPersonKeys(individualId, null, includeVisitors: false); if (matchingPerson != null) { var person = !peopleToUpdate.ContainsKey(matchingPerson.PersonId) ? personService.Queryable(includeDeceased: true).FirstOrDefault(p => p.Id == matchingPerson.PersonId) : peopleToUpdate[matchingPerson.PersonId]; if (person != null) { int?creatorAliasId = null; var noteCreator = GetPersonKeys(attributeCreator); if (noteCreator != null) { creatorAliasId = noteCreator.PersonAliasId; } if (!isBenevolenceAttribute) { // could have multiple attributes assigned to this person, don't overwrite previous if (person.Attributes == null || person.AttributeValues == null) { person.Attributes = new Dictionary <string, AttributeCache>(); person.AttributeValues = new Dictionary <string, AttributeValueCache>(); } var attributeValue = attributeDate.HasValue ? attributeDate.Value.ToString("yyyy-MM-dd") : attributeComment; if (string.IsNullOrWhiteSpace(attributeValue)) { // add today's date so that the attribute at least gets a value attributeValue = RockDateTime.Now.ToString("yyyy-MM-dd"); } AddEntityAttributeValue(lookupContext, primaryAttribute, person, attributeValue); if (personBaptizedHere) { AddEntityAttributeValue(lookupContext, baptizedHereAttribute, person, "Yes"); } // Add the campus attribute value if (campusAttribute != null && campusId.HasValue) { var campus = CampusList.FirstOrDefault(c => c.Id.Equals(campusId)); AddEntityAttributeValue(lookupContext, campusAttribute, person, campus.Guid.ToString()); } // convert the attribute comment to a person note if (!string.IsNullOrWhiteSpace(attributeComment)) { // add the note to the person AddEntityNote(lookupContext, PersonEntityTypeId, person.Id, attributeName, attributeComment, false, false, attributeGroupName, null, true, attributeDate, $"Imported {ImportDateTime}", creatorAliasId); } } // benevolences require a date else if (attributeDate.HasValue) { var requestText = !string.IsNullOrWhiteSpace(attributeComment) ? attributeComment : "N/A"; var benevolence = new BenevolenceRequest { CampusId = campusId, RequestDateTime = attributeDate.Value, FirstName = person.FirstName, LastName = person.LastName, Email = person.Email, RequestedByPersonAliasId = person.PrimaryAliasId, ConnectionStatusValueId = person.ConnectionStatusValueId, CaseWorkerPersonAliasId = creatorAliasId, RequestStatusValueId = ParseBenevolenceStatus(attributeName), RequestText = requestText, CreatedDateTime = attributeDate.Value, ModifiedDateTime = attributeDate.Value, CreatedByPersonAliasId = creatorAliasId, ModifiedByPersonAliasId = ImportPersonAliasId, ForeignKey = $"Benevolence imported {ImportDateTime}" }; newBenevolences.Add(benevolence); } // store the person lookup for this batch if (!peopleToUpdate.ContainsKey(matchingPerson.PersonId)) { peopleToUpdate.Add(matchingPerson.PersonId, person); } else { peopleToUpdate[matchingPerson.PersonId] = person; } } } completedItems++; if (completedItems % percentage < 1) { var percentComplete = completedItems / percentage; ReportProgress(percentComplete, $"{completedItems:N0} attributes imported ({percentComplete}% complete)."); } if (completedItems % ReportingNumber < 1) { SaveAttributes(peopleToUpdate); SaveBenevolenceRequests(newBenevolences); // reset so context doesn't bloat lookupContext.Dispose(); lookupContext = new RockContext(); personService = new PersonService(lookupContext); peopleToUpdate.Clear(); newBenevolences.Clear(); ReportPartialProgress(); } } SaveAttributes(peopleToUpdate); SaveBenevolenceRequests(newBenevolences); ReportProgress(100, $"Finished attribute import: {completedItems:N0} attributes imported."); }