public async Task <ActionResult> Delete(int id)
    {
        // Find existing attendanceState record in DB
        AttendanceState attendanceState = await _context.AttendanceStates.FindAsync(id);

        if (attendanceState == null)
        {
            Logger.Msg <AttendanceStatesController>($"[{User.FindFirstValue("email")}] [DELETE] StateID: {id} not found", Serilog.Events.LogEventLevel.Debug);
            return(NotFound());
        }

        try
        {
            _context.AttendanceStates.Remove(attendanceState);
            await _context.SaveChangesAsync();

            Logger.Msg <AttendanceStatesController>($"[{User.FindFirstValue("email")}] [DELETE] StateID: {id} success", Serilog.Events.LogEventLevel.Information);
            return(Ok(new AttendanceStateDTO(attendanceState)));
        }
        catch (Exception ex)
        {
            // Probably due to FK violation
            Logger.Msg <AttendanceStatesController>($"[DELETE] Database sync error {ex.Message}", Serilog.Events.LogEventLevel.Error);

            // Return response to client
            return(StatusCode(500, new { errors = "Database update failed." }));
        }
    } // End of Delete
Exemplo n.º 2
0
        /// <summary>
        /// 老師更新點名簽到記錄
        /// </summary>
        /// <param name="learningId">學習圈Id</param>
        /// <param name="token">老師token</param>
        /// <param name="eventId">點名活動Guid</param>
        /// <param name="studId">被編輯點名狀態的學生MemberId</param>
        /// <param name="status">點名狀態 1出席,2缺席,3遲到,4早退,5請假</param>
        /// <returns></returns>
        public async Task SignIn_Modify(string circleKey, Guid token, string outerKey, int stuId, int status)
        {
            try
            {
                var auth = new ServerCheckItem()
                {
                    OuterKey = outerKey, CircleKey = circleKey, ModuleFun = SignInFunction.Admin
                };
                bool chekc = AuthCheck(token, ref auth);
                if (chekc)
                {
                    if (auth.ModuleAuth)
                    {
                        if (AttendanceState.Status.ContainsKey(status.ToString()))
                        {
                            // 更新點名紀錄
                            var log = signInLogService.UpdateLog(auth.MemberId, auth.EventId, stuId, status.ToString());

                            // 新增一筆通知
                            string stateName     = AttendanceState.GetStateName(status.ToString());
                            string text          = "您的狀態已更新:" + stateName;
                            var    noticeService = new NoticeService();
                            noticeService.AddNoticeSaveChange(circleKey, stuId, auth.EventId, text);
                            var signalrService = new SignalrService();
                            //發通知給學生
                            var connectIdAndNoticeData = signalrService.GetConnectIdAndData(circleKey.ToLower(), log.StuId, SignalrConnectIdType.One, SignalrDataType.Notice);

                            SignalrClientHelper.SendNotice(connectIdAndNoticeData);
                            //告訴同學點名狀態已改變
                            Clients.Group(circleKey.ToLower()).signIn_StatusChanged(outerKey, log);

                            // 發送推播
                            await PushOnChangedSignIn(circleKey.ToLower(), auth.EventId, log.StudId, stateName);
                        }
                        else
                        {
                            Clients.Caller.onError("SignIn_Modify", "狀態錯誤!");
                        }
                    }
                    else
                    {
                        Clients.Caller.onError("SignIn_Modify", "您沒有權限!");
                    }
                }
                else
                {
                    Clients.Caller.onError("SignIn_Modify", "身分驗證失敗,請重新登入!token:[" + token + "]");
                }
            }
            catch (Exception ex)
            {
                Clients.Caller.onError("SignIn_Modify", "老師點名發生意外: " + ex.Message);
            }
        }
Exemplo n.º 3
0
        public DismissionChecker(AttendanceInfo firstNode)
        {
            this.FirstAbsentNode = firstNode;
            this.PreNode         = firstNode;

            this.AbsentDays = 0;

            this.PreState = AttendanceState.Absent;

            this.NextState = AttendanceState.Absent;
        }
Exemplo n.º 4
0
        public void Reset(AttendanceInfo currNode)
        {
            this.AbsentDays = 0;

            this.PreNode         = currNode;
            this.FirstAbsentNode = currNode;

            this.PreState = AttendanceState.Absent;

            this.NextState = AttendanceState.Absent;
        }
    public async Task <ActionResult> ModifyAttendanceState([FromBody] AttendanceStateDTO attendanceState)
    {
        if (AttendanceStateExists(attendanceState.StateID))
        {
            // Call BLL AttendanceState Modify method with all the parameters
            object BLLResponse = new AttendanceStateBLL(_context).ModifyAttendanceStateBLL(attendanceState: attendanceState);

            if (BLLResponse.GetType().BaseType == typeof(Exception))
            {
                // Create log entries for Debug log
                ((APIException)BLLResponse).Exceptions.ForEach(ex => Logger.Msg <AttendanceStatesController>((Exception)ex, Serilog.Events.LogEventLevel.Debug));

                // Return response from API
                return(BadRequest(new { errors = ((APIException)BLLResponse).Exceptions.Select(x => x.Message).ToArray() }));
            }
            else
            {
                try
                {
                    AttendanceStateDTO modAttendanceState = (AttendanceStateDTO)BLLResponse;

                    // Find the existing record based on ID
                    AttendanceState currentRecord = _context.AttendanceStates.Where(x => x.StateID == modAttendanceState.StateID).First();

                    // Modify the record
                    currentRecord.Description = modAttendanceState.Description;

                    // Save changes
                    await _context.SaveChangesAsync();

                    Logger.Msg <AttendanceStatesController>($"[{User.FindFirstValue("email")}] [MODIFY] StateID: {currentRecord.StateID} successful", Serilog.Events.LogEventLevel.Information);

                    // Return modified record as a DTO
                    AttendanceStateDTO response = new AttendanceStateDTO(currentRecord);
                    return(Ok(response));
                }
                catch (Exception ex)
                {
                    // Local log entry. Database reconciliation issues are more serious so reported as Error
                    Logger.Msg <AttendanceStatesController>($"[MODIFY] Database sync error {ex.Message}", Serilog.Events.LogEventLevel.Error);

                    // Return response to client
                    return(StatusCode(500, new { errors = "Database update failed. Contact the administrator to resolve this issue." }));
                }
            }
        }
        else
        {
            return(NotFound());
        }
    } // End of ModifyAttendanceState
    public async Task <ActionResult> AddAttendanceState(string description)
    {
        // Call BLL Attendance Add method with all the parameters
        object BLLResponse = new AttendanceStateBLL(_context).AddAttendanceStateBLL(description: description);

        // Get the base class for the response
        // Ref: https://docs.microsoft.com/en-us/dotnet/api/system.type.basetype?view=netcore-3.1
        if (BLLResponse.GetType().BaseType == typeof(Exception))
        {
            // Create log entries for Debug log
            ((APIException)BLLResponse).Exceptions.ForEach(ex => Logger.Msg <AttendanceStatesController>((Exception)ex, Serilog.Events.LogEventLevel.Debug));

            // Return response from API
            return(BadRequest(new { errors = ((APIException)BLLResponse).Exceptions.Select(x => x.Message).ToArray() }));
        }
        else
        {
            try
            {
                AttendanceState newAttendanceState = new AttendanceState {
                    Description = ((AttendanceStateDTO)BLLResponse).Description
                };

                // Create the record
                _context.AttendanceStates.Add(newAttendanceState);
                await _context.SaveChangesAsync();

                Logger.Msg <AttendanceStatesController>($"[{User.FindFirstValue("email")}] [ADD] AttendanceState '{description}' successful", Serilog.Events.LogEventLevel.Information);

                // Convert back to DTO and return to user
                AttendanceStateDTO response = new AttendanceStateDTO(newAttendanceState);
                return(Ok(response));
            }
            catch (Exception ex)
            {
                // Local log entry. Database reconciliation issues are more serious so reported as Error
                Logger.Msg <AttendanceStatesController>($"[ADD] Database sync error {ex.Message}", Serilog.Events.LogEventLevel.Error);

                // Return response to client
                return(StatusCode(500, new { errors = "Database update failed. Contact the administrator to resolve this issue." }));
            }
        }
    } // End of AddAttendanceState
Exemplo n.º 7
0
        private BaseResponse <string> UpdateSignIn(string circleKey, Guid token, string outerKey, string checkType, string[] keys)
        {
            var response = new BaseResponse <string>();

            try
            {
                var auth = new ServerCheckItem()
                {
                    OuterKey = outerKey, CircleKey = circleKey, ModuleFun = SignInFunction.Member
                };
                bool check = AuthCheck(token, ref auth);
                if (check)
                {
                    // 取出目前的點名活動
                    var eve = signInService.GetSignInInfomation(auth.EventId);

                    #region //確認活動正在進行

                    var act = activityService.GetByEventId(auth.EventId);

                    var endTime = act.StartDate.Value.Add(new TimeSpan(0, 0, act.Duration.Value));
                    if (act.StartDate != null && (DateTime.UtcNow <= act.StartDate || DateTime.UtcNow >= endTime))
                    {
                        response.Success = false;
                        response.Message = "現在活動不是進行中";
                        Clients.Caller.signIn_Failed("UpdateSignIn", outerKey, "現在活動不是進行中");
                        return(response);
                    }
                    #endregion

                    #region //確認學生可以被點名

                    if (auth.ModuleAuth == false)
                    {
                        response.Success = false;
                        response.Message = "你沒有修這堂課";
                        Clients.Caller.signIn_Failed("UpdateSignIn", outerKey, "你沒有修這堂課");
                        return(response);
                    }

                    #endregion

                    #region //缺席才可簽到

                    var log = signInLogService.GetLogData(eve.Id, auth.MemberId, AttendanceState.Absence);
                    if (log == null)
                    {
                        Clients.Caller.signIn_Failed("UpdateSignIn", outerKey, "只有缺席的學生可以簽到");
                        response.Success = false;
                        response.Message = "只有缺席的學生可以簽到";
                        return(response);
                    }
                    #endregion

                    #region // 簽到碼檢查

                    switch (checkType)
                    {
                    // 若學生不在教室,回傳錯誤訊息
                    case "beacon":
                        if (!keys.Contains(eve.SignInKey))
                        {
                            var msg = string.Format("你不在教室!\n教室beacons:\n{0}\n\n偵測到:\n{1}", eve.SignInKey, string.Join("\n", keys));
                            Clients.Caller.signIn_Failed("SignIn_BeaconSignIn", outerKey, msg);
                            response.Success = false;
                            response.Message = msg;
                            return(response);
                        }
                        break;

                    // 簽到密碼錯誤,回傳錯誤訊息
                    case "pwd":
                        if (eve.SignInPwd != keys[0])
                        {
                            response.Success = false;
                            response.Message = "驗證碼錯誤";
                            Clients.Caller.signIn_Failed("SignIn_PasswordSignIn", outerKey, "驗證碼錯誤!");
                            return(response);
                        }
                        break;
                    }
                    #endregion

                    string stateCode = AttendanceState.Attend;

                    // 檢查通過,save data
                    var mylog = signInLogService.UpdateLog(auth.MemberId, auth.EventId, auth.MemberId, stateCode);

                    // 新增一筆通知
                    string stateName = AttendanceState.GetStateName(stateCode);
                    string text      = "您的狀態已更新:" + stateName;
                    AddNotice(circleKey, auth.EventId, auth.MemberId, text);
                    //告訴同學點名狀態已改變
                    Clients.Group(circleKey.ToLower()).signIn_StatusChanged(outerKey, mylog);


                    // 2016-09-20 mark by sophiee:APP team告知,如果是學生自己簽到就不發送推播
                    // await PushOnChangedSignIn(circleKey, auth.EventId, mylog.StudId, stateName);
                    response.Success = true;
                }
                else
                {
                    response.Message = "身分驗證失敗,請重新登入";
                    Clients.Caller.onError("UpdateSignIn", "身分驗證失敗,請重新登入!token:[" + token + "]");
                    response.Success = false;
                }
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = "學生簽到發生意外";
                Clients.Caller.onError("UpdateSignIn", "學生簽到發生意外: " + string.Format("{0}\n\n{1}", ex.Message, ex.StackTrace));
            }
            return(response);
        }
 public AttendanceStateDTO(AttendanceState inputAttendanceState)
 {
     StateID     = inputAttendanceState.StateID;
     Description = inputAttendanceState.Description;
 }
Exemplo n.º 9
0
        public static void Verify(ref List <string> errors)
        {
            RockContext       rockContext       = new RockContext();
            AttendanceService attendanceService = new AttendanceService(rockContext);
            var attendances = attendanceService.Queryable("Occurrence")
                              .Where(a => a.CreatedDateTime.HasValue && a.CreatedDateTime >= Rock.RockDateTime.Today)
                              .ToList();
            var attendanceCaches = All();

            if (attendances.Count != attendanceCaches.Count)
            {
                var recordIds       = attendances.Select(r => r.Id);
                var cacheIds        = attendanceCaches.Select(r => r.Id);
                var missingCacheIds = recordIds.Except(cacheIds).ToList();
                var extraCacheIds   = cacheIds.Except(recordIds).ToList();
                foreach (var id in missingCacheIds)
                {
                    errors.Add($"Warning: Attendance Cache missing from All(): {id}");
                }

                foreach (var id in extraCacheIds)
                {
                    errors.Add($"Error: Extraneous Attendance Cache: {id}");
                }
            }

            foreach (var attendance in attendances)
            {
                var attendanceCache = AttendanceCache.Get(attendance.Id);
                if (attendanceCache == null)
                {
                    errors.Add("Error: Attendance Cache missing for Attendance Id: " + attendance.Id.ToString());
                    continue;
                }

                AttendanceState attendanceState = AttendanceState.CheckedOut;
                bool            withParent      = false;

                if (attendance.EndDateTime.HasValue)   //End date means checked out
                {
                    attendanceState = AttendanceState.CheckedOut;
                }
                else //has not been checked out yet
                {
                    if (attendance.DidAttend == false && attendance.QualifierValueId.HasValue)
                    {
                        attendanceState = AttendanceState.MobileReserve;
                    }
                    else if (attendance.DidAttend == true)
                    {
                        attendanceState = AttendanceState.InRoom;
                        if (attendance.QualifierValueId == DefinedValueCache.GetId(Constants.DEFINED_VALUE_ATTENDANCE_STATUS_WITH_PARENT.AsGuid()))
                        {
                            withParent = true;
                        }
                    }
                    else
                    {
                        attendanceState = AttendanceState.EnRoute;
                    }
                }

                if (attendance.Occurrence.GroupId != attendanceCache.GroupId)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: GroupId - DB:{attendance.Occurrence.GroupId} - Cache:{attendanceCache.GroupId}");
                }

                if (attendance.PersonAlias.PersonId != attendanceCache.PersonId)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: PersonId - DB:{attendance.PersonAlias.PersonId} - Cache:{attendanceCache.PersonId}");
                }

                if (attendance.Occurrence.LocationId != attendanceCache.LocationId)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: LocationId - DB:{attendance.Occurrence.LocationId} - Cache:{attendanceCache.LocationId}");
                }

                if (attendance.Occurrence.ScheduleId != attendanceCache.ScheduleId)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: ScheduleId - DB:{attendance.Occurrence.ScheduleId} - Cache:{attendanceCache.ScheduleId}");
                }

                if (attendanceState != attendanceCache.AttendanceState)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: attendanceState - DB:{attendanceState} - Cache:{attendanceCache.AttendanceState}");
                }

                if (withParent != attendanceCache.WithParent)
                {
                    errors.Add($"Error: Attendance Cache (Id:{attendance.Id}) Desync: WithParent - DB:{withParent} - Cache:{attendanceCache.WithParent}");
                }
            }
        }
Exemplo n.º 10
0
        public void GetNextInfo(AttendanceInfo nextInfo)
        {
            // assert there is no weekend days in the list
            if (!WorkdayUtil.IsWorkday(nextInfo.Date))
            {
                Debug.Assert(false, "there is weekend in the list");
            }

            // filter out the absent days
            if (nextInfo.State != AttendanceState.Absent)
            {
                return;
            }

            // first node
            if (this.AbsentDays == 0)
            {
                this.Reset(nextInfo);

                this.AbsentDays++;

                return;
            }

            // date is not continous, reset the points
            if ((nextInfo.Date.DayOfWeek == DayOfWeek.Monday) &&
                (nextInfo.Date.DayOfYear - this.PreNode.Date.DayOfYear > 3))
            {
                if (this.PreState == AttendanceState.Dimission)
                {
                    // change to absent
                    this.NextState = AttendanceState.Absent;
                    this.NextNode  = nextInfo;
                }
                else
                {
                    this.Reset(nextInfo);
                }

                return;
            }
            if ((nextInfo.Date.DayOfWeek != DayOfWeek.Monday) &&
                (nextInfo.Date.DayOfYear - this.PreNode.Date.DayOfYear > 1))
            {
                if (this.PreState == AttendanceState.Dimission)
                {
                    // change to absent
                    this.NextState = AttendanceState.Absent;
                    this.NextNode  = nextInfo;
                }
                else
                {
                    this.Reset(nextInfo);
                }
                return;
            }

            // change state to left
            if ((++this.AbsentDays > MAX_ABSENT_DAYS) && (this.PreState == AttendanceState.Absent))
            {
                this.NextState = AttendanceState.Dimission;
                this.NextNode  = nextInfo;
            }

            this.PreNode = nextInfo;
        }
Exemplo n.º 11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="info"></param>
        /// <param name="faultDate"></param>
        /// <returns>
        /// false - did not do anything
        /// true - correct successfully
        /// </returns>
        static bool CorrectSystemFault(AttendanceInfo info, DateTime faultDate, AttendanceState errorState, AttendanceState correctState)
        {
            if (!info.Date.Equals(faultDate))
            {
                return(false);
            }

            PersonInfo personInfo = PersonInfoRepo.GetPersonInfo(info.Name);

            if (personInfo == null)
            {
                //MessageBox.Show(nextInfo.Name + " 没有台账信息!");
                Trace.WriteLine("cannot find " + info.Name);
                return(false);
            }

            // check dismission date
            DateTime dimissionDate = DateTime.MaxValue;

            try
            {
                if (!string.IsNullOrWhiteSpace(personInfo.DimissionDate) &&
                    !DISMISSION_FORMAT_EXCEPTION.ContainsKey(personInfo.Name))
                {
                    dimissionDate = Convert.ToDateTime(personInfo.DimissionDate);
                }
            }
            catch (FormatException)
            {
                Trace.WriteLine("error dismission date format: " + personInfo.DimissionDate);
                dimissionDate = DateTime.MinValue;
                DISMISSION_FORMAT_EXCEPTION[personInfo.Name] = personInfo;
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.Message);
                return(false);
            }
            if (dimissionDate < faultDate)
            {
                return(false); // skip the leave early case
            }

            // check onboard date
            DateTime onboardDate = DateTime.MinValue;

            try
            {
                if (!string.IsNullOrWhiteSpace(personInfo.OnboardDate) &&
                    !ONBOARD_FORMAT_EXCEPTION.ContainsKey(personInfo.Name))
                {
                    onboardDate = Convert.ToDateTime(personInfo.OnboardDate);
                }
            }
            catch (FormatException)
            {
                Trace.WriteLine("error onboard date format: " + personInfo.OnboardDate);
                onboardDate = DateTime.MaxValue;
                ONBOARD_FORMAT_EXCEPTION[personInfo.Name] = personInfo;
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.Message);
                return(false);
            }
            if (onboardDate > faultDate)
            {
                return(false); // skip the onboard later case
            }

            // correct the status
            if (errorState == AttendanceState.None)
            {
                info.State = correctState; // for all the case
            }
            else if (info.State == errorState)
            {
                info.State = correctState; // for specific case
            }

            return(true);
        }