protected void btnImport_Click(object sender, EventArgs e)
        {
            btnImport.Enabled = false;
            var rockContext = new RockContext();
            var volunteerTrackingContext   = new VolunteerTrackingContext();
            var volunteerMembershipService = new VolunteerMembershipService(volunteerTrackingContext);
            var groupService = new GroupService(rockContext);

            var groupTypeGuids = GetAttributeValue("GroupTypes").SplitDelimitedValues().AsGuidList();
            var groupTypeIds   = new GroupTypeService(rockContext).GetByGuids(groupTypeGuids).Select(gt => gt.Id);
            var groups         = groupService.Queryable().Where(g => groupTypeIds.Contains(g.GroupTypeId)).ToList();

            foreach (var group in groups)
            {
                foreach (var groupMember in group.Members)
                {
                    var volunteerMember = volunteerMembershipService.Queryable().FirstOrDefault(v => v.GroupId == groupMember.GroupId && v.PersonId == groupMember.PersonId && v.LeftGroupDateTime == null);
                    if (volunteerMember == null)
                    {
                        volunteerMember = new VolunteerMembership
                        {
                            GroupId             = groupMember.GroupId,
                            PersonId            = groupMember.PersonId,
                            GroupRoleId         = groupMember.GroupRoleId,
                            JoinedGroupDateTime = DateTime.Now
                        };

                        volunteerMembershipService.Add(volunteerMember);
                    }
                }
            }

            volunteerTrackingContext.SaveChanges();
            btnImport.Enabled = true;
        }
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            var entityTypeGroupGuid  = Rock.SystemGuid.EntityType.GROUP.AsGuid();
            var entityTypePersonGuid = Rock.SystemGuid.EntityType.PERSON.AsGuid();

            RockContext                rockContext                = new RockContext();
            PersonService              personService              = new PersonService(rockContext);
            GroupService               groupService               = new GroupService(rockContext);
            GroupTypeService           groupTypeService           = new GroupTypeService(rockContext);
            VolunteerMembershipService volunteerMembershipService = new VolunteerMembershipService(new VolunteerTrackingContext());

            var servingTeamGroupTypeGuid = GetAttributeValue("ServingGroupType").AsGuidOrNull();

            if (servingTeamGroupTypeGuid.HasValue)
            {
                var servingTeamChildGroupTypes = groupTypeService.GetChildGroupTypes(servingTeamGroupTypeGuid.Value);

                var servingGroupQry = groupService.Queryable().Where(g => servingTeamChildGroupTypes.Select(gt => gt.Id).Contains(g.GroupTypeId));

                var servingGroupIds = servingGroupQry.Select(g => g.Id).ToList();

                var servingGroups = new List <GroupSummary>();

                foreach (var servingGroup in servingGroupQry.ToList())
                {
                    servingGroup.LoadAttributes();
                    servingGroups.Add(new GroupSummary
                    {
                        GroupId         = servingGroup.Id,
                        ParentGroupId   = servingGroup.ParentGroupId,
                        GroupName       = servingGroup.Name,
                        ParentGroupName = servingGroup.ParentGroupId != null ? servingGroup.ParentGroup.Name : string.Empty,
                        Director        = servingGroup.GetAttributeValue(GetAttributeValue("DirectorAttributeKey")),
                        VolunteerGoal   = servingGroup.GetAttributeValue(GetAttributeValue("VolunteerGoalAttributeKey")).AsIntegerOrNull(),
                        LeaderGoal      = servingGroup.GetAttributeValue(GetAttributeValue("LeaderGoalAttributeKey")).AsIntegerOrNull()
                    });
                }

                var volunteerQry = volunteerMembershipService.Queryable().Where(vm => servingGroupIds.Contains(vm.GroupId));

                var volunteerSummary = volunteerQry.Select(vm => new
                {
                    GroupId   = vm.GroupId,
                    Volunteer = vm
                })
                                       .GroupBy(vm => vm.GroupId)
                                       .Select(vmg => new
                {
                    GroupId    = vmg.Key,
                    Volunteers = vmg.Select(v => v.Volunteer).ToList()
                });

                var servingGroupSummary = from g in servingGroups
                                          join vmg in volunteerSummary
                                          on g.GroupId equals vmg.GroupId into joinResult
                                          from x in joinResult.DefaultIfEmpty(new { GroupId = g.GroupId, Volunteers = new List <VolunteerMembership>() })
                                          select new
                {
                    Group      = g,
                    Volunteers = x.Volunteers
                };

                DateRange dateRange = new DateRange(dpStart.SelectedDate, dpEnd.SelectedDate);
                if (dpStart.SelectedDate == null)
                {
                    dateRange.Start = RockDateTime.Now;
                }

                if (dpStart.SelectedDate == null)
                {
                    dateRange.End = RockDateTime.Now;
                }

                IEnumerable <DateRange> dateRangeList = SplitDateRangeIntoWeeks(dateRange);

                var gListSource = servingGroupSummary.SelectMany(g => dateRangeList, (g, d) => new
                {
                    Ministry           = g.Group.ParentGroupId != null ? g.Group.ParentGroupName : g.Group.GroupName,
                    Director           = g.Group.Director,
                    DateRange          = d.Start.Value.ToShortDateString() + " - " + d.End.Value.ToShortDateString(),
                    StartingVolunteers = g.Volunteers.Where(vm => !vm.GroupRole.IsLeader &&
                                                            (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.Start.Value) &&
                                                            vm.JoinedGroupDateTime < d.Start.Value)
                                         .DistinctBy(vm => vm.PersonId)
                                         .Count(),
                    NewVolunteers = g.Volunteers.Where(vm => !vm.GroupRole.IsLeader &&
                                                       (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                       (vm.JoinedGroupDateTime >= d.Start.Value && vm.JoinedGroupDateTime < d.End.Value))
                                    .DistinctBy(vm => vm.PersonId).Count(),
                    LostVolunteers = g.Volunteers.Where(vm => !vm.GroupRole.IsLeader)
                                     .GroupBy(vm => vm.PersonId)
                                     .Where(vmg => vmg.Where(v => v.LeftGroupDateTime >= d.Start.Value && v.LeftGroupDateTime < d.End.Value).Count() > vmg.Where(v => v.JoinedGroupDateTime >= d.Start.Value && v.JoinedGroupDateTime < d.End.Value).Count())
                                     .Count(),
                    TotalVolunteers = g.Volunteers.Where(vm => !vm.GroupRole.IsLeader &&
                                                         (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                         vm.JoinedGroupDateTime < d.End.Value)
                                      .DistinctBy(vm => vm.PersonId)
                                      .Count(),
                    VolunteerGoal    = g.Group.VolunteerGoal ?? null,
                    VolunteerPercent = g.Group.VolunteerGoal != null ? g.Volunteers.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                          (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                                                          vm.JoinedGroupDateTime < d.End.Value)
                                       .DistinctBy(vm => vm.PersonId)
                                       .Count() / g.Group.VolunteerGoal : null,
                    StartingLeaders = g.Volunteers.Where(vm => vm.GroupRole.IsLeader &&
                                                         (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.Start.Value) &&
                                                         vm.JoinedGroupDateTime < d.Start.Value)
                                      .DistinctBy(vm => vm.PersonId)
                                      .Count(),
                    NewLeaders = g.Volunteers.Where(vm => vm.GroupRole.IsLeader &&
                                                    (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                    (vm.JoinedGroupDateTime >= d.Start.Value && vm.JoinedGroupDateTime < d.End.Value))
                                 .DistinctBy(vm => vm.PersonId).Count(),
                    LostLeaders = g.Volunteers.Where(vm => vm.GroupRole.IsLeader)
                                  .GroupBy(vm => vm.PersonId)
                                  .Where(vmg => vmg.Where(v => v.LeftGroupDateTime >= d.Start.Value && v.LeftGroupDateTime < d.End.Value).Count() > vmg.Where(v => v.JoinedGroupDateTime >= d.Start.Value && v.JoinedGroupDateTime < d.End.Value).Count())
                                  .Count(),
                    TotalLeaders = g.Volunteers.Where(vm => vm.GroupRole.IsLeader &&
                                                      (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                      vm.JoinedGroupDateTime < d.End.Value)
                                   .DistinctBy(vm => vm.PersonId)
                                   .Count(),
                    LeaderGoal    = g.Group.LeaderGoal ?? null,
                    LeaderPercent = g.Group.LeaderGoal != null ? g.Volunteers.Where(vm => vm.GroupRole.IsLeader &&
                                                                                    (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > d.End.Value) &&
                                                                                    vm.JoinedGroupDateTime < d.End.Value)
                                    .DistinctBy(vm => vm.PersonId)
                                    .Count() / g.Group.LeaderGoal : null
                }).ToList();

                gList.DataSource = gListSource.ToList();
                gList.DataBind();


                var gVolunteersSource = new[] { new {
                                                    StartingVolunteers = volunteerQry.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                            (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.Start.Value) &&
                                                                                            vm.JoinedGroupDateTime < dateRange.Start.Value)
                                                                         .DistinctBy(vm => vm.PersonId)
                                                                         .Count(),
                                                    NewVolunteers = volunteerQry.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                       (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                       (vm.JoinedGroupDateTime >= dateRange.Start.Value && vm.JoinedGroupDateTime < dateRange.End.Value))
                                                                    .DistinctBy(vm => vm.PersonId).Count(),
                                                    LostVolunteers = volunteerQry.Where(vm => !vm.GroupRole.IsLeader)
                                                                     .GroupBy(vm => vm.PersonId)
                                                                     .Where(vmg => vmg.Where(v => v.LeftGroupDateTime >= dateRange.Start.Value && v.LeftGroupDateTime < dateRange.End.Value).Count() > vmg.Where(v => v.JoinedGroupDateTime >= dateRange.Start.Value && v.JoinedGroupDateTime < dateRange.End.Value).Count())
                                                                     .Count(),
                                                    TotalVolunteers = volunteerQry.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                         (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                         vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                      .DistinctBy(vm => vm.PersonId)
                                                                      .Count(),
                                                    VolunteerGoal    = servingGroups.Sum(g => g.VolunteerGoal) ?? null,
                                                    VolunteerPercent = servingGroups.Sum(g => g.VolunteerGoal) > 0 ? volunteerQry.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                                                                        (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                                                                        vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                       .DistinctBy(vm => vm.PersonId)
                                                                       .Count() / servingGroups.Sum(g => g.VolunteerGoal) : null,
                                                } };

                gVolunteers.DataSource = gVolunteersSource.ToList();
                gVolunteers.DataBind();
                gVolunteers.ShowFooter = false;

                var gLeadersSource = new[] { new {
                                                 StartingLeaders = volunteerQry.Where(vm => vm.GroupRole.IsLeader &&
                                                                                      (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.Start.Value) &&
                                                                                      vm.JoinedGroupDateTime < dateRange.Start.Value)
                                                                   .DistinctBy(vm => vm.PersonId)
                                                                   .Count(),
                                                 NewLeaders = volunteerQry.Where(vm => vm.GroupRole.IsLeader &&
                                                                                 (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                 (vm.JoinedGroupDateTime >= dateRange.Start.Value && vm.JoinedGroupDateTime < dateRange.End.Value))
                                                              .DistinctBy(vm => vm.PersonId).Count(),
                                                 LostLeaders = volunteerQry.Where(vm => vm.GroupRole.IsLeader)
                                                               .GroupBy(vm => vm.PersonId)
                                                               .Where(vmg => vmg.Where(v => v.LeftGroupDateTime >= dateRange.Start.Value && v.LeftGroupDateTime < dateRange.End.Value).Count() > vmg.Where(v => v.JoinedGroupDateTime >= dateRange.Start.Value && v.JoinedGroupDateTime < dateRange.End.Value).Count())
                                                               .Count(),
                                                 TotalLeaders = volunteerQry.Where(vm => vm.GroupRole.IsLeader &&
                                                                                   (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                   vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                .DistinctBy(vm => vm.PersonId)
                                                                .Count(),
                                                 LeaderGoal    = servingGroups.Sum(g => g.LeaderGoal) ?? null,
                                                 LeaderPercent = servingGroups.Sum(g => g.LeaderGoal) > 0 ? volunteerQry.Where(vm => vm.GroupRole.IsLeader &&
                                                                                                                               (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                                                               vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                 .DistinctBy(vm => vm.PersonId)
                                                                 .Count() / servingGroups.Sum(g => g.LeaderGoal) : null,
                                             } };

                gLeaders.DataSource = gLeadersSource.ToList();
                gLeaders.DataBind();

                var gUniquesSource = new[] { new {
                                                 UniqueVolunteers = volunteerQry.Where(vm => !vm.GroupRole.IsLeader &&
                                                                                       (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                       vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                    .DistinctBy(vm => vm.PersonId)
                                                                    .Count(),
                                                 UniqueLeaders = volunteerQry.Where(vm => vm.GroupRole.IsLeader &&
                                                                                    (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                    vm.JoinedGroupDateTime < dateRange.End.Value)
                                                                 .DistinctBy(vm => vm.PersonId)
                                                                 .Count(),
                                                 UniqueTotal = volunteerQry.Where(vm =>
                                                                                  (!vm.LeftGroupDateTime.HasValue || vm.LeftGroupDateTime > dateRange.End.Value) &&
                                                                                  vm.JoinedGroupDateTime < dateRange.End.Value)
                                                               .DistinctBy(vm => vm.PersonId)
                                                               .Count()
                                             } };

                gUniques.DataSource = gUniquesSource.ToList();
                gUniques.DataBind();
            }
        }
        /// <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>();

            // Determine the group
            Group group = null;

            var guidGroupAttribute = GetAttributeValue(action, "Group").AsGuidOrNull();

            if (guidGroupAttribute.HasValue)
            {
                var attributeGroup = AttributeCache.Read(guidGroupAttribute.Value, rockContext);
                if (attributeGroup != null)
                {
                    var groupGuid = action.GetWorklowAttributeValue(guidGroupAttribute.Value).AsGuidOrNull();

                    if (groupGuid.HasValue)
                    {
                        group = new GroupService(rockContext).Get(groupGuid.Value);
                    }
                }
            }

            if (group == null)
            {
                errorMessages.Add("No group was provided");
            }

            // determine the person
            Person person = null;

            // get the Attribute.Guid for this workflow's Person Attribute so that we can lookup the value
            var guidPersonAttribute = GetAttributeValue(action, "Person").AsGuidOrNull();

            if (guidPersonAttribute.HasValue)
            {
                var attributePerson = AttributeCache.Read(guidPersonAttribute.Value, rockContext);
                if (attributePerson != null)
                {
                    string attributePersonValue = action.GetWorklowAttributeValue(guidPersonAttribute.Value);
                    if (!string.IsNullOrWhiteSpace(attributePersonValue))
                    {
                        if (attributePerson.FieldType.Class == typeof(Rock.Field.Types.PersonFieldType).FullName)
                        {
                            var personAliasGuid = attributePersonValue.AsGuid();
                            if (!personAliasGuid.IsEmpty())
                            {
                                person = new PersonAliasService(rockContext).Queryable()
                                         .Where(a => a.Guid.Equals(personAliasGuid))
                                         .Select(a => a.Person)
                                         .FirstOrDefault();
                            }
                        }
                        else
                        {
                            errorMessages.Add("The attribute used to provide the person was not of type 'Person'.");
                        }
                    }
                }
            }

            if (person == null)
            {
                errorMessages.Add(string.Format("Person could not be found for selected value ('{0}')!", guidPersonAttribute));
            }

            // Mark Volunteer as Left
            if (!errorMessages.Any())
            {
                var volunteerTrackingContext   = new VolunteerTrackingContext();
                var volunteerMembershipService = new VolunteerMembershipService(volunteerTrackingContext);
                var volunteerMembership        = volunteerMembershipService.Queryable().FirstOrDefault(v => v.GroupId == group.Id && v.PersonId == person.Id && v.LeftGroupDateTime == null);
                if (volunteerMembership != null)
                {
                    volunteerMembership.LeftGroupDateTime = DateTime.Now;
                    volunteerTrackingContext.SaveChanges();
                }
                else
                {
                    // the person is not in the group provided
                    errorMessages.Add("The person was not in the group provided.");
                }
            }

            errorMessages.ForEach(m => action.AddLogEntry(m, true));

            return(true);
        }