/// <summary> /// Adds the changes. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="modelType">Type of the model.</param> /// <param name="categoryGuid">The category unique identifier.</param> /// <param name="entityId">The entity identifier.</param> /// <param name="changes">The changes.</param> /// <param name="caption">The caption.</param> /// <param name="relatedModelType">Type of the related model.</param> /// <param name="relatedEntityId">The related entity identifier.</param> /// <param name="modifiedByPersonAliasId">The modified by person alias identifier.</param> public static void AddChanges( RockContext rockContext, Type modelType, Guid categoryGuid, int entityId, List<string> changes, string caption, Type relatedModelType, int? relatedEntityId, int? modifiedByPersonAliasId = null ) { var entityType = EntityTypeCache.Read( modelType ); var category = CategoryCache.Read( categoryGuid ); var creationDate = RockDateTime.Now; int? relatedEntityTypeId = null; if ( relatedModelType != null ) { var relatedEntityType = EntityTypeCache.Read( relatedModelType ); if ( relatedModelType != null ) { relatedEntityTypeId = relatedEntityType.Id; } } if ( entityType != null && category != null ) { var historyService = new HistoryService( rockContext ); foreach ( string message in changes.Where( m => m != null && m != "" ) ) { var history = new History(); history.EntityTypeId = entityType.Id; history.CategoryId = category.Id; history.EntityId = entityId; history.Caption = caption.Truncate(200); history.Summary = message; history.RelatedEntityTypeId = relatedEntityTypeId; history.RelatedEntityId = relatedEntityId; if ( modifiedByPersonAliasId.HasValue ) { history.CreatedByPersonAliasId = modifiedByPersonAliasId; } // Manually set creation date on these history items so that they will be grouped together history.CreatedDateTime = creationDate; historyService.Add( history ); } } }
/// <summary> /// Sends the specified communication. /// </summary> /// <param name="communication">The communication.</param> /// <exception cref="System.NotImplementedException"></exception> public override void Send( Rock.Model.Communication communication ) { using ( var rockContext = new RockContext() ) { // Requery the Communication object communication = new CommunicationService( rockContext ) .Queryable( "CreatedByPersonAlias.Person" ) .FirstOrDefault( c => c.Id == communication.Id ); if ( communication != null && communication.Status == Model.CommunicationStatus.Approved && communication.Recipients.Where( r => r.Status == Model.CommunicationRecipientStatus.Pending ).Any() && ( !communication.FutureSendDateTime.HasValue || communication.FutureSendDateTime.Value.CompareTo( RockDateTime.Now ) <= 0 ) ) { var currentPerson = communication.CreatedByPersonAlias.Person; var globalAttributes = Rock.Web.Cache.GlobalAttributesCache.Read(); var globalConfigValues = Rock.Web.Cache.GlobalAttributesCache.GetMergeFields( currentPerson ); // From - if none is set, use the one in the Organization's GlobalAttributes. string fromAddress = communication.GetMediumDataValue( "FromAddress" ); if ( string.IsNullOrWhiteSpace( fromAddress ) ) { fromAddress = globalAttributes.GetValue( "OrganizationEmail" ); } string fromName = communication.GetMediumDataValue( "FromName" ); if ( string.IsNullOrWhiteSpace( fromName ) ) { fromName = globalAttributes.GetValue( "OrganizationName" ); } // Resolve any possible merge fields in the from address fromAddress = fromAddress.ResolveMergeFields( globalConfigValues, currentPerson ); fromName = fromName.ResolveMergeFields( globalConfigValues, currentPerson ); MailMessage message = new MailMessage(); message.From = new MailAddress( fromAddress, fromName ); // Reply To string replyTo = communication.GetMediumDataValue( "ReplyTo" ); if ( !string.IsNullOrWhiteSpace( replyTo ) ) { message.ReplyToList.Add( new MailAddress( replyTo ) ); } CheckSafeSender( message, globalAttributes ); // CC string cc = communication.GetMediumDataValue( "CC" ); if ( !string.IsNullOrWhiteSpace( cc ) ) { foreach ( string ccRecipient in cc.SplitDelimitedValues() ) { message.CC.Add( new MailAddress( ccRecipient ) ); } } // BCC string bcc = communication.GetMediumDataValue( "BCC" ); if ( !string.IsNullOrWhiteSpace( bcc ) ) { foreach ( string bccRecipient in bcc.SplitDelimitedValues() ) { message.Bcc.Add( new MailAddress( bccRecipient ) ); } } message.IsBodyHtml = true; message.Priority = MailPriority.Normal; using ( var smtpClient = GetSmtpClient() ) { // Add Attachments string attachmentIds = communication.GetMediumDataValue( "Attachments" ); if ( !string.IsNullOrWhiteSpace( attachmentIds ) ) { var binaryFileService = new BinaryFileService( rockContext ); foreach ( string idVal in attachmentIds.SplitDelimitedValues() ) { int binaryFileId = int.MinValue; if ( int.TryParse( idVal, out binaryFileId ) ) { var binaryFile = binaryFileService.Get( binaryFileId ); if ( binaryFile != null ) { message.Attachments.Add( new Attachment( binaryFile.ContentStream, binaryFile.FileName ) ); } } } } var historyService = new HistoryService( rockContext ); var recipientService = new CommunicationRecipientService( rockContext ); var personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id; var communicationEntityTypeId = EntityTypeCache.Read( "Rock.Model.Communication" ).Id; var communicationCategoryId = CategoryCache.Read( Rock.SystemGuid.Category.HISTORY_PERSON_COMMUNICATIONS.AsGuid(), rockContext ).Id; bool recipientFound = true; while ( recipientFound ) { var recipient = Rock.Model.Communication.GetNextPending( communication.Id, rockContext ); if ( recipient != null ) { if ( string.IsNullOrWhiteSpace( recipient.PersonAlias.Person.Email ) ) { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "No Email Address"; } else { try { message.To.Clear(); message.Headers.Clear(); message.AlternateViews.Clear(); message.To.Add( new MailAddress( recipient.PersonAlias.Person.Email, recipient.PersonAlias.Person.FullName ) ); // Create merge field dictionary var mergeObjects = recipient.CommunicationMergeValues( globalConfigValues ); // Subject message.Subject = communication.Subject.ResolveMergeFields( mergeObjects, currentPerson ); // convert any special microsoft word characters to normal chars so they don't look funny (for example "Hey “double-quotes†from ‘single quote’") message.Subject = message.Subject.ReplaceWordChars(); // Add any additional headers that specific SMTP provider needs AddAdditionalHeaders( message, recipient ); // Add text view first as last view is usually treated as the preferred view by email readers (gmail) string plainTextBody = Rock.Communication.Medium.Email.ProcessTextBody( communication, globalAttributes, mergeObjects, currentPerson ); // convert any special microsoft word characters to normal chars so they don't look funny plainTextBody = plainTextBody.ReplaceWordChars(); if ( !string.IsNullOrWhiteSpace( plainTextBody ) ) { AlternateView plainTextView = AlternateView.CreateAlternateViewFromString( plainTextBody, new System.Net.Mime.ContentType( MediaTypeNames.Text.Plain ) ); message.AlternateViews.Add( plainTextView ); } // Add Html view string htmlBody = Rock.Communication.Medium.Email.ProcessHtmlBody( communication, globalAttributes, mergeObjects, currentPerson ); // convert any special microsoft word characters to normal chars so they don't look funny htmlBody = htmlBody.ReplaceWordChars(); if ( !string.IsNullOrWhiteSpace( htmlBody ) ) { AlternateView htmlView = AlternateView.CreateAlternateViewFromString( htmlBody, new System.Net.Mime.ContentType( MediaTypeNames.Text.Html ) ); message.AlternateViews.Add( htmlView ); } smtpClient.Send( message ); recipient.Status = CommunicationRecipientStatus.Delivered; string statusNote = StatusNote; if ( !string.IsNullOrWhiteSpace( statusNote ) ) { recipient.StatusNote = statusNote; } recipient.TransportEntityTypeName = this.GetType().FullName; historyService.Add( new History { CreatedByPersonAliasId = communication.SenderPersonAliasId, EntityTypeId = personEntityTypeId, CategoryId = communicationCategoryId, EntityId = recipient.PersonAlias.PersonId, Summary = string.Format( "Sent communication from <span class='field-value'>{0}</span>.", message.From.DisplayName ), Caption = message.Subject, RelatedEntityTypeId = communicationEntityTypeId, RelatedEntityId = communication.Id } ); } catch ( Exception ex ) { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "Exception: " + ex.Message; } } rockContext.SaveChanges(); } else { recipientFound = false; } } } } } }
/// <summary> /// Handles the Click event of the btnSave 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 btnSave_Click( object sender, EventArgs e ) { // confirmation was disabled by btnSave on client-side. So if returning without a redirect, // it should be enabled. If returning with a redirect, the control won't be updated to reflect // confirmation being enabled, so it's ok to enable it here confirmExit.Enabled = true; if ( Page.IsValid ) { confirmExit.Enabled = true; RockTransactionScope.WrapTransaction( () => { var rockContext = new RockContext(); var familyService = new GroupService( rockContext ); var familyMemberService = new GroupMemberService( rockContext ); var personService = new PersonService( rockContext ); var historyService = new HistoryService( rockContext ); var familyChanges = new List<string>(); // SAVE FAMILY _family = familyService.Get( _family.Id ); History.EvaluateChange( familyChanges, "Family Name", _family.Name, tbFamilyName.Text ); _family.Name = tbFamilyName.Text; int? campusId = cpCampus.SelectedValueAsInt(); if ( _family.CampusId != campusId ) { History.EvaluateChange( familyChanges, "Campus", _family.CampusId.HasValue ? CampusCache.Read( _family.CampusId.Value ).Name : string.Empty, campusId.HasValue ? CampusCache.Read( campusId.Value ).Name : string.Empty ); _family.CampusId = campusId; } var familyGroupTypeId = _family.GroupTypeId; rockContext.SaveChanges(); // SAVE FAMILY MEMBERS int? recordStatusValueID = ddlRecordStatus.SelectedValueAsInt(); int? reasonValueId = ddlReason.SelectedValueAsInt(); var newFamilies = new List<Group>(); foreach ( var familyMember in FamilyMembers ) { var memberChanges = new List<string>(); var demographicChanges = new List<string>(); var role = familyRoles.Where( r => r.Guid.Equals( familyMember.RoleGuid ) ).FirstOrDefault(); if ( role == null ) { role = familyRoles.FirstOrDefault(); } bool isChild = role != null && role.Guid.Equals( new Guid( Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_CHILD ) ); // People added to family (new or from other family) if ( !familyMember.ExistingFamilyMember ) { var groupMember = new GroupMember(); if ( familyMember.Id == -1 ) { // added new person demographicChanges.Add( "Created" ); var person = new Person(); person.FirstName = familyMember.FirstName; person.NickName = familyMember.NickName; History.EvaluateChange( demographicChanges, "First Name", string.Empty, person.FirstName ); person.LastName = familyMember.LastName; History.EvaluateChange( demographicChanges, "Last Name", string.Empty, person.LastName ); person.Gender = familyMember.Gender; History.EvaluateChange( demographicChanges, "Gender", null, person.Gender ); person.BirthDate = familyMember.BirthDate; History.EvaluateChange( demographicChanges, "Birth Date", null, person.BirthDate ); if ( !isChild ) { person.GivingGroupId = _family.Id; History.EvaluateChange( demographicChanges, "Giving Group", string.Empty, _family.Name ); } person.EmailPreference = EmailPreference.EmailAllowed; groupMember.Person = person; } else { // added from other family groupMember.Person = personService.Get( familyMember.Id ); } if ( recordStatusValueID > 0 ) { History.EvaluateChange( demographicChanges, "Record Status", DefinedValueCache.GetName( groupMember.Person.RecordStatusValueId ), DefinedValueCache.GetName( recordStatusValueID ) ); groupMember.Person.RecordStatusValueId = recordStatusValueID; History.EvaluateChange( demographicChanges, "Record Status Reason", DefinedValueCache.GetName( groupMember.Person.RecordStatusReasonValueId ), DefinedValueCache.GetName( reasonValueId ) ); groupMember.Person.RecordStatusReasonValueId = reasonValueId; } groupMember.GroupId = _family.Id; if ( role != null ) { History.EvaluateChange( memberChanges, "Role", string.Empty, role.Name ); groupMember.GroupRoleId = role.Id; } if ( groupMember.Person != null ) { familyMemberService.Add( groupMember ); rockContext.SaveChanges(); familyMember.Id = groupMember.Person.Id; } } else { // existing family members var groupMember = familyMemberService.Queryable( "Person" ).Where( m => m.PersonId == familyMember.Id && m.Group.GroupTypeId == familyGroupTypeId && m.GroupId == _family.Id ).FirstOrDefault(); if ( groupMember != null ) { if ( familyMember.Removed ) { var newFamilyChanges = new List<string>(); // Family member was removed and should be created in their own new family var newFamily = new Group(); newFamily.Name = familyMember.LastName + " Family"; History.EvaluateChange( newFamilyChanges, "Family", string.Empty, newFamily.Name ); newFamily.GroupTypeId = familyGroupTypeId; if ( _family.CampusId.HasValue ) { History.EvaluateChange( newFamilyChanges, "Campus", string.Empty, CampusCache.Read( _family.CampusId.Value ).Name ); } newFamily.CampusId = _family.CampusId; familyService.Add( newFamily ); rockContext.SaveChanges(); // If person's previous giving group was this family, set it to their new family id if ( groupMember.Person.GivingGroup != null && groupMember.Person.GivingGroupId == _family.Id ) { History.EvaluateChange( demographicChanges, "Giving Group", groupMember.Person.GivingGroup.Name, _family.Name ); groupMember.Person.GivingGroupId = newFamily.Id; } groupMember.Group = newFamily; rockContext.SaveChanges(); var newMemberChanges = new List<string>(); History.EvaluateChange( newMemberChanges, "Role", string.Empty, groupMember.GroupRole.Name ); HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), groupMember.Person.Id, newFamilyChanges, newFamily.Name, typeof( Group ), newFamily.Id ); newFamilies.Add( newFamily ); History.EvaluateChange( memberChanges, "Role", groupMember.GroupRole.Name, string.Empty ); } else { // Existing member was not remvoved if ( role != null ) { History.EvaluateChange( memberChanges, "Role", groupMember.GroupRole != null ? groupMember.GroupRole.Name : string.Empty, role.Name ); groupMember.GroupRoleId = role.Id; if ( recordStatusValueID > 0 ) { History.EvaluateChange( demographicChanges, "Record Status", DefinedValueCache.GetName( groupMember.Person.RecordStatusValueId ), DefinedValueCache.GetName( recordStatusValueID ) ); groupMember.Person.RecordStatusValueId = recordStatusValueID; History.EvaluateChange( demographicChanges, "Record Status Reason", DefinedValueCache.GetName( groupMember.Person.RecordStatusReasonValueId ), DefinedValueCache.GetName( reasonValueId ) ); groupMember.Person.RecordStatusReasonValueId = reasonValueId; } rockContext.SaveChanges(); } } } } // Remove anyone that was moved from another family if ( familyMember.RemoveFromOtherFamilies ) { var otherFamilies = familyMemberService.Queryable() .Where( m => m.PersonId == familyMember.Id && m.Group.GroupTypeId == familyGroupTypeId && m.GroupId != _family.Id ) .ToList(); foreach ( var otherFamilyMember in otherFamilies ) { var fm = familyMemberService.Get( otherFamilyMember.Id ); // If the person's giving group id was the family they are being removed from, update it to this new family's id if ( fm.Person.GivingGroupId == fm.GroupId ) { var person = personService.Get( fm.PersonId ); History.EvaluateChange( demographicChanges, "Giving Group", person.GivingGroup.Name, _family.Name ); person.GivingGroupId = _family.Id; rockContext.SaveChanges(); } var oldMemberChanges = new List<string>(); History.EvaluateChange( oldMemberChanges, "Role", fm.GroupRole.Name, string.Empty ); History.EvaluateChange( oldMemberChanges, "Family", fm.Group.Name, string.Empty ); HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), fm.Person.Id, oldMemberChanges, fm.Group.Name, typeof( Group ), fm.Group.Id ); familyMemberService.Delete( fm ); rockContext.SaveChanges(); var f = familyService.Queryable() .Where( g => g.Id == otherFamilyMember.GroupId && !g.Members.Any() ) .FirstOrDefault(); if ( f != null ) { familyService.Delete( f ); rockContext.SaveChanges(); } } } HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), familyMember.Id, demographicChanges ); HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), familyMember.Id, memberChanges, _family.Name, typeof( Group ), _family.Id ); } // SAVE LOCATIONS var groupLocationService = new GroupLocationService( rockContext ); // delete any group locations that were removed var remainingLocationIds = FamilyAddresses.Where( a => a.Id > 0 ).Select( a => a.Id ).ToList(); foreach ( var removedLocation in groupLocationService.Queryable( "GroupLocationTypeValue,Location" ) .Where( l => l.GroupId == _family.Id && !remainingLocationIds.Contains( l.Id ) ) ) { History.EvaluateChange( familyChanges, removedLocation.GroupLocationTypeValue.Name + " Location", removedLocation.Location.ToString(), string.Empty ); groupLocationService.Delete( removedLocation ); } rockContext.SaveChanges(); foreach ( var familyAddress in FamilyAddresses ) { Location updatedAddress = null; if ( familyAddress.LocationIsDirty ) { updatedAddress = new LocationService( rockContext ).Get( familyAddress.Street1, familyAddress.Street2, familyAddress.City, familyAddress.State, familyAddress.Zip ); } GroupLocation groupLocation = null; if ( familyAddress.Id > 0 ) { groupLocation = groupLocationService.Get( familyAddress.Id ); } if ( groupLocation == null ) { groupLocation = new GroupLocation(); groupLocation.GroupId = _family.Id; groupLocationService.Add( groupLocation ); } History.EvaluateChange( familyChanges, "Location Type", groupLocation.GroupLocationTypeValueId.HasValue ? DefinedValueCache.Read( groupLocation.GroupLocationTypeValueId.Value ).Name : string.Empty, familyAddress.LocationTypeName ); groupLocation.GroupLocationTypeValueId = familyAddress.LocationTypeId; History.EvaluateChange( familyChanges, familyAddress.LocationTypeName + " Is Mailing", groupLocation.IsMailingLocation.ToString(), familyAddress.IsMailing.ToString() ); groupLocation.IsMailingLocation = familyAddress.IsMailing; History.EvaluateChange( familyChanges, familyAddress.LocationTypeName + " Is Map Location", groupLocation.IsMappedLocation.ToString(), familyAddress.IsLocation.ToString() ); groupLocation.IsMappedLocation = familyAddress.IsLocation; if ( updatedAddress != null ) { History.EvaluateChange( familyChanges, familyAddress.LocationTypeName + " Location", groupLocation.Location != null ? groupLocation.Location.ToString() : "", updatedAddress.ToString() ); groupLocation.Location = updatedAddress; } rockContext.SaveChanges(); // Add the same locations to any new families created by removing an existing family member if ( newFamilies.Any() ) { //reload grouplocation for access to child properties groupLocation = groupLocationService.Get( groupLocation.Id ); foreach ( var newFamily in newFamilies ) { var newFamilyLocation = new GroupLocation(); newFamilyLocation.GroupId = newFamily.Id; newFamilyLocation.LocationId = groupLocation.LocationId; newFamilyLocation.GroupLocationTypeValueId = groupLocation.GroupLocationTypeValueId; newFamilyLocation.IsMailingLocation = groupLocation.IsMailingLocation; newFamilyLocation.IsMappedLocation = groupLocation.IsMappedLocation; groupLocationService.Add( newFamilyLocation ); } rockContext.SaveChanges(); } } foreach ( var fm in _family.Members ) { HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), fm.PersonId, familyChanges, _family.Name, typeof( Group ), _family.Id ); } _family = familyService.Get( _family.Id ); if ( _family.Members.Any( m => m.PersonId == Person.Id ) ) { Response.Redirect( string.Format( "~/Person/{0}", Person.Id ), false ); } else { var fm = _family.Members .Where( m => m.GroupRole.Guid.Equals( new Guid( Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT ) ) && m.Person.Gender == Gender.Male ) .OrderByDescending( m => m.Person.Age ) .FirstOrDefault(); if ( fm == null ) { fm = _family.Members .Where( m => m.GroupRole.Guid.Equals( new Guid( Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT ) ) ) .OrderByDescending( m => m.Person.Age ) .FirstOrDefault(); } if ( fm == null ) { fm = _family.Members .OrderByDescending( m => m.Person.Age ) .FirstOrDefault(); } if ( fm != null ) { Response.Redirect( string.Format( "~/Person/{0}", fm.PersonId ), false ); } else { Response.Redirect( "~", false ); } } } ); } }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { if (Person != null) { var familyIds = families.Select( f => f.Key ).ToList(); var qry = new HistoryService( new RockContext() ).Queryable( "CreatedByPersonAlias.Person" ) .Where( h => ( h.EntityTypeId == personEntityTypeId && h.EntityId == Person.Id ) || ( h.EntityTypeId == groupEntityTypeId && familyIds.Contains( h.EntityId ) ) ); int categoryId = int.MinValue; if (int.TryParse(gfSettings.GetUserPreference("Category"), out categoryId)) { qry = qry.Where( h => h.CategoryId == categoryId); } string summary = gfSettings.GetUserPreference("Summary Contains"); if (!string.IsNullOrWhiteSpace(summary)) { qry = qry.Where( h => h.Summary.Contains( summary ) ); } int personId = int.MinValue; if ( int.TryParse( gfSettings.GetUserPreference( "Who" ), out personId ) ) { qry = qry.Where( h => h.CreatedByPersonAlias.PersonId == personId ); } var drp = new DateRangePicker(); drp.DelimitedValues = gfSettings.GetUserPreference( "Date Range" ); if ( drp.LowerValue.HasValue ) { qry = qry.Where( h => h.CreatedDateTime >= drp.LowerValue.Value ); } if ( drp.UpperValue.HasValue ) { DateTime upperDate = drp.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( h => h.CreatedDateTime < upperDate ); } SortProperty sortProperty = gHistory.SortProperty; if ( sortProperty != null ) { qry = qry.Sort( sortProperty ); } else { qry = qry.OrderByDescending( t => t.CreatedDateTime ); } // Combine history records that were saved at the same time var histories = new List<History>(); foreach(var history in qry) { var existingHistory = histories .Where( h => h.CreatedByPersonAliasId == history.CreatedByPersonAliasId && h.CreatedDateTime == history.CreatedDateTime && h.EntityTypeId == history.EntityTypeId && h.EntityId == history.EntityId && h.CategoryId == history.CategoryId && h.RelatedEntityTypeId == history.RelatedEntityTypeId && h.RelatedEntityId == history.RelatedEntityId ).FirstOrDefault(); if (existingHistory != null) { existingHistory.Summary += "<br/>" + history.Summary; } else { histories.Add(history); } } gHistory.DataSource = histories.Select( h => new { Id = h.Id, CategoryId = h.CategoryId, Category = h.Category != null ? h.Category.Name : "", EntityTypeId = h.EntityTypeId, EntityId = h.EntityId, Caption = h.Caption ?? string.Empty, Summary = h.Summary, RelatedEntityTypeId = h.RelatedEntityTypeId ?? 0, RelatedEntityId = h.RelatedEntityId ?? 0, CreatedByPersonId = h.CreatedByPersonAlias != null ? h.CreatedByPersonAlias.PersonId : 0, PersonName = h.CreatedByPersonAlias != null && h.CreatedByPersonAlias.Person != null ? h.CreatedByPersonAlias.Person.NickName + " " + h.CreatedByPersonAlias.Person.LastName : "", CreatedDateTime = h.CreatedDateTime } ).ToList(); gHistory.DataBind(); } }
/// <summary> /// Job that will run quick SQL queries on a schedule. /// /// 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; Guid? entryWorkflowType = dataMap.GetString( "EraEntryWorkflow" ).AsGuidOrNull(); Guid? exitWorkflowType = dataMap.GetString( "EraExitWorkflow" ).AsGuidOrNull(); bool updateVisitDates = dataMap.GetBooleanValue( "SetVisitDates" ); var groupTypeList = dataMap.GetString( "GroupTypes" ); // configuration // // giving int exitGivingCount = 1; // attendance int exitAttendanceCountShort = 1; int exitAttendanceCountLong = 8; // get era dataset from stored proc var resultContext = new RockContext(); var eraAttribute = AttributeCache.Read( SystemGuid.Attribute.PERSON_ERA_CURRENTLY_AN_ERA.AsGuid() ); var eraStartAttribute = AttributeCache.Read( SystemGuid.Attribute.PERSON_ERA_START_DATE.AsGuid() ); var eraEndAttribute = AttributeCache.Read( SystemGuid.Attribute.PERSON_ERA_END_DATE.AsGuid() ); resultContext.Database.CommandTimeout = 3600; var results = resultContext.Database.SqlQuery<EraResult>( "spCrm_FamilyAnalyticsEraDataset" ).ToList(); int personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id; int attributeEntityTypeId = EntityTypeCache.Read( "Rock.Model.Attribute" ).Id; int eraAttributeId = AttributeCache.Read( SystemGuid.Attribute.PERSON_ERA_CURRENTLY_AN_ERA.AsGuid() ).Id; int personAnalyticsCategoryId = CategoryCache.Read( SystemGuid.Category.HISTORY_PERSON_ANALYTICS.AsGuid() ).Id; foreach (var result in results ) { // create new rock context for each family (https://weblog.west-wind.com/posts/2014/Dec/21/Gotcha-Entity-Framework-gets-slow-in-long-Iteration-Loops) RockContext updateContext = new RockContext(); var attributeValueService = new AttributeValueService( updateContext ); var historyService = new HistoryService( updateContext ); // if era ensure it still meets requirements if ( result.IsEra ) { if (result.ExitGiftCountDuration < exitGivingCount && result.ExitAttendanceCountDurationShort < exitAttendanceCountShort && result.ExitAttendanceCountDurationLong < exitAttendanceCountLong ) { // exit era (delete attribute value from each person in family) var family = new GroupService( updateContext ).Queryable( "Members, Members.Person" ).AsNoTracking().Where( m => m.Id == result.FamilyId ).FirstOrDefault(); if ( family != null ) { foreach ( var person in family.Members.Select( m => m.Person ) ) { // remove the era flag var eraAttributeValue = attributeValueService.Queryable().Where( v => v.AttributeId == eraAttribute.Id && v.EntityId == person.Id ).FirstOrDefault(); if ( eraAttributeValue != null ) { attributeValueService.Delete( eraAttributeValue ); } // set end date var eraEndAttributeValue = attributeValueService.Queryable().Where( v => v.AttributeId == eraEndAttribute.Id && v.EntityId == person.Id ).FirstOrDefault(); if ( eraEndAttributeValue == null ) { eraEndAttributeValue = new AttributeValue(); eraEndAttributeValue.EntityId = person.Id; eraEndAttributeValue.AttributeId = eraEndAttribute.Id; attributeValueService.Add( eraEndAttributeValue ); } eraEndAttributeValue.Value = RockDateTime.Now.ToString(); // add a history record if ( personAnalyticsCategoryId != 0 && personEntityTypeId != 0 && attributeEntityTypeId != 0 && eraAttributeId != 0 ) { History historyRecord = new History(); historyService.Add( historyRecord ); historyRecord.EntityTypeId = personEntityTypeId; historyRecord.EntityId = person.Id; historyRecord.CreatedDateTime = RockDateTime.Now; historyRecord.CreatedByPersonAliasId = person.PrimaryAliasId; historyRecord.Caption = "eRA"; historyRecord.Summary = "Exited eRA Status"; historyRecord.Verb = "EXITED"; historyRecord.RelatedEntityTypeId = attributeEntityTypeId; historyRecord.RelatedEntityId = eraAttributeId; historyRecord.CategoryId = personAnalyticsCategoryId; } updateContext.SaveChanges(); } // launch exit workflow if ( exitWorkflowType.HasValue ) { LaunchWorkflow( exitWorkflowType.Value, family ); } } } } else { // entered era var family = new GroupService( updateContext ).Queryable( "Members" ).AsNoTracking().Where( m => m.Id == result.FamilyId ).FirstOrDefault(); if ( family != null ) { foreach ( var person in family.Members.Select( m => m.Person ) ) { // set era attribute to true var eraAttributeValue = attributeValueService.Queryable().Where( v => v.AttributeId == eraAttribute.Id && v.EntityId == person.Id ).FirstOrDefault(); if ( eraAttributeValue == null ) { eraAttributeValue = new AttributeValue(); eraAttributeValue.EntityId = person.Id; eraAttributeValue.AttributeId = eraAttribute.Id; attributeValueService.Add( eraAttributeValue ); } eraAttributeValue.Value = bool.TrueString; // add start date var eraStartAttributeValue = attributeValueService.Queryable().Where( v => v.AttributeId == eraStartAttribute.Id && v.EntityId == person.Id ).FirstOrDefault(); if (eraStartAttributeValue == null ) { eraStartAttributeValue = new AttributeValue(); eraStartAttributeValue.EntityId = person.Id; eraStartAttributeValue.AttributeId = eraStartAttribute.Id; attributeValueService.Add( eraStartAttributeValue ); } eraStartAttributeValue.Value = RockDateTime.Now.ToString(); // delete end date if it exists var eraEndAttributeValue = attributeValueService.Queryable().Where( v => v.AttributeId == eraEndAttribute.Id && v.EntityId == person.Id ).FirstOrDefault(); if ( eraEndAttributeValue != null ) { attributeValueService.Delete( eraEndAttributeValue ); } // add a history record if ( personAnalyticsCategoryId != 0 && personEntityTypeId != 0 && attributeEntityTypeId != 0 && eraAttributeId != 0 ) { History historyRecord = new History(); historyService.Add( historyRecord ); historyRecord.EntityTypeId = personEntityTypeId; historyRecord.EntityId = person.Id; historyRecord.CreatedDateTime = RockDateTime.Now; historyRecord.CreatedByPersonAliasId = person.PrimaryAliasId; historyRecord.Caption = "eRA"; historyRecord.Summary = "Entered eRA Status"; historyRecord.Verb = "ENTERED"; historyRecord.RelatedEntityTypeId = attributeEntityTypeId; historyRecord.RelatedEntityId = eraAttributeId; historyRecord.CategoryId = personAnalyticsCategoryId; } updateContext.SaveChanges(); } // launch entry workflow if ( entryWorkflowType.HasValue ) { LaunchWorkflow( entryWorkflowType.Value, family ); } } } // update stats } // load giving attributes resultContext.Database.ExecuteSqlCommand( "spCrm_FamilyAnalyticsGiving" ); // load attendance attributes resultContext.Database.ExecuteSqlCommand( "spCrm_FamilyAnalyticsAttendance" ); // process history for group types if (!string.IsNullOrWhiteSpace( groupTypeList ) ) { string[] groupTypeGuids = groupTypeList.Split( ',' ); var inactiveRecordValue = DefinedValueCache.Read( SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE ); var groupTypeEntityTypeId = EntityTypeCache.Read( "Rock.Model.GroupType" ).Id; foreach ( var groupTypeGuid in groupTypeGuids ) { var groupType = GroupTypeCache.Read( groupTypeGuid.AsGuid() ); if ( groupType != null ) { // if the person is in a group of that type and the last history record for that group type isn't START write a start RockContext rockContext = new RockContext(); // get history for this group type var historyRecords = new HistoryService( rockContext ).Queryable() .Where( h => h.EntityTypeId == personEntityTypeId && h.RelatedEntityTypeId == groupTypeEntityTypeId && h.RelatedEntityId == groupType.Id ) .GroupBy( h => h.EntityId ) .Select( g => g.OrderByDescending( h => h.CreatedDateTime ).Select( h => new { h.EntityId, h.Verb } ).FirstOrDefault() ) .ToList(); // get group member information var groupMemberInfo = new GroupMemberService( rockContext ).Queryable() .Where( m => m.Group.GroupTypeId == groupType.Id && m.GroupMemberStatus == GroupMemberStatus.Active && m.Group.IsActive //&& m.Person.RecordStatusValueId != inactiveRecordValue.Id ) .GroupBy( m => m.PersonId ) .Select( g => g.OrderBy( m => m.CreatedDateTime ).Select( m => new { m.PersonId, m.CreatedDateTime, PersonAliasId = m.Person.Aliases.Select( p => p.Id ).FirstOrDefault() } ).FirstOrDefault() ) .ToList(); var needsStartDate = groupMemberInfo.Where( m => !historyRecords.Any( h => h.EntityId == m.PersonId && h.Verb == "STARTED" ) ); foreach ( var startItem in needsStartDate ) { using ( RockContext updateContext = new RockContext() ) { var historyService = new HistoryService( updateContext ); History history = new History(); historyService.Add( history ); history.EntityTypeId = personEntityTypeId; history.EntityId = startItem.PersonId; history.RelatedEntityTypeId = groupTypeEntityTypeId; history.RelatedEntityId = groupType.Id; history.Caption = groupType.Name; history.Summary = "Started Membership in Group Of Type"; history.Verb = "STARTED"; history.CreatedDateTime = startItem.CreatedDateTime; history.CreatedByPersonAliasId = startItem.PersonAliasId; history.CategoryId = personAnalyticsCategoryId; updateContext.SaveChanges(); } } var needsStoppedDate = historyRecords.Where( h => h.Verb == "STARTED" && !groupMemberInfo.Any( m => m.PersonId == h.EntityId ) ); foreach ( var stopItem in needsStoppedDate ) { using ( RockContext updateContext = new RockContext() ) { var person = new PersonService( updateContext ).Get( stopItem.EntityId ); if ( person != null ) { var historyService = new HistoryService( updateContext ); History history = new History(); historyService.Add( history ); history.EntityTypeId = personEntityTypeId; history.EntityId = person.Id; history.RelatedEntityTypeId = groupTypeEntityTypeId; history.RelatedEntityId = groupType.Id; history.Caption = groupType.Name; history.Summary = "Stopped Membership in Group Of Type"; history.Verb = "STOPPED"; history.CreatedDateTime = RockDateTime.Now; history.CreatedByPersonAliasId = person.PrimaryAliasId; history.CategoryId = personAnalyticsCategoryId; updateContext.SaveChanges(); } } } } } } // process visit dates if ( updateVisitDates ) { resultContext.Database.ExecuteSqlCommand( "spCrm_FamilyAnalyticsUpdateVisitDates" ); } }
/// <summary> /// Deletes any saved history items. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="modelType">Type of the model.</param> /// <param name="entityId">The entity identifier.</param> public static void DeleteChanges( RockContext rockContext, Type modelType, int entityId ) { var entityType = EntityTypeCache.Read( modelType ); if ( entityType != null ) { var historyService = new HistoryService( rockContext ); foreach( var history in historyService.Queryable() .Where( h => h.EntityTypeId == entityType.Id && h.EntityId == entityId ) ) { historyService.Delete( history ); } rockContext.SaveChanges(); } }
/// <summary> /// Sends the specified communication. /// </summary> /// <param name="communication">The communication.</param> /// <exception cref="System.NotImplementedException"></exception> public override void Send( Rock.Model.Communication communication ) { using ( var rockContext = new RockContext() ) { // Requery the Communication communication = new CommunicationService( rockContext ).Get( communication.Id ); if ( communication != null && communication.Status == CommunicationStatus.Approved && communication.Recipients.Any(r => r.Status == CommunicationRecipientStatus.Pending) && ( !communication.FutureSendDateTime.HasValue || communication.FutureSendDateTime.Value.CompareTo( RockDateTime.Now ) <= 0 ) ) { // Remove all non alpha numeric from fromValue string fromValue = communication.GetMediumDataValue( "NoReply_FromValue" ); //Ensure that the fromValue is correct fromValue = new string( fromValue.ToCharArray().Where( c => char.IsLetterOrDigit( c ) || char.IsWhiteSpace( c ) ).Take( 11 ).ToArray() ) ; string senderGuid = communication.GetMediumDataValue( "SenderGuid" ); if ( !string.IsNullOrWhiteSpace( fromValue ) && !string.IsNullOrWhiteSpace( senderGuid ) ) { string accountSid = GetAttributeValue( "SID" ); string authToken = GetAttributeValue( "Token" ); if (string.IsNullOrWhiteSpace(accountSid) || string.IsNullOrWhiteSpace(authToken)) { throw new Exception("Either SID or Token not provided"); } var twilio = new TwilioRestClient( accountSid, authToken ); var historyService = new HistoryService( rockContext ); int personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id; int communicationEntityTypeId = EntityTypeCache.Read( "Rock.Model.Communication" ).Id; int communicationCategoryId = CategoryCache.Read( Rock.SystemGuid.Category.HISTORY_PERSON_COMMUNICATIONS.AsGuid(), rockContext ).Id; var sender = new PersonService( rockContext ).Get( senderGuid.AsGuid() ); var mergeFields = GlobalAttributesCache.GetMergeFields( null ); if ( sender != null ) { mergeFields.Add( "Sender", sender ); } bool recipientFound = true; while ( recipientFound ) { var recipient = Rock.Model.Communication.GetNextPending( communication.Id, rockContext ); if ( recipient != null ) { try { var phoneNumber = recipient.PersonAlias.Person.PhoneNumbers .FirstOrDefault(p => p.IsMessagingEnabled); if ( phoneNumber != null ) { // Create merge field dictionary var mergeObjects = recipient.CommunicationMergeValues( mergeFields ); string message = communication.GetMediumDataValue( "NoReply_Message" ); string footer = GetAttributeValue( "footer" ); if ( communication.GetMediumDataValue( "NoReply_AppendUserInfo" ).AsBoolean() && !string.IsNullOrEmpty( footer ) ) { message += "\n " + footer; } else { message += "\n This message was sent on behalf of {{ GlobalAttribute.OrganizationName }} from a no reply number."; } message = message.ReplaceWordChars(); message = message.ResolveMergeFields( mergeObjects ); string twilioNumber = phoneNumber.Number; if ( !string.IsNullOrWhiteSpace( phoneNumber.CountryCode ) ) { twilioNumber = "+" + phoneNumber.CountryCode + phoneNumber.Number; } var globalAttributes = GlobalAttributesCache.Read(); if (globalAttributes == null) { throw new Exception("Error getting Global Attributes"); } string callbackUrl = globalAttributes.GetValue( "PublicApplicationRoot" ) + "Webhooks/Twilio.ashx"; var response = twilio.SendMessage( fromValue, twilioNumber, message, callbackUrl ); if (response != null) { recipient.Status = GetCommunicationRecipientStatus(response); recipient.TransportEntityTypeName = GetType().FullName; recipient.UniqueMessageId = response.Sid; try { historyService.Add(new History { CreatedByPersonAliasId = communication.SenderPersonAliasId, EntityTypeId = personEntityTypeId, CategoryId = communicationCategoryId, EntityId = recipient.PersonAlias.PersonId, Summary = "Sent an alphanumeric SMS message from " + fromValue + ".", Caption = message.Truncate(200), RelatedEntityTypeId = communicationEntityTypeId, RelatedEntityId = communication.Id }); } catch (Exception ex) { ExceptionLogService.LogException(ex, null); } } else { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "No response from Twilio"; } } else { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "No phone number with messaging enabled"; } } catch ( Exception ex ) { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "Twilio Exception: " + ex.Message; ExceptionLogService.LogException( ex, null ); } rockContext.SaveChanges(); } else { recipientFound = false; } } } } } }
/// <summary> /// Sends the specified communication. /// </summary> /// <param name="communication">The communication.</param> /// <exception cref="System.NotImplementedException"></exception> public override void Send( Rock.Model.Communication communication ) { var rockContext = new RockContext(); // Requery the Communication communication = new CommunicationService( rockContext ).Get( communication.Id ); if ( communication != null && communication.Status == Model.CommunicationStatus.Approved && communication.Recipients.Where( r => r.Status == Model.CommunicationRecipientStatus.Pending ).Any() && ( !communication.FutureSendDateTime.HasValue || communication.FutureSendDateTime.Value.CompareTo( RockDateTime.Now ) <= 0 ) ) { string fromPhone = string.Empty; string fromValue = communication.GetMediumDataValue( "FromValue" ); int fromValueId = int.MinValue; if ( int.TryParse( fromValue, out fromValueId ) ) { fromPhone = DefinedValueCache.Read( fromValueId, rockContext ).Value; } if ( !string.IsNullOrWhiteSpace( fromPhone ) ) { string accountSid = GetAttributeValue( "SID" ); string authToken = GetAttributeValue( "Token" ); var twilio = new TwilioRestClient( accountSid, authToken ); var historyService = new HistoryService( rockContext ); var recipientService = new CommunicationRecipientService( rockContext ); var personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id; var communicationEntityTypeId = EntityTypeCache.Read( "Rock.Model.Communication" ).Id; var communicationCategoryId = CategoryCache.Read( Rock.SystemGuid.Category.HISTORY_PERSON_COMMUNICATIONS.AsGuid(), rockContext ).Id; var globalConfigValues = GlobalAttributesCache.GetMergeFields( null ); bool recipientFound = true; while ( recipientFound ) { var recipient = recipientService.Get( communication.Id, CommunicationRecipientStatus.Pending ).FirstOrDefault(); if ( recipient != null ) { try { var phoneNumber = recipient.PersonAlias.Person.PhoneNumbers .Where( p => p.IsMessagingEnabled ) .FirstOrDefault(); if ( phoneNumber != null ) { // Create merge field dictionary var mergeObjects = recipient.CommunicationMergeValues( globalConfigValues ); string message = communication.GetMediumDataValue( "Message" ); message = message.ResolveMergeFields( mergeObjects ); string twilioNumber = phoneNumber.Number; if ( !string.IsNullOrWhiteSpace( phoneNumber.CountryCode ) ) { twilioNumber = "+" + phoneNumber.CountryCode + phoneNumber.Number; } var globalAttributes = Rock.Web.Cache.GlobalAttributesCache.Read(); string callbackUrl = globalAttributes.GetValue( "PublicApplicationRoot" ) + "Webhooks/Twilio.ashx"; var response = twilio.SendMessage( fromPhone, twilioNumber, message, callbackUrl ); recipient.Status = CommunicationRecipientStatus.Delivered; recipient.TransportEntityTypeName = this.GetType().FullName; recipient.UniqueMessageId = response.Sid; try { historyService.Add( new History { CreatedByPersonAliasId = communication.SenderPersonAliasId, EntityTypeId = personEntityTypeId, CategoryId = communicationCategoryId, EntityId = recipient.PersonAlias.PersonId, Summary = "Sent SMS message.", Caption = message.Truncate( 200 ), RelatedEntityTypeId = communicationEntityTypeId, RelatedEntityId = communication.Id } ); } catch (Exception ex) { ExceptionLogService.LogException( ex, null ); } } else { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "No Phone Number with Messaging Enabled"; } } catch ( Exception ex ) { recipient.Status = CommunicationRecipientStatus.Failed; recipient.StatusNote = "Twilio Exception: " + ex.Message; } rockContext.SaveChanges(); } else { recipientFound = false; } } } } }
/// <summary> /// Updates the last login. /// </summary> /// <param name="userName">Name of the user.</param> public static void UpdateLastLogin( string userName ) { using ( var rockContext = new RockContext() ) { var userLoginService = new UserLoginService( rockContext ); var historyService = new HistoryService( rockContext ); var personEntityTypeId = EntityTypeCache.Read( "Rock.Model.Person" ).Id; var activityCategoryId = CategoryCache.Read( Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), rockContext ).Id; if ( !string.IsNullOrWhiteSpace( userName ) && !userName.StartsWith( "rckipid=" ) ) { var userLogin = userLoginService.GetByUserName( userName ); if ( userLogin != null ) { userLogin.LastLoginDateTime = RockDateTime.Now; if ( userLogin.PersonId.HasValue ) { var summary = new System.Text.StringBuilder(); summary.AppendFormat( "User logged in with <span class='field-name'>{0}</span> username", userLogin.UserName ); if ( HttpContext.Current != null && HttpContext.Current.Request != null ) { summary.AppendFormat( ", to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>", HttpContext.Current.Request.Url.AbsoluteUri, HttpContext.Current.Request.UserHostAddress ); } summary.Append( "." ); historyService.Add( new History { EntityTypeId = personEntityTypeId, CategoryId = activityCategoryId, EntityId = userLogin.PersonId.Value, Summary = summary.ToString() } ); } rockContext.SaveChanges(); } } } }
/// <summary> /// Handles the Click event of the btnSave 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 btnSave_Click( object sender, EventArgs e ) { // if a Location is getting edited, validate and save it if ( gLocations.EditIndex >= 0 ) { var row = gLocations.Rows[gLocations.EditIndex]; AddressControl acAddress = row.FindControl( "acAddress" ) as AddressControl; if ( acAddress.IsValid ) { gLocations_RowUpdating( sender, new GridViewUpdateEventArgs( gLocations.EditIndex ) ); } else { // acAddress will render an error message return; } } if ( !IsUserAuthorized( Rock.Security.Authorization.EDIT ) ) { return; } // confirmation was disabled by btnSave on client-side. So if returning without a redirect, // it should be enabled. If returning with a redirect, the control won't be updated to reflect // confirmation being enabled, so it's ok to enable it here confirmExit.Enabled = true; if ( Page.IsValid ) { confirmExit.Enabled = true; var rockContext = new RockContext(); rockContext.WrapTransaction( () => { var groupService = new GroupService( rockContext ); var groupMemberService = new GroupMemberService( rockContext ); var personService = new PersonService( rockContext ); var historyService = new HistoryService( rockContext ); var groupChanges = new List<string>(); // SAVE GROUP _group = groupService.Get( _group.Id ); History.EvaluateChange( groupChanges, "Group Name", _group.Name, tbGroupName.Text ); _group.Name = tbGroupName.Text; int? campusId = cpCampus.SelectedValueAsInt(); if ( _group.CampusId != campusId ) { History.EvaluateChange( groupChanges, "Campus", _group.CampusId.HasValue ? CampusCache.Read( _group.CampusId.Value ).Name : string.Empty, campusId.HasValue ? CampusCache.Read( campusId.Value ).Name : string.Empty ); _group.CampusId = campusId; } rockContext.SaveChanges(); // SAVE GROUP MEMBERS int? recordStatusValueID = ddlRecordStatus.SelectedValueAsInt(); int? reasonValueId = ddlReason.SelectedValueAsInt(); var newGroups = new List<Group>(); foreach ( var groupMemberInfo in GroupMembers ) { var memberChanges = new List<string>(); var demographicChanges = new List<string>(); var role = _groupType.Roles.Where( r => r.Guid.Equals( groupMemberInfo.RoleGuid ) ).FirstOrDefault(); if ( role == null ) { role = _groupType.Roles.FirstOrDefault(); } bool isAdult = role != null && role.Guid.Equals( Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT ); // People added to group (new or from other group ) if ( !groupMemberInfo.ExistingGroupMember ) { Person person = null; if ( groupMemberInfo.Id == -1 ) { // added new person demographicChanges.Add( "Created" ); person = new Person(); person.TitleValueId = groupMemberInfo.TitleValueId; person.FirstName = groupMemberInfo.FirstName; person.NickName = groupMemberInfo.NickName; person.LastName = groupMemberInfo.LastName; person.SuffixValueId = groupMemberInfo.SuffixValueId; person.Gender = groupMemberInfo.Gender; DateTime? birthdate = groupMemberInfo.BirthDate; if ( birthdate.HasValue ) { // If setting a future birthdate, subtract a century until birthdate is not greater than today. var today = RockDateTime.Today; while ( birthdate.Value.CompareTo( today ) > 0 ) { birthdate = birthdate.Value.AddYears( -100 ); } } person.SetBirthDate( birthdate ); person.MaritalStatusValueId = groupMemberInfo.MaritalStatusValueId; person.GradeOffset = groupMemberInfo.GradeOffset; person.ConnectionStatusValueId = groupMemberInfo.ConnectionStatusValueId; if ( isAdult ) { person.GivingGroupId = _group.Id; } person.IsEmailActive = true; person.EmailPreference = EmailPreference.EmailAllowed; person.RecordTypeValueId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid() ).Id; } else { person = personService.Get( groupMemberInfo.Id ); } if ( person == null ) { // shouldn't happen return; } if ( _isFamilyGroupType ) { if ( person.RecordStatusValueId != recordStatusValueID ) { History.EvaluateChange( demographicChanges, "Record Status", DefinedValueCache.GetName( person.RecordStatusValueId ), DefinedValueCache.GetName( recordStatusValueID ) ); person.RecordStatusValueId = recordStatusValueID; } if ( person.RecordStatusValueId != recordStatusValueID ) { History.EvaluateChange( demographicChanges, "Record Status Reason", DefinedValueCache.GetName( person.RecordStatusReasonValueId ), DefinedValueCache.GetName( reasonValueId ) ); person.RecordStatusReasonValueId = reasonValueId; } } PersonService.AddPersonToGroup( person, person.Id == 0, _group.Id, role.Id, rockContext ); } else { // existing group members var groupMember = groupMemberService.Queryable( "Person", true ).Where( m => m.PersonId == groupMemberInfo.Id && m.Group.GroupTypeId == _groupType.Id && m.GroupId == _group.Id ).FirstOrDefault(); if ( groupMember != null ) { if ( groupMemberInfo.Removed ) { if ( !groupMemberInfo.IsInOtherGroups ) { var newFamilyChanges = new List<string>(); // Family member was removed and should be created in their own new family var newGroup = new Group(); newGroup.Name = groupMemberInfo.LastName + " " + _groupType.Name; History.EvaluateChange( newFamilyChanges, "Family", string.Empty, newGroup.Name ); newGroup.GroupTypeId = _groupType.Id; if ( _group.CampusId.HasValue ) { History.EvaluateChange( newFamilyChanges, "Campus", string.Empty, CampusCache.Read( _group.CampusId.Value ).Name ); } newGroup.CampusId = _group.CampusId; groupService.Add( newGroup ); rockContext.SaveChanges(); // If person's previous giving group was this family, set it to their new family id if ( _isFamilyGroupType && groupMember.Person.GivingGroup != null && groupMember.Person.GivingGroupId == _group.Id ) { History.EvaluateChange( demographicChanges, "Giving Group", groupMember.Person.GivingGroup.Name, _group.Name ); groupMember.Person.GivingGroupId = newGroup.Id; } groupMember.Group = newGroup; rockContext.SaveChanges(); var newMemberChanges = new List<string>(); if ( _isFamilyGroupType ) { History.EvaluateChange( newMemberChanges, "Role", string.Empty, groupMember.GroupRole.Name ); HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), groupMember.Person.Id, newFamilyChanges, newGroup.Name, typeof( Group ), newGroup.Id ); } newGroups.Add( newGroup ); History.EvaluateChange( memberChanges, "Role", groupMember.GroupRole.Name, string.Empty ); } else { History.EvaluateChange( groupChanges, "Family", groupMember.Group.Name, string.Empty ); groupMemberService.Delete( groupMember ); rockContext.SaveChanges(); } } else { // Existing member was not remvoved if ( role != null ) { History.EvaluateChange( memberChanges, "Role", groupMember.GroupRole != null ? groupMember.GroupRole.Name : string.Empty, role.Name ); groupMember.GroupRoleId = role.Id; if ( _isFamilyGroupType ) { if ( recordStatusValueID > 0 ) { History.EvaluateChange( demographicChanges, "Record Status", DefinedValueCache.GetName( groupMember.Person.RecordStatusValueId ), DefinedValueCache.GetName( recordStatusValueID ) ); groupMember.Person.RecordStatusValueId = recordStatusValueID; History.EvaluateChange( demographicChanges, "Record Status Reason", DefinedValueCache.GetName( groupMember.Person.RecordStatusReasonValueId ), DefinedValueCache.GetName( reasonValueId ) ); groupMember.Person.RecordStatusReasonValueId = reasonValueId; } } rockContext.SaveChanges(); } } } } // Remove anyone that was moved from another family if ( groupMemberInfo.RemoveFromOtherGroups ) { PersonService.RemovePersonFromOtherFamilies( _group.Id, groupMemberInfo.Id, rockContext ); } HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), groupMemberInfo.Id, demographicChanges ); if ( _isFamilyGroupType ) { HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), groupMemberInfo.Id, memberChanges, _group.Name, typeof( Group ), _group.Id ); } } // SAVE LOCATIONS var groupLocationService = new GroupLocationService( rockContext ); // delete any group locations that were removed var remainingLocationIds = GroupAddresses.Where( a => a.Id > 0 ).Select( a => a.Id ).ToList(); foreach ( var removedLocation in groupLocationService.Queryable( "GroupLocationTypeValue,Location" ) .Where( l => l.GroupId == _group.Id && !remainingLocationIds.Contains( l.Id ) ) ) { History.EvaluateChange( groupChanges, ( removedLocation.GroupLocationTypeValue != null ? removedLocation.GroupLocationTypeValue.Value : "Unknown" ) + " Location", removedLocation.Location.ToString(), string.Empty ); groupLocationService.Delete( removedLocation ); } rockContext.SaveChanges(); foreach ( var groupAddressInfo in GroupAddresses.Where( a => a.Id >= 0 ) ) { Location updatedAddress = null; if ( groupAddressInfo.LocationIsDirty ) { updatedAddress = new LocationService( rockContext ).Get( groupAddressInfo.Street1, groupAddressInfo.Street2, groupAddressInfo.City, groupAddressInfo.State, groupAddressInfo.PostalCode, groupAddressInfo.Country ); } GroupLocation groupLocation = null; if ( groupAddressInfo.Id > 0 ) { groupLocation = groupLocationService.Get( groupAddressInfo.Id ); } if ( groupLocation == null ) { groupLocation = new GroupLocation(); groupLocation.GroupId = _group.Id; groupLocationService.Add( groupLocation ); } History.EvaluateChange( groupChanges, "Location Type", groupLocation.GroupLocationTypeValueId.HasValue ? DefinedValueCache.Read( groupLocation.GroupLocationTypeValueId.Value ).Value : string.Empty, groupAddressInfo.LocationTypeName ); groupLocation.GroupLocationTypeValueId = groupAddressInfo.LocationTypeId; History.EvaluateChange( groupChanges, groupAddressInfo.LocationTypeName + " Is Mailing", groupLocation.IsMailingLocation.ToString(), groupAddressInfo.IsMailing.ToString() ); groupLocation.IsMailingLocation = groupAddressInfo.IsMailing; History.EvaluateChange( groupChanges, groupAddressInfo.LocationTypeName + " Is Map Location", groupLocation.IsMappedLocation.ToString(), groupAddressInfo.IsLocation.ToString() ); groupLocation.IsMappedLocation = groupAddressInfo.IsLocation; if ( updatedAddress != null ) { History.EvaluateChange( groupChanges, groupAddressInfo.LocationTypeName + " Location", groupLocation.Location != null ? groupLocation.Location.ToString() : string.Empty, updatedAddress.ToString() ); groupLocation.Location = updatedAddress; } rockContext.SaveChanges(); // Add the same locations to any new families created by removing an existing family member if ( newGroups.Any() ) { // reload grouplocation for access to child properties groupLocation = groupLocationService.Get( groupLocation.Id ); foreach ( var newGroup in newGroups ) { var newGroupLocation = new GroupLocation(); newGroupLocation.GroupId = newGroup.Id; newGroupLocation.LocationId = groupLocation.LocationId; newGroupLocation.GroupLocationTypeValueId = groupLocation.GroupLocationTypeValueId; newGroupLocation.IsMailingLocation = groupLocation.IsMailingLocation; newGroupLocation.IsMappedLocation = groupLocation.IsMappedLocation; groupLocationService.Add( newGroupLocation ); } rockContext.SaveChanges(); } } _group.LoadAttributes(); Rock.Attribute.Helper.GetEditValues( phGroupAttributes, _group ); _group.SaveAttributeValues( rockContext ); if ( _isFamilyGroupType ) { foreach ( var fm in _group.Members ) { HistoryService.SaveChanges( rockContext, typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), fm.PersonId, groupChanges, _group.Name, typeof( Group ), _group.Id ); } } Response.Redirect( string.Format( "~/Person/{0}", Person.Id ), false ); } ); } }
protected void btnNext_Click( object sender, EventArgs e ) { if ( Page.IsValid ) { if ( CurrentCategoryIndex < attributeControls.Count ) { CurrentCategoryIndex++; ShowAttributeCategory( CurrentCategoryIndex ); } else { var familyMembers = GetControlData(); if ( familyMembers.Any() ) { RockTransactionScope.WrapTransaction( () => { using ( new UnitOfWorkScope() ) { var familyGroupType = GroupTypeCache.GetFamilyGroupType(); var familyChanges = new List<string>(); var familyMemberChanges = new Dictionary<Guid, List<string>>(); var familyDemographicChanges = new Dictionary<Guid, List<string>>(); if ( familyGroupType != null ) { var groupService = new GroupService(); var groupTypeRoleService = new GroupTypeRoleService(); var familyGroup = new Group(); familyGroup.GroupTypeId = familyGroupType.Id; familyChanges.Add("Created"); familyGroup.Name = familyMembers.FirstOrDefault().Person.LastName + " Family"; History.EvaluateChange( familyChanges, "Name", string.Empty, familyGroup.Name ); int? campusId = cpCampus.SelectedValueAsInt(); if (campusId.HasValue) { History.EvaluateChange( familyChanges, "Campus", string.Empty, CampusCache.Read( campusId.Value ).Name ); } familyGroup.CampusId = campusId; foreach(var familyMember in familyMembers) { var person = familyMember.Person; if ( person != null ) { familyGroup.Members.Add( familyMember ); var demographicChanges = new List<string>(); demographicChanges.Add( "Created" ); History.EvaluateChange( demographicChanges, "Record Status", string.Empty, person.RecordStatusReasonValueId.HasValue ? DefinedValueCache.GetName( person.RecordStatusReasonValueId.Value ) : string.Empty ); History.EvaluateChange( demographicChanges, "Title", string.Empty, person.TitleValueId.HasValue ? DefinedValueCache.GetName( person.TitleValueId ) : string.Empty ); History.EvaluateChange( demographicChanges, "First Name", string.Empty, person.FirstName); History.EvaluateChange( demographicChanges, "Nick Name", string.Empty, person.NickName ); History.EvaluateChange( demographicChanges, "Middle Name", string.Empty, person.MiddleName ); History.EvaluateChange( demographicChanges, "Last Name", string.Empty, person.LastName ); History.EvaluateChange( demographicChanges, "Gender", null, person.Gender ); History.EvaluateChange( demographicChanges, "Birth Date", null, person.BirthDate ); History.EvaluateChange( demographicChanges, "Connection Status", string.Empty, person.ConnectionStatusValueId.HasValue ? DefinedValueCache.GetName( person.ConnectionStatusValueId ) : string.Empty ); History.EvaluateChange( demographicChanges, "Graduation Date", null, person.GraduationDate ); familyDemographicChanges.Add( person.Guid, demographicChanges ); var memberChanges = new List<string>(); string roleName = familyGroupType.Roles[familyMember.GroupRoleId] ?? string.Empty; History.EvaluateChange( memberChanges, "Role", string.Empty, roleName ); familyMemberChanges.Add( person.Guid, memberChanges ); } } if ( !String.IsNullOrWhiteSpace( tbStreet1.Text ) || !String.IsNullOrWhiteSpace( tbStreet2.Text ) || !String.IsNullOrWhiteSpace( tbCity.Text ) || !String.IsNullOrWhiteSpace( tbZip.Text ) ) { string addressChangeField = "Address"; var groupLocation = new GroupLocation(); var location = new LocationService().Get( tbStreet1.Text, tbStreet2.Text, tbCity.Text, ddlState.SelectedValue, tbZip.Text ); groupLocation.Location = location; Guid locationTypeGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "LocationType" ), out locationTypeGuid ) ) { var locationType = Rock.Web.Cache.DefinedValueCache.Read( locationTypeGuid ); if ( locationType != null ) { addressChangeField = string.Format("{0} Address", locationType.Name); groupLocation.GroupLocationTypeValueId = locationType.Id; } } familyGroup.GroupLocations.Add( groupLocation ); History.EvaluateChange( familyChanges, addressChangeField, string.Empty, groupLocation.Location.ToString() ); } groupService.Add( familyGroup, CurrentPersonId ); groupService.Save( familyGroup, CurrentPersonId ); var historyService = new HistoryService(); historyService.SaveChanges( typeof( Group ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), familyGroup.Id, familyChanges, CurrentPersonId ); var personService = new PersonService(); foreach ( var groupMember in familyMembers ) { var person = personService.Get( groupMember.PersonId ); if ( person != null ) { var changes = familyDemographicChanges[person.Guid]; if ( groupMember.GroupRoleId != _childRoleId ) { person.GivingGroupId = familyGroup.Id; personService.Save( person, CurrentPersonId ); History.EvaluateChange( changes, "Giving Group", string.Empty, familyGroup.Name ); } foreach ( var attributeControl in attributeControls ) { foreach ( var attribute in attributeControl.AttributeList ) { string attributeValue = person.GetAttributeValue( attribute.Key ); if ( !string.IsNullOrWhiteSpace( attributeValue ) ) { Rock.Attribute.Helper.SaveAttributeValue( person, attribute, attributeValue, CurrentPersonId ); attributeValue = attribute.FieldType.Field.FormatValue( null, attributeValue, attribute.QualifierValues, false ); History.EvaluateChange( changes, attribute.Name, string.Empty, attributeValue ); } } } historyService.SaveChanges( typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), person.Id, changes, CurrentPersonId ); historyService.SaveChanges( typeof( Person ), Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(), person.Id, familyMemberChanges[person.Guid], familyGroup.Name, typeof( Group), familyGroup.Id, CurrentPersonId ); } } } } } ); Response.Redirect( string.Format( "~/Person/{0}", familyMembers[0].Person.Id ), false ); } } } }