Exemple #1
0
        /// <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 )
        {
            var rockContext = new RockContext();
            rockContext.WrapTransaction( () =>
            {
                var personService = new PersonService( rockContext );

                var changes = new List<string>();

                var person = personService.Get( CurrentPersonId ?? 0 );
                if ( person != null )
                {
                    int? orphanedPhotoId = null;
                    if ( person.PhotoId != imgPhoto.BinaryFileId )
                    {
                        orphanedPhotoId = person.PhotoId;
                        person.PhotoId = imgPhoto.BinaryFileId;

                        if ( orphanedPhotoId.HasValue )
                        {
                            if ( person.PhotoId.HasValue )
                            {
                                changes.Add( "Modified the photo." );
                            }
                            else
                            {
                                changes.Add( "Deleted the photo." );
                            }
                        }
                        else if ( person.PhotoId.HasValue )
                        {
                            changes.Add( "Added a photo." );
                        }
                    }

                    int? newTitleId = ddlTitle.SelectedValueAsInt();
                    History.EvaluateChange( changes, "Title", DefinedValueCache.GetName( person.TitleValueId ), DefinedValueCache.GetName( newTitleId ) );
                    person.TitleValueId = newTitleId;

                    History.EvaluateChange( changes, "First Name", person.FirstName, tbFirstName.Text );
                    person.FirstName = tbFirstName.Text;

                    History.EvaluateChange(changes, "Nick Name", person.NickName, tbNickName.Text);
                    person.NickName = tbNickName.Text;

                    History.EvaluateChange( changes, "Last Name", person.LastName, tbLastName.Text );
                    person.LastName = tbLastName.Text;

                    int? newSuffixId = ddlSuffix.SelectedValueAsInt();
                    History.EvaluateChange( changes, "Suffix", DefinedValueCache.GetName( person.SuffixValueId ), DefinedValueCache.GetName( newSuffixId ) );
                    person.SuffixValueId = newSuffixId;

                    var birthMonth = person.BirthMonth;
                    var birthDay = person.BirthDay;
                    var birthYear = person.BirthYear;

                    var birthday = bpBirthDay.SelectedDate;
                    if ( birthday.HasValue )
                    {
                        // If setting a future birthdate, subtract a century until birthdate is not greater than today.
                        var today = RockDateTime.Today;
                        while ( birthday.Value.CompareTo( today ) > 0 )
                        {
                            birthday = birthday.Value.AddYears( -100 );
                        }

                        person.BirthMonth = birthday.Value.Month;
                        person.BirthDay = birthday.Value.Day;
                        if ( birthday.Value.Year != DateTime.MinValue.Year )
                        {
                            person.BirthYear = birthday.Value.Year;
                        }
                        else
                        {
                            person.BirthYear = null;
                        }
                    }
                    else
                    {
                        person.SetBirthDate( null );
                    }

                    History.EvaluateChange( changes, "Birth Month", birthMonth, person.BirthMonth );
                    History.EvaluateChange( changes, "Birth Day", birthDay, person.BirthDay );
                    History.EvaluateChange( changes, "Birth Year", birthYear, person.BirthYear );

                    var newGender = rblGender.SelectedValue.ConvertToEnum<Gender>();
                    History.EvaluateChange( changes, "Gender", person.Gender, newGender );
                    person.Gender = newGender;

                    var phoneNumberTypeIds = new List<int>();

                    bool smsSelected = false;

                    foreach ( RepeaterItem item in rContactInfo.Items )
                    {
                        HiddenField hfPhoneType = item.FindControl( "hfPhoneType" ) as HiddenField;
                        PhoneNumberBox pnbPhone = item.FindControl( "pnbPhone" ) as PhoneNumberBox;
                        CheckBox cbUnlisted = item.FindControl( "cbUnlisted" ) as CheckBox;
                        CheckBox cbSms = item.FindControl( "cbSms" ) as CheckBox;

                        if ( hfPhoneType != null &&
                            pnbPhone != null &&
                            cbSms != null &&
                            cbUnlisted != null )
                        {
                            if ( !string.IsNullOrWhiteSpace( PhoneNumber.CleanNumber( pnbPhone.Number ) ) )
                            {
                                int phoneNumberTypeId;
                                if ( int.TryParse( hfPhoneType.Value, out phoneNumberTypeId ) )
                                {
                                    var phoneNumber = person.PhoneNumbers.FirstOrDefault( n => n.NumberTypeValueId == phoneNumberTypeId );
                                    string oldPhoneNumber = string.Empty;
                                    if ( phoneNumber == null )
                                    {
                                        phoneNumber = new PhoneNumber { NumberTypeValueId = phoneNumberTypeId };
                                        person.PhoneNumbers.Add( phoneNumber );
                                    }
                                    else
                                    {
                                        oldPhoneNumber = phoneNumber.NumberFormattedWithCountryCode;
                                    }

                                    phoneNumber.CountryCode = PhoneNumber.CleanNumber( pnbPhone.CountryCode );
                                    phoneNumber.Number = PhoneNumber.CleanNumber( pnbPhone.Number );

                                    // Only allow one number to have SMS selected
                                    if ( smsSelected )
                                    {
                                        phoneNumber.IsMessagingEnabled = false;
                                    }
                                    else
                                    {
                                        phoneNumber.IsMessagingEnabled = cbSms.Checked;
                                        smsSelected = cbSms.Checked;
                                    }

                                    phoneNumber.IsUnlisted = cbUnlisted.Checked;
                                    phoneNumberTypeIds.Add( phoneNumberTypeId );

                                    History.EvaluateChange(
                                        changes,
                                        string.Format( "{0} Phone", DefinedValueCache.GetName( phoneNumberTypeId ) ),
                                        oldPhoneNumber,
                                        phoneNumber.NumberFormattedWithCountryCode );
                                }
                            }
                        }
                    }

                    // Remove any blank numbers
                    var phoneNumberService = new PhoneNumberService( rockContext );
                    foreach ( var phoneNumber in person.PhoneNumbers
                        .Where( n => n.NumberTypeValueId.HasValue && !phoneNumberTypeIds.Contains( n.NumberTypeValueId.Value ) )
                        .ToList() )
                    {
                        History.EvaluateChange(
                            changes,
                            string.Format( "{0} Phone", DefinedValueCache.GetName( phoneNumber.NumberTypeValueId ) ),
                            phoneNumber.ToString(),
                            string.Empty );

                        person.PhoneNumbers.Remove( phoneNumber );
                        phoneNumberService.Delete( phoneNumber );
                    }

                    History.EvaluateChange( changes, "Email", person.Email, tbEmail.Text );
                    person.Email = tbEmail.Text.Trim();

                    var newEmailPreference = rblEmailPreference.SelectedValue.ConvertToEnum<EmailPreference>();
                    History.EvaluateChange( changes, "Email Preference", person.EmailPreference, newEmailPreference );
                    person.EmailPreference = newEmailPreference;

                    if ( person.IsValid )
                    {
                        if ( rockContext.SaveChanges() > 0 )
                        {
                            if ( changes.Any() )
                            {
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof( Person ),
                                    Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                    person.Id,
                                    changes );
                            }

                            if ( orphanedPhotoId.HasValue )
                            {
                                BinaryFileService binaryFileService = new BinaryFileService( rockContext );
                                var binaryFile = binaryFileService.Get( orphanedPhotoId.Value );
                                if ( binaryFile != null )
                                {
                                    // marked the old images as IsTemporary so they will get cleaned up later
                                    binaryFile.IsTemporary = true;
                                    rockContext.SaveChanges();
                                }
                            }

                            // if they used the ImageEditor, and cropped it, the uncropped file is still in BinaryFile. So clean it up
                            if ( imgPhoto.CropBinaryFileId.HasValue )
                            {
                                if ( imgPhoto.CropBinaryFileId != person.PhotoId )
                                {
                                    BinaryFileService binaryFileService = new BinaryFileService( rockContext );
                                    var binaryFile = binaryFileService.Get( imgPhoto.CropBinaryFileId.Value );
                                    if ( binaryFile != null && binaryFile.IsTemporary )
                                    {
                                        string errorMessage;
                                        if ( binaryFileService.CanDelete( binaryFile, out errorMessage ) )
                                        {
                                            binaryFileService.Delete( binaryFile );
                                            rockContext.SaveChanges();
                                        }
                                    }
                                }
                            }
                        }

                        // save address
                        if ( pnlAddress.Visible )
                        {
                            Guid? familyGroupTypeGuid = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuidOrNull();
                            if ( familyGroupTypeGuid.HasValue )
                            {
                                var familyGroup = new GroupService( rockContext ).Queryable()
                                                .Where( f => f.GroupType.Guid == familyGroupTypeGuid.Value
                                                    && f.Members.Any( m => m.PersonId == person.Id ) )
                                                .FirstOrDefault();
                                if ( familyGroup != null )
                                {
                                    Guid? addressTypeGuid = GetAttributeValue("LocationType").AsGuidOrNull();
                                    if ( addressTypeGuid.HasValue )
                                    {
                                        var groupLocationService = new GroupLocationService( rockContext );

                                        var dvHomeAddressType = DefinedValueCache.Read( addressTypeGuid.Value );
                                        var familyAddress = groupLocationService.Queryable().Where( l => l.GroupId == familyGroup.Id && l.GroupLocationTypeValueId == dvHomeAddressType.Id ).FirstOrDefault();
                                        if ( familyAddress != null && string.IsNullOrWhiteSpace( acAddress.Street1 ) )
                                        {
                                            // delete the current address
                                            History.EvaluateChange( changes, familyAddress.GroupLocationTypeValue.Value + " Location", familyAddress.Location.ToString(), string.Empty );
                                            groupLocationService.Delete( familyAddress );
                                            rockContext.SaveChanges();
                                        }
                                        else
                                        {
                                            if ( !string.IsNullOrWhiteSpace( acAddress.Street1 ) )
                                            {
                                                if ( familyAddress == null )
                                                {
                                                    familyAddress = new GroupLocation();
                                                    groupLocationService.Add( familyAddress );
                                                    familyAddress.GroupLocationTypeValueId = dvHomeAddressType.Id;
                                                    familyAddress.GroupId = familyGroup.Id;
                                                    familyAddress.IsMailingLocation = true;
                                                    familyAddress.IsMappedLocation = true;
                                                }
                                                else if ( hfStreet1.Value != string.Empty ) {

                                                    // user clicked move so create a previous address
                                                    var previousAddress = new GroupLocation();
                                                    groupLocationService.Add( previousAddress );

                                                    var previousAddressValue = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_PREVIOUS.AsGuid() );
                                                    if ( previousAddressValue  != null )
                                                    {
                                                        previousAddress.GroupLocationTypeValueId = previousAddressValue.Id;
                                                        previousAddress.GroupId = familyGroup.Id;

                                                        Location previousAddressLocation = new Location();
                                                        previousAddressLocation.Street1 = hfStreet1.Value;
                                                        previousAddressLocation.Street2 = hfStreet2.Value;
                                                        previousAddressLocation.City = hfCity.Value;
                                                        previousAddressLocation.State = hfState.Value;
                                                        previousAddressLocation.PostalCode = hfPostalCode.Value;
                                                        previousAddressLocation.Country = hfCountry.Value;

                                                        previousAddress.Location = previousAddressLocation;
                                                    }
                                                }

                                                familyAddress.IsMailingLocation = cbIsMailingAddress.Checked;
                                                familyAddress.IsMappedLocation = cbIsPhysicalAddress.Checked;

                                                var updatedHomeAddress = new Location();
                                                acAddress.GetValues( updatedHomeAddress );

                                                History.EvaluateChange( changes, dvHomeAddressType.Value + " Location", familyAddress.Location != null ? familyAddress.Location.ToString() : string.Empty, updatedHomeAddress.ToString() );

                                                familyAddress.Location = updatedHomeAddress;
                                                rockContext.SaveChanges();
                                            }
                                        }

                                        HistoryService.SaveChanges(
                                            rockContext,
                                            typeof( Person ),
                                            Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                            person.Id,
                                            changes );
                                    }
                                }
                            }
                        }

                        NavigateToParentPage();
                    }
                }
            } );
        }
        /// <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>
        /// Creates the person.
        /// </summary>
        /// <returns></returns>
        private Person CreatePerson()
        {
            var rockContext = new RockContext();

            DefinedValueCache dvcConnectionStatus = DefinedValueCache.Read( GetAttributeValue( "ConnectionStatus" ).AsGuid() );
            DefinedValueCache dvcRecordStatus = DefinedValueCache.Read( GetAttributeValue( "RecordStatus" ).AsGuid() );

            Person person = new Person();
            person.FirstName = tbFirstName.Text;
            person.LastName = tbLastName.Text;
            person.Email = tbEmail.Text;
            person.IsEmailActive = true;
            person.EmailPreference = EmailPreference.EmailAllowed;
            person.RecordTypeValueId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid() ).Id;
            if ( dvcConnectionStatus != null )
            {
                person.ConnectionStatusValueId = dvcConnectionStatus.Id;
            }

            if ( dvcRecordStatus != null )
            {
                person.RecordStatusValueId = dvcRecordStatus.Id;
            }

            switch ( ddlGender.SelectedValue )
            {
                case "M":
                    person.Gender = Gender.Male;
                    break;
                case "F":
                    person.Gender = Gender.Female;
                    break;
                default:
                    person.Gender = Gender.Unknown;
                    break;
            }

            var birthday = bdaypBirthDay.SelectedDate;
            if ( birthday.HasValue )
            {
                person.BirthMonth = birthday.Value.Month;
                person.BirthDay = birthday.Value.Day;
                if ( birthday.Value.Year != DateTime.MinValue.Year )
                {
                    person.BirthYear = birthday.Value.Year;
                }
            }

            bool smsSelected = false;

            foreach ( RepeaterItem item in rPhoneNumbers.Items )
            {
                HiddenField hfPhoneType = item.FindControl( "hfPhoneType" ) as HiddenField;
                PhoneNumberBox pnbPhone = item.FindControl( "pnbPhone" ) as PhoneNumberBox;
                CheckBox cbUnlisted = item.FindControl( "cbUnlisted" ) as CheckBox;
                CheckBox cbSms = item.FindControl( "cbSms" ) as CheckBox;

                if ( !string.IsNullOrWhiteSpace( PhoneNumber.CleanNumber( pnbPhone.Number ) ) )
                {
                    int phoneNumberTypeId;
                    if ( int.TryParse( hfPhoneType.Value, out phoneNumberTypeId ) )
                    {
                        var phoneNumber = new PhoneNumber { NumberTypeValueId = phoneNumberTypeId };
                        person.PhoneNumbers.Add( phoneNumber );
                        phoneNumber.CountryCode = PhoneNumber.CleanNumber( pnbPhone.CountryCode );
                        phoneNumber.Number = PhoneNumber.CleanNumber( pnbPhone.Number );

                        // Only allow one number to have SMS selected
                        if ( smsSelected )
                        {
                            phoneNumber.IsMessagingEnabled = false;
                        }
                        else
                        {
                            phoneNumber.IsMessagingEnabled = cbSms.Checked;
                            smsSelected = cbSms.Checked;
                        }

                        phoneNumber.IsUnlisted = cbUnlisted.Checked;
                    }
                }
            }

            PersonService.SaveNewPerson( person, rockContext, null, false );

            // save address
            if ( pnlAddress.Visible )
            {
                if ( acAddress.IsValid && !string.IsNullOrWhiteSpace(acAddress.Street1) && !string.IsNullOrWhiteSpace( acAddress.City ) && !string.IsNullOrWhiteSpace( acAddress.PostalCode ) )
                {
                    Guid locationTypeGuid = GetAttributeValue( "LocationType" ).AsGuid();
                    if ( locationTypeGuid != Guid.Empty )
                    {
                        Guid familyGroupTypeGuid = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
                        GroupService groupService = new GroupService( rockContext );
                        GroupLocationService groupLocationService = new GroupLocationService( rockContext );
                        var family = groupService.Queryable().Where( g => g.GroupType.Guid == familyGroupTypeGuid && g.Members.Any( m => m.PersonId == person.Id ) ).FirstOrDefault();

                        var groupLocation = new GroupLocation();
                        groupLocation.GroupId = family.Id;
                        groupLocationService.Add( groupLocation );

                        var location = new LocationService( rockContext ).Get( acAddress.Street1, acAddress.Street2, acAddress.City, acAddress.State, acAddress.PostalCode, acAddress.Country );
                        groupLocation.Location = location;

                        groupLocation.GroupLocationTypeValueId = DefinedValueCache.Read( locationTypeGuid).Id;
                        groupLocation.IsMailingLocation = true;
                        groupLocation.IsMappedLocation = true;

                        rockContext.SaveChanges();
                    }
                }
            }

            return person;
        }
        /// <summary>
        /// Handles the Click event of the lbSave 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 lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();
            rockContext.WrapTransaction( () =>
            {
                var personService = new PersonService( rockContext );
                var changes = new List<string>();
                Person business = null;

                if ( int.Parse( hfBusinessId.Value ) != 0 )
                {
                    business = personService.Get( int.Parse( hfBusinessId.Value ) );
                }

                if ( business == null )
                {
                    business = new Person();
                    personService.Add( business );
                }

                // Business Name
                History.EvaluateChange( changes, "Last Name", business.LastName, tbBusinessName.Text );
                business.LastName = tbBusinessName.Text;

                // Phone Number
                var businessPhoneTypeId = new DefinedValueService( rockContext ).GetByGuid( new Guid( Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_WORK ) ).Id;

                string oldPhoneNumber = string.Empty;
                string newPhoneNumber = string.Empty;

                var phoneNumber = business.PhoneNumbers.FirstOrDefault( n => n.NumberTypeValueId == businessPhoneTypeId );
                if ( phoneNumber != null )
                {
                    oldPhoneNumber = phoneNumber.NumberFormattedWithCountryCode;
                }

                if ( !string.IsNullOrWhiteSpace( PhoneNumber.CleanNumber( pnbPhone.Number ) ) )
                {
                    if ( phoneNumber == null )
                    {
                        phoneNumber = new PhoneNumber { NumberTypeValueId = businessPhoneTypeId };
                        business.PhoneNumbers.Add( phoneNumber );
                    }
                    phoneNumber.CountryCode = PhoneNumber.CleanNumber( pnbPhone.CountryCode );
                    phoneNumber.Number = PhoneNumber.CleanNumber( pnbPhone.Number );
                    phoneNumber.IsMessagingEnabled = cbSms.Checked;
                    phoneNumber.IsUnlisted = cbUnlisted.Checked;

                    newPhoneNumber = phoneNumber.NumberFormattedWithCountryCode;
                }
                else
                {
                    if ( phoneNumber != null )
                    {
                        business.PhoneNumbers.Remove( phoneNumber );
                        new PhoneNumberService( rockContext ).Delete( phoneNumber );
                    }
                }

                History.EvaluateChange(
                    changes,
                    string.Format( "{0} Phone", DefinedValueCache.GetName( businessPhoneTypeId ) ),
                    oldPhoneNumber,
                    newPhoneNumber );

                // Record Type - this is always "business". it will never change.
                business.RecordTypeValueId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_BUSINESS.AsGuid() ).Id;

                // Record Status
                int? newRecordStatusId = ddlRecordStatus.SelectedValueAsInt();
                History.EvaluateChange( changes, "Record Status", DefinedValueCache.GetName( business.RecordStatusValueId ), DefinedValueCache.GetName( newRecordStatusId ) );
                business.RecordStatusValueId = newRecordStatusId;

                // Record Status Reason
                int? newRecordStatusReasonId = null;
                if ( business.RecordStatusValueId.HasValue && business.RecordStatusValueId.Value == DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE ) ).Id )
                {
                    newRecordStatusReasonId = ddlReason.SelectedValueAsInt();
                }

                History.EvaluateChange( changes, "Record Status Reason", DefinedValueCache.GetName( business.RecordStatusReasonValueId ), DefinedValueCache.GetName( newRecordStatusReasonId ) );
                business.RecordStatusReasonValueId = newRecordStatusReasonId;

                // Email
                business.IsEmailActive = true;
                History.EvaluateChange( changes, "Email", business.Email, tbEmail.Text );
                business.Email = tbEmail.Text.Trim();

                var newEmailPreference = rblEmailPreference.SelectedValue.ConvertToEnum<EmailPreference>();
                History.EvaluateChange( changes, "EmailPreference", business.EmailPreference, newEmailPreference );
                business.EmailPreference = newEmailPreference;

                if ( business.IsValid )
                {
                    if ( rockContext.SaveChanges() > 0 )
                    {
                        if ( changes.Any() )
                        {
                            HistoryService.SaveChanges(
                                rockContext,
                                typeof( Person ),
                                Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                business.Id,
                                changes );
                        }
                    }
                }

                // Add/Update Family Group
                var familyGroupType = GroupTypeCache.GetFamilyGroupType();
                int adultRoleId = familyGroupType.Roles
                    .Where( r => r.Guid.Equals( Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT.AsGuid() ) )
                    .Select( r => r.Id )
                    .FirstOrDefault();
                var adultFamilyMember = UpdateGroupMember( business.Id, familyGroupType, business.LastName + " Business", ddlCampus.SelectedValueAsInt(), adultRoleId, rockContext );
                business.GivingGroup = adultFamilyMember.Group;

                // Add/Update Known Relationship Group Type
                var knownRelationshipGroupType = GroupTypeCache.Read( Rock.SystemGuid.GroupType.GROUPTYPE_KNOWN_RELATIONSHIPS.AsGuid() );
                int knownRelationshipOwnerRoleId = knownRelationshipGroupType.Roles
                    .Where( r => r.Guid.Equals( Rock.SystemGuid.GroupRole.GROUPROLE_KNOWN_RELATIONSHIPS_OWNER.AsGuid() ) )
                    .Select( r => r.Id )
                    .FirstOrDefault();
                var knownRelationshipOwner = UpdateGroupMember( business.Id, knownRelationshipGroupType, "Known Relationship", null, knownRelationshipOwnerRoleId, rockContext );

                // Add/Update Implied Relationship Group Type
                var impliedRelationshipGroupType = GroupTypeCache.Read( Rock.SystemGuid.GroupType.GROUPTYPE_IMPLIED_RELATIONSHIPS.AsGuid() );
                int impliedRelationshipOwnerRoleId = impliedRelationshipGroupType.Roles
                    .Where( r => r.Guid.Equals( Rock.SystemGuid.GroupRole.GROUPROLE_IMPLIED_RELATIONSHIPS_OWNER.AsGuid() ) )
                    .Select( r => r.Id )
                    .FirstOrDefault();
                var impliedRelationshipOwner = UpdateGroupMember( business.Id, impliedRelationshipGroupType, "Implied Relationship", null, impliedRelationshipOwnerRoleId, rockContext );

                rockContext.SaveChanges();

                // Every business should have an alias record with same id.  If it's missing, create it
                if ( !business.Aliases.Any( a => a.AliasPersonId == business.Id ) )
                {
                    // refetch the business to make sure we have an Id
                    business = personService.Get( business.Id );
                    if ( business != null )
                    {
                        business.Aliases.Add( new PersonAlias { AliasPersonId = business.Id, AliasPersonGuid = business.Guid } );
                        rockContext.SaveChanges();
                    }
                }

                // Location
                int workLocationTypeId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_WORK ).Id;

                var groupLocationService = new GroupLocationService( rockContext );
                var workLocation = groupLocationService.Queryable( "Location" )
                    .Where( gl =>
                        gl.GroupId == adultFamilyMember.Group.Id &&
                        gl.GroupLocationTypeValueId == workLocationTypeId )
                    .FirstOrDefault();

                if ( string.IsNullOrWhiteSpace( acAddress.Street1 ) )
                {
                    if ( workLocation != null )
                    {
                        groupLocationService.Delete( workLocation );
                        History.EvaluateChange( changes, "Address", workLocation.Location.ToString(), string.Empty );
                    }
                }
                else
                {
                    var oldValue = string.Empty;

                    var newLocation = new LocationService( rockContext ).Get(
                        acAddress.Street1, acAddress.Street2, acAddress.City, acAddress.State, acAddress.PostalCode, acAddress.Country );

                    if ( workLocation != null )
                    {
                        oldValue = workLocation.Location.ToString();
                    }
                    else
                    {
                        workLocation = new GroupLocation();
                        groupLocationService.Add( workLocation );
                        workLocation.GroupId = adultFamilyMember.Group.Id;
                        workLocation.GroupLocationTypeValueId = workLocationTypeId;
                    }
                    workLocation.Location = newLocation;

                    History.EvaluateChange( changes, "Address", oldValue, newLocation.ToString() );
                }

                rockContext.SaveChanges();

                hfBusinessId.Value = business.Id.ToString();
            } );

            ShowSummary( hfBusinessId.Value.AsInteger() );
        }
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute( RockContext rockContext, WorkflowAction action, Object entity, out List<string> errorMessages )
        {
            errorMessages = new List<string>();

            // get person
            Person person = null;

            string personAttributeValue = GetAttributeValue( action, "Person" );
            Guid? guidPersonAttribute = personAttributeValue.AsGuidOrNull();
            if ( guidPersonAttribute.HasValue )
            {
                var attributePerson = AttributeCache.Read( guidPersonAttribute.Value, rockContext );
                if ( attributePerson != null || attributePerson.FieldType.Class != "Rock.Field.Types.PersonFieldType" )
                {
                    string attributePersonValue = action.GetWorklowAttributeValue( guidPersonAttribute.Value );
                    if ( !string.IsNullOrWhiteSpace( attributePersonValue ) )
                    {
                        Guid personAliasGuid = attributePersonValue.AsGuid();
                        if ( !personAliasGuid.IsEmpty() )
                        {
                            person = new PersonAliasService( rockContext ).Queryable()
                                .Where( a => a.Guid.Equals( personAliasGuid ) )
                                .Select( a => a.Person )
                                .FirstOrDefault();
                            if ( person == null )
                            {
                                errorMessages.Add( string.Format( "Person could not be found for selected value ('{0}')!", guidPersonAttribute.ToString() ) );
                                return false;
                            }
                        }
                    }
                }
            }

            if ( person == null )
            {
                errorMessages.Add( "The attribute used to provide the person was invalid, or not of type 'Person'." );
                return false;
            }

            // determine the location type to edit
            DefinedValueCache locationType = null;
            var locationTypeAttributeValue = action.GetWorklowAttributeValue( GetAttributeValue( action, "LocationTypeAttribute" ).AsGuid() );
            if ( locationTypeAttributeValue != null )
            {
                locationType = DefinedValueCache.Read( locationTypeAttributeValue.AsGuid() );
            }
            if ( locationType == null )
            {
                locationType = DefinedValueCache.Read( GetAttributeValue( action, "LocationType" ).AsGuid() );
            }
            if ( locationType == null )
            {
                errorMessages.Add( "The location type to be updated was not selected." );
                return false;
            }

            // get the new phone number value
            Location location = null;
            string locationValue = GetAttributeValue( action, "Location" );
            Guid? locationGuid = locationValue.AsGuidOrNull();
            if ( !locationGuid.HasValue || locationGuid.Value.IsEmpty() )
            {
                string locationAttributeValue = GetAttributeValue( action, "LocationAttribute" );
                Guid? locationAttributeValueGuid = locationAttributeValue.AsGuidOrNull();
                if ( locationAttributeValueGuid.HasValue )
                {
                    locationGuid = action.GetWorklowAttributeValue( locationAttributeValueGuid.Value ).AsGuidOrNull();
                }
            }

            if ( locationGuid.HasValue )
            {
                location = new LocationService( rockContext ).Get( locationGuid.Value );
            }

            if ( location == null )
            {
                errorMessages.Add( "The location value could not be determined." );
                return false;
            }

            // gets value indicating if location is a mailing location
            string mailingValue = GetAttributeValue( action, "IsMailing" );
            Guid? mailingValueGuid = mailingValue.AsGuidOrNull();
            if ( mailingValueGuid.HasValue )
            {
                mailingValue = action.GetWorklowAttributeValue( mailingValueGuid.Value );
            }
            else
            {
                mailingValue = mailingValue.ResolveMergeFields( GetMergeFields( action ) );
            }
            bool? mailing = mailingValue.AsBooleanOrNull();

            // gets value indicating if location is a mapped location
            string mappedValue = GetAttributeValue( action, "IsMapped" );
            Guid? mappedValueGuid = mappedValue.AsGuidOrNull();
            if ( mappedValueGuid.HasValue )
            {
                mappedValue = action.GetWorklowAttributeValue( mappedValueGuid.Value );
            }
            else
            {
                mappedValue = mappedValue.ResolveMergeFields( GetMergeFields( action ) );
            }
            bool? mapped = mappedValue.AsBooleanOrNull();

            var groupLocationService = new GroupLocationService( rockContext );
            foreach ( var family in person.GetFamilies( rockContext ).ToList() )
            {
                var groupLocation = family.GroupLocations.FirstOrDefault( l => l.GroupLocationTypeValueId == locationType.Id );
                string oldValue = string.Empty;
                if ( groupLocation == null )
                {
                    groupLocation = new GroupLocation();
                    groupLocation.GroupId = family.Id;
                    groupLocation.GroupLocationTypeValueId = locationType.Id;
                    groupLocationService.Add( groupLocation );
                }
                else
                {
                    oldValue = groupLocation.Location.ToString();
                }

                var groupChanges = new List<string>();

                History.EvaluateChange(
                    groupChanges,
                    locationType.Value + " Location",
                    oldValue,
                    location.ToString() );

                groupLocation.Location = location;

                if ( mailing.HasValue )
                {
                    History.EvaluateChange(
                        groupChanges,
                        locationType.Value + " Is Mailing",
                        groupLocation.IsMailingLocation.ToString(),
                        mailing.Value.ToString() );
                    groupLocation.IsMailingLocation = mailing.Value;
                }

                if ( mapped.HasValue )
                {
                    History.EvaluateChange(
                        groupChanges,
                        locationType.Value + " Is Map Location",
                        groupLocation.IsMappedLocation.ToString(),
                        mapped.Value.ToString() );
                    groupLocation.IsMappedLocation = mapped.Value;
                }

                if ( groupChanges.Any() )
                {
                    groupChanges.Add( string.Format( "<em>(Updated by the '{0}' workflow)</em>", action.ActionType.ActivityType.WorkflowType.Name ) );
                    foreach ( var fm in family.Members )
                    {
                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( Person ),
                            Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                            fm.PersonId,
                            groupChanges,
                            family.Name,
                            typeof( Group ),
                            family.Id,
                            false );
                    }
                }

                rockContext.SaveChanges();

                action.AddLogEntry( string.Format( "Updated the {0} location for {1} (family: {2}) to {3}", locationType.Value, person.FullName, family.Name, location.ToString() ) );
            }

            return true;
        }
Exemple #6
0
        /// <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 );

                } );
            }
        }