public Response Exit([FromBody] Request req)
        {
            try
            {
                RockContext rockContext = new RockContext();

                Attendance attendeeAttendance = ValidationHelper.GetAttendeeAttendance(req, rockContext);

                if (attendeeAttendance == null)
                {
                    return(new Response(false, "Attendance record not found.", false));
                }
                if (Rock.RockDateTime.Today != attendeeAttendance.StartDateTime.Date)
                {
                    return(new Response(false, "Attendance record not from today.", false));
                }

                var  person    = attendeeAttendance.PersonAlias.Person;
                var  location  = new LocationService(rockContext).Get(req.LocationId);
                bool isSubroom = ValidationHelper.IsSubRoom(location);
                if (isSubroom)
                {
                    req.LocationId = location.ParentLocationId ?? 0;
                }

                var attendances = ValidationHelper.GetAttendancesForAttendee(rockContext, attendeeAttendance);
                attendances = attendances.Where(a => a.LocationId == req.LocationId);


                //If person is a volunteer, children are checked in, and would result in less than 2 volunteers
                //Then don't allow for check-out
                if ((attendances.Where(a => VolunteerGroupIds.Contains(a.GroupId ?? 0)).Any() ||
                     attendances.Where(a => a.GroupId == 0 || a.GroupId == null).Any()) &&
                    AreChildrenCheckedIn(req.LocationId) &&
                    NumberOfVolunteersCheckedIn(req.LocationId) <= 2)
                {
                    return(new Response(false, "Cannot checkout volunteer with children still in class. Two volunteers are required at all times.", false));
                }

                foreach (var attendance in attendances)
                {
                    var stayedFifteenMinutes = (Rock.RockDateTime.Now - attendance.StartDateTime) > new TimeSpan(0, 15, 0);
                    attendance.DidAttend   = stayedFifteenMinutes;
                    attendance.EndDateTime = Rock.RockDateTime.Now;
                    CheckInCountCache.RemoveAttendance(attendance);
                    var personId = attendeeAttendance.PersonAlias.PersonId;
                    InMemoryPersonStatus.RemoveFromWorship(personId);
                    InMemoryPersonStatus.RemoveFromWithParent(personId);
                }

                //Add history of exit
                DataHelper.AddExitHistory(rockContext, location, attendeeAttendance, isSubroom);

                rockContext.SaveChanges();

                var message = string.Format("{0} has been checked-out of {1}.", person.FullName, location.Name);
                return(new Response(true, message, false, personId: person.Id));
            }
            catch (Exception e)
            {
                ExceptionLogService.LogException(e, System.Web.HttpContext.Current);
                return(new Response(false, "An error occured", false));
            }
        }
        public Response Entry([FromBody] Request req)
        {
            try
            {
                RockContext       rockContext        = new RockContext();
                AttendanceService attendanceService  = new AttendanceService(rockContext);
                Attendance        attendeeAttendance = ValidationHelper.GetAttendeeAttendance(req, rockContext);

                if (attendeeAttendance == null)
                {
                    return(new Response(false, "Attendance record not found.", false));
                }
                if (Rock.RockDateTime.Today != attendeeAttendance.StartDateTime.Date)
                {
                    return(new Response(false, "Attendance record not from today.", false));
                }

                var  person    = attendeeAttendance.PersonAlias.Person;
                var  location  = new LocationService(rockContext).Get(req.LocationId);
                bool isSubroom = ValidationHelper.IsSubRoom(location);
                if (isSubroom)
                {
                    req.LocationId = location.ParentLocationId ?? 0;
                }

                var attendances = ValidationHelper.GetAttendancesForAttendee(rockContext, attendeeAttendance);

                if (!attendances.Any())
                {
                    return(new Response(false, string.Format("{0} has been checked out of all locations.", person.FullName), false));
                }

                //If no volunteers are checked in and not checking-in a volunteer
                if (NumberOfVolunteersCheckedIn(req.LocationId) < 2 &&
                    !attendances.Where(a => VolunteerGroupIds.Contains(a.GroupId ?? 0)).Any())
                {
                    return(new Response(
                               false,
                               "Cannot check-in child before 2 volunteers are checked-in.",
                               false));
                }

                var attendancesToModify = attendances.Where(a => a.LocationId == req.LocationId).ToList();

                //There was an attendance record, but not for the selected location
                if (!attendancesToModify.Any() && !req.Override)
                {
                    var currentAttendances = new StringBuilder();
                    foreach (var attendance in attendances)
                    {
                        currentAttendances.Append(string.Format(
                                                      "\n{0} @ {1}",
                                                      attendance.Location?.Name ?? "Unknown Location",
                                                      attendance.Schedule?.Name ?? "Unknown Schedule"));
                    }

                    return(new Response(false, string.Format("{0} is not checked-in to {1}. \n\n{2} is currently checked in to: {3} \n\nWould you like to override?",
                                                             person.FullName,
                                                             location.Name,
                                                             person.Gender == Gender.Female ? "She" : "He",
                                                             currentAttendances.ToString()
                                                             ), true));
                }

                //Need to move this person to a different location
                if (!attendancesToModify.Any() && req.Override)
                {
                    AttributeValueService attributeValueService = new AttributeValueService(new RockContext());
                    var childGroupIds = attributeValueService.Queryable().Where(av => av.AttributeId == volAttribute.Id && av.Value == "False").Select(av => av.EntityId.Value).ToList();

                    if (childGroupIds.Contains(attendeeAttendance.GroupId ?? 0))
                    {
                        //This section tests for attendances that can be moved to this location.
                        //It tests for people
                        GroupLocationService groupLocationService = new GroupLocationService(rockContext);
                        var acceptableServiceIds = groupLocationService.Queryable()
                                                   .Where(gl => gl.LocationId == req.LocationId && childGroupIds.Contains(gl.GroupId))
                                                   .SelectMany(gl => gl.Schedules)
                                                   .Select(s => s.Id).ToList();
                        var availableAttendances = attendances.Where(a => acceptableServiceIds.Contains(a.ScheduleId ?? 0));

                        if (availableAttendances.Any())
                        {
                            attendances = availableAttendances;
                        }
                        else
                        {
                            //If there are no attendances that match this schedule,
                            //Take one preferably if it isn't attended yet.
                            attendances = attendances.OrderBy(a => a.DidAttend).Take(1);
                        }
                    }

                    if (!attendances.Any())
                    {
                        return(new Response(false, "There are no attendances which can be moved to this location", false));
                    }

                    if (ValidationHelper.LocationsFull(attendances.ToList(), req.LocationId, VolunteerGroupIds, rockContext))
                    {
                        return(new Response(false, "Could not move location. Location is full.", false));
                    }

                    foreach (var attendance in attendances)
                    {
                        DataHelper.CloneAttendance(attendance, isSubroom, location, attendanceService, req);
                    }

                    DataHelper.CloseActiveAttendances(rockContext, attendeeAttendance, location, isSubroom);
                    //Set person history showing that the person was moved on scan in
                    DataHelper.AddMoveHistory(rockContext, location, attendeeAttendance, isSubroom);
                    rockContext.SaveChanges();
                    return(DataHelper.GetEntryResponse(rockContext, person, location));
                }

                foreach (var attendance in attendancesToModify.ToList())
                {
                    attendance.DidAttend     = true;
                    attendance.StartDateTime = Rock.RockDateTime.Now;
                    if (isSubroom)
                    {
                        attendance.ForeignId = location.Id;
                    }
                    CheckInCountCache.UpdateAttendance(attendance);
                }

                DataHelper.CloseActiveAttendances(rockContext, attendeeAttendance, location, isSubroom);
                DataHelper.AddEntranceHistory(rockContext, location, attendeeAttendance, isSubroom);
                rockContext.SaveChanges();

                return(DataHelper.GetEntryResponse(rockContext, person, location));
            }
            catch (Exception e)
            {
                ExceptionLogService.LogException(e, System.Web.HttpContext.Current);
                return(new Response(false, "An error occured", false));
            }
        }
Example #3
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 checkInState = GetCheckInState(entity, out errorMessages);

            if (checkInState != null)
            {
                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);

                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)
                                        {
                                            // 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.LocationId == location.Location.Id &&
                                                                       a.ScheduleId == schedule.Schedule.Id &&
                                                                       a.GroupId == group.Group.Id &&
                                                                       a.PersonAlias.PersonId == person.Person.Id)
                                                                .FirstOrDefault();

                                            if (oldAttendance != null)
                                            {
                                                oldAttendance.EndDateTime = Rock.RockDateTime.Now;
                                                oldAttendance.DidAttend   = false;
                                            }
                                            var attendance = rockContext.Attendances.Create();
                                            attendance.LocationId          = location.Location.Id;
                                            attendance.CampusId            = location.CampusId;
                                            attendance.ScheduleId          = schedule.Schedule.Id;
                                            attendance.GroupId             = group.Group.Id;
                                            attendance.PersonAliasId       = primaryAlias.Id;
                                            attendance.DeviceId            = checkInState.Kiosk.Device.Id;
                                            attendance.SearchTypeValueId   = checkInState.CheckIn.SearchType.Id;
                                            attendance.SearchValue         = checkInState.CheckIn.SearchValue;
                                            attendance.SearchResultGroupId = family.Group.Id;
                                            attendance.AttendanceCodeId    = attendanceCode.Id;
                                            attendance.StartDateTime       = startDateTime;
                                            attendance.EndDateTime         = null;
                                            attendance.DidAttend           = groupType.GroupType.GetAttributeValue("SetDidAttend").AsBoolean();
                                            attendanceService.Add(attendance);
                                            CheckInCountCache.AddAttendance(attendance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                rockContext.SaveChanges();
                return(true);
            }

            return(false);
        }