/// <summary>
        /// This method takes the attribute values of the original blocks, and creates copies of them that point to the copied blocks.
        /// In addition, any block attribute value pointing to a page in the original page tree is now updated to point to the
        /// corresponding page in the copied page tree.
        /// </summary>
        /// <param name="pageGuidDictionary">The dictionary containing the original page guids and the corresponding copied page guids.</param>
        /// <param name="blockGuidDictionary">The dictionary containing the original block guids and the corresponding copied block guids.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="currentPersonAliasId">The current person alias identifier.</param>
        private void GenerateBlockAttributeValues(Dictionary <Guid, Guid> pageGuidDictionary, Dictionary <Guid, Guid> blockGuidDictionary, RockContext rockContext, int?currentPersonAliasId = null)
        {
            var attributeValueService = new AttributeValueService(rockContext);
            var pageService           = new PageService(rockContext);
            var blockService          = new BlockService(rockContext);
            var pageGuid  = Rock.SystemGuid.EntityType.PAGE.AsGuid();
            var blockGuid = Rock.SystemGuid.EntityType.BLOCK.AsGuid();

            Dictionary <Guid, int> blockIntDictionary = blockService.Queryable()
                                                        .Where(p => blockGuidDictionary.Keys.Contains(p.Guid) || blockGuidDictionary.Values.Contains(p.Guid))
                                                        .ToDictionary(p => p.Guid, p => p.Id);

            var attributeValues = attributeValueService.Queryable().Where(a =>
                                                                          a.Attribute.EntityType.Guid == blockGuid && blockIntDictionary.Values.Contains(a.EntityId.Value))
                                  .ToList();

            foreach (var attributeValue in attributeValues)
            {
                var attribute    = AttributeCache.Get(attributeValue.AttributeId);
                var fieldType    = attribute?.FieldType.Field as Field.FieldType;
                var currentValue = attributeValue;

                var newAttributeValue = attributeValue.Clone(false);
                newAttributeValue.CreatedByPersonAlias    = null;
                newAttributeValue.CreatedByPersonAliasId  = currentPersonAliasId;
                newAttributeValue.CreatedDateTime         = RockDateTime.Now;
                newAttributeValue.ModifiedByPersonAlias   = null;
                newAttributeValue.ModifiedByPersonAliasId = currentPersonAliasId;
                newAttributeValue.ModifiedDateTime        = RockDateTime.Now;
                newAttributeValue.Id       = 0;
                newAttributeValue.Guid     = Guid.NewGuid();
                newAttributeValue.EntityId = blockIntDictionary[blockGuidDictionary[blockIntDictionary.Where(d => d.Value == attributeValue.EntityId.Value).FirstOrDefault().Key]];

                if (fieldType != null && currentValue != null && currentValue.Value != null)
                {
                    newAttributeValue.Value = fieldType.GetCopyValue(currentValue.Value, rockContext);
                }

                if (attributeValue.Attribute.FieldType.Guid == Rock.SystemGuid.FieldType.PAGE_REFERENCE.AsGuid())
                {
                    if (pageGuidDictionary.ContainsKey(attributeValue.Value.AsGuid()))
                    {
                        newAttributeValue.Value = pageGuidDictionary[attributeValue.Value.AsGuid()].ToString();
                    }
                }

                attributeValueService.Add(newAttributeValue);
            }

            rockContext.SaveChanges();
        }
        /// <summary>
        /// This method takes the attribute values of the original blocks, and creates copies of them that point to the copied blocks. 
        /// In addition, any block attribute value pointing to a page in the original page tree is now updated to point to the
        /// corresponding page in the copied page tree.
        /// </summary>
        /// <param name="pageGuidDictionary">The dictionary containing the original page guids and the corresponding copied page guids.</param>
        /// <param name="blockGuidDictionary">The dictionary containing the original block guids and the corresponding copied block guids.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="currentPersonAliasId">The current person alias identifier.</param>
        private void GenerateBlockAttributeValues( Dictionary<Guid, Guid> pageGuidDictionary, Dictionary<Guid, Guid> blockGuidDictionary, RockContext rockContext, int? currentPersonAliasId = null )
        {
            var attributeValueService = new AttributeValueService( rockContext );
            var pageService = new PageService( rockContext );
            var blockService = new BlockService( rockContext );
            var pageGuid = Rock.SystemGuid.EntityType.PAGE.AsGuid();
            var blockGuid = Rock.SystemGuid.EntityType.BLOCK.AsGuid();

            Dictionary<Guid, int> blockIntDictionary = blockService.Queryable()
                .Where( p => blockGuidDictionary.Keys.Contains( p.Guid ) || blockGuidDictionary.Values.Contains( p.Guid ) )
                .ToDictionary( p => p.Guid, p => p.Id );

            var attributeValues = attributeValueService.Queryable().Where( a =>
                a.Attribute.EntityType.Guid == blockGuid && blockIntDictionary.Values.Contains( a.EntityId.Value ) )
                .ToList();

            foreach ( var attributeValue in attributeValues )
            {
                var newAttributeValue = attributeValue.Clone( false );
                newAttributeValue.CreatedByPersonAlias = null;
                newAttributeValue.CreatedByPersonAliasId = currentPersonAliasId;
                newAttributeValue.CreatedDateTime = RockDateTime.Now;
                newAttributeValue.ModifiedByPersonAlias = null;
                newAttributeValue.ModifiedByPersonAliasId = currentPersonAliasId;
                newAttributeValue.ModifiedDateTime = RockDateTime.Now;
                newAttributeValue.Id = 0;
                newAttributeValue.Guid = Guid.NewGuid();
                newAttributeValue.EntityId = blockIntDictionary[blockGuidDictionary[blockIntDictionary.Where( d => d.Value == attributeValue.EntityId.Value ).FirstOrDefault().Key]];

                if ( attributeValue.Attribute.FieldType.Guid == Rock.SystemGuid.FieldType.PAGE_REFERENCE.AsGuid() )
                {
                    if ( pageGuidDictionary.ContainsKey( attributeValue.Value.AsGuid() ) )
                    {
                        newAttributeValue.Value = pageGuidDictionary[attributeValue.Value.AsGuid()].ToString();
                    }
                }

                attributeValueService.Add( newAttributeValue );
            }

            rockContext.SaveChanges();
        }
        /// <summary>
        /// Sets the value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="saveValue">if set to <c>true</c> [save value].</param>
        /// <param name="rockContext">The rock context.</param>
        public void SetValue( string key, string value, bool saveValue, RockContext rockContext = null )
        {
            if ( saveValue )
            {
                if ( rockContext == null )
                {
                    rockContext = new RockContext();
                }

                // Save new value
                var attributeValueService = new AttributeValueService( rockContext );
                var attributeValue = attributeValueService.GetGlobalAttributeValue( key );

                if ( attributeValue == null )
                {
                    var attributeService = new AttributeService( rockContext );
                    var attribute = attributeService.GetGlobalAttribute( key );
                    if ( attribute == null )
                    {
                        attribute = new Rock.Model.Attribute();
                        attribute.FieldTypeId = FieldTypeCache.Read( new Guid( SystemGuid.FieldType.TEXT ) ).Id;
                        attribute.EntityTypeQualifierColumn = string.Empty;
                        attribute.EntityTypeQualifierValue = string.Empty;
                        attribute.Key = key;
                        attribute.Name = key.SplitCase();
                        attributeService.Add( attribute );
                        rockContext.SaveChanges();

                        Attributes.Add( AttributeCache.Read( attribute.Id ) );
                    }

                    attributeValue = new AttributeValue();
                    attributeValueService.Add( attributeValue );
                    attributeValue.IsSystem = false;
                    attributeValue.AttributeId = attribute.Id;

                    if ( !AttributeValues.Keys.Contains( key ) )
                    {
                        AttributeValues.Add( key, new KeyValuePair<string, string>( attribute.Name, value ) );
                    }
                }

                attributeValue.Value = value;
                rockContext.SaveChanges();
            }

            var attributeCache = Attributes.FirstOrDefault( a => a.Key.Equals( key, StringComparison.OrdinalIgnoreCase ) );
            if ( attributeCache != null ) // (Should never be null)
            {
                if ( AttributeValues.Keys.Contains( key ) )
                {
                    AttributeValues[key] = new KeyValuePair<string, string>( attributeCache.Name, value );
                }
                else
                {
                    AttributeValues.Add( key, new KeyValuePair<string, string>( attributeCache.Name, value ) );
                }
            }
        }
        /// <summary>
        /// Saves a <see cref="Rock.Model.Person">Person's</see> user preference setting by key.
        /// </summary>
        /// <param name="person">The <see cref="Rock.Model.Person"/> who the preference value belongs to.</param>
        /// <param name="key">A <see cref="System.String"/> representing the key (name) of the preference setting.</param>
        /// <param name="value">The value.</param>
        public static void SaveUserPreference( Person person, string key, string value )
        {
            int? PersonEntityTypeId = Rock.Web.Cache.EntityTypeCache.Read( Person.USER_VALUE_ENTITY ).Id;

            using ( var rockContext = new RockContext() )
            {
                var attributeService = new Model.AttributeService( rockContext );
                var attribute = attributeService.Get( PersonEntityTypeId, string.Empty, string.Empty, key );

                if ( attribute == null )
                {
                    var fieldTypeService = new Model.FieldTypeService( rockContext );
                    var fieldType = FieldTypeCache.Read( Rock.SystemGuid.FieldType.TEXT.AsGuid() );

                    attribute = new Model.Attribute();
                    attribute.IsSystem = false;
                    attribute.EntityTypeId = PersonEntityTypeId;
                    attribute.EntityTypeQualifierColumn = string.Empty;
                    attribute.EntityTypeQualifierValue = string.Empty;
                    attribute.Key = key;
                    attribute.Name = key;
                    attribute.IconCssClass = string.Empty;
                    attribute.DefaultValue = string.Empty;
                    attribute.IsMultiValue = false;
                    attribute.IsRequired = false;
                    attribute.Description = string.Empty;
                    attribute.FieldTypeId = fieldType.Id;
                    attribute.Order = 0;

                    attributeService.Add( attribute );
                    rockContext.SaveChanges();
                }

                var attributeValueService = new Model.AttributeValueService( rockContext );
                var attributeValue = attributeValueService.GetByAttributeIdAndEntityId( attribute.Id, person.Id );

                if ( string.IsNullOrWhiteSpace( value ) )
                {
                    // Delete existing value if no existing value
                    if ( attributeValue != null )
                    {
                        attributeValueService.Delete( attributeValue );
                    }
                }
                else
                {
                    if ( attributeValue == null )
                    {
                        attributeValue = new Model.AttributeValue();
                        attributeValue.AttributeId = attribute.Id;
                        attributeValue.EntityId = person.Id;
                        attributeValueService.Add( attributeValue );
                    }
                    attributeValue.Value = value;
                }

                rockContext.SaveChanges();
            }
        }
        /// <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>
        /// Sets the value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="saveValue">if set to <c>true</c> [save value].</param>
        /// <param name="rockContext">The rock context.</param>
        public void SetValue( string key, string value, bool saveValue, RockContext rockContext )
        {
            AttributeCache attributeCache = null;

            if ( saveValue )
            {
                // Save new value
                rockContext = rockContext ?? new RockContext();
                var attributeValueService = new AttributeValueService( rockContext );
                var attributeValue = attributeValueService.GetGlobalAttributeValue( key );

                if ( attributeValue == null )
                {
                    var attributeService = new AttributeService( rockContext );
                    var attribute = attributeService.GetGlobalAttribute( key );
                    if ( attribute == null )
                    {
                        attribute = new Rock.Model.Attribute();
                        attribute.FieldTypeId = FieldTypeCache.Read( new Guid( SystemGuid.FieldType.TEXT ) ).Id;
                        attribute.EntityTypeQualifierColumn = string.Empty;
                        attribute.EntityTypeQualifierValue = string.Empty;
                        attribute.Key = key;
                        attribute.Name = key.SplitCase();
                        attributeService.Add( attribute );
                        rockContext.SaveChanges();
                    }

                    attributeValue = new AttributeValue();
                    attributeValue.IsSystem = false;
                    attributeValue.AttributeId = attribute.Id;
                    attributeValueService.Add( attributeValue );
                }

                attributeValue.Value = value;
                rockContext.SaveChanges();
            }

            lock(_obj)
            {
                attributeIds = null;
            }

            AttributeValues.AddOrUpdate( key, value, ( k, v ) => value );

            attributeCache = Attributes.FirstOrDefault( a => a.Key.Equals( key, StringComparison.OrdinalIgnoreCase ) );
            if ( attributeCache != null )
            {
                value = attributeCache.FieldType.Field.FormatValue( null, value, attributeCache.QualifierValues, false );
            }
            AttributeValuesFormatted.AddOrUpdate( key, value, (k, v) => value);
        }
Exemple #7
0
        /// <summary>
        /// Handles the SaveClick event of the mdAttributeValue 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 mdAttributeValue_SaveClick( object sender, EventArgs e )
        {
            if ( _displayValueEdit )
            {
                int attributeId = 0;
                if ( hfIdValues.Value != string.Empty && !int.TryParse( hfIdValues.Value, out attributeId ) )
                {
                    attributeId = 0;
                }

                if ( attributeId != 0 && phEditControls.Controls.Count > 0 )
                {
                    var attribute = Rock.Web.Cache.AttributeCache.Read( attributeId );

                    var rockContext = new RockContext();
                    AttributeValueService attributeValueService = new AttributeValueService( rockContext );
                    var attributeValue = attributeValueService.GetByAttributeIdAndEntityId( attributeId, _entityId );
                    if ( attributeValue == null )
                    {
                        attributeValue = new Rock.Model.AttributeValue();
                        attributeValue.AttributeId = attributeId;
                        attributeValue.EntityId = _entityId;
                        attributeValueService.Add( attributeValue );
                    }

                    var fieldType = Rock.Web.Cache.FieldTypeCache.Read( attribute.FieldType.Id );
                    attributeValue.Value = fieldType.Field.GetEditValue( attribute.GetControl( phEditControls.Controls[0] ), attribute.QualifierValues );

                    rockContext.SaveChanges();

                    Rock.Web.Cache.AttributeCache.Flush( attributeId );
                    if ( !_entityTypeId.HasValue && _entityQualifierColumn == string.Empty && _entityQualifierValue == string.Empty && ( !_entityId.HasValue || _entityId.Value == 0 ) )
                    {
                        Rock.Web.Cache.GlobalAttributesCache.Flush();
                    }
                }

                hfIdValues.Value = string.Empty;

                HideDialog();
            }

            BindGrid();
        }
Exemple #8
0
        /// <summary>
        /// Handles the SaveClick event of the modalDetails 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 modalDetails_SaveClick( object sender, EventArgs e )
        {
            if ( _displayValueEdit )
            {
                int attributeId = 0;
                if ( hfIdValues.Value != string.Empty && !int.TryParse( hfIdValues.Value, out attributeId ) )
                {
                    attributeId = 0;
                }

                if ( attributeId != 0 && phEditControl.Controls.Count > 0 )
                {
                    var attribute = Rock.Web.Cache.AttributeCache.Read( attributeId );

                    AttributeValueService attributeValueService = new AttributeValueService();
                    var attributeValue = attributeValueService.GetByAttributeIdAndEntityId( attributeId, _entityId ).FirstOrDefault();
                    if ( attributeValue == null )
                    {
                        attributeValue = new Rock.Model.AttributeValue();
                        attributeValue.AttributeId = attributeId;
                        attributeValue.EntityId = _entityId;
                        attributeValueService.Add( attributeValue, CurrentPersonId );
                    }

                    var fieldType = Rock.Web.Cache.FieldTypeCache.Read( attribute.FieldType.Id );
                    attributeValue.Value = fieldType.Field.GetEditValue( phEditControl.Controls[0], attribute.QualifierValues );

                    attributeValueService.Save( attributeValue, CurrentPersonId );

                    Rock.Web.Cache.AttributeCache.Flush( attributeId );
                    if ( !_entityTypeId.HasValue && _entityQualifierColumn == string.Empty && _entityQualifierValue == string.Empty && !_entityId.HasValue )
                    {
                        Rock.Web.Cache.GlobalAttributesCache.Flush();
                    }
                }

                hfIdValues.Value = string.Empty;

                modalDetails.Hide();
            }

            BindGrid();
        }
        /// <summary>
        /// Maps the authorizations to an attribute.
        /// </summary>
        /// <param name="tableData">The table data.</param>
        private void MapAuthorizations( IQueryable<Row> tableData )
        {
            var lookupContext = new RockContext();
            var rockContext = new RockContext();
            var categoryService = new CategoryService( lookupContext );
            var personService = new PersonService( lookupContext );

            var noteList = new List<Note>();

            int completed = 0;
            int totalRows = tableData.Count();
            int percentage = ( totalRows - 1 ) / 100 + 1;
            ReportProgress( 0, string.Format( "Verifying Authorization import ({0:N0} found).", totalRows ) );

            var attributeList = new AttributeService( lookupContext ).Queryable().ToList();
            int authorizationAttributeId = 0;
            if ( attributeList.Find( a => a.Key == "PickupAuthorization" ) != null )
            {
                authorizationAttributeId = attributeList.Find( a => a.Key == "PickupAuthorization" ).Id;
            }

            var authorizationAttributeValueList = new List<AttributeValue>();
            authorizationAttributeValueList = new AttributeValueService( rockContext ).Queryable().Where( av => av.AttributeId == authorizationAttributeId ).ToList();

            int f1HouseholdIdAttributeId = attributeList.Find( a => a.Key == "F1HouseholdId" ).Id;

            //places all household attributes in a dictionary where the key is the personId and the houshold is the value.
            var householdDictionary = new AttributeValueService( lookupContext ).Queryable()
                .Where( av => av.AttributeId == f1HouseholdIdAttributeId )
                .Select( av => new { PersonId = av.EntityId, HouseholdId = av.Value } )
                .ToDictionary( t => t.PersonId, t => t.HouseholdId );

            foreach ( var row in tableData )
            {
                //var rockContext = new RockContext();
                var categoryList = new CategoryService( rockContext ).Queryable().ToList();

                //check if category exists
                //If it doesn't (though it should), it will create a new category called Authorization
                if ( categoryList.Find( c => c.Name == "Childhood Information" ) == null )
                {
                    var entityType = new EntityTypeService( rockContext );
                    //creates if category doesn't exist
                    var newCategory = new Category();
                    newCategory.IsSystem = false;
                    newCategory.EntityTypeId = entityType.Queryable().Where( e => e.Name == "Rock.Model.Attribute" ).Select( e => e.Id ).FirstOrDefault();
                    newCategory.EntityTypeQualifierColumn = "EntityTypeId";
                    newCategory.EntityTypeQualifierValue = Convert.ToString( PersonEntityTypeId );
                    newCategory.Name = "Authorization";
                    newCategory.Description = "Contains the pickup authorization";

                    //var newCategoryContext = new RockContext();
                    //newCategoryContext.WrapTransaction( () =>
                    //{
                    //    newCategoryContext.Configuration.AutoDetectChangesEnabled = false;
                    //    newCategoryContext.Categories.Add( newCategory );
                    //    newCategoryContext.SaveChanges( DisableAudit );
                    //} );
                    rockContext.WrapTransaction( () =>
                    {
                        rockContext.Configuration.AutoDetectChangesEnabled = false;
                        rockContext.Categories.Add( newCategory );
                        rockContext.SaveChanges( DisableAudit );
                    } );
                }
                attributeList = new AttributeService( lookupContext ).Queryable().ToList();

                //Check if Attribute exists
                //If it doesn't it creates the attribute
                if ( attributeList.Find( a => a.Key == "PickupAuthorization" ) == null )
                {
                    var fieldType = new FieldTypeService( rockContext );
                    //var newAttributeList = new List<Rock.Model.Attribute>();
                    var fieldTypeId = fieldType.Queryable().Where( e => e.Name == "Memo" ).FirstOrDefault().Id;
                    var category2 = new CategoryService( rockContext ).Queryable().Where( gt => gt.Name == "Childhood Information" ).FirstOrDefault();
                    var category3 = new CategoryService( rockContext ).Queryable().Where( gt => gt.Name == "Authorization" ).FirstOrDefault();

                    //Creates if attribute doesn't exist
                    //The attribute is a memo attribute
                    var newAttribute = new Rock.Model.Attribute();
                    newAttribute.Key = "PickupAuthorization";
                    newAttribute.Name = "Pickup Authorization";
                    newAttribute.FieldTypeId = fieldTypeId;
                    newAttribute.EntityTypeId = PersonEntityTypeId;
                    newAttribute.EntityTypeQualifierValue = string.Empty;
                    newAttribute.EntityTypeQualifierColumn = string.Empty;
                    newAttribute.Description = "Lists who is authorized to pickup this child along with their current phone number.";
                    newAttribute.DefaultValue = string.Empty;
                    newAttribute.IsMultiValue = false;
                    newAttribute.IsRequired = false;

                    if ( categoryList.Find( c => c.Name == "Childhood Information" ) != null )
                    {
                        newAttribute.Categories = new List<Category>();
                        newAttribute.Categories.Add( category2 );

                    }
                        //If authorization category was create, this is where the attribute is set to that category.
                    else
                    {
                        newAttribute.Categories = new List<Category>();
                        newAttribute.Categories.Add( category3 );  //Sets to Authorization Attribute Category.
                    }

                    //saves the attribute
                    rockContext.WrapTransaction( () =>
                    {
                        rockContext.Configuration.AutoDetectChangesEnabled = false;
                        rockContext.Attributes.Add( newAttribute );
                        rockContext.SaveChanges( DisableAudit );
                    } );
                }
                //Adding to the person's attributes
                int? householdId = row["HouseholdID"] as int?;
                string personName = row["PersonName"] as string;
                DateTime? authorizationDate = row["AuthorizationDate"] as DateTime?;

                attributeList = new AttributeService( rockContext ).Queryable().ToList();

                //Gets the Attribute Id for Pickup Authorization.
                authorizationAttributeId = attributeList.Find(a => a.Key == "PickupAuthorization").Id;

                //since F1 authorization applies to the household id and not individual I have to apply it to all members in that household.
                //Value in F1 is a text entry and not a person select. Discuss with staff that we need to break away from this and start using known relationships for authorization
                foreach ( var household in householdDictionary.Where( h => h.Value == Convert.ToString( householdId ) ) )
                {
                    //checks if a record already exists in the list

                    if ( authorizationAttributeValueList.Find( a => a.AttributeId == authorizationAttributeId && a.EntityId == household.Key ) == null )
                    {
                        var person = new PersonService( rockContext ).Queryable().Where( p => p.Id == household.Key ).FirstOrDefault();

                        //trying to keep from adding this attribute to adult records
                        if ( person != null && (person.Age <= 18 || person.Age == null) )
                        {
                            //creates new attribute record if it does not exist.
                            var newAuthorizationAttribute = new AttributeValue();
                            newAuthorizationAttribute.IsSystem = false;
                            newAuthorizationAttribute.AttributeId = authorizationAttributeId;
                            newAuthorizationAttribute.EntityId = household.Key; //the key is the person ID
                            newAuthorizationAttribute.Value = personName + ", "; //text field
                            newAuthorizationAttribute.CreatedDateTime = authorizationDate;

                            //adds the new record to the list
                            authorizationAttributeValueList.Add( newAuthorizationAttribute );
                        }
                    }
                        //if a record already exists
                    else
                    {
                        //adds to the current value.
                        authorizationAttributeValueList.Find( a => a.AttributeId == authorizationAttributeId && a.EntityId == household.Key ).Value = personName + ", ";
                    }

                }
                completed++;
                if ( completed % percentage < 1 )
                {
                    int percentComplete = completed / percentage;
                    ReportProgress( percentComplete, string.Format( "{0:N0} authorizations imported ({1}% complete).", completed, percentComplete ) );
                }
                else if ( completed % ReportingNumber < 1 )
                {
                   //rockContext.WrapTransaction( () =>
                   // {
                   //     rockContext.Configuration.AutoDetectChangesEnabled = false;
                   //     rockContext.AttributeValues.AddRange( authorizationAttributeValueList );
                   //     rockContext.SaveChanges( DisableAudit );  //I get can't insert duplicate entry error
                   // } );

                    ReportPartialProgress();
                }

            }

            if ( authorizationAttributeValueList.Any() )
            {
                //var rockContext = new RockContext();
                rockContext.WrapTransaction( () =>
                {
                    rockContext.Configuration.AutoDetectChangesEnabled = false;
                    rockContext.AttributeValues.AddRange( authorizationAttributeValueList );
                    rockContext.SaveChanges( DisableAudit );
                } );
            }

            ReportProgress( 100, string.Format( "Finished authorization import: {0:N0} notes imported.", completed ) );
        }
        /// <summary>
        /// Processes the confirmation.
        /// </summary>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        private bool ProcessConfirmation( out string errorMessage )
        {
            var rockContext = new RockContext();
            if ( string.IsNullOrWhiteSpace( TransactionCode ) )
            {
                GatewayComponent gateway = null;
                var financialGateway = hfPaymentTab.Value == "ACH" ? _achGateway : _ccGateway;
                if ( financialGateway != null )
                {
                    gateway = financialGateway.GetGatewayComponent();
                }

                if ( gateway == null )
                {
                    errorMessage = "There was a problem creating the payment gateway information";
                    return false;
                }

                Person person = GetPerson( true );
                if ( person == null )
                {
                    errorMessage = "There was a problem creating the person information";
                    return false;
                }

                if ( !person.PrimaryAliasId.HasValue )
                {
                    errorMessage = "There was a problem creating the person's primary alias";
                    return false;
                }

                PaymentInfo paymentInfo = GetPaymentInfo();
                if ( paymentInfo == null )
                {
                    errorMessage = "There was a problem creating the payment information";
                    return false;
                }
                else
                {
                    paymentInfo.FirstName = person.FirstName;
                    paymentInfo.LastName = person.LastName;
                }

                if ( paymentInfo.CreditCardTypeValue != null )
                {
                    CreditCardTypeValueId = paymentInfo.CreditCardTypeValue.Id;
                }

                if ( _showCommmentEntry )
                {
                    paymentInfo.Comment1 = !string.IsNullOrWhiteSpace( GetAttributeValue( "PaymentComment" ) ) ? string.Format( "{0}: {1}", GetAttributeValue( "PaymentComment" ), txtCommentEntry.Text ) : txtCommentEntry.Text;
                }
                else
                {
                    paymentInfo.Comment1 = GetAttributeValue( "PaymentComment" );
                }

                PaymentSchedule schedule = GetSchedule();
                if ( schedule != null )
                {
                    schedule.PersonId = person.Id;

                    var scheduledTransaction = gateway.AddScheduledPayment( financialGateway, schedule, paymentInfo, out errorMessage );
                    if ( scheduledTransaction != null )
                    {
                        scheduledTransaction.TransactionFrequencyValueId = schedule.TransactionFrequencyValue.Id;
                        scheduledTransaction.AuthorizedPersonAliasId = person.PrimaryAliasId.Value;
                        scheduledTransaction.FinancialGatewayId = financialGateway.Id;

                        if ( scheduledTransaction.FinancialPaymentDetail == null )
                        {
                            scheduledTransaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                        }
                        scheduledTransaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext );

                        var changeSummary = new StringBuilder();
                        changeSummary.AppendFormat( "{0} starting {1}", schedule.TransactionFrequencyValue.Value, schedule.StartDate.ToShortDateString() );
                        changeSummary.AppendLine();
                        changeSummary.Append( paymentInfo.CurrencyTypeValue.Value );
                        if ( paymentInfo.CreditCardTypeValue != null )
                        {
                            changeSummary.AppendFormat( " - {0}", paymentInfo.CreditCardTypeValue.Value );
                        }
                        changeSummary.AppendFormat( " {0}", paymentInfo.MaskedNumber );
                        changeSummary.AppendLine();

                        foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) )
                        {
                            var transactionDetail = new FinancialScheduledTransactionDetail();
                            transactionDetail.Amount = account.Amount;
                            transactionDetail.AccountId = account.Id;
                            scheduledTransaction.ScheduledTransactionDetails.Add( transactionDetail );
                            changeSummary.AppendFormat( "{0}: {1}", account.Name, account.Amount.FormatAsCurrency() );
                            changeSummary.AppendLine();
                        }

                        var transactionService = new FinancialScheduledTransactionService( rockContext );
                        transactionService.Add( scheduledTransaction );
                        rockContext.SaveChanges();

                        // Add a note about the change
                        var noteType = NoteTypeCache.Read( Rock.SystemGuid.NoteType.SCHEDULED_TRANSACTION_NOTE.AsGuid() );
                        if ( noteType != null )
                        {
                            var noteService = new NoteService( rockContext );
                            var note = new Note();
                            note.NoteTypeId = noteType.Id;
                            note.EntityId = scheduledTransaction.Id;
                            note.Caption = "Created Transaction";
                            note.Text = changeSummary.ToString();
                            noteService.Add( note );
                        }
                        rockContext.SaveChanges();

                        ScheduleId = scheduledTransaction.GatewayScheduleId;
                        TransactionCode = scheduledTransaction.TransactionCode;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    var transaction = gateway.Charge( financialGateway, paymentInfo, out errorMessage );
                    if ( transaction != null )
                    {
                        var txnChanges = new List<string>();
                        txnChanges.Add( "Created Transaction" );

                        History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode );

                        transaction.AuthorizedPersonAliasId = person.PrimaryAliasId;
                        History.EvaluateChange( txnChanges, "Person", string.Empty, person.FullName );

                        transaction.TransactionDateTime = RockDateTime.Now;
                        History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime );

                        transaction.FinancialGatewayId = financialGateway.Id;
                        History.EvaluateChange( txnChanges, "Gateway", string.Empty, financialGateway.Name );

                        var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ) );
                        transaction.TransactionTypeValueId = txnType.Id;
                        History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value );

                        if ( transaction.FinancialPaymentDetail == null )
                        {
                            transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                        }
                        transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges );

                        Guid sourceGuid = Guid.Empty;
                        if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) )
                        {
                            var source = DefinedValueCache.Read( sourceGuid );
                            if ( source != null )
                            {
                                transaction.SourceTypeValueId = source.Id;
                                History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value );
                            }
                        }

                        foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) )
                        {
                            var transactionDetail = new FinancialTransactionDetail();
                            transactionDetail.Amount = account.Amount;
                            transactionDetail.AccountId = account.Id;
                            transaction.TransactionDetails.Add( transactionDetail );
                            History.EvaluateChange( txnChanges, account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() );
                        }

                        var batchService = new FinancialBatchService( rockContext );

                        // Get the batch
                        var batch = batchService.Get(
                            GetAttributeValue( "BatchNamePrefix" ),
                            paymentInfo.CurrencyTypeValue,
                            paymentInfo.CreditCardTypeValue,
                            transaction.TransactionDateTime.Value,
                            financialGateway.GetBatchTimeOffset() );

                        var batchChanges = new List<string>();

                        if ( batch.Id == 0 )
                        {
                            batchChanges.Add( "Generated the batch" );
                            History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name );
                            History.EvaluateChange( batchChanges, "Status", null, batch.Status );
                            History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime );
                            History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime );
                        }

                        decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
                        History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() );
                        batch.ControlAmount = newControlAmount;

                        transaction.BatchId = batch.Id;
                        batch.Transactions.Add( transaction );

                        rockContext.SaveChanges();

                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            batchChanges
                        );

                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                            batch.Id,
                            txnChanges,
                            person.FullName,
                            typeof( FinancialTransaction ),
                            transaction.Id
                        );

                        SendReceipt( transaction.Id );

                        TransactionCode = transaction.TransactionCode;
                    }
                    else
                    {
                        return false;
                    }
                }

                tdTransactionCodeReceipt.Description = TransactionCode;
                tdTransactionCodeReceipt.Visible = !string.IsNullOrWhiteSpace( TransactionCode );

                tdScheduleId.Description = ScheduleId;
                tdScheduleId.Visible = !string.IsNullOrWhiteSpace( ScheduleId );

                tdNameReceipt.Description = paymentInfo.FullName;
                tdPhoneReceipt.Description = paymentInfo.Phone;
                tdEmailReceipt.Description = paymentInfo.Email;
                tdAddressReceipt.Description = string.Format( "{0} {1}, {2} {3}", paymentInfo.Street1, paymentInfo.City, paymentInfo.State, paymentInfo.PostalCode );

                rptAccountListReceipt.DataSource = SelectedAccounts.Where( a => a.Amount != 0 );
                rptAccountListReceipt.DataBind();

                tdTotalReceipt.Description = paymentInfo.Amount.ToString( "C" );

                tdPaymentMethodReceipt.Description = paymentInfo.CurrencyTypeValue.Description;
                tdAccountNumberReceipt.Description = paymentInfo.MaskedNumber;
                tdWhenReceipt.Description = schedule != null ? schedule.ToString() : "Today";

                // If there was a transaction code returned and this was not already created from a previous saved account,
                // show the option to save the account.
                if ( !( paymentInfo is ReferencePaymentInfo ) && !string.IsNullOrWhiteSpace( TransactionCode ) && gateway.SupportsSavedAccount( paymentInfo.CurrencyTypeValue ) )
                {
                    cbSaveAccount.Visible = true;
                    pnlSaveAccount.Visible = true;
                    txtSaveAccount.Visible = true;

                    // If current person does not have a login, have them create a username and password
                    phCreateLogin.Visible = !new UserLoginService( rockContext ).GetByPersonId( person.Id ).Any();
                }
                else if ( !new UserLoginService( rockContext ).GetByPersonId( person.Id ).Any() )
                {
                    pnlSaveAccount.Visible = true;
                    phCreateLogin.Visible = true;
                    cbSaveAccount.Visible = false;
                    txtSaveAccount.Visible = false;
                }
                else
                {
                    pnlSaveAccount.Visible = false;
                }

                if ( PageParameter( "argsd" ) == "1" )
                {
                    var rc = new RockContext();
                    var ats = new AttributeService( rc );
                    var argsd = ats.Queryable().Where( x => x.Key == "AutomatedRecurringGiftSetupDate" ).FirstOrDefault();
                    if ( argsd == null )
                    {
                        argsd = new Rock.Model.Attribute();
                        argsd.FieldTypeId = 85;
                        argsd.EntityTypeId = 15;
                        argsd.Key = "AutomatedRecurringGiftSetupDate";
                        argsd.Name = "Automated Recurring Gift Setup Date";
                        argsd.Guid = Guid.NewGuid();
                        argsd.CreatedDateTime = argsd.ModifiedDateTime = DateTime.Now;
                        ats.Add( argsd );
                        rc.SaveChanges();
                        rc = new RockContext();
                        ats = new AttributeService( rc );
                        argsd = ats.Queryable().Where( x => x.Key == "AutomatedRecurringGiftSetupDate" ).FirstOrDefault();
                    }
                    if ( argsd != null )
                    {
                        var atvs = new AttributeValueService( rc );
                        var argsdVal = atvs.Queryable().Where( x => x.AttributeId == argsd.Id && x.EntityId == person.Id ).FirstOrDefault();
                        if ( argsdVal == null )
                        {
                            argsdVal = new Rock.Model.AttributeValue();
                            argsdVal.AttributeId = argsd.Id;
                            argsdVal.EntityId = person.Id;
                            argsdVal.Value = DateTime.Now.ToString( "o" );
                            argsdVal.Guid = Guid.NewGuid();
                            argsdVal.CreatedDateTime = argsdVal.ModifiedDateTime = DateTime.Now;

                            atvs.Add( argsdVal );
                            rc.SaveChanges();
                        }
                        else
                        {
                            argsdVal.Value = DateTime.Now.ToString( "o" );
                            rc.SaveChanges();
                        }
                    }
                }
                return true;
            }
            else
            {
                pnlDupWarning.Visible = true;
                divActions.Visible = false;
                errorMessage = string.Empty;
                return false;
            }
        }
        void lvAttributeValues_ItemUpdating( object sender, ListViewUpdateEventArgs e )
        {
            PlaceHolder phEditValue = lvAttributeValues.EditItem.FindControl( "phEditValue" ) as PlaceHolder;
            if ( phEditValue != null && phEditValue.Controls.Count == 1 )
            {
                string value = _attribute.FieldType.Field.GetEditValue( phEditValue.Controls[0], _attribute.QualifierValues );

                var attributeValueService = new AttributeValueService();
                var attributeValue = attributeValueService.Get( ( int )e.Keys["Id"] );
                if ( attributeValue == null )
                {
                    attributeValue = new AttributeValue();
                    attributeValueService.Add( attributeValue, _currentPersonId );

                    attributeValue.AttributeId = _attribute.Id;
                    attributeValue.EntityId = _model.Id;
                }

                attributeValue.Value = value;
                attributeValueService.Save( attributeValue, _currentPersonId );

                _model.LoadAttributes();
            }

            lvAttributeValues.EditIndex = -1;
            BindData();
        }
        void lvAttributeValues_ItemInserting( object sender, ListViewInsertEventArgs e )
        {
            PlaceHolder phInsertValue = lvAttributeValues.InsertItem.FindControl( "phInsertValue" ) as PlaceHolder;
            if ( phInsertValue != null && phInsertValue.Controls.Count == 1 )
            {
                string value = _attribute.FieldType.Field.GetEditValue( phInsertValue.Controls[0], _attribute.QualifierValues );

                var attributeValueService = new AttributeValueService();
                var attributeValue = new AttributeValue();
                attributeValue.AttributeId = _attribute.Id;
                attributeValue.EntityId = _model.Id;
                attributeValue.Value = value;

                int? maxOrder = attributeValueService.Queryable().
                    Where( a => a.AttributeId == attributeValue.AttributeId &&
                        a.EntityId == attributeValue.EntityId).
                    Select( a => ( int? )a.Order ).Max();

                attributeValue.Order = maxOrder.HasValue ? maxOrder.Value + 1 : 0;

                attributeValueService.Add( attributeValue, _currentPersonId);
                attributeValueService.Save( attributeValue, _currentPersonId );
                _model.LoadAttributes();
            }

            lvAttributeValues.EditIndex = -1;
            BindData();
        }