/// <summary> /// Creates the table controls. /// </summary> /// <param name="batchId">The batch identifier.</param> /// <param name="dataViewId">The data view identifier.</param> private void BindHtmlGrid(int?batchId, int?dataViewId) { _financialTransactionDetailList = null; RockContext rockContext = new RockContext(); nbSaveSuccess.Visible = false; btnSave.Visible = false; List <DataControlField> tableColumns = new List <DataControlField>(); tableColumns.Add(new RockLiteralField { ID = "lPerson", HeaderText = "Person" }); tableColumns.Add(new RockLiteralField { ID = "lAmount", HeaderText = "Amount" }); tableColumns.Add(new RockLiteralField { ID = "lAccount", HeaderText = "Account" }); tableColumns.Add(new RockLiteralField { ID = "lTransactionType", HeaderText = "Transaction Type" }); string entityColumnHeading = this.GetAttributeValue("EntityColumnHeading"); if (string.IsNullOrEmpty(entityColumnHeading)) { if (_transactionEntityType != null) { entityColumnHeading = _entityTypeQualifiedName; } } tableColumns.Add(new RockLiteralField { ID = "lEntityColumn", HeaderText = entityColumnHeading }); var additionalColumns = this.GetAttributeValue(CustomGridColumnsConfig.AttributeKey).FromJsonOrNull <CustomGridColumnsConfig>(); if (additionalColumns != null) { foreach (var columnConfig in additionalColumns.ColumnsConfig) { int insertPosition; if (columnConfig.PositionOffsetType == CustomGridColumnsConfig.ColumnConfig.OffsetType.LastColumn) { insertPosition = tableColumns.Count - columnConfig.PositionOffset; } else { insertPosition = columnConfig.PositionOffset; } var column = columnConfig.GetGridColumn(); tableColumns.Insert(insertPosition, column); insertPosition++; } } StringBuilder headers = new StringBuilder(); foreach (var tableColumn in tableColumns) { if (tableColumn.HeaderStyle.CssClass.IsNotNullOrWhiteSpace()) { headers.AppendFormat("<th class='{0}'>{1}</th>", tableColumn.HeaderStyle.CssClass, tableColumn.HeaderText); } else { headers.AppendFormat("<th>{0}</th>", tableColumn.HeaderText); } } lHeaderHtml.Text = headers.ToString(); int? transactionId = this.PageParameter("TransactionId").AsIntegerOrNull(); DataView dataView = null; if (batchId.HasValue || dataViewId.HasValue || transactionId.HasValue) { nbErrorMessage.Visible = false; try { var financialTransactionDetailQuery = new FinancialTransactionDetailService(rockContext).Queryable() .Include(a => a.Transaction) .Include(a => a.Transaction.AuthorizedPersonAlias.Person); if (batchId.HasValue) { financialTransactionDetailQuery = financialTransactionDetailQuery.Where(a => a.Transaction.BatchId == batchId.Value); } if (dataViewId.HasValue && dataViewId > 0) { dataView = new DataViewService(rockContext).Get(dataViewId.Value); var transactionDetailIdsQry = dataView.GetQuery(new DataViewGetQueryArgs { DbContext = rockContext }).Select(a => a.Id); financialTransactionDetailQuery = financialTransactionDetailQuery.Where(a => transactionDetailIdsQry.Contains(a.Id)); } if (transactionId.HasValue) { financialTransactionDetailQuery = financialTransactionDetailQuery.Where(a => transactionId == a.TransactionId); } int maxResults = this.GetAttributeValue("MaxNumberofResults").AsIntegerOrNull() ?? 1000; _financialTransactionDetailList = financialTransactionDetailQuery.OrderByDescending(a => a.Transaction.TransactionDateTime).Take(maxResults).ToList(); } catch (Exception ex) { ExceptionLogService.LogException(ex); var sqlTimeoutException = ReportingHelper.FindSqlTimeoutException(ex); if (sqlTimeoutException != null) { nbErrorMessage.NotificationBoxType = NotificationBoxType.Warning; nbErrorMessage.Text = "This report did not complete in a timely manner. You can try again or adjust the timeout setting of this block."; } else { if (ex is RockDataViewFilterExpressionException) { RockDataViewFilterExpressionException rockDataViewFilterExpressionException = ex as RockDataViewFilterExpressionException; nbErrorMessage.Text = rockDataViewFilterExpressionException.GetFriendlyMessage(dataView); } else { nbErrorMessage.Text = "There was a problem with one of the filters for this report's dataview."; } nbErrorMessage.NotificationBoxType = NotificationBoxType.Danger; nbErrorMessage.Details = ex.Message; nbErrorMessage.Visible = true; return; } } phTableRows.Controls.Clear(); btnSave.Visible = _financialTransactionDetailList.Any(); string appRoot = this.ResolveRockUrl("~/"); string themeRoot = this.ResolveRockUrl("~~/"); foreach (var financialTransactionDetail in _financialTransactionDetailList) { var tr = new HtmlGenericContainer("tr"); foreach (var tableColumn in tableColumns) { var literalControl = new LiteralControl(); if (tableColumn is RockLiteralField) { tr.Controls.Add(literalControl); var literalTableColumn = tableColumn as RockLiteralField; if (literalTableColumn.ID == "lPerson") { literalControl.Text = string.Format("<td>{0}</td>", financialTransactionDetail.Transaction.AuthorizedPersonAlias); } else if (literalTableColumn.ID == "lAmount") { literalControl.Text = string.Format("<td>{0}</td>", financialTransactionDetail.Amount.FormatAsCurrency()); } else if (literalTableColumn.ID == "lAccount") { literalControl.Text = string.Format("<td>{0}</td>", financialTransactionDetail.Account.ToString()); } else if (literalTableColumn.ID == "lTransactionType") { literalControl.ID = "lTransactionType_" + financialTransactionDetail.Id.ToString(); literalControl.Text = string.Format("<td>{0}</td>", financialTransactionDetail.Transaction.TransactionTypeValue); } else if (literalTableColumn.ID == "lEntityColumn") { var tdEntityControls = new HtmlGenericContainer("td") { ID = "pnlEntityControls_" + financialTransactionDetail.Id.ToString() }; tr.Controls.Add(tdEntityControls); if (_transactionEntityType != null) { if (_transactionEntityType.Id == EntityTypeCache.GetId <GroupMember>()) { var ddlGroup = new RockDropDownList { ID = "ddlGroup_" + financialTransactionDetail.Id.ToString(), EnhanceForLongLists = true }; ddlGroup.Label = "Group"; ddlGroup.AutoPostBack = true; ddlGroup.SelectedIndexChanged += ddlGroup_SelectedIndexChanged; tdEntityControls.Controls.Add(ddlGroup); var ddlGroupMember = new RockDropDownList { ID = "ddlGroupMember_" + financialTransactionDetail.Id.ToString(), Visible = false, EnhanceForLongLists = true }; ddlGroupMember.Label = "Group Member"; tdEntityControls.Controls.Add(ddlGroupMember); } else if (_transactionEntityType.Id == EntityTypeCache.GetId <Group>()) { var ddlGroup = new RockDropDownList { ID = "ddlGroup_" + financialTransactionDetail.Id.ToString(), EnhanceForLongLists = true }; ddlGroup.AutoPostBack = false; tdEntityControls.Controls.Add(ddlGroup); } else if (_transactionEntityType.Id == EntityTypeCache.GetId <DefinedValue>()) { var ddlDefinedValue = new DefinedValuePicker { ID = "ddlDefinedValue_" + financialTransactionDetail.Id.ToString(), EnhanceForLongLists = true }; tdEntityControls.Controls.Add(ddlDefinedValue); } else if (_transactionEntityType.SingleValueFieldType != null) { var entityPicker = _transactionEntityType.SingleValueFieldType.Field.EditControl(new Dictionary <string, Rock.Field.ConfigurationValue>(), "entityPicker_" + financialTransactionDetail.Id.ToString()); tdEntityControls.Controls.Add(entityPicker); } } } } else if (tableColumn is LavaField) { tr.Controls.Add(literalControl); var lavaField = tableColumn as LavaField; Dictionary <string, object> mergeValues = new Dictionary <string, object>(); mergeValues.Add("Row", financialTransactionDetail); string lavaOutput = lavaField.LavaTemplate.ResolveMergeFields(mergeValues); // Resolve any dynamic url references lavaOutput = lavaOutput.Replace("~~/", themeRoot).Replace("~/", appRoot); if (lavaField.ItemStyle.CssClass.IsNotNullOrWhiteSpace()) { literalControl.Text = string.Format("<td class='{0}'>{1}</td>", lavaField.ItemStyle.CssClass, lavaOutput); } else { literalControl.Text = string.Format("<td>{0}</td>", lavaOutput); } } } phTableRows.Controls.Add(tr); pnlTransactions.Visible = true; } } else { pnlTransactions.Visible = false; } }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public virtual void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; var emailTemplateGuid = dataMap.GetString("SystemEmail").AsGuidOrNull(); var dataViewGuid = dataMap.GetString("DataView").AsGuidOrNull(); if (dataViewGuid != null && emailTemplateGuid.HasValue) { var rockContext = new RockContext(); var dataView = new DataViewService(rockContext).Get((Guid)dataViewGuid); List <IEntity> resultSet = null; var errorMessages = new List <string>(); var dataTimeout = dataMap.GetString("DatabaseTimeout").AsIntegerOrNull() ?? 180; try { var qry = dataView.GetQuery(null, rockContext, dataTimeout, out errorMessages); if (qry != null) { resultSet = qry.AsNoTracking().ToList(); } } catch (Exception exception) { ExceptionLogService.LogException(exception, HttpContext.Current); while (exception != null) { if (exception is SqlException && (exception as SqlException).Number == -2) { // if there was a SQL Server Timeout, have the warning be a friendly message about that. errorMessages.Add("This dataview did not complete in a timely manner. You can try again or adjust the timeout setting of this block."); exception = exception.InnerException; } else { errorMessages.Add(exception.Message); exception = exception.InnerException; } return; } } var recipients = new List <RockEmailMessageRecipient>(); if (resultSet.Any()) { foreach (Person person in resultSet) { if (!person.IsEmailActive || person.Email.IsNullOrWhiteSpace() || person.EmailPreference == EmailPreference.DoNotEmail) { continue; } var mergeFields = Lava.LavaHelper.GetCommonMergeFields(null); mergeFields.Add("Person", person); recipients.Add(new RockEmailMessageRecipient(person, mergeFields)); } } var emailMessage = new RockEmailMessage(emailTemplateGuid.Value); emailMessage.SetRecipients(recipients); var errors = new List <string>(); emailMessage.Send(out errors); context.Result = string.Format("{0} emails sent", recipients.Count()); if (errors.Any()) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.Append(string.Format("{0} Errors: ", errors.Count())); errors.ForEach(e => { sb.AppendLine(); sb.Append(e); }); string errorMessage = sb.ToString(); context.Result += errorMessage; var exception = new Exception(errorMessage); HttpContext context2 = HttpContext.Current; ExceptionLogService.LogException(exception, context2); throw exception; } } }
/// <summary> /// Clears the existing data from class var attendances and repopulates it with data for the selected group and filter criteria. /// Data is organized by each person in the group. /// </summary> private List <Attendance> GetAttendanceData() { this.SetBlockUserPreference(UserPreferenceKey.SelectedDateRange, sdrpDateRange.DelimitedValues); this.SetBlockUserPreference(UserPreferenceKey.SelectedViewBy, hfTabs.Value); this.SetBlockUserPreference(UserPreferenceKey.SelectedGroupId, gpGroups.GroupId.ToString()); this.SetBlockUserPreference(UserPreferenceKey.SelectedLocationIds, cblLocations.SelectedValues.AsDelimited(",")); this.SetBlockUserPreference(UserPreferenceKey.SelectedScheduleIds, cblSchedules.SelectedValues.AsDelimited(",")); this.SetBlockUserPreference(UserPreferenceKey.SelectedDataViewId, dvDataViews.SelectedValue); this.SetBlockUserPreference(UserPreferenceKey.SelectedPersonId, ppPerson.SelectedValue.ToString()); // Create URL for selected settings var pageReference = CurrentPageReference; foreach (var setting in GetBlockUserPreferences()) { pageReference.Parameters.AddOrReplace(setting.Key, setting.Value); } Uri uri = new Uri(Request.Url.ToString()); btnCopyToClipboard.Attributes["data-clipboard-text"] = uri.GetLeftPart(UriPartial.Authority) + pageReference.BuildUrl(); btnCopyToClipboard.Disabled = false; // Source data for all tables and graphs using (var rockContext = new RockContext()) { var attendanceService = new AttendanceService(rockContext); var groupAttendances = attendanceService .Queryable() .Include(a => a.PersonAlias) .AsNoTracking() .Where(a => a.RequestedToAttend == true); switch (hfTabs.Value) { case "group": groupAttendances = groupAttendances.Where(a => a.Occurrence.GroupId == gpGroups.GroupId); // add selected locations to the query if (cblLocations.SelectedValues.Any()) { groupAttendances = groupAttendances.Where(a => cblLocations.SelectedValuesAsInt.Contains(a.Occurrence.LocationId ?? -1)); } // add selected schedules to the query if (cblSchedules.SelectedValues.Any()) { groupAttendances = groupAttendances.Where(a => cblSchedules.SelectedValuesAsInt.Contains(a.Occurrence.ScheduleId ?? -1)); } break; case "person": groupAttendances = groupAttendances.Where(a => a.PersonAlias.PersonId == ppPerson.PersonId); break; case "dataview": var dataView = new DataViewService(rockContext).Get(dvDataViews.SelectedValueAsInt().Value); var personsFromDv = dataView.GetQuery(null, rockContext, null, out _errorMessages) as IQueryable <Person>; var personAliasIds = personsFromDv.Select(d => d.Aliases.Where(a => a.AliasPersonId == d.Id).Select(a => a.Id).FirstOrDefault()).ToList(); groupAttendances = groupAttendances.Where(a => personAliasIds.Contains(a.PersonAliasId.Value)); break; default: break; } // parse the date range and add to query if (sdrpDateRange.DelimitedValues.IsNotNullOrWhiteSpace()) { var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(sdrpDateRange.DelimitedValues); if (dateRange.Start.HasValue) { groupAttendances = groupAttendances.Where(a => DbFunctions.TruncateTime(a.StartDateTime) >= dateRange.Start.Value); } if (dateRange.End.HasValue) { groupAttendances = groupAttendances.Where(a => DbFunctions.TruncateTime(a.StartDateTime) <= dateRange.End.Value); } } return(groupAttendances.ToList()); } }
public DataSet GetContributionPersonGroupAddress([FromBody] ContributionStatementOptions options) { Dictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("startDate", options.StartDate); if (options.EndDate.HasValue) { parameters.Add("endDate", options.EndDate.Value); } else { parameters.Add("endDate", DateTime.MaxValue); } if (options.AccountIds != null) { parameters.Add("accountIds", options.AccountIds.AsDelimited(",")); } else { parameters.Add("accountIds", DBNull.Value); } if (options.PersonId.HasValue) { parameters.Add("personId", options.PersonId); } else { parameters.Add("personId", DBNull.Value); } if (options.IncludeIndividualsWithNoAddress) { parameters.Add("includeIndividualsWithNoAddress", options.IncludeIndividualsWithNoAddress); } else { parameters.Add("includeIndividualsWithNoAddress", false); } parameters.Add("orderByPostalCode", options.OrderByPostalCode); var result = DbService.GetDataSet("spFinance_ContributionStatementQuery", System.Data.CommandType.StoredProcedure, parameters); if (result.Tables.Count > 0) { var dataTable = result.Tables[0]; dataTable.TableName = "contribution_person_group_address"; if (options.DataViewId.HasValue) { var dataView = new DataViewService(new RockContext()).Get(options.DataViewId.Value); if (dataView != null) { List <string> errorMessages = new List <string>(); var personList = dataView.GetQuery(null, null, out errorMessages).OfType <Rock.Model.Person>().Select(a => new { a.Id, a.GivingGroupId }).ToList(); HashSet <int> personIds = new HashSet <int>(personList.Select(a => a.Id)); HashSet <int> groupsIds = new HashSet <int>(personList.Where(a => a.GivingGroupId.HasValue).Select(a => a.GivingGroupId.Value).Distinct()); foreach (var row in dataTable.Rows.OfType <DataRow>().ToList()) { var personId = row["PersonId"]; var groupId = row["GroupId"]; if (personId != null && personId is int) { if (!personIds.Contains(( int )personId)) { dataTable.Rows.Remove(row); } } else if (groupId != null && groupId is int) { if (!groupsIds.Contains(( int )groupId)) { dataTable.Rows.Remove(row); } } } } } } return(result); }
/// <summary> /// Gets the filter person Ids based on dataview and optout group /// </summary> /// <param name="campaignConfiguration">The campaign configuration.</param> /// <param name="rockContext">The rock context.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> private static List <int> GetFilteredPersonIds(CampaignItem campaignConfiguration, RockContext rockContext, out List <string> errorMessages) { errorMessages = new List <string>(); var dataView = new DataViewService(rockContext).Get(campaignConfiguration.DataViewGuid); var personService = new PersonService(rockContext); var filteredPersonIds = new List <int>(); var personList = dataView.GetQuery(null, null, out errorMessages).OfType <Rock.Model.Person>().AsNoTracking().ToList(); if (!personList.Any()) { return(filteredPersonIds); } if (campaignConfiguration.FamilyLimits == FamilyLimits.HeadOfHouse) { var familyWithMembers = new Dictionary <int, List <GroupMember> >(); //// Get all family group Id and all it's family member in dictionary. //// We will all the family members to both figure out if might be opted out //// and to figure out the head of household foreach (var person in personList) { var family = person.GetFamily(rockContext); if (family != null && !familyWithMembers.ContainsKey(family.Id)) { var familyMembers = personService.GetFamilyMembers(family, person.Id, true).AsNoTracking().ToList(); familyWithMembers.Add(family.Id, familyMembers); } } if (campaignConfiguration.OptOutGroupGuid.HasValue) { var optOutGroup = new GroupService(rockContext).Get(campaignConfiguration.OptOutGroupGuid.Value); if (optOutGroup != null) { var personIds = optOutGroup.ActiveMembers().Select(a => a.PersonId).ToList(); // exclude families in which any member is part of optOut Group. familyWithMembers = familyWithMembers.Where(a => !a.Value.Any(b => personIds.Contains(b.PersonId))).ToDictionary(a => a.Key, b => b.Value); } } foreach (var familyId in familyWithMembers.Keys) { /* 2020-05-07 MDP * It is possible that a person is the Head Of Household in more than one family. For example: * -- Alex is in Ted Decker family. Ted Decker is Head of Household * -- Ted Decker is in Grandpa Decker family, and also the head of household for that one too * * We'll deal with that by putting a Distinct on the filteredPersonIds */ // Get all the head of house personIds of leftout family. var headOfHouse = familyWithMembers[familyId] .Where(m => !m.Person.IsDeceased) .OrderBy(m => m.GroupRole.Order) .ThenBy(m => m.Person.Gender) .Select(a => a.PersonId) .FirstOrDefault(); if (headOfHouse != default(int)) { filteredPersonIds.Add(headOfHouse); } } } else { if (campaignConfiguration.OptOutGroupGuid.HasValue) { var optOutGroup = new GroupService(rockContext).Get(campaignConfiguration.OptOutGroupGuid.Value); if (optOutGroup != null) { var personIds = optOutGroup.ActiveMembers().Select(a => a.PersonId).ToList(); personList = personList.Where(a => !personIds.Contains(a.Id)).ToList(); } } filteredPersonIds = personList.Select(a => a.Id).ToList(); } // just in case the same person is in multiple times (for example, head of household in multiple families), get just the distinct person ids filteredPersonIds = filteredPersonIds.Distinct().ToList(); return(filteredPersonIds); }
/// <summary> /// Clears the existing data from class var attendances and repopulates it with data for the selected group and filter criteria. /// Data is organized by each person in the group. /// </summary> private void GetAttendanceData() { attendances.Clear(); // Source data for all tables and graphs using (var rockContext = new RockContext()) { var attendanceService = new AttendanceService(rockContext); var groupAttendances = attendanceService .Queryable() .AsNoTracking() .Where(a => a.RequestedToAttend == true); switch (hfTabs.Value) { case "group": groupAttendances = groupAttendances.Where(a => a.Occurrence.GroupId == gpGroups.GroupId); break; case "person": groupAttendances = groupAttendances.Where(a => a.PersonAliasId == ppPerson.PersonAliasId); break; case "dataview": var dataView = new DataViewService(rockContext).Get(dvDataViews.SelectedValueAsInt().Value); var personsFromDv = dataView.GetQuery(null, rockContext, null, out _errorMessages) as IQueryable <Person>; var personAliasIds = personsFromDv.Select(d => d.Aliases.Where(a => a.AliasPersonId == d.Id).Select(a => a.Id).FirstOrDefault()).ToList(); groupAttendances = groupAttendances.Where(a => personAliasIds.Contains(a.PersonAliasId.Value)); break; default: break; } // parse the date range and add to query if (sdrpDateRange.DelimitedValues.IsNotNullOrWhiteSpace()) { var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(sdrpDateRange.DelimitedValues); if (dateRange.Start.HasValue) { groupAttendances = groupAttendances.Where(a => DbFunctions.TruncateTime(a.StartDateTime) >= dateRange.Start.Value); } if (dateRange.End.HasValue) { groupAttendances = groupAttendances.Where(a => DbFunctions.TruncateTime(a.StartDateTime) <= dateRange.End.Value); } } // add selected locations to the query if (cblLocations.SelectedValues.Any()) { groupAttendances = groupAttendances.Where(a => cblLocations.SelectedValuesAsInt.Contains(a.Occurrence.LocationId ?? -1)); } // add selected schedules to the query if (cblSchedules.SelectedValues.Any()) { groupAttendances = groupAttendances.Where(a => cblSchedules.SelectedValuesAsInt.Contains(a.Occurrence.ScheduleId ?? -1)); } attendances = groupAttendances.ToList(); } }
/// <summary> /// Job that will sync groups. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; try { // get groups set to sync RockContext rockContext = new RockContext(); GroupService groupService = new GroupService(rockContext); var groupsThatSync = groupService.Queryable().Where(g => g.SyncDataViewId != null).ToList(); foreach (var syncGroup in groupsThatSync) { bool hasGroupChanged = false; GroupMemberService groupMemberService = new GroupMemberService(rockContext); var syncSource = new DataViewService(rockContext).Get(syncGroup.SyncDataViewId.Value); // ensure this is a person dataview bool isPersonDataSet = syncSource.EntityTypeId == EntityTypeCache.Read(typeof(Rock.Model.Person)).Id; if (isPersonDataSet) { SortProperty sortById = new SortProperty(); sortById.Property = "Id"; sortById.Direction = System.Web.UI.WebControls.SortDirection.Ascending; List <string> errorMessages = new List <string>(); var sourceItems = syncSource.GetQuery(sortById, 180, out errorMessages).Select(q => q.Id).ToList(); var targetItems = groupMemberService.Queryable("Person").Where(gm => gm.GroupId == syncGroup.Id).ToList(); // delete items from the target not in the source foreach (var targetItem in targetItems.Where(t => !sourceItems.Contains(t.PersonId))) { // made a clone of the person as it will be detached when the group member is deleted. Also // saving the delete before the email is sent in case an exception occurs so the user doesn't // get an email everytime the agent runs. Person recipient = (Person)targetItem.Person.Clone(); groupMemberService.Delete(targetItem); rockContext.SaveChanges(); hasGroupChanged = true; if (syncGroup.ExitSystemEmailId.HasValue) { SendExitEmail(syncGroup.ExitSystemEmailId.Value, recipient, syncGroup); } } // add items not in target but in the source foreach (var sourceItem in sourceItems.Where(s => !targetItems.Select(t => t.PersonId).Contains(s))) { // add source to target var newGroupMember = new GroupMember { Id = 0 }; newGroupMember.PersonId = sourceItem; newGroupMember.Group = syncGroup; newGroupMember.GroupMemberStatus = GroupMemberStatus.Active; newGroupMember.GroupRoleId = syncGroup.GroupType.DefaultGroupRoleId ?? syncGroup.GroupType.Roles.FirstOrDefault().Id; groupMemberService.Add(newGroupMember); hasGroupChanged = true; if (syncGroup.WelcomeSystemEmailId.HasValue) { SendWelcomeEmail(syncGroup.WelcomeSystemEmailId.Value, sourceItem, syncGroup, syncGroup.AddUserAccountsDuringSync ?? false); } } rockContext.SaveChanges(); if (hasGroupChanged && (syncGroup.IsSecurityRole || syncGroup.GroupType.Guid.Equals(Rock.SystemGuid.GroupType.GROUPTYPE_SECURITY_ROLE.AsGuid()))) { Rock.Security.Role.Flush(syncGroup.Id); } } } } catch (System.Exception ex) { HttpContext context2 = HttpContext.Current; ExceptionLogService.LogException(ex, context2); throw; } }