Пример #1
0
        protected void gMobileRecords_RowSelected(object sender, RowEventArgs e)
        {
            var recordId = e.RowKeyId;
            var record   = MobileCheckinRecordCache.Get(recordId);

            ShowAttendances(record.AttendanceIds);
        }
Пример #2
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The workflow action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            var checkInState = GetCheckInState(entity, out errorMessages);

            if (checkInState != null)
            {
                var people = checkInState.CheckIn.CurrentFamily.People
                             .Where(p => p.Selected)
                             .Select(p => p.Person)
                             .ToList();

                var checkInLabels = CheckinLabelGen.GenerateLabels(people, checkInState.Kiosk.Device, GetAttributeValue(action, "AggregatedLabel").AsGuidOrNull());

                var groupType = checkInState.CheckIn.CurrentFamily.People
                                .Where(p => p.Selected)
                                .SelectMany(p => p.GroupTypes.Where(gt => gt.Selected))
                                .FirstOrDefault();

                if (groupType != null)
                {
                    groupType.Labels = checkInLabels;
                }


                //For mobile check-in we need to serialize this data and save it in the database.
                //This will mean that when it's time to finish checkin in
                //All we will need to do is deserialize and pass the data to the printer
                if (GetAttributeValue(action, "IsMobile").AsBoolean())
                {
                    MobileCheckinRecordService mobileCheckinRecordService = new MobileCheckinRecordService(rockContext);
                    MobileCheckinRecord        mobileCheckinRecord        = mobileCheckinRecordService.Queryable()
                                                                            .Where(r => r.Status == MobileCheckinStatus.Active)
                                                                            .Where(r => r.CreatedDateTime > Rock.RockDateTime.Today)
                                                                            .Where(r => r.UserName == checkInState.CheckIn.SearchValue)
                                                                            .FirstOrDefault();

                    if (mobileCheckinRecord == null)
                    {
                        ExceptionLogService.LogException("Mobile Check-in failed to find mobile checkin record");
                    }
                    mobileCheckinRecord.SerializedCheckInState = JsonConvert.SerializeObject(checkInLabels);

                    rockContext.SaveChanges();

                    //Freshen cache (we're going to need it soon)
                    MobileCheckinRecordCache.Update(mobileCheckinRecord.Id);
                }
                return(true);
            }
            errorMessages.Add($"Attempted to run {this.GetType().GetFriendlyTypeName()} in check-in, but the check-in state was null.");
            return(false);
        }
Пример #3
0
 protected void btnMobileRecords_Click(object sender, EventArgs e)
 {
     btnOccurrences.CssClass   = defaultCss;
     btnAttendances.CssClass   = defaultCss;
     btnMobileRecords.CssClass = activeCss;
     btnKioskTypes.CssClass    = defaultCss;
     pnlOccurrences.Visible    = false;
     pnlAttendances.Visible    = false;
     pnlMobileRecords.Visible  = true;
     pnlKioskTypes.Visible     = false;
     pnlVerify.Visible         = false;
     gMobileRecords.DataSource = MobileCheckinRecordCache.All();
     gMobileRecords.DataBind();
 }
Пример #4
0
        protected void btnCancelReseration_Click(object sender, EventArgs e)
        {
            var mobileCheckinRecord = MobileCheckinRecordCache.GetActiveByFamilyGroupId(currentPerson.PrimaryFamilyId ?? 0);

            if (mobileCheckinRecord == null)
            {
                string kioskName = currentUser.UserName;
                mobileCheckinRecord = MobileCheckinRecordCache.GetActiveByUserName(kioskName);
            }

            if (mobileCheckinRecord != null)
            {
                MobileCheckinRecordCache.CancelReservation(mobileCheckinRecord, true);
            }
            NavigateToCurrentPage();
        }
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute(IJobExecutionContext context)
        {
            JobDataMap dataMap = context.JobDetail.JobDataMap;

            var records = MobileCheckinRecordCache.All()
                          .Where(r => !r.ExpirationDateTime.HasValue || r.ExpirationDateTime < Rock.RockDateTime.Now ||
                                 (r.CreatedDateTime.HasValue && r.CreatedDateTime < Rock.RockDateTime.Today))
                          .ToList();

            foreach (var record in records)
            {
                MobileCheckinRecordCache.CancelReservation(record, true);
            }

            context.Result = $"Removed {records.Count} expired records.";
        }
Пример #6
0
        private void ShowQRCode(MobileCheckinRecordCache record)
        {
            pnlQr.Visible           = true;
            iQr.ImageUrl            = "/api/qr/" + record.AccessKey;
            ltCodeInstructions.Text = GetAttributeValue(AttributeKeys.CodeInstructions);
            if (record.ReservedUntilDateTime.HasValue)
            {
                ltValidUntil.Text = record.ReservedUntilDateTime.Value.ToString("h:mm tt");
            }
            else
            {
                ltValidUntil.Text = "some time in the future";
            }

            SetRefreshTimer(30);
        }
Пример #7
0
        private void UpdateView()
        {
            pnlQr.Visible           = false;
            pnlLoading.Visible      = false;
            pnlPostCheckin.Visible  = false;
            pnlSelectCampus.Visible = false;

            if (currentUser == null)
            {
                ltError.Text     = GetAttributeValue(AttributeKeys.NotLoggedInMessage);
                pnlError.Visible = true;
                return;
            }

            string kioskName = currentUser.UserName;

            var mobileCheckinRecord = MobileCheckinRecordCache.GetActiveByFamilyGroupId(currentPerson.PrimaryFamilyId ?? 0);

            if (mobileCheckinRecord == null)
            {
                mobileCheckinRecord = MobileCheckinRecordCache.GetActiveByUserName(kioskName);
            }

            if (mobileCheckinRecord != null)
            {
                ShowQRCode(mobileCheckinRecord);
                return;
            }
            else
            {
                var completeMobileCheckins = MobileCheckinRecordCache.All()
                                             .Where(r => r.FamilyGroupId == currentPerson.PrimaryFamilyId && r.Status == MobileCheckinStatus.Complete)
                                             .SelectMany(r => r.AttendanceIds)
                                             .Select(i => AttendanceCache.Get(i))
                                             .Where(a => a.AttendanceState != AttendanceState.CheckedOut)
                                             .Any();
                if (completeMobileCheckins)
                {
                    ShowCheckinCompletion();
                    return;
                }
            }

            ConfigureForUser(kioskName);

            pnlSelectCampus.Visible = true;
        }
Пример #8
0
        private void VerifyCache()
        {
            List <string> errors = new List <string>();

            KioskTypeCache.Verify(ref errors);
            AttendanceCache.Verify(ref errors);
            MobileCheckinRecordCache.Verify(ref errors);

            if (errors.Any())
            {
                ltVerify.Text = string.Join("<br>", errors);
            }
            else
            {
                ltVerify.Text = "<b>No Errors</b>";
            }
        }
Пример #9
0
        public HttpResponseMessage GetEntityGuid(string code)
        {
            if (code.StartsWith("MCR"))
            {
                var mobileCheckinRecord = MobileCheckinRecordCache.GetByAccessKey(code);
                if (mobileCheckinRecord == null)
                {
                    throw new Exception("Invalid Key");
                }
            }
            else
            {
                //Check to see if is a person's search key
                RockContext            rockContext            = new RockContext();
                PersonSearchKeyService personSearchKeyService = new PersonSearchKeyService(rockContext);
                var key = personSearchKeyService.Queryable().Where(k => k.SearchValue == code);
                if (!key.Any())
                {
                    throw new Exception("Invalid Key");
                }
            }

            var qr = GenerateQR(code);

            if (qr == null)
            {
                throw new Exception("Code Invalid");
            }
            MemoryStream stream = new MemoryStream();

            qr.Save(stream, ImageFormat.Png);
            var buffer   = stream.ToArray();
            var response = Request.CreateResponse(HttpStatusCode.OK);

            response.Content = new StreamContent(new MemoryStream(buffer));

            response.Content.Headers.ContentType   = new MediaTypeHeaderValue("image/png");
            response.Content.Headers.ContentLength = stream.Length;

            return(response);
        }
        private void MobileCheckin(string accessKey)
        {
            var mobileDidAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_DID_ATTEND).Id;
            var mobileNotAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_NOT_ATTEND).Id;

            RockContext rockContext = new RockContext();
            MobileCheckinRecordService mobileCheckinRecordService = new MobileCheckinRecordService(rockContext);

            var mobileCheckinRecord = mobileCheckinRecordService.Queryable().Where(r => r.AccessKey == accessKey).FirstOrDefault();

            if (mobileCheckinRecord == null)
            {
                mdAlert.Show("Mobile check-in record not found", ModalAlertType.Alert);
                BindRepeater();
                return;
            }
            else if (mobileCheckinRecord.Status == MobileCheckinStatus.Canceled)
            {
                mdAlert.Show("Mobile check-in record is expired.", ModalAlertType.Alert);
                BindRepeater();
                return;
            }
            else if (mobileCheckinRecord.Status == MobileCheckinStatus.Complete)
            {
                mdAlert.Show("Mobile check-in record has already been completed.", ModalAlertType.Alert);
                BindRepeater();
                return;
            }

            try
            {
                if (mobileCheckinRecord == null)
                {
                    return;
                }

                List <CheckInLabel> labels = null;

                if (mobileCheckinRecord.Attendances.Any(a => a.EndDateTime != null))
                {
                    var people = mobileCheckinRecord.Attendances.Select(a => a.PersonAlias.Person).DistinctBy(p => p.Id).ToList();
                    labels = CheckinLabelGen.GenerateLabels(people, CurrentCheckInState.Kiosk.Device, GetAttributeValue("AggregatedLabel").AsGuidOrNull());
                }
                else
                {
                    labels = JsonConvert.DeserializeObject <List <CheckInLabel> >(mobileCheckinRecord.SerializedCheckInState);
                }

                LabelPrinter labelPrinter = new LabelPrinter()
                {
                    Request = Request,
                    Labels  = labels
                };

                labelPrinter.PrintNetworkLabels();
                var script = labelPrinter.GetClientScript();
                ScriptManager.RegisterStartupScript(upContent, upContent.GetType(), "addLabelScript", script, true);

                foreach (var attendance in mobileCheckinRecord.Attendances)
                {
                    if (attendance.QualifierValueId == mobileDidAttendId)
                    {
                        attendance.DidAttend        = true;
                        attendance.QualifierValueId = null;
                        attendance.StartDateTime    = Rock.RockDateTime.Now;
                    }
                    else if (attendance.QualifierValueId == mobileNotAttendId)
                    {
                        attendance.DidAttend        = false;
                        attendance.QualifierValueId = null;
                    }
                    attendance.Note = "Completed mobile check-in at: " + CurrentCheckInState.Kiosk.Device.Name;
                }

                mobileCheckinRecord.Status = MobileCheckinStatus.Complete;

                rockContext.SaveChanges();

                //wait until we successfully save to update cache
                foreach (var attendance in mobileCheckinRecord.Attendances)
                {
                    AttendanceCache.AddOrUpdate(attendance);
                }
                MobileCheckinRecordCache.Update(mobileCheckinRecord.Id);
                BindRepeater();
            }
            catch (Exception e)
            {
                LogException(e);
                mdAlert.Show("An unexpected issue occurred.", ModalAlertType.Alert);
                BindRepeater();
            }
        }
Пример #11
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The workflow action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override bool Execute(RockContext rockContext, Rock.Model.WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            var isMobile          = GetAttributeValue(action, "IsMobile").AsBoolean();
            var mobileDidAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_DID_ATTEND).Id;
            var mobileNotAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_NOT_ATTEND).Id;

            var checkInState = GetCheckInState(entity, out errorMessages);

            if (checkInState != null)
            {
                KioskService kioskService = new KioskService(rockContext);
                var          kioskTypeId  = kioskService.GetByClientName(checkInState.Kiosk.Device.Name).KioskTypeId;
                var          kioskType    = KioskTypeCache.Get(kioskTypeId.Value);
                var          campusId     = kioskType.CampusId;
                if (campusId == null)
                {
                    var compatableKioskType = KioskTypeCache.All().Where(kt => kt.CampusId.HasValue && kt.CheckinTemplateId == kioskType.CheckinTemplateId).FirstOrDefault();
                    if (compatableKioskType != null)
                    {
                        campusId = compatableKioskType.CampusId;
                    }
                    else
                    {
                        campusId = 0;
                    }
                }

                campusId = GetCampusOrFamilyCampusId(campusId, checkInState.CheckIn.CurrentFamily.Group.CampusId);


                AttendanceCode attendanceCode = null;
                DateTime       startDateTime  = Rock.RockDateTime.Now;
                DateTime       today          = startDateTime.Date;
                DateTime       tomorrow       = startDateTime.AddDays(1);

                bool reuseCodeForFamily = checkInState.CheckInType != null && checkInState.CheckInType.ReuseSameCode;
                int  securityCodeLength = checkInState.CheckInType != null ? checkInState.CheckInType.SecurityCodeAlphaNumericLength : 3;

                var attendanceCodeService = new AttendanceCodeService(rockContext);
                var attendanceService     = new AttendanceService(rockContext);
                var groupMemberService    = new GroupMemberService(rockContext);
                var personAliasService    = new PersonAliasService(rockContext);

                //This list is just for mobile check-in
                List <Attendance> attendances = new List <Attendance>();

                var family = checkInState.CheckIn.CurrentFamily;
                if (family != null)
                {
                    foreach (var person in family.GetPeople(true))
                    {
                        if (reuseCodeForFamily && attendanceCode != null)
                        {
                            person.SecurityCode = attendanceCode.Code;
                        }
                        else
                        {
                            attendanceCode      = AttendanceCodeService.GetNew(securityCodeLength);
                            person.SecurityCode = attendanceCode.Code;
                        }

                        foreach (var groupType in person.GetGroupTypes(true))
                        {
                            foreach (var group in groupType.GetGroups(true))
                            {
                                if (groupType.GroupType.AttendanceRule == AttendanceRule.AddOnCheckIn &&
                                    groupType.GroupType.DefaultGroupRoleId.HasValue &&
                                    !groupMemberService.GetByGroupIdAndPersonId(group.Group.Id, person.Person.Id, true).Any())
                                {
                                    var groupMember = new GroupMember();
                                    groupMember.GroupId     = group.Group.Id;
                                    groupMember.PersonId    = person.Person.Id;
                                    groupMember.GroupRoleId = groupType.GroupType.DefaultGroupRoleId.Value;
                                    groupMemberService.Add(groupMember);
                                }

                                foreach (var location in group.GetLocations(true))
                                {
                                    foreach (var schedule in location.GetSchedules(true))
                                    {
                                        var primaryAlias = personAliasService.GetPrimaryAlias(person.Person.Id);
                                        if (primaryAlias != null)
                                        {
                                            int groupId = ActualGroupId(group.Group);
                                            // If a like attendance service exists close it before creating another one.
                                            var oldAttendance = attendanceService.Queryable()
                                                                .Where(a =>
                                                                       a.StartDateTime >= today &&
                                                                       a.StartDateTime < tomorrow &&
                                                                       a.Occurrence.LocationId == location.Location.Id &&
                                                                       a.Occurrence.ScheduleId == schedule.Schedule.Id &&
                                                                       a.Occurrence.GroupId == groupId &&
                                                                       a.PersonAlias.PersonId == person.Person.Id)
                                                                .FirstOrDefault();

                                            if (oldAttendance != null)
                                            {
                                                oldAttendance.EndDateTime = Rock.RockDateTime.Now;
                                                oldAttendance.DidAttend   = false;
                                            }
                                            var attendance = attendanceService.AddOrUpdate(primaryAlias.Id, startDateTime.Date, groupId,
                                                                                           location.Location.Id, schedule.Schedule.Id, campusId ?? location.CampusId,
                                                                                           checkInState.Kiosk.Device.Id, checkInState.CheckIn.SearchType.Id,
                                                                                           checkInState.CheckIn.SearchValue, family.Group.Id, attendanceCode.Id);

                                            attendance.DeviceId                 = checkInState.Kiosk.Device.Id;
                                            attendance.SearchTypeValueId        = checkInState.CheckIn.SearchType.Id;
                                            attendance.SearchValue              = checkInState.CheckIn.SearchValue;
                                            attendance.CheckedInByPersonAliasId = checkInState.CheckIn.CheckedInByPersonAliasId;
                                            attendance.SearchResultGroupId      = family.Group.Id;
                                            attendance.AttendanceCodeId         = attendanceCode.Id;
                                            attendance.CreatedDateTime          = startDateTime;
                                            attendance.StartDateTime            = startDateTime;
                                            attendance.EndDateTime              = null;
                                            attendance.Note      = group.Notes;
                                            attendance.DidAttend = isMobile ? false : groupType.GroupType.GetAttributeValue("SetDidAttend").AsBoolean();
                                            if (isMobile)
                                            {
                                                if (groupType.GroupType.GetAttributeValue("SetDidAttend").AsBoolean())
                                                {
                                                    attendance.QualifierValueId = mobileDidAttendId;
                                                }
                                                else
                                                {
                                                    attendance.QualifierValueId = mobileNotAttendId;
                                                }
                                            }
                                            ;

                                            attendanceService.Add(attendance);
                                            attendances.Add(attendance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (isMobile)
                {
                    var alreadyExistingMobileCheckin = MobileCheckinRecordCache.GetActiveByFamilyGroupId(checkInState.CheckIn.CurrentFamily.Group.Id);
                    if (alreadyExistingMobileCheckin != null)
                    {
                        //This should never run, it's just in case. Each family should only have 1 mobile check-in reservation.
                        MobileCheckinRecordCache.CancelReservation(alreadyExistingMobileCheckin, true);
                    }

                    campusId = RollUpToParentCampus(campusId);

                    MobileCheckinRecordService mobileCheckinRecordService = new MobileCheckinRecordService(rockContext);
                    var mobileCheckinRecord = new MobileCheckinRecord
                    {
                        AccessKey             = "MCR" + Guid.NewGuid().ToString("N").Substring(0, 12),
                        ReservedUntilDateTime = Rock.RockDateTime.Now.AddMinutes(kioskType.MinutesValid ?? 10),
                        ExpirationDateTime    = Rock.RockDateTime.Now.AddMinutes((kioskType.MinutesValid ?? 10) + (kioskType.GraceMinutes ?? 60)),
                        UserName      = checkInState.CheckIn.SearchValue,
                        FamilyGroupId = checkInState.CheckIn.CurrentFamily.Group.Id,
                        CampusId      = campusId.Value
                    };

                    foreach (var attendance in attendances)
                    {
                        mobileCheckinRecord.Attendances.Add(attendance);
                    }

                    mobileCheckinRecordService.Add(mobileCheckinRecord);
                }

                rockContext.SaveChanges();
                foreach (var attendance in attendances)
                {
                    AttendanceCache.AddOrUpdate(attendance);
                }
                return(true);
            }
            errorMessages.Add($"Attempted to run {this.GetType().GetFriendlyTypeName()} in check-in, but the check-in state was null.");
            return(false);
        }
Пример #12
0
        private void MobileCheckin(string accessKey)
        {
            var mobileDidAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_DID_ATTEND).Id;
            var mobileNotAttendId = DefinedValueCache.Get(Constants.DEFINED_VALUE_MOBILE_NOT_ATTEND).Id;

            RockContext rockContext = new RockContext();
            MobileCheckinRecordService mobileCheckinRecordService = new MobileCheckinRecordService(rockContext);

            var mobileCheckinRecord = mobileCheckinRecordService.Queryable().Where(r => r.AccessKey == accessKey).FirstOrDefault();

            if (mobileCheckinRecord == null)
            {
                MobileCheckinMessage(GetAttributeValue(AttributeKeys.NoMobileCheckinRecord));
                return;
            }
            else if (mobileCheckinRecord.Status == MobileCheckinStatus.Canceled)
            {
                MobileCheckinMessage(GetAttributeValue(AttributeKeys.ExpiredMobileCheckinRecord));
                return;
            }
            else if (mobileCheckinRecord.Status == MobileCheckinStatus.Complete)
            {
                MobileCheckinMessage(GetAttributeValue(AttributeKeys.AlreadyCompleteCheckinRecord));
                return;
            }

            try
            {
                if (mobileCheckinRecord == null)
                {
                    return;
                }

                if (KioskType.CampusId.HasValue && KioskType.CampusId != 0 && KioskType.CampusId != mobileCheckinRecord.CampusId)
                {
                    ShowWrongCampusSign(mobileCheckinRecord.Campus.Name, KioskType.Campus.Name);
                    return;
                }
                List <CheckInLabel> labels = JsonConvert.DeserializeObject <List <CheckInLabel> >(mobileCheckinRecord.SerializedCheckInState);

                LabelPrinter labelPrinter = new LabelPrinter()
                {
                    Request = Request,
                    Labels  = labels
                };

                labelPrinter.PrintNetworkLabels();
                var script = labelPrinter.GetClientScript();
                ScriptManager.RegisterStartupScript(upContent, upContent.GetType(), "addLabelScript", script, true);

                foreach (var attendance in mobileCheckinRecord.Attendances)
                {
                    if (attendance.QualifierValueId == mobileDidAttendId)
                    {
                        attendance.DidAttend        = true;
                        attendance.QualifierValueId = null;
                        attendance.StartDateTime    = Rock.RockDateTime.Now;
                    }
                    else if (attendance.QualifierValueId == mobileNotAttendId)
                    {
                        attendance.DidAttend        = false;
                        attendance.QualifierValueId = null;
                    }
                    attendance.Note = "Completed mobile check-in at: " + CurrentCheckInState.Kiosk.Device.Name;
                }

                mobileCheckinRecord.Status = MobileCheckinStatus.Complete;

                rockContext.SaveChanges();

                //wait until we successfully save to update cache
                foreach (var attendance in mobileCheckinRecord.Attendances)
                {
                    AttendanceCache.AddOrUpdate(attendance);
                }
                MobileCheckinRecordCache.Update(mobileCheckinRecord.Id);
                MobileCheckinMessage(GetAttributeValue(AttributeKeys.CompletingMobileCheckin), 5);
            }
            catch (Exception e)
            {
            }
        }
Пример #13
0
 protected void btnFlushMCR_Click(object sender, EventArgs e)
 {
     MobileCheckinRecordCache.Clear();
     MobileCheckinRecordCache.All();
 }
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The workflow action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            var checkInState = GetCheckInState(entity, out errorMessages);

            CheckInGroupType lastCheckinGroupType = null;

            List <string>       labelCodes = new List <string>();
            List <int>          childGroupIds;
            List <CheckInLabel> checkInLabels = new List <CheckInLabel>();

            var    volAttributeGuid = GetAttributeValue(action, "VolunteerGroupAttribute");
            string volAttributeKey  = "";

            if (!string.IsNullOrWhiteSpace(volAttributeGuid))
            {
                volAttributeKey = AttributeCache.Get(volAttributeGuid.AsGuid()).Key;
                childGroupIds   = checkInState.Kiosk.KioskGroupTypes
                                  .SelectMany(g => g.KioskGroups)
                                  .Where(g => !g.Group.GetAttributeValue(volAttributeKey).AsBoolean())
                                  .Select(g => g.Group.Id).ToList();
            }
            else
            {
                childGroupIds = new List <int>();
            }

            if (checkInState != null)
            {
                var attendanceService = new AttendanceService(rockContext);
                var globalAttributes  = Rock.Web.Cache.GlobalAttributesCache.Get();
                var globalMergeValues = Rock.Lava.LavaHelper.GetCommonMergeFields(null);

                var groupMemberService = new GroupMemberService(rockContext);

                foreach (var family in checkInState.CheckIn.Families.Where(f => f.Selected))
                {
                    foreach (var person in family.People.Where(p => p.Selected))
                    {
                        if (person.GroupTypes.Where(gt => gt.Selected).SelectMany(gt => gt.Groups).Where(g => g.Selected && childGroupIds.Contains(g.Group.Id)).Any())
                        {
                            labelCodes.Add((person.SecurityCode) + "-" + LabelAge(person.Person));
                        }

                        if (string.IsNullOrEmpty(person.SecurityCode))
                        {
                            var lastAttendance = attendanceService.Queryable()
                                                 .Where(a => a.PersonAlias.PersonId == person.Person.Id && a.AttendanceCode != null)
                                                 .OrderByDescending(a => a.StartDateTime)
                                                 .FirstOrDefault();
                            if (lastAttendance != null)
                            {
                                person.SecurityCode = lastAttendance.AttendanceCode.Code;
                            }
                        }

                        var firstCheckinGroupType = person.GroupTypes.Where(g => g.Selected).FirstOrDefault();
                        if (firstCheckinGroupType != null)
                        {
                            List <Guid> labelGuids = new List <Guid>();

                            var mergeObjects = new Dictionary <string, object>();
                            foreach (var keyValue in globalMergeValues)
                            {
                                mergeObjects.Add(keyValue.Key, keyValue.Value);
                            }
                            mergeObjects.Add("Person", person);
                            mergeObjects.Add("GroupTypes", person.GroupTypes.Where(g => g.Selected).ToList());
                            List <Group>    mergeGroups    = new List <Group>();
                            List <Location> mergeLocations = new List <Location>();
                            List <Schedule> mergeSchedules = new List <Schedule>();

                            var sets = attendanceService
                                       .Queryable().AsNoTracking().Where(a =>
                                                                         a.PersonAlias.Person.Id == person.Person.Id &&
                                                                         a.StartDateTime >= Rock.RockDateTime.Today &&
                                                                         a.EndDateTime == null &&
                                                                         a.Occurrence.Group != null &&
                                                                         a.Occurrence.Schedule != null &&
                                                                         a.Occurrence.Location != null
                                                                         )
                                       .Select(a =>
                                               new
                            {
                                Group          = a.Occurrence.Group,
                                Location       = a.Occurrence.Location,
                                Schedule       = a.Occurrence.Schedule,
                                AttendanceGuid = a.Guid
                            }
                                               )
                                       .ToList()
                                       .OrderBy(a => a.Schedule.StartTimeOfDay);

                            //Load breakout group
                            var breakoutGroups = GetBreakoutGroups(person.Person, rockContext, action);

                            //Add in an empty object as a placeholder for our breakout group
                            mergeObjects.Add("BreakoutGroup", "");

                            //Add in GUID for QR code
                            if (sets.Any())
                            {
                                mergeObjects.Add("AttendanceGuid", sets.FirstOrDefault().AttendanceGuid.ToString());
                            }

                            foreach (var set in sets)
                            {
                                mergeGroups.Add(set.Group);
                                mergeLocations.Add(set.Location);
                                mergeSchedules.Add(set.Schedule);

                                //Add the breakout group mergefield
                                if (breakoutGroups.Any())
                                {
                                    var breakoutGroup = breakoutGroups.Where(g => g.ScheduleId == set.Schedule.Id).FirstOrDefault();
                                    if (breakoutGroup != null)
                                    {
                                        var breakoutGroupEntity = new GroupService(rockContext).Get(breakoutGroup.Id);
                                        if (breakoutGroupEntity != null)
                                        {
                                            breakoutGroupEntity.LoadAttributes();
                                            var letter = breakoutGroupEntity.GetAttributeValue("Letter");
                                            if (!string.IsNullOrWhiteSpace(letter))
                                            {
                                                mergeObjects["BreakoutGroup"] = letter;
                                            }
                                        }
                                    }
                                }
                            }
                            mergeObjects.Add("Groups", mergeGroups);
                            mergeObjects.Add("Locations", mergeLocations);
                            mergeObjects.Add("Schedules", mergeSchedules);

                            foreach (var groupType in person.GroupTypes.Where(g => g.Selected))
                            {
                                lastCheckinGroupType = groupType;

                                groupType.Labels = new List <CheckInLabel>();

                                GetGroupTypeLabels(groupType.GroupType, firstCheckinGroupType.Labels, mergeObjects, labelGuids);

                                var PrinterIPs = new Dictionary <int, string>();

                                foreach (var label in groupType.Labels)
                                {
                                    label.PrintFrom = checkInState.Kiosk.Device.PrintFrom;
                                    label.PrintTo   = checkInState.Kiosk.Device.PrintToOverride;

                                    if (label.PrintTo == PrintTo.Default)
                                    {
                                        label.PrintTo = groupType.GroupType.AttendancePrintTo;
                                    }

                                    if (label.PrintTo == PrintTo.Kiosk)
                                    {
                                        var device = checkInState.Kiosk.Device;
                                        if (device != null)
                                        {
                                            label.PrinterDeviceId = device.PrinterDeviceId;
                                        }
                                    }
                                    else if (label.PrintTo == PrintTo.Location)
                                    {
                                        // Should only be one
                                        var group = groupType.Groups.Where(g => g.Selected).FirstOrDefault();
                                        if (group != null)
                                        {
                                            var location = group.Locations.Where(l => l.Selected).FirstOrDefault();
                                            if (location != null)
                                            {
                                                var device = location.Location.PrinterDevice;
                                                if (device != null)
                                                {
                                                    label.PrinterDeviceId = device.PrinterDeviceId;
                                                }
                                            }
                                        }
                                    }

                                    if (label.PrinterDeviceId.HasValue)
                                    {
                                        if (PrinterIPs.ContainsKey(label.PrinterDeviceId.Value))
                                        {
                                            label.PrinterAddress = PrinterIPs[label.PrinterDeviceId.Value];
                                        }
                                        else
                                        {
                                            var printerDevice = new DeviceService(rockContext).Get(label.PrinterDeviceId.Value);
                                            if (printerDevice != null)
                                            {
                                                PrinterIPs.Add(printerDevice.Id, printerDevice.IPAddress);
                                                label.PrinterAddress = printerDevice.IPAddress;
                                            }
                                        }
                                    }
                                    checkInLabels.Add(label);
                                }
                            }
                        }
                    }

                    //Add in custom labels for parents
                    //This is the aggregate part
                    List <CheckInLabel> customLabels = new List <CheckInLabel>();

                    List <string> mergeCodes = (( string )GetAttributeValue(action, "MergeText")).Split(',').ToList();
                    while (labelCodes.Count > 0)
                    {
                        var mergeDict = new Dictionary <string, string>();

                        foreach (var mergeCode in mergeCodes)
                        {
                            if (labelCodes.Count > 0)
                            {
                                mergeDict.Add(mergeCode, labelCodes[0]);
                                labelCodes.RemoveAt(0);
                            }
                            else
                            {
                                mergeDict.Add(mergeCode, "");
                            }
                        }

                        mergeDict.Add("Date", Rock.RockDateTime.Today.DayOfWeek.ToString().Substring(0, 3) + " " + Rock.RockDateTime.Today.ToMonthDayString());

                        var labelCache = KioskLabel.Get(new Guid(GetAttributeValue(action, "AggregatedLabel")));
                        if (labelCache != null)
                        {
                            var checkInLabel = new CheckInLabel(labelCache, new Dictionary <string, object>());
                            checkInLabel.FileGuid = new Guid(GetAttributeValue(action, "AggregatedLabel"));

                            foreach (var keyValue in mergeDict)
                            {
                                if (checkInLabel.MergeFields.ContainsKey(keyValue.Key))
                                {
                                    checkInLabel.MergeFields[keyValue.Key] = keyValue.Value;
                                }
                                else
                                {
                                    checkInLabel.MergeFields.Add(keyValue.Key, keyValue.Value);
                                }
                            }

                            checkInLabel.PrintFrom = checkInState.Kiosk.Device.PrintFrom;
                            checkInLabel.PrintTo   = checkInState.Kiosk.Device.PrintToOverride;

                            if (checkInLabel.PrintTo == PrintTo.Default)
                            {
                                checkInLabel.PrintTo = lastCheckinGroupType.GroupType.AttendancePrintTo;
                            }

                            if (checkInLabel.PrintTo == PrintTo.Kiosk)
                            {
                                var device = checkInState.Kiosk.Device;
                                if (device != null)
                                {
                                    checkInLabel.PrinterDeviceId = device.PrinterDeviceId;
                                }
                            }
                            else if (checkInLabel.PrintTo == PrintTo.Location)
                            {
                                // Should only be one
                                var group = lastCheckinGroupType.Groups.Where(g => g.Selected).FirstOrDefault();
                                if (group != null)
                                {
                                    var location = group.Locations.Where(l => l.Selected).FirstOrDefault();
                                    if (location != null)
                                    {
                                        var device = location.Location.PrinterDevice;
                                        if (device != null)
                                        {
                                            checkInLabel.PrinterDeviceId = device.PrinterDeviceId;
                                        }
                                    }
                                }
                            }
                            if (checkInLabel.PrinterDeviceId.HasValue)
                            {
                                var printerDevice = new DeviceService(rockContext).Get(checkInLabel.PrinterDeviceId.Value);
                                checkInLabel.PrinterAddress = printerDevice.IPAddress;
                            }
                            if (lastCheckinGroupType != null)
                            {
                                lastCheckinGroupType.Labels.Add(checkInLabel);
                                checkInLabels.Add(checkInLabel);
                            }
                        }
                    }
                }

                //For mobile check-in we need to serialize this data and save it in the database.
                //This will mean that when it's time to finish checkin in
                //All we will need to do is deserialize and pass the data to the printer
                if (GetAttributeValue(action, "IsMobile").AsBoolean())
                {
                    MobileCheckinRecordService mobileCheckinRecordService = new MobileCheckinRecordService(rockContext);
                    MobileCheckinRecord        mobileCheckinRecord        = mobileCheckinRecordService.Queryable()
                                                                            .Where(r => r.Status == MobileCheckinStatus.Active)
                                                                            .Where(r => r.CreatedDateTime > Rock.RockDateTime.Today)
                                                                            .Where(r => r.UserName == checkInState.CheckIn.SearchValue)
                                                                            .FirstOrDefault();

                    if (mobileCheckinRecord == null)
                    {
                        ExceptionLogService.LogException("Mobile Check-in failed to find mobile checkin record");
                    }
                    mobileCheckinRecord.SerializedCheckInState = JsonConvert.SerializeObject(checkInLabels);

                    rockContext.SaveChanges();

                    //Freshen cache (we're going to need it soon)
                    MobileCheckinRecordCache.Update(mobileCheckinRecord.Id);
                }
                return(true);
            }
            errorMessages.Add($"Attempted to run {this.GetType().GetFriendlyTypeName()} in check-in, but the check-in state was null.");
            return(false);
        }