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
/// <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); } }
public DismissionChecker(AttendanceInfo firstNode) { this.FirstAbsentNode = firstNode; this.PreNode = firstNode; this.AbsentDays = 0; this.PreState = AttendanceState.Absent; this.NextState = AttendanceState.Absent; }
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
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; }
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}"); } } }
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; }
/// <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); }