private void setNonLateEarly(Att_Workday workday) { workday.LateDuration1 = 0; workday.LateDuration2 = 0; workday.LateDuration3 = 0; workday.LateDuration4 = 0; workday.EarlyDuration1 = 0; workday.EarlyDuration2 = 0; workday.EarlyDuration3 = 0; workday.EarlyDuration4 = 0; workday.LateEarlyDuration = 0; workday.LateEarlyRoot = 0; }
public string SaveLeaveDay(Att_Workday Workday, string LeaveTypeCode, string UserLogin) { if (Workday == null) return string.Empty; using (var context = new VnrHrmDataContext()) { var unitOfWork = (IUnitOfWork)(new UnitOfWork(context)); var repoCat_Shift = new CustomBaseRepository<Cat_Shift>(unitOfWork); var repoCat_LeaveDayType = new CustomBaseRepository<Cat_LeaveDayType>(unitOfWork); var repoAtt_LeaveDay = new CustomBaseRepository<Att_LeaveDay>(unitOfWork); var repoHre_Profile = new CustomBaseRepository<Hre_Profile>(unitOfWork); var repoAtt_Grade = new CustomBaseRepository<Att_Grade>(unitOfWork); var repoCat_GradeAttendance = new CustomBaseRepository<Cat_GradeAttendance>(unitOfWork); var repoHre_WorkHistory = new CustomBaseRepository<Hre_WorkHistory>(unitOfWork); var repoAtt_Roster = new CustomBaseRepository<Att_Roster>(unitOfWork); var repoAtt_RosterGroup = new CustomBaseRepository<Att_RosterGroup>(unitOfWork); var repoCat_DayOff = new CustomBaseRepository<Cat_DayOff>(unitOfWork); var shifts = repoCat_Shift.FindBy(s => s.IsDelete == null).ToList(); Att_LeavedayServices leavedayServices = new Att_LeavedayServices(); LeaveTypeCode = LeaveTypeCode.Replace("...", string.Empty); Guid? ShiftID = Workday.ShiftApprove ?? Workday.ShiftID; double DurationHour = 8; var shift = repoCat_Shift.FindBy(m => m.ID == ShiftID).FirstOrDefault(); //Cat_Shift shift = EntityService.CreateQueryable<Cat_Shift>(false, GuidContext, Guid.Empty, m => m.ID == ShiftID).FirstOrDefault(); if (shift != null) DurationHour = shift.WorkHours ?? 8; var leaveType = new List<Cat_LeaveDayType>().Select(m => new { m.ID, m.Code, m.CodeStatistic }).FirstOrDefault(); if (!string.IsNullOrEmpty(LeaveTypeCode)) { leaveType = repoCat_LeaveDayType.FindBy(m => m.Code == LeaveTypeCode).Select(m => new { m.ID, m.Code, m.CodeStatistic }).FirstOrDefault(); //leaveType = EntityService.CreateQueryable<Cat_LeaveDayType>(false, GuidContext, Guid.Empty, m => m.CodeStatistic == LeaveTypeCode).Select(m => new { m.ID, m.Code, m.CodeStatistic }).FirstOrDefault(); } DateTime workday = Workday.WorkDate; DateTime beginDate = workday.Date; DateTime endDate = beginDate.AddDays(1).AddMinutes(-1); DateTime beginShift = workday.AddHours(shift.InTime.Hour).AddMinutes(shift.InTime.Minute); DateTime endShift = beginShift.AddHours(shift.CoOut); string E_APPROVED = LeaveDayStatus.E_APPROVED.ToString(); string E_REJECTED = LeaveDayStatus.E_REJECTED.ToString(); List<Att_LeaveDay> lstLeaveDayInDbUpdate = repoAtt_LeaveDay.FindBy(m => m.DateStart <= endDate && m.DateEnd >= beginDate && m.ProfileID == Workday.ProfileID && m.Status != E_REJECTED).ToList<Att_LeaveDay>(); List<Att_LeaveDay> lstLeaveDayInsert = new List<Att_LeaveDay>(); if (lstLeaveDayInDbUpdate.Count > 0) { if (!lstLeaveDayInDbUpdate.Any(m => m.Status == LeaveDayStatus.E_APPROVED.ToString())) { if (leaveType != null) { lstLeaveDayInDbUpdate.ForEach(m => m.LeaveDayTypeID = leaveType.ID); } else { lstLeaveDayInDbUpdate.ForEach(m => m.IsDelete = true); } } else lstLeaveDayInDbUpdate = new List<Att_LeaveDay>(); } else { if (leaveType != null) { Att_LeaveDay LeavedayInsert = new Att_LeaveDay(); LeavedayInsert.ID = Guid.Empty; LeavedayInsert.ProfileID = Workday.ProfileID; LeavedayInsert.TotalDuration = 1; LeavedayInsert.LeaveDays = 1; LeavedayInsert.Duration = shift.WorkHours ?? 8; LeavedayInsert.LeaveHours = shift.WorkHours ?? 8; LeavedayInsert.DurationType = LeaveDayDurationType.E_FULLSHIFT.ToString(); LeavedayInsert.DateStart = workday; LeavedayInsert.DateEnd = workday; LeavedayInsert.LeaveDayTypeID = leaveType.ID; LeavedayInsert.Status = LeaveDayStatus.E_SUBMIT.ToString(); lstLeaveDayInsert.Add(LeavedayInsert); } } //Cap nhat leavedayID cho workday o day if (lstLeaveDayInsert.Count > 0) { if (lstLeaveDayInsert.Count > 1) { Workday.LeaveDayID1 = lstLeaveDayInsert[0].ID; Workday.LeaveDayID2 = lstLeaveDayInsert[1].ID; //Workday.udLeavedayCode1 = LeaveTypeCode; //Workday.udLeavedayCode2 = LeaveTypeCode; //Workday.udLeavedayStatus1 = lstLeaveDayInsert.FirstOrDefault().Status.TranslateString(); //Workday.udLeavedayStatus2 = lstLeaveDayInsert.FirstOrDefault().Status.TranslateString(); } else { Workday.LeaveDayID1 = lstLeaveDayInsert[0].ID; //Workday.udLeavedayCode1 = LeaveTypeCode; //Workday.udLeavedayStatus1 = lstLeaveDayInsert.FirstOrDefault().Status.TranslateString(); } } //else if (lstLeaveDayInDbUpdate.Count > 0) //{ // if (lstLeaveDayInDbUpdate.Count >= 2) // { // Workday.udLeavedayCode1 = LeaveTypeCode; // Workday.udLeavedayCode2 = LeaveTypeCode; // Workday.udLeavedayStatus1 = lstLeaveDayInDbUpdate.FirstOrDefault().Status.TranslateString(); // Workday.udLeavedayStatus2 = lstLeaveDayInDbUpdate.FirstOrDefault().Status.TranslateString(); // } // else // { // Workday.udLeavedayCode1 = LeaveTypeCode; // Workday.udLeavedayStatus1 = lstLeaveDayInDbUpdate.FirstOrDefault().Status.TranslateString(); // Workday.udLeavedayStatus2 = lstLeaveDayInDbUpdate.FirstOrDefault().Status.TranslateString(); // } //} #region Triet.Mai Validate Nghỉ Bù if (lstLeaveDayInsert.Count > 0) { List<Guid> LeaveTypeDayOffID = repoCat_LeaveDayType.FindBy(m => m.IsTimeOffInLieu == true).Select(m => m.ID).ToList<Guid>(); //List<Guid> LeaveTypeDayOffID = EntityService.CreateQueryable<Cat_LeaveDayType>(false, GuidContext, Guid.Empty, m => m.IsTimeOffInLieu == true).Select(m => m.ID).ToList<Guid>(); if (lstLeaveDayInsert.FirstOrDefault().Status != OverTimeStatus.E_CANCEL.ToString() && LeaveTypeDayOffID.Any(m => m == lstLeaveDayInsert.FirstOrDefault().LeaveDayTypeID)) { string Error = leavedayServices.ValidateLeaveDayTimeOff(lstLeaveDayInsert.Select(m => m.ProfileID).Distinct().ToList(), lstLeaveDayInsert); if (Error != string.Empty) { return Error; } } } #endregion #region triet.mai validate vấn đề ngày nghỉ dành cho nhân viên thực tập string E_STANDARD_WORKDAY = AppConfig.E_STANDARD_WORKDAY.ToString(); string status = string.Empty; List<object> lstO = new List<object>(); lstO.Add(E_STANDARD_WORKDAY); lstO.Add(null); lstO.Add(null); Sys_AllSetting config = GetData<Sys_AllSetting>(lstO, ConstantSql.hrm_sys_sp_get_AllSetting, UserLogin, ref status).FirstOrDefault(); //Sys_AppConfig config = EntityService.GetEntity<Sys_AppConfig>(false, GuidContext, Guid.Empty, m => m.Info == E_STANDARD_WORKDAY); string validateEmpProbation = leavedayServices.ValidateLeaveTypeByNewEmployee(config, lstLeaveDayInsert); if (validateEmpProbation != string.Empty) { return validateEmpProbation; } #endregion #region triet.mai cap nhat leaveDays va leaveHours lstLeaveDayInsert.AddRange(lstLeaveDayInDbUpdate); if (lstLeaveDayInsert.Count > 0) { List<Cat_LeaveDayType> lstLeaveDayType = repoCat_LeaveDayType.FindBy(m => m.IsDelete == null).ToList<Cat_LeaveDayType>(); //List<Cat_LeaveDayType> lstLeaveDayType = EntityService.CreateQueryable<Cat_LeaveDayType>(false, GuidContext, Guid.Empty).ToList<Cat_LeaveDayType>(); List<Guid> lstProfileID1 = lstLeaveDayInsert.Select(m => m.ProfileID).Distinct().ToList<Guid>(); List<Hre_Profile> lstProfile = repoHre_Profile.FindBy(m => lstProfileID1.Contains(m.ID)).ToList<Hre_Profile>(); //List<Hre_Profile> lstProfile = EntityService.CreateQueryable<Hre_Profile>(false, GuidContext, Guid.Empty, m => lstProfileID1.Contains(m.ID)).ToList<Hre_Profile>(); DateTime dateMin1 = lstLeaveDayInsert.Min(m => m.DateStart).Date; DateTime dateMax1 = lstLeaveDayInsert.Max(m => m.DateEnd); List<Att_Roster> lstRosterTypeGroup = new List<Att_Roster>(); List<Att_RosterGroup> lstRosterGroup = new List<Att_RosterGroup>(); var lstGrade = repoAtt_Grade.FindBy(m => lstProfileID1.Contains(m.ProfileID.Value)) .Select(m => new { m.ID, m.ProfileID, m.MonthStart, m.GradeAttendanceID }) .OrderByDescending(m => m.MonthStart).ToList(); //var lstGrade = EntityService.CreateQueryable<Sal_Grade>(false, GuidContext, Guid.Empty, m => lstProfileID1.Contains(m.ProfileID)) // .Select(m => new { m.ID, m.ProfileID, m.MonthStart, m.GradeID }) // .OrderByDescending(m => m.MonthStart) // .Execute(); List<Cat_GradeAttendance> lstGradeAttendance = repoCat_GradeAttendance.FindBy(m => m.IsDelete == null).ToList(); //List<Cat_GradeCfg> lstGradeCfg = EntityService.CreateQueryable<Cat_GradeCfg>(false, GuidContext, Guid.Empty).ToList<Cat_GradeCfg>(); List<Hre_WorkHistory> listWorkHistory = repoHre_WorkHistory.FindBy(m => m.DateEffective <= dateMax1 && lstProfileID1.Contains(m.ProfileID)).OrderByDescending(m => m.DateEffective).ToList<Hre_WorkHistory>(); //List<Hre_WorkHistory> listWorkHistory = EntityService.CreateQueryable<Hre_WorkHistory>(false, GuidContext, Guid.Empty, m => m.DateEffective <= dateMax1 && lstProfileID1.Contains(m.ProfileID)).OrderByDescending(m => m.DateEffective).ToList<Hre_WorkHistory>(); E_APPROVED = RosterStatus.E_APPROVED.ToString(); string E_ROSTERGROUP = RosterType.E_ROSTERGROUP.ToString(); if (dateMin1 == null || dateMax1 == null) { lstRosterTypeGroup = repoAtt_Roster.FindBy(m => lstProfileID1.Contains(m.ProfileID) && m.Status == E_APPROVED && m.Type == E_ROSTERGROUP).ToList<Att_Roster>(); //lstRosterTypeGroup = EntityService.Instance.CreateQueryable<Att_Roster>(false, guidContext, Guid.Empty, m => lstProfileID.Contains(m.ProfileID) && m.Status == E_APPROVED && m.Type == E_ROSTERGROUP).ToList<Att_Roster>(); lstRosterGroup = repoAtt_RosterGroup.FindBy(m => m.DateStart != null && m.DateEnd != null).ToList<Att_RosterGroup>(); //lstRosterGroup = EntityService.Instance.CreateQueryable<Att_RosterGroup>(false, guidContext, Guid.Empty, m => m.DateStart != null && m.DateEnd != null).ToList<Att_RosterGroup>(); } else { lstRosterTypeGroup = repoAtt_Roster.FindBy(m => lstProfileID1.Contains(m.ProfileID) && m.Status == E_APPROVED && m.Type == E_ROSTERGROUP && m.DateStart <= dateMax1).ToList<Att_Roster>(); //lstRosterTypeGroup = EntityService.Instance.CreateQueryable<Att_Roster>(false, guidContext, Guid.Empty, m => lstProfileID.Contains(m.ProfileID) && m.Status == E_APPROVED && m.Type == E_ROSTERGROUP && m.DateStart <= DateTo).ToList<Att_Roster>(); lstRosterGroup = repoAtt_RosterGroup.FindBy(m => m.DateStart != null && m.DateEnd != null && m.DateStart <= dateMax1 && m.DateEnd >= dateMin1).ToList<Att_RosterGroup>(); //lstRosterGroup = EntityService.Instance.CreateQueryable<Att_RosterGroup>(false, guidContext, Guid.Empty, m => m.DateStart != null && m.DateEnd != null && m.DateStart <= DateTo && m.DateEnd >= DateFrom).ToList<Att_RosterGroup>(); } //RosterDAO.GetRosterGroup(GuidContext, lstProfileID1, dateMin1, dateMax1, out lstRosterTypeGroup, out lstRosterGroup); List<Cat_DayOff> lstHoliday = repoCat_DayOff.FindBy(m => m.IsDelete == null).ToList<Cat_DayOff>(); //List<Cat_DayOff> lstHoliday = EntityService.CreateQueryable<Cat_DayOff>(false, GuidContext, Guid.Empty).ToList<Cat_DayOff>(); string E_APPROVED1 = RosterStatus.E_APPROVED.ToString(); E_ROSTERGROUP = RosterType.E_ROSTERGROUP.ToString(); List<Att_Roster> lstRoster = repoAtt_Roster.FindBy(m => m.Status == E_APPROVED1 && m.DateStart <= dateMax1 && m.DateEnd >= dateMin1 && lstProfileID1.Contains(m.ProfileID)).ToList<Att_Roster>(); //List<Att_Roster> lstRoster = EntityService.CreateQueryable<Att_Roster>(false, GuidContext, Guid.Empty, m => m.Status == E_APPROVED1 && m.DateStart <= dateMax1 && m.DateEnd >= dateMin1 && lstProfileID1.Contains(m.ProfileID)).ToList<Att_Roster>(); List<DateTime> lstHolidayType = lstHoliday.Select(m => m.DateOff).ToList<DateTime>(); //LeaveDayDAO ldDao = new LeaveDayDAO(); foreach (var item in lstLeaveDayInsert) { if (item.DurationType != null && item.DurationType != LeaveDayDurationType.E_FULLSHIFT.ToString()) continue; Cat_LeaveDayType leaveDayType = lstLeaveDayType.Where(m => m.ID == item.LeaveDayTypeID).FirstOrDefault(); if (leaveDayType == null) continue; Hre_Profile profileInLeave = lstProfile.Where(m => m.ID == item.ProfileID).FirstOrDefault(); if (profileInLeave == null) continue; DateTime dateFrom = item.DateStart; DateTime dateTo = item.DateEnd; dateTo = dateTo.AddDays(1).AddMinutes(-1); Guid GradeAttendanceID = lstGrade.Where(m => m.ProfileID == profileInLeave.ID && m.MonthStart <= dateMax1 && m.GradeAttendanceID.HasValue).Select(m => m.GradeAttendanceID.Value).FirstOrDefault(); Cat_GradeAttendance gradeAttendance = lstGradeAttendance.Where(m => m.ID == GradeAttendanceID).FirstOrDefault(); List<Att_Roster> lstRosterByProfile = lstRoster.Where(m => m.ProfileID == profileInLeave.ID).ToList(); List<Hre_WorkHistory> listWorkHistoryByProfile = listWorkHistory.Where(m => m.ProfileID == profileInLeave.ID && m.DateEffective < dateTo).ToList(); List<Att_Roster> lstRosterByProfileTypeGroup = lstRosterByProfile.Where(m => m.Type == E_ROSTERGROUP).ToList(); leavedayServices.AnalyseTotalLeaveDaysAndHours(item, leaveDayType, profileInLeave, gradeAttendance, lstRosterByProfile, lstRosterGroup, listWorkHistoryByProfile, lstHoliday, shifts); if (item.ID == Guid.Empty) { item.ID = Guid.NewGuid(); repoAtt_LeaveDay.Add(item); } else repoAtt_LeaveDay.Edit(item); } } #endregion //repoAtt_LeaveDay.Add(lstLeaveDayInsert); repoAtt_LeaveDay.SaveChanges(); //EntityService.AddEntity<Att_LeaveDay>(GuidContext, lstLeaveDayInsert.ToArray()); return string.Empty; } }
public void AnalyzeLeaveLateSecondShift(Att_Workday Workday, List<Att_Pregnancy> lstPrenancy, List<Cat_LateEarlyRule> lstLateEarlyRule, List<Cat_Shift> lstShift, List<Att_Grade> lstGrade, List<Cat_GradeAttendance> lstGradeConfig, List<DateTime> lstDayOff, out int LateRound,out int EarLyRound) { LateRound = 0; EarLyRound = 0; if (Workday.InTime2 == null || Workday.OutTime2 == null) return; Cat_Shift Shift = null; Guid? ShiftID = Workday.ShiftApprove2 ?? Workday.Shift2ID; Shift = lstShift.Where(m => m.ID == ShiftID).FirstOrDefault(); if (Shift == null) return; DateTime Date = Workday.WorkDate; if (lstDayOff.Any(m => m == Date.Date)) return; DateTime? dateStartShift = Date.Date.AddHours(Shift.InTime.Hour).AddMinutes(Shift.InTime.Minute); DateTime? dateEndShift = dateStartShift.Value.AddHours(Shift.CoOut); string E_LEAVE_EARLY = PregnancyType.E_LEAVE_EARLY.ToString(); Att_Pregnancy Prenancy = lstPrenancy .Where(m => m.ProfileID == Workday.ProfileID && m.DateStart <= Workday.WorkDate && m.DateEnd > Workday.WorkDate && m.Type == E_LEAVE_EARLY) .FirstOrDefault(); Att_Grade GradeByProfile = lstGrade .Where(m => m.ProfileID == Workday.ProfileID && m.MonthStart < Workday.WorkDate) .OrderByDescending(m => m.MonthStart) .FirstOrDefault(); Cat_GradeAttendance GradeCfg = null; List<Cat_LateEarlyRule> lstLateEarlyRule_By_Config = new List<Cat_LateEarlyRule>(); if (GradeByProfile != null) { GradeCfg = lstGradeConfig.Where(m => m.ID == GradeByProfile.GradeAttendanceID).FirstOrDefault(); } if (GradeCfg != null) { lstLateEarlyRule_By_Config = lstLateEarlyRule.Where(m => m.GradeCfgID == GradeCfg.ID).ToList(); } if (GradeCfg == null) return; #region tính có trễ sớm cho trường hơp đầu ca cuối ca //2. Kiểm tra đủ đk để không bị trễ sớm bool BeLate = true; bool BeEarly = true; double HourLate = 0; double HourEarly = 0; #region cặp thứ 2 if (Workday.InTime2 != null && Workday.OutTime2 != null) { if (!IsHaveLateEarly(dateStartShift.Value, dateEndShift.Value, Workday.InTime2.Value, Workday.OutTime2.Value, ref BeLate, ref BeEarly, ref HourLate, ref HourEarly, new Dictionary<DateTime, DateTime>(), Shift)) { } } #endregion double Late = HourLate * 60; //Phut neen nhaan cho 60 double EarLy = HourEarly * 60; //Phut neen nhaan cho 60 if (Late > 480) { Late = 480; EarLy = 0; } if ((Late - (int)Late) > 0) { Late = (int)Late + 1; } else { Late = (int)Late; } if ((EarLy - (int)EarLy) > 0) { EarLy = (int)EarLy + 1; } else { EarLy = (int)EarLy; } bool isCheck = false; if (GradeCfg.AttendanceMethod == AttendanceMethod.E_TAM.ToString()) isCheck = true; bool isUseLateEarlyRule = false; if (GradeCfg.AttendanceMethod == AttendanceMethod.E_TAM.ToString() && GradeCfg.IsDeductInLateOutEarly == true && GradeCfg.IsLateEarlyRounding == true) isUseLateEarlyRule = true; RoundLateEarly(Prenancy, lstLateEarlyRule_By_Config, ref HourLate, ref HourEarly, isCheck, isUseLateEarlyRule); LateRound =(int) (HourLate * 60); EarLyRound =(int) (HourEarly * 60); if (LateRound > 480) { LateRound = 480; EarLyRound = 0; } if ((LateRound - (int)LateRound) > 0) { LateRound = (int)LateRound + 1; } else { LateRound = (int)LateRound; } if ((EarLyRound - (int)EarLyRound) > 0) { EarLyRound = (int)EarLyRound + 1; } else { EarLyRound = (int)EarLyRound; } #endregion }
private int ComputeAttendance(IUnitOfWork unitOfWork, Guid userID, DateTime monthYear, Guid cutOffDurationID, DateTime attendanceFrom, DateTime attendanceTo, Hre_ProfileEntity profile, Cat_GradeAttendance gradeCfg, List<Cat_Shift> listShift, List<Att_AnnualDetail> listAnnualDetailByProfile, List<Hre_HDTJob> listHDTJobByProfile, List<Att_LeaveDayEntity> listLeaveDayByProfile, List<Cat_LeaveDayType> listLeaveDayType, List<Att_OvertimeEntity> listOvertimeByProfile, List<Cat_OvertimeType> listOvertimeType, List<Att_PregnancyEntity> listPregnancyByProfile, List<Cat_LateEarlyRule> listLateEarlyRule, List<Att_Workday> listWorkDayByProfile, List<Att_AttendanceTableEntity> listPreAttendanceTableByProfile, List<Att_TimeOffInLieuEntity> listTimeOffInLieuByProfile, Sys_AllSetting notAutoRegHolidayLeave, Sys_AllSetting otholidayscompute400, Sys_AllSetting missTAM_LeaveType, Dictionary<DateTime, List<Guid?>> listMonthShiftID, List<Cat_DayOff> listHoliday) { Guid profileID = profile.ID; if (gradeCfg == null || profile == null) { return 0; } DateTime midCutOffDate = attendanceTo; bool isMidCutOffDay = false; #region Tạo Att_AttendanceTable theo khoảng thời gian Att_AttendanceTable attendanceTable = new Att_AttendanceTable(); unitOfWork.AddObject(typeof(Att_AttendanceTable), attendanceTable); attendanceTable.Status = AttendanceTableStatus.E_WAITING.ToString(); attendanceTable.ID = Guid.NewGuid(); attendanceTable.ProfileID = profileID; attendanceTable.MonthYear = monthYear; attendanceTable.DateStart = attendanceFrom; attendanceTable.DateEnd = attendanceTo; double anlDayTaken = 0D; double sickDayTaken = 0D; double coBeginPeriod = 0D; double coEndPeriod = 0D; if (cutOffDurationID != Guid.Empty) { attendanceTable.CutOffDurationID = cutOffDurationID; } //Tính công đến ngày cấu hình trong grade, những ngày sau mặc định full công - Khách hàng CPG if (gradeCfg != null && gradeCfg.IsMonthlyMidCutOff == true && gradeCfg.MidCutOffDay > 0) { if (!profile.DateQuit.HasValue || profile.DateQuit > attendanceTo) { midCutOffDate = new DateTime(monthYear.Year, monthYear.Month, gradeCfg.MidCutOffDay.Value); //Luôn tạo một dòng Ứng công lúc tính công, kô cần biết có nghỉ không Att_AdvanceTableItem advanceTableItem = new Att_AdvanceTableItem(); advanceTableItem.Att_AttendanceTable = attendanceTable; advanceTableItem.DateFrom = midCutOffDate.AddDays(1); advanceTableItem.DateTo = attendanceTo; isMidCutOffDay = true; } } #endregion #region Tạo Att_AttendanceTableItem theo khoảng thời gian List<Att_AttendanceTableItem> listAttendanceTableItemByProfile = new List<Att_AttendanceTableItem>(); for (DateTime date = attendanceFrom.Date; date <= attendanceTo; date = date.AddDays(1)) { var workdayByProfile = listWorkDayByProfile.Where(d => d.WorkDate.Date == date).FirstOrDefault(); Guid? shiftID1 = Guid.Empty; Guid? shiftID2 = Guid.Empty; var shiftByDate = listMonthShiftID.Where(d => d.Key.Date == date).Select(d => d.Value).FirstOrDefault(); if (shiftByDate != null) { if (shiftByDate.Count() > 0) { shiftID1 = shiftByDate[0]; } if (shiftByDate.Count() > 1) { shiftID2 = shiftByDate[1]; } } if (workdayByProfile == null && gradeCfg.EDType == PayrollComputeMethod.E_SUBTRACT.ToString()) { if (shiftID1.HasValue && shiftID1 != Guid.Empty) { workdayByProfile = new Att_Workday { ShiftID = shiftID1, ShiftApprove = shiftID1, ShiftActual = shiftID1, WorkDate = date }; if (shiftID2.HasValue && shiftID2 != Guid.Empty) { workdayByProfile.Shift2ID = shiftID2; workdayByProfile.ShiftApprove2 = shiftID2; workdayByProfile.ShiftActual2 = shiftID2; } if (listHoliday.Any(d => d.DateOff.Date == date)) { workdayByProfile.Type = WorkdayType.E_HOLIDAY.ToString(); } } } Att_AttendanceTableItem attendanceTableItem = new Att_AttendanceTableItem(); listAttendanceTableItemByProfile.Add(attendanceTableItem); attendanceTableItem.ID = Guid.NewGuid(); attendanceTableItem.Att_AttendanceTable = attendanceTable; attendanceTableItem.DutyCode = DutyCode.E_OFF.ToString(); attendanceTableItem.WorkDate = date; double nightDuration = 0F; double workDuration = 0F; attendanceTableItem.WorkPaidHours = 0; attendanceTableItem.PaidLeaveHours = 0; attendanceTableItem.UnpaidLeaveHours = 0; attendanceTableItem.LateEarlyMinutes = 0; attendanceTableItem.LateInMinutes = 0; attendanceTableItem.EarlyOutMinutes = 0; attendanceTableItem.LeaveHours = 0; attendanceTableItem.LeaveDays = 0; attendanceTableItem.WorkHourFirstHaftShift = 0; attendanceTableItem.WorkHourLastHaftShift = 0; if (workdayByProfile != null) { attendanceTableItem.MissInOutReasonID = workdayByProfile.MissInOutReason; attendanceTableItem.FirstInTime = workdayByProfile.FirstInTime; attendanceTableItem.LastOutTime = workdayByProfile.LastOutTime; attendanceTableItem.RootInTime = workdayByProfile.FirstInTime; attendanceTableItem.RootOutTime = workdayByProfile.LastOutTime; attendanceTableItem.ShiftID = workdayByProfile.ShiftID; attendanceTableItem.Shift2ID = workdayByProfile.Shift2ID; List<DateTime?> listInTime = new List<DateTime?>(); List<DateTime?> listOutTime = new List<DateTime?>(); listInTime.Add(workdayByProfile.InTime1); listInTime.Add(workdayByProfile.InTime2); listInTime.Add(workdayByProfile.InTime3); listInTime.Add(workdayByProfile.InTime4); listOutTime.Add(workdayByProfile.OutTime1); listOutTime.Add(workdayByProfile.OutTime2); listOutTime.Add(workdayByProfile.OutTime3); listOutTime.Add(workdayByProfile.OutTime4); attendanceTableItem.FirstInTime = listInTime.Where(d => d.HasValue).OrderBy(d => d).FirstOrDefault(); attendanceTableItem.LastOutTime = listOutTime.Where(d => d.HasValue).OrderBy(d => d).LastOrDefault(); if (workdayByProfile.ShiftApprove.HasValue) { attendanceTableItem.ShiftID = workdayByProfile.ShiftApprove.Value; } if (workdayByProfile.ShiftApprove2.HasValue) { attendanceTableItem.Shift2ID = workdayByProfile.ShiftApprove2.Value; } if (gradeCfg.AttendanceMethod == AttendanceMethod.E_FULL.ToString()) { if (listMonthShiftID.Any(d => d.Key.Date == date)) { //Bao.Tran: khi không kiểm tra vào ra thì ưu tiên ca đã tạo trong lịch làm việc if (shiftID1 != Guid.Empty) { attendanceTableItem.ShiftID = shiftID1; } if (shiftID2 != Guid.Empty) { attendanceTableItem.Shift2ID = shiftID2; } } //Bao.Tran: yêu cầu nếu công ko kiểm tra in/out thì không lấy in/out attendanceTableItem.FirstInTime = null; attendanceTableItem.LastOutTime = null; //comment code này do ảnh hưởng task 0046036 : ko tính được ngày nghỉ lễ ////Bao.Tran: do khi THNC cũ, Nếu ko bỏ type thì nó sẽ tính ngày công trên là holiday (attendanceTableItem.IsHoliday = true;) //workdayByProfile.Type = WorkdayType.E_NORMAL.ToString(); } //kiểm tra ngày làm việc có Lịch làm việc hay ko? if (attendanceTableItem.ShiftID != null && workdayByProfile.FirstInTime != null && workdayByProfile.LastOutTime != null) { #region Kiểm tra HDTJob var listHDTJobByProfileByDate = listHDTJobByProfile.Where(d => (d.DateFrom.Value.Date <= date && d.DateTo == null) || (d.DateTo != null && d.DateFrom.Value.Date <= date && d.DateTo.Value.Date >= date)).ToList(); foreach (var HDTJobByProfile in listHDTJobByProfileByDate) { if (HDTJobByProfile != null) { attendanceTableItem.HDTJobType = HDTJobByProfile.Type; } } #endregion } } var shiftByProfile1 = listShift.Where(d => d.ID == attendanceTableItem.ShiftID).FirstOrDefault(); var shiftByProfile2 = listShift.Where(d => d.ID == attendanceTableItem.Shift2ID).FirstOrDefault(); if (shiftByProfile1 != null) { attendanceTableItem.Cat_Shift = shiftByProfile1; attendanceTableItem.AvailableHours = shiftByProfile1.udAvailableHours; } if (shiftByProfile2 != null) { attendanceTableItem.Cat_Shift1 = shiftByProfile2; } if ((workdayByProfile != null && workdayByProfile.Type == WorkdayType.E_HOLIDAY.ToString()) || (attendanceTableItem.ShiftID.HasValue && attendanceTableItem.ShiftID != Guid.Empty)) { //Ngày đang xét là ngày làm việc bình thường attendanceTableItem.DutyCode = DutyCode.E_ON.ToString(); if (workdayByProfile.Type == WorkdayType.E_HOLIDAY.ToString()) { attendanceTableItem.IsHoliday = true; } } else { //Ngày đang xét không phải là ngày làm việc bình thường attendanceTableItem.DutyCode = DutyCode.E_OFF.ToString(); } #region Kiểm tra ngày nghỉ - leaveday if (attendanceTableItem.DutyCode != DutyCode.E_OFF.ToString()) { var listLeaveDayByProfileByDate = listLeaveDayByProfile.Where(d => d.DateStart.Date <= date && d.DateEnd.Date >= date).ToList(); foreach (var leaveDayByProfile in listLeaveDayByProfileByDate) { if (leaveDayByProfile != null) { double leaveHours = 0D; double leaveDays = 0D; var leaveDayType = listLeaveDayType.Where(d => d.ID == leaveDayByProfile.LeaveDayTypeID).FirstOrDefault(); var standardWorkHours = attendanceTableItem.AvailableHours; if (leaveDayByProfile.DurationType == LeaveDayDurationType.E_FULLSHIFT.ToString()) { //Lấy giờ nghỉ của ngày đang xét dựa vào ca làm việc leaveHours = standardWorkHours; leaveDays = 1;//Nghỉ full shift } else { leaveHours = leaveDayByProfile.LeaveHours.GetDouble(); leaveDays = leaveDayByProfile.LeaveDays.GetDouble(); } leaveHours = leaveHours > standardWorkHours ? standardWorkHours : leaveHours; leaveDays = leaveDays > 1 ? 1 : leaveDays;//Tối đa là nghỉ 1 ngày if (!attendanceTableItem.LeaveTypeID.HasValue) { attendanceTableItem.LeaveTypeID = leaveDayByProfile.LeaveDayTypeID; attendanceTableItem.Cat_LeaveDayType = leaveDayType; attendanceTableItem.LeaveHours = leaveHours; attendanceTableItem.LeaveDays = leaveDays; } else if (!attendanceTableItem.ExtraLeaveTypeID.HasValue) { attendanceTableItem.ExtraLeaveTypeID = leaveDayByProfile.LeaveDayTypeID; attendanceTableItem.Cat_LeaveDayType1 = leaveDayType; attendanceTableItem.ExtraLeaveHours = leaveHours; attendanceTableItem.ExtraLeaveDays = leaveDays; } if (leaveDayType != null && leaveDays > 0) { if (leaveDayType.Code == LeavedayTypeCode.ANL.ToString()) { anlDayTaken += leaveDays; } if (leaveDayType.Code == LeavedayTypeCode.SICK.ToString()) { sickDayTaken += leaveDays; } } } } } #endregion #region Kiểm tra làm thêm - overtime if (gradeCfg != null && gradeCfg.IsReceiveOvertimeBonus.Get_Boolean()) { var listOvertimeByProfileByDate = listOvertimeByProfile.Where(d => d.WorkDate.Date == date).ToList(); foreach (var overtime in listOvertimeByProfileByDate) { if (overtime != null) { double overtimeHours = overtime.ConfirmHours; string overTimeStatus = OverTimeStatus.E_APPROVED.ToString(); if (overTimeStatus == OverTimeStatus.E_APPROVED.ToString()) { overtimeHours = overtime.ApproveHours.GetDouble(); } else if (overTimeStatus == OverTimeStatus.E_CONFIRM.ToString()) { overtimeHours = overtime.ConfirmHours; } if (!attendanceTableItem.OvertimeTypeID.HasValue) { attendanceTableItem.OvertimeTypeID = overtime.OvertimeTypeID; attendanceTableItem.Cat_OvertimeType = listOvertimeType.Where(s => s.ID == overtime.OvertimeTypeID).FirstOrDefault(); attendanceTableItem.OvertimeDurationType = overtime.DurationType; attendanceTableItem.OvertimeRegisterHours = overtime.RegisterHours; attendanceTableItem.OvertimeHours = overtimeHours; } else if (!attendanceTableItem.ExtraOvertimeTypeID.HasValue) { attendanceTableItem.ExtraOvertimeTypeID = overtime.OvertimeTypeID; attendanceTableItem.Cat_OvertimeType1 = listOvertimeType.Where(s => s.ID == overtime.OvertimeTypeID).FirstOrDefault(); attendanceTableItem.ExtraOvertimeDurationType = overtime.DurationType; attendanceTableItem.ExtraOvertimeRegisterHours = overtime.RegisterHours; attendanceTableItem.ExtraOvertimeHours = overtimeHours; } else if (!attendanceTableItem.ExtraOvertimeType2ID.HasValue) { attendanceTableItem.ExtraOvertimeType2ID = overtime.OvertimeTypeID; attendanceTableItem.Cat_OvertimeType2 = listOvertimeType.Where(s => s.ID == overtime.OvertimeTypeID).FirstOrDefault(); attendanceTableItem.ExtraOvertimeDurationType2 = overtime.DurationType; attendanceTableItem.ExtraOvertimeRegisterHours2 = overtime.RegisterHours; attendanceTableItem.ExtraOvertimeHours2 = overtimeHours; } else if (!attendanceTableItem.ExtraOvertimeType3ID.HasValue) { attendanceTableItem.ExtraOvertimeType3ID = overtime.OvertimeTypeID; attendanceTableItem.Cat_OvertimeType3 = listOvertimeType.Where(s => s.ID == overtime.OvertimeTypeID).FirstOrDefault(); attendanceTableItem.ExtraOvertimeDurationType3 = overtime.DurationType; attendanceTableItem.ExtraOvertimeRegisterHours3 = overtime.RegisterHours; attendanceTableItem.ExtraOvertimeHours3 = overtimeHours; } } } } #endregion #region Kiểm tra có thai sản không var pregnancyByProfile = listPregnancyByProfile.Where(d => date >= d.DateStart && date <= d.DateEnd).FirstOrDefault(); if (pregnancyByProfile != null) { attendanceTableItem.IsHavingPregTreatment = true; } #endregion #region Nhân viên đã nghỉ hoặc chưa đi làm if ((profile.DateQuit.HasValue && profile.DateQuit.Value.Date <= date.Date) || (profile.DateHire.HasValue && profile.DateHire.Value.Date > date.Date)) { if (attendanceTableItem.DutyCode == DutyCode.E_ON.ToString()) { if (profile.DateHire.HasValue && profile.DateHire.Value.Date > date.Date) { if (shiftByProfile1 != null) { attendanceTableItem.udNotHiredHours = shiftByProfile1.WorkHours.GetDouble(); } else { attendanceTableItem.udNotHiredHours = attendanceTableItem.udStandardWorkHours; } if (shiftByProfile2 != null) { attendanceTableItem.udNotHiredHours += shiftByProfile2.WorkHours.GetDouble(); } } if (profile.DateQuit.HasValue && profile.DateQuit.Value.Date <= date.Date) { if (shiftByProfile1 != null) { attendanceTableItem.udTerminatedHours = shiftByProfile1.WorkHours.GetDouble(); } else { attendanceTableItem.udTerminatedHours = attendanceTableItem.udStandardWorkHours; } if (shiftByProfile2 != null) { attendanceTableItem.udTerminatedHours += shiftByProfile2.WorkHours.GetDouble(); } } } attendanceTableItem.Cat_LeaveDayType = null; continue; } #endregion #region Loại ngày nghỉ là ngày làm việc if (attendanceTableItem.Cat_LeaveDayType != null) { //Trường hợp ngày nghỉ tính như ngày đi làm => không tính nghỉ if (attendanceTableItem.Cat_LeaveDayType.IsWorkDay) { attendanceTableItem.WorkHours += attendanceTableItem.LeaveHours; attendanceTableItem.WorkPaidHours += attendanceTableItem.LeaveHours; attendanceTableItem.LeaveWorkDayHour = attendanceTableItem.LeaveHours; attendanceTableItem.LeaveWorkDayDays = attendanceTableItem.LeaveHours / attendanceTableItem.udStandardWorkHours; attendanceTableItem.Cat_LeaveDayType2 = attendanceTableItem.Cat_LeaveDayType; attendanceTableItem.Cat_LeaveDayType = null; attendanceTableItem.LeaveHours = 0; attendanceTableItem.LeaveDays = 0; } else { attendanceTableItem.PaidLeaveHours += attendanceTableItem.LeaveHours * attendanceTableItem.Cat_LeaveDayType.PaidRate; attendanceTableItem.UnpaidLeaveHours += attendanceTableItem.LeaveHours * (1 - attendanceTableItem.Cat_LeaveDayType.PaidRate); attendanceTableItem.PaidLeaveDays = attendanceTableItem.PaidLeaveHours / attendanceTableItem.udStandardWorkHours; attendanceTableItem.UnpaidLeaveDays = attendanceTableItem.UnpaidLeaveHours / attendanceTableItem.udStandardWorkHours; } } if (attendanceTableItem.Cat_LeaveDayType1 != null) { if (attendanceTableItem.Cat_LeaveDayType1.IsWorkDay) { attendanceTableItem.WorkHours += attendanceTableItem.ExtraLeaveHours; attendanceTableItem.WorkPaidHours += attendanceTableItem.ExtraLeaveHours; attendanceTableItem.Cat_LeaveDayType1 = null; attendanceTableItem.ExtraLeaveHours = 0; } else { attendanceTableItem.PaidLeaveHours += attendanceTableItem.ExtraLeaveHours * attendanceTableItem.Cat_LeaveDayType1.PaidRate; attendanceTableItem.UnpaidLeaveHours += attendanceTableItem.ExtraLeaveHours * (1 - attendanceTableItem.Cat_LeaveDayType1.PaidRate); } } #endregion if (attendanceTableItem.DutyCode == DutyCode.E_ON.ToString()) { #region IsHavingPregTreatment if (attendanceTableItem.IsHavingPregTreatment) { if ((attendanceTableItem.WorkPaidHours + attendanceTableItem.PaidLeaveHours) > attendanceTableItem.AvailableHours) { attendanceTableItem.WorkPaidHours = attendanceTableItem.AvailableHours - attendanceTableItem.PaidLeaveHours; } else { attendanceTableItem.WorkPaidHours = attendanceTableItem.WorkPaidHours; } } #endregion #region LateEarlyMinutes attendanceTableItem.LateEarlyMinutes = (int)workdayByProfile.LateEarlyDuration.GetDouble(); attendanceTableItem.RealLateEarlyMinutes = attendanceTableItem.LateEarlyMinutes; #endregion #region Tính số giờ đi làm if (workdayByProfile != null && shiftByProfile1 != null) { DateTime timeShiftStart1 = workdayByProfile.WorkDate.Date.Add(shiftByProfile1.InTime.TimeOfDay); DateTime timeShiftEnd1 = timeShiftStart1.AddHours(shiftByProfile1.CoOut); //Thời gian bắt đầu và kết thúc nghỉ giữa ca - dùng cho tính toán DateTime timeShiftBreakIn1 = timeShiftStart1.AddHours(shiftByProfile1.CoBreakIn); DateTime timeShiftBreakOut1 = timeShiftStart1.AddHours(shiftByProfile1.CoBreakOut); workDuration = GetDuration(workdayByProfile, timeShiftStart1, timeShiftEnd1, timeShiftBreakIn1, timeShiftBreakOut1, shiftByProfile1.InOutDynamic); #region Tính số giờ làm ca đêm if (shiftByProfile1.IsNightShift) { DateTime nightTimeStart = workdayByProfile.WorkDate.Date.AddHours(22); DateTime nightTimeEnd = workdayByProfile.WorkDate.Date.AddDays(1).AddHours(6); nightTimeStart = workdayByProfile.WorkDate.Date.Add(shiftByProfile1.NightTimeStart.Value.TimeOfDay); nightTimeEnd = workdayByProfile.WorkDate.Date.Add(shiftByProfile1.NightTimeEnd.Value.TimeOfDay); nightTimeEnd = nightTimeStart > nightTimeEnd ? nightTimeEnd.AddDays(1) : nightTimeEnd; //Truong hop nghi giua ca nam trong khoang bat dau ca dem nightDuration = GetDuration(workdayByProfile, nightTimeStart, nightTimeEnd, timeShiftBreakIn1, timeShiftBreakOut1, shiftByProfile1.InOutDynamic); } #endregion } if (workdayByProfile != null && shiftByProfile2 != null) { DateTime timeShiftStart2 = workdayByProfile.WorkDate.Date.Add(shiftByProfile2.InTime.TimeOfDay); DateTime timeShiftEnd2 = timeShiftStart2.AddHours(shiftByProfile2.CoOut); //Thời gian bắt đầu và kết thúc nghỉ giữa ca - dùng cho tính toán DateTime timeShiftBreakIn2 = timeShiftStart2.AddHours(shiftByProfile2.CoBreakIn); DateTime timeShiftBreakOut2 = timeShiftStart2.AddHours(shiftByProfile2.CoBreakOut); workDuration += GetDuration(workdayByProfile, timeShiftStart2, timeShiftEnd2, timeShiftBreakIn2, timeShiftBreakOut2, shiftByProfile2.InOutDynamic); #region Tính số giờ làm ca đêm if (shiftByProfile2.IsNightShift) { DateTime nightTimeStart = workdayByProfile.WorkDate.Date.AddHours(22); DateTime nightTimeEnd = workdayByProfile.WorkDate.Date.AddDays(1).AddHours(6); nightTimeStart = workdayByProfile.WorkDate.Date.Add(shiftByProfile2.NightTimeStart.Value.TimeOfDay); nightTimeEnd = workdayByProfile.WorkDate.Date.Add(shiftByProfile2.NightTimeEnd.Value.TimeOfDay); nightTimeEnd = nightTimeStart > nightTimeEnd ? nightTimeEnd.AddDays(1) : nightTimeEnd; //Truong hop nghi giua ca nam trong khoang bat dau ca dem nightDuration = GetDuration(workdayByProfile, nightTimeStart, nightTimeEnd, timeShiftBreakIn2, timeShiftBreakOut2, shiftByProfile2.InOutDynamic); } #endregion } attendanceTableItem.NightShiftHours = (nightDuration / 60);//lưu số giờ attendanceTableItem.WorkPaidHours = (workDuration / 60);//lưu số giờ attendanceTableItem.WorkHours = (workDuration / 60);//lưu số giờ attendanceTableItem.WorkPaidHours = attendanceTableItem.WorkPaidHours < 0 ? 0 : attendanceTableItem.WorkPaidHours; attendanceTableItem.WorkPaidHours = attendanceTableItem.WorkPaidHours > attendanceTableItem.AvailableHours ? attendanceTableItem.AvailableHours : attendanceTableItem.WorkPaidHours; #endregion if (gradeCfg.AttendanceMethod == AttendanceMethod.E_FULL.ToString()) { #region gradeCfg.AttendanceMethod = E_FULL if (shiftByProfile1 != null && shiftByProfile1.IsNightShift == true) { if (shiftByProfile1.NightTimeEnd != null && shiftByProfile1.NightTimeStart != null) { DateTime dateStartNightShift = shiftByProfile1.NightTimeStart.Value; DateTime dateEndNightShift = shiftByProfile1.NightTimeEnd.Value; if (dateStartNightShift > dateEndNightShift) { dateEndNightShift = dateEndNightShift.AddDays(1); } attendanceTableItem.NightShiftHours = dateEndNightShift.Subtract(dateStartNightShift).TotalHours; } else { attendanceTableItem.NightShiftHours = shiftByProfile1.WorkHours ?? 0; } } else if (shiftByProfile2 != null && shiftByProfile2.IsNightShift == true) { if (shiftByProfile2.NightTimeEnd != null && shiftByProfile2.NightTimeStart != null) { DateTime dateStartNightShift = shiftByProfile2.NightTimeStart.Value; DateTime dateEndNightShift = shiftByProfile2.NightTimeEnd.Value; if (dateStartNightShift > dateEndNightShift) { dateEndNightShift = dateEndNightShift.AddDays(1); } attendanceTableItem.NightShiftHours = dateEndNightShift.Subtract(dateStartNightShift).TotalHours; } else { attendanceTableItem.NightShiftHours = shiftByProfile2.WorkHours ?? 0; } } if ((shiftByProfile1 != null && shiftByProfile1.IsNightShift == true) || shiftByProfile2 != null && shiftByProfile2.IsNightShift == true) { if (attendanceTableItem.Cat_LeaveDayType != null) { double hourLeave = attendanceTableItem.LeaveHours + attendanceTableItem.PaidLeaveHours + attendanceTableItem.ExtraLeaveHours; attendanceTableItem.NightShiftHours = attendanceTableItem.NightShiftHours - hourLeave; if (attendanceTableItem.NightShiftHours < 0) { attendanceTableItem.NightShiftHours = 0; } } } if (attendanceTableItem.IsHoliday) { attendanceTableItem.LeaveHours = attendanceTableItem.PaidLeaveHours = 0; attendanceTableItem.WorkPaidHours = attendanceTableItem.LateEarlyMinutes = 0; attendanceTableItem.UnpaidLeaveHours = attendanceTableItem.AvailableHours; bool isNoLongerWorking = false; if ((profile.DateHire.HasValue && attendanceTableItem.WorkDate < profile.DateHire.Value) || (profile.DateQuit.HasValue && attendanceTableItem.WorkDate >= profile.DateQuit.Value)) { isNoLongerWorking = true; } if (!attendanceTableItem.IsHavingPregTreatment && !isNoLongerWorking && (notAutoRegHolidayLeave == null || notAutoRegHolidayLeave.Value1 != bool.TrueString)) { attendanceTableItem.WorkPaidHours = 0; attendanceTableItem.LateEarlyMinutes = 0; attendanceTableItem.UnpaidLeaveHours = 0; attendanceTableItem.LeaveHours = attendanceTableItem.AvailableHours; attendanceTableItem.PaidLeaveHours = attendanceTableItem.AvailableHours; attendanceTableItem.Cat_LeaveDayType = listLeaveDayType.Where(d => d.Code == LeavedayTypeCode.HLD.ToString()).FirstOrDefault(); } } attendanceTableItem.WorkHours = 0;//Thời gian làm việc = 0 attendanceTableItem.WorkPaidHours = attendanceTableItem.AvailableHours - attendanceTableItem.UnpaidLeaveHours - attendanceTableItem.PaidLeaveHours; #endregion } #region Trường hợp tăng ca trong ngày lễ if (attendanceTableItem.Cat_LeaveDayType != null && attendanceTableItem.Cat_LeaveDayType.Code == LeavedayTypeCode.HLD.ToString() && (otholidayscompute400 == null || otholidayscompute400.Value1 != bool.TrueString) && attendanceTableItem.Cat_OvertimeType != null) { var totalOvertimeHours = attendanceTableItem.OvertimeHours + attendanceTableItem.ExtraOvertimeHours + attendanceTableItem.ExtraOvertimeHours2 + attendanceTableItem.ExtraOvertimeHours3; if (gradeCfg.EDType == PayrollComputeMethod.E_SUBTRACT.ToString()) { if (attendanceTableItem.AvailableHours > totalOvertimeHours) { attendanceTableItem.LeaveHours = attendanceTableItem.AvailableHours - totalOvertimeHours; attendanceTableItem.ExtraLeaveHours = totalOvertimeHours; attendanceTableItem.PaidLeaveHours = attendanceTableItem.LeaveHours; attendanceTableItem.Cat_LeaveDayType1 = null; } else { attendanceTableItem.Cat_LeaveDayType = null; attendanceTableItem.LeaveHours = attendanceTableItem.AvailableHours; attendanceTableItem.PaidLeaveHours = 0; } } else { if (attendanceTableItem.AvailableHours >= totalOvertimeHours) { attendanceTableItem.LeaveHours = attendanceTableItem.PaidLeaveHours = attendanceTableItem.AvailableHours - totalOvertimeHours; } else { attendanceTableItem.LeaveHours = attendanceTableItem.PaidLeaveHours = 0; } } attendanceTableItem.WorkPaidHours = 0; } #endregion } unitOfWork.AddObject(typeof(Att_AttendanceTableItem), attendanceTableItem); } #endregion #region Tính toán lại phép năm và phép ốm trong kỳ var annualLeaveDetail = listAnnualDetailByProfile.Where(d => d.Type == AnnualLeaveDetailType.E_ANNUAL_LEAVE.ToString()).FirstOrDefault(); var sickLeaveDetail = listAnnualDetailByProfile.Where(d => d.Type == AnnualLeaveDetailType.E_SICK_LEAVE.ToString()).FirstOrDefault(); var preAttendanceTable = listPreAttendanceTableByProfile.Where(d => d.ProfileID == profileID).FirstOrDefault(); attendanceTable.AnlDayTaken = anlDayTaken; attendanceTable.SickDayTaken = sickDayTaken; if (preAttendanceTable != null) { if (annualLeaveDetail != null && annualLeaveDetail.MonthYear.HasValue && annualLeaveDetail.MonthYear.Value.Date == monthYear.Date) { attendanceTable.AnlDayAdjacent = anlDayTaken; } else { //VinhTran - 0030581 - AnlDayAdjacent là số ngày đã nghỉ tính tới đầu tháng đang tính công attendanceTable.AnlDayAdjacent = preAttendanceTable.AnlDayAdjacent.GetDouble() + anlDayTaken; } if (sickLeaveDetail != null && sickLeaveDetail.MonthYear.HasValue && sickLeaveDetail.MonthYear.Value.Date == monthYear.Date) { attendanceTable.SickDayAdjacent = sickDayTaken; } else { //VinhTran - 0030581 - AnlDayAdjacent là số ngày đã nghỉ tính tới đầu tháng đang tính công attendanceTable.SickDayAdjacent = preAttendanceTable.SickDayAdjacent.GetDouble() + sickDayTaken; } } else { attendanceTable.AnlDayAdjacent = anlDayTaken; attendanceTable.SickDayAdjacent = sickDayTaken; } if (annualLeaveDetail != null && annualLeaveDetail.MonthYear.HasValue) { attendanceTable.TotalAnlDayAvailable = annualLeaveDetail.Available.Get_Double(); attendanceTable.AnlDayAvailable = attendanceTable.TotalAnlDayAvailable.GetDouble() - attendanceTable.AnlDayAdjacent.GetDouble(); } else if (preAttendanceTable != null) { attendanceTable.AnlDayAvailable = preAttendanceTable.AnlDayAvailable - attendanceTable.AnlDayTaken; } if (sickLeaveDetail != null && sickLeaveDetail.MonthYear.HasValue) { attendanceTable.TotalSickDayAvailable = sickLeaveDetail.Available.Get_Double(); attendanceTable.SickDayAvailable = attendanceTable.TotalSickDayAvailable.GetDouble() - attendanceTable.SickDayAdjacent.GetDouble(); } else if (preAttendanceTable != null) { //tháng 7: còn 13, liền kề 1, hiện tại 1 => tháng 8: liền kề 2, hiện tại 1, còn 12 attendanceTable.SickDayAvailable = preAttendanceTable.SickDayAvailable.GetDouble() - attendanceTable.SickDayTaken.GetDouble(); } #endregion #region Tính toán lại phép bù trong kỳ foreach (var leaveDayByProfile in listLeaveDayByProfile) { if (leaveDayByProfile != null) { var dateStart = leaveDayByProfile.DateStart; var dateEnd = leaveDayByProfile.DateEnd; if (leaveDayByProfile.DateOvertimeOff.HasValue) { dateStart = leaveDayByProfile.DateOvertimeOff.Value; dateEnd = leaveDayByProfile.DateOvertimeOff.Value; } for (DateTime date = dateStart.Date; date <= dateEnd; date = date.AddDays(1)) { double leaveHours = 0D; double leaveDays = 0D; double standardWorkHours = 0; var leaveDayType = listLeaveDayType.Where(d => d.ID == leaveDayByProfile.LeaveDayTypeID).FirstOrDefault(); var attendanceTableItem = attendanceTable.Att_AttendanceTableItem.Where(d => d.WorkDate == date).FirstOrDefault(); if (attendanceTableItem!=null) standardWorkHours = attendanceTableItem.udStandardWorkHours; if (leaveDayByProfile.DurationType == LeaveDayDurationType.E_FULLSHIFT.ToString()) { //Lấy giờ nghỉ của ngày đang xét dựa vào ca làm việc leaveHours = standardWorkHours; leaveDays = 1;//Nghỉ full shift } else { leaveHours = leaveDayByProfile.LeaveHours.GetDouble(); leaveDays = leaveDayByProfile.LeaveDays.GetDouble(); } leaveHours = leaveHours > standardWorkHours ? standardWorkHours : leaveHours; leaveDays = leaveDays > 1 ? 1 : leaveDays;//Tối đa là nghỉ 1 ngày if (leaveDayType != null && leaveDays > 0) { if (leaveDayType.Code == LeavedayTypeCode.CPS.ToString() || leaveDayType.Code == LeavedayTypeCode.OCPS.ToString()) { if ((leaveDayByProfile.DateOvertimeOff.HasValue && leaveDayByProfile.DateStart > attendanceTo) || date > attendanceTo) { //Nghỉ CO tháng sau => coEndPeriod coEndPeriod += leaveDays; } else if (date >= attendanceFrom && date <= attendanceTo) { //Nghỉ CO trong tháng => coBeginPeriod coBeginPeriod += leaveDays; } } } } } } attendanceTable.COBeginPeriod = coBeginPeriod; attendanceTable.COEndPeriod = coEndPeriod; #endregion #region Cập nhật Att_AttendanceTable sau khi tính xong #region Sum type HDTJob var _type4 = attendanceTable.Att_AttendanceTableItem.Where(d => d.HDTJobType == EnumDropDown.HDTJobType.E_TYPE4.ToString()); var _type5 = attendanceTable.Att_AttendanceTableItem.Where(d => d.HDTJobType == EnumDropDown.HDTJobType.E_TYPE5.ToString()); attendanceTable.HDTJobType1 = EnumDropDown.HDTJobType.E_TYPE4.ToString(); attendanceTable.HDTJobType2 = EnumDropDown.HDTJobType.E_TYPE5.ToString(); attendanceTable.HDTJobDayCount1 = _type4 != null ? _type4.Count() : 0; attendanceTable.HDTJobDayCount2 = _type5 != null ? _type5.Count() : 0; #endregion attendanceTable.RealWorkDayCount = attendanceTable.Att_AttendanceTableItem.Where(d => d.udWorkHours > 0).Sum(d => (d.WorkPaidHours + d.LateEarlyMinutes / 60.0) / (d.udStandardWorkHours * d.udStandardWorkHours / d.udWorkHours)); attendanceTable.NightShiftHours = attendanceTable.Att_AttendanceTableItem.Where(d => d.DutyCode == DutyCode.E_ON.ToString()).Sum(d => d.NightShiftHours); attendanceTable.OTNightShiftHours = attendanceTable.Att_AttendanceTableItem.Where(d => d.DutyCode == DutyCode.E_ON.ToString()).Sum(d => d.OTNightShiftHours.GetDouble()); attendanceTable.LateEarlyDeductionHours += attendanceTable.Att_AttendanceTableItem.Sum(d => d.LateEarlyMinutes) / 60.0; attendanceTable.UnPaidLeave = attendanceTable.Att_AttendanceTableItem.Sum(d => d.UnpaidLeaveDays.GetDouble()); attendanceTable.PaidLeaveDays = attendanceTable.Att_AttendanceTableItem.Sum(d => d.PaidLeaveDays.GetDouble()); //Tính nghỉ bù attendanceTable.COBeginPeriod = coBeginPeriod; attendanceTable.COEndPeriod = coEndPeriod; //Tính số ngày công chuẩn int weekendDaysCount = attendanceTable.Att_AttendanceTableItem.Where(d => d.IsHoliday).Count(); attendanceTable.StdWorkDayCount = GetStandardWorkDays(gradeCfg, listHoliday, listShift, listMonthShiftID, monthYear, attendanceFrom, attendanceTo); attendanceTable.StdWorkDayOTCount = GetOTStandardWorkDays(weekendDaysCount, gradeCfg, listHoliday, listShift, listMonthShiftID, monthYear, attendanceFrom, attendanceTo); //Tổng số ngày được trả lương của nhân viên đang xét => ngày thực tế attendanceTable.PaidWorkDayCount = attendanceTable.RealWorkDayCount; if (gradeCfg.EDType == PayrollComputeMethod.E_SUBTRACT.ToString()) { //Số ngày công thực tế + số ngày nghỉ hưởng lương Double workAndPaidLeaveDays = attendanceTable.RealWorkDayCount; double unHiredDays = 0; double terminatedDays = 0; if (attendanceTable.Att_AttendanceTableItem.Count() > 0) { workAndPaidLeaveDays += attendanceTable.Att_AttendanceTableItem.Sum(d => d.PaidLeaveHours / d.udStandardWorkHours); } //Nếu nhân viên không vào làm hoặc nghỉ việc trong tháng và số ngày công thực tế + số ngày nghỉ hưởng lương > số ngày công tối thiểu if (((profile.DateHire.HasValue && profile.DateHire.Value.Date < attendanceFrom) || workAndPaidLeaveDays > attendanceTable.StdWorkDayCount) && ((!profile.DateQuit.HasValue || profile.DateQuit.Value.Date > attendanceTo) || workAndPaidLeaveDays > attendanceTable.StdWorkDayCount) && workAndPaidLeaveDays >= gradeCfg.MinWorkDay.Value) { //Tổng số ngày nghỉ loại 1 và loại 2 khi có trường hợp 1 ngày mà nghỉ 2 loại Double totalLeaveDays = attendanceTable.Att_AttendanceTableItem.Sum(d => (d.LeaveHours + d.ExtraLeaveHours) / d.udStandardWorkHours); if (isMidCutOffDay) { totalLeaveDays = attendanceTable.Att_AttendanceTableItem.Where(d => d.WorkDate <= midCutOffDate) .Sum(d => d.LeaveHours + d.ExtraLeaveHours / d.udStandardWorkHours);//Số ngày nghỉ không ứng công } //Cộng thêm số ngày chưa làm việc - trường hợp làm nửa ca totalLeaveDays += attendanceTable.Att_AttendanceTableItem.Sum(d => d.udNotHiredHours / d.udStandardWorkHours); if (profile.DateQuit.HasValue) { //Cộng thêm số ngày đã nghỉ việc totalLeaveDays += attendanceTable.Att_AttendanceTableItem.Sum(d => d.udTerminatedHours / d.udStandardWorkHours); } //Tính số ngày công tính lương = số ngày công chuẩn - tổng số ngày nghỉ attendanceTable.PaidWorkDayCount = attendanceTable.StdWorkDayCount - totalLeaveDays; if (attendanceTable.PaidWorkDayCount < 0) { attendanceTable.PaidWorkDayCount = 0; } } else if ((gradeCfg.IsApplySubSalaryNewQuitEmp.GetBoolean() && workAndPaidLeaveDays >= gradeCfg.MinWorkDayNewQuitEmp.GetDouble()) && ((profile.DateHire.HasValue && profile.DateHire.Value.Date >= attendanceFrom) || (profile.DateQuit.HasValue && profile.DateQuit.Value.Date <= attendanceTo))) { Double totalLeaveDays = attendanceTable.Att_AttendanceTableItem.Sum(it => (it.LeaveHours + it.ExtraLeaveHours) / it.udStandardWorkHours); Double DayNonShiftInUnEmployeeTime = 0;//Thời gian của nhân viên không có lịch làm việc trước khi vào công ty hoặc là sau khi ra khỏi công ty trong tháng if (profile.DateHire.HasValue && profile.DateHire.Value > attendanceFrom) { unHiredDays = profile.DateHire.Value.Subtract(attendanceFrom).Days; for (DateTime DateCheck = attendanceFrom; DateCheck < profile.DateHire.Value; DateCheck = DateCheck.AddDays(1)) { if (listMonthShiftID == null || !listMonthShiftID.Any(d => d.Key.Date == DateCheck.Date && d.Value != null)) { DayNonShiftInUnEmployeeTime++; } } } if (profile.DateQuit.HasValue && profile.DateQuit.Value < attendanceTo) { terminatedDays = attendanceTo.Subtract(profile.DateQuit.Value).Days + 1; for (DateTime DateCheck = profile.DateQuit.Value; DateCheck < attendanceTo; DateCheck = DateCheck.AddDays(1)) { if (listMonthShiftID == null || !listMonthShiftID.Any(d => d.Key.Date == DateCheck.Date && d.Value != null)) { DayNonShiftInUnEmployeeTime++; } } } Double paidWorkDay = attendanceTable.StdWorkDayCount - totalLeaveDays; paidWorkDay = paidWorkDay - (unHiredDays + terminatedDays - DayNonShiftInUnEmployeeTime) * gradeCfg.RateUneven.GetDouble(); attendanceTable.PaidWorkDayCount = paidWorkDay; } } #region Tính tổng thời gian theo từng loại ngày nghỉ và loại làm thêm TotalGroupByLeaveDayType(attendanceTable, attendanceTo); TotalGroupByOvertimeType(attendanceTable, attendanceTo); #endregion #region Tính tổng thời gian và làm tròn attendanceTable.TotalPaidWorkDayCount = attendanceTable.PaidWorkDayCount; attendanceTable.TotalRealWorkDayCount = attendanceTable.RealWorkDayCount; //Cấu hình làm tròng trễ sớm theo tháng if (gradeCfg != null && gradeCfg.IsLateEarlyFirstLastShiftRound == true) { attendanceTable.LateEarlyDeductionHours = Att_AttendanceLib.RoundLateEarlyMinutes(listLateEarlyRule.Where(d => d.GradeCfgID == gradeCfg.ID).ToList(), Convert.ToInt32(attendanceTable.LateEarlyDeductionHours * 60)) / 60; } #endregion #endregion return attendanceTable != null ? 1 : 0; }
public DataTable GetReportExceptionDataAdvList(Att_ReportExceptionDataAdv_ConditionEntity condition, string userExport, string UserLogin) { DataTable viewData = new DataTable(); viewData = getSchema_ExceptionDataAdv(); using (var context = new VnrHrmDataContext()) { var unitOfWork = (IUnitOfWork)(new UnitOfWork(context)); var repoAtt_Grade = new CustomBaseRepository<Att_Grade>(unitOfWork); var repoCat_DayOff = new CustomBaseRepository<Cat_DayOff>(unitOfWork); var repoCat_GradeAttendance = new CustomBaseRepository<Cat_GradeAttendance>(unitOfWork); var repoCat_Position = new CustomBaseRepository<Cat_Position>(unitOfWork); var repoCat_JobTitle = new CustomBaseRepository<Cat_JobTitle>(unitOfWork); var repoCat_OrgStructure = new CustomBaseRepository<Cat_OrgStructure>(unitOfWork); DateTime DateStart = condition.DateStart.Value; DateTime DateEnd = condition.DateEnd.Value; //DateTime start = Common.ConvertStringToDateTime(TextBox_DateStart.Text, ApplicationSettings.ShortDateTimeFormat); //DateTime end = Common.ConvertStringToDateTime(TextBox_DateEnd.Text, ApplicationSettings.ShortDateTimeFormat); var baseService = new BaseService(); var status = string.Empty; List<Hre_ProfileEntity> lstPro = new List<Hre_ProfileEntity>(); List<object> lstObj = new List<object>(); lstObj.Add(condition.OrgStructureID); lstObj.Add(null); lstObj.Add(null); lstPro = baseService.GetData<Hre_ProfileEntity>(lstObj, ConstantSql.hrm_hr_sp_get_ProfileIdsByOrg, UserLogin, ref status); List<Att_Workday> listInOut = new List<Att_Workday>(); List<Hre_Profile> listProfile = LoadProfileStatus(lstPro, condition.StatusEmployee, DateStart, DateEnd); //if (MultiCheckTreeControl1.SelectedValues.Count > 0) // listProfile = listProfile.Where(s => s.OrgStructureID != null && MultiCheckTreeControl1.SelectedValues.Contains(s.OrgStructureID.Value)).ToList(); listProfile = listProfile.OrderBy(p => p.OrgStructureID).ToList(); List<Guid> lstProfileID = Hre_ProfileServices.GetProfileIdList(listProfile); DateTime dateStart_First = DateStart.Date; DateTime DateEnd_Last = DateEnd.Date.AddDays(1).AddMinutes(-1); #region Hàm getdata bằng Store var listPosition = repoCat_Position.FindBy(s => s.Code != null).ToList(); var listJobTitle = repoCat_JobTitle.FindBy(s => s.Code != null).ToList(); var listOrgStructure = repoCat_OrgStructure.FindBy(s => s.Code != null).ToList(); List<object> lst2ParamNull = new List<object>(); lst2ParamNull.Add(condition.OrgStructureID); lst2ParamNull.Add(null); List<object> lst3ParamNull = new List<object>(); lst3ParamNull.Add(null); lst3ParamNull.Add(null); lst3ParamNull.Add(null); List<object> lst4Param = new List<object>(); lst4Param.Add(condition.OrgStructureID); lst4Param.Add(DateStart); lst4Param.Add(DateEnd); lst4Param.Add(RosterStatus.E_APPROVED.ToString()); List<object> lst3ParamSE = new List<object>(); lst3ParamSE.Add(condition.OrgStructureID); lst3ParamSE.Add(dateStart_First); lst3ParamSE.Add(DateEnd_Last); var dataAtt_LeaveDay = GetData<Att_LeaveDay>(lst3ParamNull, ConstantSql.hrm_att_getdata_LeaveDay, UserLogin, ref status).ToList(); var dataAtt_Roster_Inner = GetData<Att_Roster>(lst4Param, ConstantSql.hrm_att_getdata_Roster_Inner, UserLogin, ref status).ToList(); var dataAtt_TAMScanLog = GetData<Att_TAMScanLog>(lst3ParamSE, ConstantSql.hrm_att_getdata_TamScanLog, UserLogin, ref status).ToList(); var dataAtt_Workday = GetData<Att_Workday>(lst3ParamSE, ConstantSql.hrm_att_getdata_Workday, UserLogin, ref status).ToList(); var dataHre_WorkHistory = GetData<Hre_WorkHistory>(lst2ParamNull, ConstantSql.hrm_hre_getdata_WorkHistory, UserLogin, ref status).ToList(); #endregion if (condition.NoScan) { //List<Att_LeaveDay> leaveDays = EntityService.GetEntityList<Att_LeaveDay>(s => DateStart.Date <= s.DateStart.Date && s.DateEnd.Date <= DateEnd.Date); //triet fix câu trên //List<Att_LeaveDay> leaveDays = EntityService.GetEntityList<Att_LeaveDay>(s => s.DateStart >= dateStart_First && s.DateEnd <= DateEnd_Last); List<Att_LeaveDay> leaveDays = dataAtt_LeaveDay.Where(s => s.DateStart <= DateEnd_Last && s.DateEnd >= dateStart_First).ToList(); if (condition.NoShift) { #region NoShift //trietmai 20121110 0015629 //Logic: trường hợp người ta đăng ký Roster là E_TIME_OFF thì loại bỏ ra khỏi list //vs dk là cùng người cùng khoảng thời gian đăng ký nghỉ v.v string E_APPROVED = RosterStatus.E_APPROVED.ToString(); string E_TIME_OFF = RosterType.E_TIME_OFF.ToString(); //List<Att_Roster> RosterTimeOff = EntityService.GetEntityList<Att_Roster>(GuidContext, LoginUserID.Value, // m => lstProfileID.Contains(m.ProfileID) // && m.DateStart <= DateEnd // && m.DateEnd >= DateStart // && m.Status == E_APPROVED // && m.Type == E_TIME_OFF // ); List<Att_Roster> RosterTimeOff = dataAtt_Roster_Inner .Where(m => lstProfileID.Contains(m.ProfileID) && m.Type == E_TIME_OFF).ToList(); //List<Att_TAMScanLog> lstTamAtt = EntityService.GetEntityList<Att_TAMScanLog>(prop => prop.TimeLog <= DateEnd_Last && prop.TimeLog >= DateStart).ToList(); List<Att_TAMScanLog> lstTamAtt = dataAtt_TAMScanLog.Where(prop => prop.TimeLog <= DateEnd_Last && prop.TimeLog >= DateStart).ToList(); foreach (Hre_Profile profile in listProfile) { for (DateTime idx = DateStart; idx <= DateEnd; idx = idx.AddDays(1)) { var haveTimeOff = RosterTimeOff.Where(m => m.ProfileID == profile.ID && m.DateStart <= idx && m.DateEnd >= idx ).ToList(); if (haveTimeOff.Count != 0) { continue; } List<Att_TAMScanLog> lstRq = lstTamAtt.Where(prop => prop.CardCode == profile.CodeAttendance && idx.Day == prop.TimeLog.Value.Day).ToList(); if (lstRq.Count == 0) { DataRow dr = viewData.NewRow(); Att_LeaveDay leaveDay = leaveDays.Where(s => s.ProfileID == profile.ID && s.DateStart.Date <= idx.Date && idx.Date <= s.DateEnd.Date).FirstOrDefault(); if (leaveDay != null) { dr[Att_ReportExceptionDataAdvEntity.FieldNames.OvertimeTypeName] = leaveDay.Comment; dr[Att_ReportExceptionDataAdvEntity.FieldNames.LeaveDayTypeName] = leaveDay.Cat_LeaveDayType; } dr[Att_ReportExceptionDataAdvEntity.FieldNames.ProfileName] = profile.ProfileName.ToString(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.CodeEmp] = profile.CodeEmp; if (profile.PositionID != null && profile.PositionID != Guid.Empty) { var pos = listPosition.Where(s => s.ID == profile.PositionID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.PositionCode] = pos.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.PositionName] = pos.PositionName; } if (profile.JobTitleID != null && profile.JobTitleID != Guid.Empty) { var jos = listJobTitle.Where(s => s.ID == profile.JobTitleID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.JobTitleCode] = jos.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.JobTitleName] = jos.JobTitleName; } if (profile.OrgStructureID != null && profile.OrgStructureID != Guid.Empty) { var org = listOrgStructure.Where(s => s.ID == profile.OrgStructureID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.OrgStructureCode] = org.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.OrgStructureName] = org.OrgStructureName; } dr[Att_ReportExceptionDataAdvEntity.FieldNames.udDateOut] = idx; viewData.Rows.Add(dr); } } } //ListControl1.DataSource = viewData; return viewData; #endregion } else { #region Noscan List<Cat_DayOff> lstHoliday = repoCat_DayOff.FindBy(s => s.IsDelete == null).ToList(); //LamLe - 20120829 - tai sao lai loai truong hop "Nghỉ theo phân công"Neu nghi thi khong load du lieu len //String RosterTypeAbsent = RosterType.E_TIME_OFF.ToString(); List<Att_Roster> lstRoster = dataAtt_Roster_Inner.Where(prop => prop.DateStart <= DateEnd && prop.DateEnd >= DateStart).ToList(); //&& prop.Type != RosterTypeAbsent); List<Att_Workday> lstInOutAll = dataAtt_Workday.Where(wd => lstProfileID.Contains(wd.ProfileID)).OrderBy(wd => wd.ProfileID).ToList(); DateTime _dateStart = DateStart; DateTime _dateEnd = DateEnd.AddDays(1).AddMinutes(-1); List<Att_LeaveDay> lstLeaveDayAll = dataAtt_LeaveDay.Where(prop => prop.DateStart <= _dateEnd && prop.DateEnd >= _dateStart).ToList(); //GradeDAO gradeDAO = new GradeDAO(); List<Att_Grade> lstGradeAll = Att_GradeServices.getAllGrade(lstProfileID, DateEnd); List<Hre_WorkHistory> lstWHistory = dataHre_WorkHistory.Where(s => lstProfileID.Contains(s.ProfileID)).ToList(); List<Guid> lstProfileIDs = listProfile.Select(m => m.ID).ToList(); List<Att_Roster> lstRosterTypeGroup = new List<Att_Roster>(); List<Att_RosterGroup> lstRosterGroup = new List<Att_RosterGroup>(); Att_RosterServices.GetRosterGroup(lstProfileIDs, DateStart, DateEnd, out lstRosterTypeGroup, out lstRosterGroup); foreach (Hre_Profile profile in listProfile) { List<Att_LeaveDay> lstProfileLeaveDay = lstLeaveDayAll.Where(ld => ld.ProfileID == profile.ID).ToList(); List<Att_Workday> lstProfileInOut = lstInOutAll.Where(ld => ld.ProfileID == profile.ID).ToList(); Att_Grade grade = lstGradeAll.Where(grad => grad.ProfileID == profile.ID).FirstOrDefault(); List<Att_Roster> lstProfileRoster = lstRoster.Where(rt => rt.ProfileID == profile.ID).ToList(); List<Hre_WorkHistory> lstWHistoryPro = lstWHistory.Where(wh => wh.ProfileID == profile.ID).ToList(); Cat_GradeAttendance gradeCfg = grade == null ? null : grade.Cat_GradeAttendance; Hashtable htRoster = Att_RosterServices.GetRosterTable(profile, lstProfileRoster, lstWHistoryPro, gradeCfg, DateStart, DateEnd, lstRosterGroup, lstRosterTypeGroup); //string[] strDepartment = GradeCfgDAO.getLinkDepartment(ListCacheOrgStructure, profile.Cat_OrgStructure); //profile.udLinkDepartmentName = strDepartment[0]; if (grade == null) continue; if (grade.Cat_GradeAttendance.AttendanceMethod != AttendanceMethod.E_TAM.ToString()) continue; for (DateTime idx = DateStart; idx <= DateEnd ; idx = idx.AddDays(1)) { //In-Out if (lstHoliday.Where(hol => hol.DateOff == idx).Count() > 0) continue; if (!Att_AttendanceServices.IsWorkDay(grade.Cat_GradeAttendance, htRoster, lstHoliday, idx) || idx < profile.DateHire || idx >= profile.DateQuit) continue; List<Att_Workday> lstDateProfileInOut = lstProfileInOut.Where(inout => inout.WorkDate == idx).ToList(); //ko di lam, ko quet the if (lstDateProfileInOut.Count <= 0) { //ko thong bao nghi doi voi nhung nhan vien dang ki nghi // neu chon vao checkbox danh sach nghi thi hien ra if (lstProfileLeaveDay.Where(ld => ld.ProfileID == profile.ID && ld.DateStart.Date <= idx && ld.DateEnd.Date >= idx).Count() <= 0 || condition.ShowListLeaveDay == true) { //exceptionData = SetExceptionData(null, profile, null, idx); //exceptionData.DataType = LanguageManager.GetString(ClassNames.Att_Workday); //exceptionData.Exception = LanguageManager.GetString(Messages.MissingInOut); //exceptionData.Description = "? - ?"; Att_Workday _inOut = new Att_Workday(); _inOut.Hre_Profile = profile; _inOut.ID = Guid.NewGuid(); _inOut.WorkDate = idx; //_inOut.udIsNew = true; _inOut.InTime1 = idx; _inOut.OutTime1 = idx; listInOut.Add(_inOut); } } } } #endregion } } else if (condition.DifferenceMoreRoster) { #region Difference List<Att_Workday> lstInOutAll = dataAtt_Workday.Where(wd => lstProfileID.Contains(wd.ProfileID)).OrderBy(wd => wd.ProfileID).ToList(); foreach (Att_Workday InOut in lstInOutAll) { if (InOut.InTime1 != null && InOut.OutTime1 != null) { if (condition.More == null) condition.More = 0.0; if (condition.More < Att_AttendanceServices.GetShiftRosterShiftInOutHour(InOut, InOut.Cat_Shift)) { //Att_ExceptionData exceptionData = SetExceptionData(InOut, InOut.Hre_Profile // , InOut.Cat_Shift, InOut.WorkDate); //exceptionData.DataType = LanguageManager.GetString(ClassNames.Att_Workday); //exceptionData.Exception = LanguageManager.GetString(Messages.DifferenceShiftRosterAndInOut) + " " + txt_Difference.Text + " " + LanguageManager.GetString(Messages.Hour); //String desc = "InOut: "; //desc += InOut.InTime.Value.ToString(ApplicationSettings.TimeShortFormat); //desc += " - "; //desc += InOut.OutTime.Value.ToString(ApplicationSettings.TimeShortFormat); //desc += " / Shift: "; //desc += InOut.Cat_Shift.ShiftName; //exceptionData.Description = desc; listInOut.Add(InOut); } } } #endregion } else if (condition.LessHours) { if (condition.Less == null) condition.Less = 0.0; #region LessHours Double minHrs = 0; //Get Hours try { minHrs = condition.Less.Value; } catch (System.Exception ex) { //Common.MessageBoxs("Error", InstanceNames.InvalidParameter_Hour // , Ext.Net.MessageBox.Icon.ERROR, txt_LessHours.ClientID); } List<Att_Workday> lstInOutAll = dataAtt_Workday.Where(wd => lstProfileID.Contains(wd.ProfileID) && wd.InTime1.HasValue && wd.OutTime1.HasValue) .OrderBy(wd => wd.ProfileID).ToList(); foreach (Att_Workday InOut in lstInOutAll) { Double workHours = Att_AttendanceServices.GetInOutWorkingHour(InOut, InOut.Cat_Shift); if (minHrs > workHours) { //Att_ExceptionData exceptionData = SetExceptionData(InOut, InOut.Hre_Profile // , InOut.Cat_Shift, InOut.WorkDate); //exceptionData.DataType = LanguageManager.GetString(ClassNames.Att_Workday); //exceptionData.Exception = LanguageManager.GetString(Messages.WorkingHoursLess) + " " + txt_LessHours.Text + " " + LanguageManager.GetString(Messages.Hour); //String desc = ""; //desc = InOut.InTime.Value.ToString(ApplicationSettings.TimeShortFormat); //desc += " - "; //desc += InOut.OutTime.Value.ToString(ApplicationSettings.TimeShortFormat); //exceptionData.Description = desc; listInOut.Add(InOut); } } #endregion } else if (condition.MissInOut) { List<Att_Workday> lstInOutAll = dataAtt_Workday.Where(wd => lstProfileID.Contains(wd.ProfileID) && ((wd.InTime1.HasValue && !wd.OutTime2.HasValue) || (!wd.InTime1.HasValue && wd.OutTime2.HasValue))) .OrderBy(wd => wd.ProfileID).ToList(); // SonNgo List<Att_Grade> lstGradeAll = Att_GradeServices.getAllGrade(lstProfileID, DateEnd); foreach (Att_Workday InOut in lstInOutAll) { if (InOut.InTime1 == null && InOut.OutTime1 == null) { listInOut.Add(InOut); } else if (InOut.InTime1 == null || InOut.OutTime1 == null) { #region don't use //Att_ExceptionData exceptionData = SetExceptionData(InOut, InOut.Hre_Profile, InOut.Cat_Shift, InOut.WorkDate); //exceptionData.DataType = LanguageManager.GetString(ClassNames.Att_Workday); //exceptionData.Exception = LanguageManager.GetString(Messages.MissingInOut); //String desc = ""; //if (InOut.InTime != null) // desc = InOut.InTime.Value.ToString(ApplicationSettings.TimeShortFormat); //else // desc = "?"; //desc += " - "; //if (InOut.OutTime != null) // desc += InOut.OutTime.Value.ToString(ApplicationSettings.TimeShortFormat); //else // desc += "?"; //exceptionData.Description = desc; #endregion // SonNgo - Neu che do luong khong tru tre som thi khong can liet ke Att_Grade grade = lstGradeAll.Where(grad => grad.ProfileID == InOut.ProfileID).FirstOrDefault(); if (grade != null && condition.ExcludeManagerStaff == true && grade.Cat_GradeAttendance != null && grade.Cat_GradeAttendance.IsDeductInLateOutEarly != true) { continue; } listInOut.Add(InOut); } } } // ListControl1.GridColumnNames = lstColumns.ToArray(); //trietmai 20121110 List<Guid> lstProfileIDT = listInOut.Select(m => m.ProfileID).Distinct().ToList(); string E_APPROVEDT = RosterStatus.E_APPROVED.ToString(); string E_TIME_OFFT = RosterType.E_TIME_OFF.ToString(); List<Att_Roster> RosterTimeOffT = dataAtt_Roster_Inner .Where(m => lstProfileIDT.Contains(m.ProfileID) && m.DateStart <= DateEnd && m.DateEnd >= DateStart && m.Type == E_TIME_OFFT ).ToList(); var listRemoveTemp = listInOut.Where(m => RosterTimeOffT.Any(u => u.ProfileID == m.ProfileID && u.DateStart <= m.WorkDate && u.DateEnd >= m.WorkDate) ).ToList(); listInOut.RemoveRange(listRemoveTemp); //listInOut = listInOut.OrderBy(oi => oi.udCodeEmp).OrderBy(oi => oi.udDepartment).ToList(); listInOut = listInOut.OrderBy(w => w.WorkDate).OrderBy(oi => oi.ProfileID).ToList(); foreach (var item in listInOut) { DataRow dr = viewData.NewRow(); var profile = lstPro.Where(s => s.ID == item.ProfileID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.ProfileName] = profile.ProfileName.ToString(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.CodeEmp] = profile.CodeEmp; if (profile.PositionID != null && profile.PositionID != Guid.Empty) { var pos = listPosition.Where(s => s.ID == profile.PositionID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.PositionCode] = pos.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.PositionName] = pos.PositionName; } if (profile.JobTitleID != null && profile.JobTitleID != Guid.Empty) { var jos = listJobTitle.Where(s => s.ID == profile.JobTitleID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.JobTitleCode] = jos.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.JobTitleName] = jos.JobTitleName; } if (profile.OrgStructureID != null && profile.OrgStructureID != Guid.Empty) { var org = listOrgStructure.Where(s => s.ID == profile.OrgStructureID).FirstOrDefault(); dr[Att_ReportExceptionDataAdvEntity.FieldNames.OrgStructureCode] = org.Code; dr[Att_ReportExceptionDataAdvEntity.FieldNames.OrgStructureName] = org.OrgStructureName; } dr[Att_ReportExceptionDataAdvEntity.FieldNames.WorkDate] = item.WorkDate; if (item.InTime1 != null) { dr[Att_ReportExceptionDataAdvEntity.FieldNames.InTime] = item.InTime1; dr[Att_ReportExceptionDataAdvEntity.FieldNames.InHour] = item.InTime1.Value.ToString("HH:mm:ss", CultureInfo.InvariantCulture); } if (item.OutTime1 != null) { dr[Att_ReportExceptionDataAdvEntity.FieldNames.OutTime] = item.OutTime1; dr[Att_ReportExceptionDataAdvEntity.FieldNames.OutHour] = item.OutTime1.Value.ToString("HH:mm:ss", CultureInfo.InvariantCulture); } dr[Att_ReportExceptionDataAdvEntity.FieldNames.UserExport] = userExport; dr[Att_ReportExceptionDataAdvEntity.FieldNames.DateExport] = DateTime.Today; viewData.Rows.Add(dr); } //ListControl1.DataSource = listInOut; // ViewState.Add("Data", tb); return viewData; } }
private static int GetDuration(Att_Workday workdayByProfile, DateTime timeShiftStart, DateTime timeShiftEnd, DateTime timeShiftBreakIn, DateTime timeShiftBreakOut, double? DynamicHour) { int duration = 0; #region Xử lý vấn đề Ca có giờ linh động cho VE VietNam Esports (Thái phụ trách) - Tính giờ làm việc linh động theo Ca Làm Việc DateTime? In1 = workdayByProfile.InTime1; if (In1 != null && In1 > timeShiftStart && DynamicHour != null && DynamicHour > 0) { double HourLate = (In1.Value - timeShiftStart).TotalHours; if (HourLate > DynamicHour) { HourLate = DynamicHour.Value; } timeShiftEnd.AddHours(HourLate); } #endregion if (timeShiftStart >= timeShiftBreakIn && timeShiftStart <= timeShiftBreakOut) { duration += GetIntersectMinutes(workdayByProfile.InTime1, workdayByProfile.OutTime1, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime2, workdayByProfile.OutTime2, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime3, workdayByProfile.OutTime3, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime4, workdayByProfile.OutTime4, timeShiftBreakOut, timeShiftEnd); } else if (timeShiftEnd >= timeShiftBreakIn && timeShiftEnd <= timeShiftBreakOut) { duration += GetIntersectMinutes(workdayByProfile.InTime1, workdayByProfile.OutTime1, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime2, workdayByProfile.OutTime2, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime3, workdayByProfile.OutTime3, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime4, workdayByProfile.OutTime4, timeShiftStart, timeShiftBreakIn); } else if (timeShiftEnd > timeShiftBreakOut && timeShiftStart < timeShiftBreakIn) { duration += GetIntersectMinutes(workdayByProfile.InTime1, workdayByProfile.OutTime1, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime1, workdayByProfile.OutTime1, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime2, workdayByProfile.OutTime2, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime2, workdayByProfile.OutTime2, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime3, workdayByProfile.OutTime3, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime3, workdayByProfile.OutTime3, timeShiftBreakOut, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime4, workdayByProfile.OutTime4, timeShiftStart, timeShiftBreakIn); duration += GetIntersectMinutes(workdayByProfile.InTime4, workdayByProfile.OutTime4, timeShiftBreakOut, timeShiftEnd); } else { duration += GetIntersectMinutes(workdayByProfile.InTime1, workdayByProfile.OutTime1, timeShiftStart, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime2, workdayByProfile.OutTime2, timeShiftStart, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime3, workdayByProfile.OutTime3, timeShiftStart, timeShiftEnd); duration += GetIntersectMinutes(workdayByProfile.InTime4, workdayByProfile.OutTime4, timeShiftStart, timeShiftEnd); } return duration; }
public static Double GetShiftRosterShiftInOutHour(Att_Workday inout, Cat_Shift shift) { DateTime workdate = new DateTime(inout.WorkDate.Year, inout.WorkDate.Month, inout.WorkDate.Day , shift.InTime.Hour, shift.InTime.Minute, shift.InTime.Second); DateTime shiftStart = workdate; DateTime shiftEnd = workdate.AddHours(shift.CoOut); DateTime dateIn = inout.InTime1.Value; DateTime dateOut = inout.OutTime1.Value; Double _hrs = 0; if (dateIn.CompareTo(shiftStart) > 0) _hrs += dateIn.Subtract(shiftStart).TotalHours; else _hrs += shiftStart.Subtract(dateIn).TotalHours; if (dateOut.CompareTo(shiftEnd) > 0) _hrs += dateOut.Subtract(shiftEnd).TotalHours; else _hrs += shiftEnd.Subtract(dateOut).TotalHours; return _hrs; }
public static Double GetInOutWorkingHour(Att_Workday inout, Cat_Shift shift) { DateTime workdate = new DateTime(inout.WorkDate.Year, inout.WorkDate.Month, inout.WorkDate.Day , shift.InTime.Hour, shift.InTime.Minute, shift.InTime.Second); DateTime shiftStart = workdate; DateTime shiftEnd = workdate.AddHours(shift.CoOut); return GetIntersectAmount(inout.InTime1.Value, inout.OutTime1.Value, shiftStart, shiftEnd).TotalHours; }
private Att_Workday CreateWorkday(IUnitOfWork unitOfWork, DateTime date, Hre_ProfileEntity profile, WorkdayConfig inOutConfig, List<Cat_DayOffEntity> listHoliday, List<Att_Workday> listWorkday, Att_Workday workday, bool isFromShift2, Guid? shiftID, Cat_Shift shiftInfo, List<Cat_Shift> listShift, Dictionary<DateTime, List<Guid?>> listMonthShifts, out Guid? actualShiftID, List<Att_TAMScanLogEntity> listTamScanLogByCardCode, List<Att_TAMScanLogEntity> listTamScanLogByCardCodeUnchecked) { #region Trường hợp có lịch làm việc #region Kiểm tra dữ liệu quẹt theo theo ngày (ca) var listTamScanLogByShift = GetTamScanLogByShift(date, listShift, shiftID, listMonthShifts, listTamScanLogByCardCodeUnchecked.ToArray()); //Checked = true để không tự detect shift cho nó listTamScanLogByShift.ForEach(d => d.Checked = true); actualShiftID = null; if (workday == null) { workday = new Att_Workday(); unitOfWork.AddObject(typeof(Att_Workday), workday); } #endregion if (inOutConfig == null || inOutConfig.TypeLoadData.IsNullOrEmpty() || inOutConfig.TypeLoadData == TypeLoadData.E_DEFAULT.ToString() || inOutConfig.TypeLoadData == TypeLoadData.E_MAXMIN.ToString()) { if (listTamScanLogByShift.Count() >= 2) { #region Trường hợp có ít nhất 2 dòng quẹt thẻ thuộc ca đang xét var inTime = listTamScanLogByShift.Select(d => d.TimeLog).FirstOrDefault(); var outTime = listTamScanLogByShift.Select(d => d.TimeLog).LastOrDefault(); //Khi phát hiện 2 quẹt thẻ hợp lệ với ca đăng ký thì nhân luôn - không detect shift workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > inTime ? inTime : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < outTime ? outTime : workday.LastOutTime; if (isFromShift2) { workday.InTime2 = inTime; workday.OutTime2 = outTime; } else { workday.InTime1 = inTime; workday.OutTime1 = outTime; } if (inOutConfig.DetectWrongShift == Boolean.TrueString) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(inTime, outTime, listShift, null); if (actualShiftID != Guid.Empty && actualShiftID != shiftID) { var listTest = GetTamScanLogByShift(inTime.Value.Date, listShift, actualShiftID, listMonthShifts, listTamScanLogByShift.ToArray()); if (listTest != null && listTest.Count() >= 2 && listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date == date)) { workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); } else { actualShiftID = null; } } } #endregion } else if (listTamScanLogByShift.Count() == 1) { #region Trường hợp có 1 dòng quẹt thẻ thuộc ca đang xét if (listTamScanLogByShift.Any(d => d.SrcType == TAMScanType.E_OUT.ToString())) { //Dữ liệu quẹt thẻ được lấy từ máy chấm công ra - có option máy vào máy ra workday.Type = WorkdayType.E_MISS_IN.ToString(); if (isFromShift2) { workday.OutTime2 = listTamScanLogByShift.Select(d => d.TimeLog).LastOrDefault(); } else { workday.OutTime1 = listTamScanLogByShift.Select(d => d.TimeLog).LastOrDefault(); } } else { //So sanh độ lệch với thời gian của ca -> gần bên nào thì tính theo bên đó var timeLog = listTamScanLogByShift.Select(d => d.TimeLog).FirstOrDefault(); var shiftInTime = date.Add(shiftInfo.InTime.TimeOfDay); if (timeLog.Value <= shiftInTime || timeLog.Value.Subtract(shiftInTime) < shiftInTime.AddHours(shiftInfo.CoOut).Subtract(timeLog.Value)) { //1 dòng quẹt thẻ rơi vào nửa đầu của ca workday.Type = WorkdayType.E_MISS_OUT.ToString(); if (isFromShift2) { workday.InTime2 = timeLog; } else { workday.InTime1 = timeLog; } } if (inOutConfig.DetectWrongShift == Boolean.TrueString) { #region Tìm quẹt thẻ phía trước //Quẹt thẻ gần với thời gian vào của ca -> miss-out hoặc làm sai ca //Tìm ca làm việc trước gần nhất và dòng quẹt thẻ trước gần nhất của nhân viên đang xét var preShift = listMonthShifts.Where(d => d.Key >= date.AddDays(-1) && d.Key < date).OrderByDescending(d => d.Key).FirstOrDefault(); var preShiftValue = preShift.Value != null && preShift.Value.Count() > 0 ? preShift.Value.LastOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ phía trước gần nhất của nhân viên đang xét để kiểm tra ca trước var listPreTamScanLog = listTamScanLogByCardCode.Where(d => d.TimeLog <= timeLog).OrderByDescending(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByPreShift = GetTamScanLogByShift(preShift.Key, listShift, preShiftValue, listMonthShifts, listPreTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ phía trước không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByPreShift == null || listTamScanLogByPreShift.Count() < 2) { var preTamScanLog = listPreTamScanLog.Where(d => d.TimeLog < timeLog).FirstOrDefault(); var currentShiftDuration = shiftInfo.MinIn + shiftInfo.CoOut + shiftInfo.MaxOut; if (preTamScanLog != null && listWorkday.Any(d => d.ProfileID == profile.ID && (d.InTime1 == preTamScanLog.TimeLog || d.InTime2 == preTamScanLog.TimeLog || d.InTime3 == preTamScanLog.TimeLog || d.InTime4 == preTamScanLog.TimeLog || d.OutTime1 == preTamScanLog.TimeLog || d.OutTime2 == preTamScanLog.TimeLog || d.OutTime3 == preTamScanLog.TimeLog || d.OutTime4 == preTamScanLog.TimeLog))) { //Trường hợp quẹt thẻ này đã sử dụng preTamScanLog = null; } //Nếu quẹt thẻ hiện tại kết với quẹt thẻ tiếp theo mà phù hợp duration thì ghép sai ca if (preTamScanLog != null && preTamScanLog.TimeLog.HasValue && timeLog.Value .Subtract(preTamScanLog.TimeLog.Value).TotalHours <= currentShiftDuration) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(preTamScanLog.TimeLog, timeLog, listShift, null); var listTest = GetTamScanLogByShift(preTamScanLog.TimeLog.Value.Date, listShift, actualShiftID, listMonthShifts, new Att_TAMScanLogEntity[] { preTamScanLog, listTamScanLogByShift.FirstOrDefault() }); if (preTamScanLog.TimeLog.Value.Date == date.Date && listTest != null && listTest.Count() >= 2 && !listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date < date.Date)) { if (isFromShift2) { workday.InTime2 = preTamScanLog.TimeLog; workday.OutTime2 = timeLog; } else { workday.InTime1 = preTamScanLog.TimeLog; workday.OutTime1 = timeLog; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > preTamScanLog.TimeLog ? preTamScanLog.TimeLog : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < timeLog ? timeLog : workday.LastOutTime; workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); preTamScanLog.Checked = true; } else { actualShiftID = null; } } } #endregion #region Tìm quẹt thẻ phía sau if (workday.Type == WorkdayType.E_MISS_OUT.ToString() || string.IsNullOrWhiteSpace(workday.Type)) { if (string.IsNullOrWhiteSpace(workday.Type)) { //1 dòng quẹt thẻ rơi vào nửa sau của ca workday.Type = WorkdayType.E_MISS_IN.ToString(); if (isFromShift2) { workday.OutTime2 = timeLog; } else { workday.OutTime1 = timeLog; } } //Quẹt thẻ gần với thời gian ra của ca -> miss-in hoặc làm sai ca //Tìm ca làm việc tiếp theo gần nhất và dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét var nextShift = listMonthShifts.Where(d => d.Key > date && d.Key <= date.AddDays(1)).OrderBy(d => d.Key).FirstOrDefault(); var nextShiftValue = nextShift.Value != null && nextShift.Value.Count() > 0 ? nextShift.Value.FirstOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét để kiểm tra ca tiếp theo var listNextTamScanLog = listTamScanLogByCardCodeUnchecked.Where(d => d.TimeLog >= timeLog).OrderBy(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByNextShift = GetTamScanLogByShift(nextShift.Key, listShift, nextShiftValue, listMonthShifts, listNextTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ tiếp theo không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByNextShift == null || listTamScanLogByNextShift.Count() < 2) { var nextTamScanLog = listNextTamScanLog.Where(d => d.TimeLog > timeLog).FirstOrDefault(); var currentShiftDuration = shiftInfo.MinIn + shiftInfo.CoOut + shiftInfo.MaxOut; //Nếu quẹt thẻ hiện tại kết với quẹt thẻ tiếp theo mà phù hợp duration thì ghép sai ca if (nextTamScanLog != null && nextTamScanLog.TimeLog.HasValue && nextTamScanLog .TimeLog.Value.Subtract(timeLog.Value).TotalHours <= currentShiftDuration) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(timeLog, nextTamScanLog.TimeLog, listShift, null); var listTest = GetTamScanLogByShift(timeLog.Value.Date, listShift, actualShiftID, listMonthShifts, new Att_TAMScanLogEntity[] { listTamScanLogByShift.FirstOrDefault(), nextTamScanLog }); if (timeLog.Value.Date == date.Date && listTest != null && listTest.Count() >= 2 && !listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date < date.Date)) { if (isFromShift2) { workday.InTime1 = timeLog; workday.OutTime1 = nextTamScanLog.TimeLog; } else { workday.InTime1 = timeLog; workday.OutTime1 = nextTamScanLog.TimeLog; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > timeLog ? timeLog : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < nextTamScanLog.TimeLog ? nextTamScanLog.TimeLog : workday.LastOutTime; workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); nextTamScanLog.Checked = true; } else { actualShiftID = null; } } } } #endregion } else { if (IsInTime(date, timeLog, shiftInfo)) { if (isFromShift2) { workday.InTime2 = timeLog; } else { workday.InTime1 = timeLog; } workday.Type = WorkdayType.E_MISS_OUT.ToString(); } else { if (isFromShift2) { workday.OutTime2 = timeLog; } else { workday.OutTime1 = timeLog; } workday.Type = WorkdayType.E_MISS_IN.ToString(); } } } #endregion } else { #region Trường hợp không có dòng quẹt thẻ thuộc ca đang xét var listTamScanLogByDate = listTamScanLogByCardCodeUnchecked.Where(d => d.TimeLog.Value.Date == date).ToList(); var shiftInTime = date.Add(shiftInfo.InTime.TimeOfDay); var listTimeLog = new List<Att_TAMScanLogEntity>(); bool isWrongShiftDetected = false; foreach (var item in listTamScanLogByDate) { if (item.TimeLog < shiftInTime) { //Quẹt thẻ gần với thời gian vào của ca -> miss-out hoặc làm sai ca //Tìm ca làm việc trước gần nhất và dòng quẹt thẻ trước gần nhất của nhân viên đang xét var preShift = listMonthShifts.Where(d => d.Key >= date.AddDays(-1) && d.Key < date).OrderByDescending(d => d.Key).FirstOrDefault(); var preShiftValue = preShift.Value != null && preShift.Value.Count() > 0 ? preShift.Value.LastOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ phía trước gần nhất của nhân viên đang xét để kiểm tra ca trước var listPreTamScanLog = listTamScanLogByCardCode.Where(d => d.TimeLog <= item.TimeLog).OrderByDescending(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByPreShift = GetTamScanLogByShift(preShift.Key, listShift, preShiftValue, listMonthShifts, listPreTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ phía trước không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByPreShift == null || listTamScanLogByPreShift.Count() < 2) { var preTamScanLog = listPreTamScanLog.Where(d => d.TimeLog < item.TimeLog).FirstOrDefault(); var currentShiftDuration = shiftInfo.MinIn + shiftInfo.CoOut + shiftInfo.MaxOut; if (preTamScanLog != null && listWorkday.Any(d => d.ProfileID == profile.ID && (d.InTime1 == preTamScanLog.TimeLog || d.InTime2 == preTamScanLog.TimeLog || d.InTime3 == preTamScanLog.TimeLog || d.InTime4 == preTamScanLog.TimeLog || d.OutTime1 == preTamScanLog.TimeLog || d.OutTime2 == preTamScanLog.TimeLog || d.OutTime3 == preTamScanLog.TimeLog || d.OutTime4 == preTamScanLog.TimeLog))) { //Trường hợp quẹt thẻ này đã sử dụng preTamScanLog = null; } //Nếu quẹt thẻ hiện tại kết với quẹt thẻ trước đó mà phù hợp duration thì ghép sai ca if (preTamScanLog != null && preTamScanLog.TimeLog.HasValue && item.TimeLog.Value .Subtract(preTamScanLog.TimeLog.Value).TotalHours <= currentShiftDuration) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(preTamScanLog.TimeLog, item.TimeLog, listShift, null); var listTest = GetTamScanLogByShift(preTamScanLog.TimeLog.Value.Date, listShift, actualShiftID, listMonthShifts, new Att_TAMScanLogEntity[] { preTamScanLog, item }); if (preTamScanLog.TimeLog.Value.Date == date.Date && listTest != null && listTest.Count() >= 2 && listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date < date.Date)) { if (isFromShift2) { workday.InTime2 = preTamScanLog.TimeLog; workday.OutTime2 = item.TimeLog; } else { workday.InTime1 = preTamScanLog.TimeLog; workday.OutTime1 = item.TimeLog; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > preTamScanLog.TimeLog ? preTamScanLog.TimeLog : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < item.TimeLog ? item.TimeLog : workday.LastOutTime; workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); preTamScanLog.Checked = true; isWrongShiftDetected = true; break;//chỉ hỗ trợ 1 ca } else { actualShiftID = null; } } else { listTimeLog.Add(item); } } else { if (!listTamScanLogByPreShift.Any(d => d.TimeLog == item.TimeLog)) { listTimeLog.Add(item); } listTimeLog = listTimeLog.Where(d => !listTamScanLogByPreShift.Contains(d)).ToList(); } } else if (item.TimeLog > shiftInTime) { //Quẹt thẻ gần với thời gian ra của ca -> miss-in hoặc làm sai ca //Tìm ca làm việc tiếp theo gần nhất và dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét var nextShift = listMonthShifts.Where(d => d.Key > date && d.Key <= date.AddDays(1)).OrderBy(d => d.Key).FirstOrDefault(); var nextShiftValue = nextShift.Value != null && nextShift.Value.Count() > 0 ? nextShift.Value.FirstOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét để kiểm tra ca tiếp theo var listNextTamScanLog = listTamScanLogByCardCodeUnchecked.Where(d => d.TimeLog >= item.TimeLog).OrderBy(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByNextShift = GetTamScanLogByShift(nextShift.Key, listShift, nextShiftValue, listMonthShifts, listNextTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ tiếp theo không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByNextShift == null || listTamScanLogByNextShift.Count() < 2) { var nextTamScanLog = listNextTamScanLog.Where(d => d.TimeLog > item.TimeLog).FirstOrDefault(); var currentShiftDuration = shiftInfo.MinIn + shiftInfo.CoOut + shiftInfo.MaxOut; //Nếu quẹt thẻ hiện tại kết với quẹt thẻ tiếp theo mà phù hợp duration thì ghép sai ca if (nextTamScanLog != null && nextTamScanLog.TimeLog.HasValue && nextTamScanLog .TimeLog.Value.Subtract(item.TimeLog.Value).TotalHours <= currentShiftDuration) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(item.TimeLog, nextTamScanLog.TimeLog, listShift, null); var listTest = GetTamScanLogByShift(item.TimeLog.Value.Date, listShift, actualShiftID, listMonthShifts, new Att_TAMScanLogEntity[] { item, nextTamScanLog }); if (item.TimeLog.Value.Date == date.Date && listTest != null && listTest.Count() >= 2 && listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date < date.Date)) { if (isFromShift2) { workday.InTime2 = item.TimeLog; workday.OutTime2 = nextTamScanLog.TimeLog; } else { workday.InTime1 = item.TimeLog; workday.OutTime1 = nextTamScanLog.TimeLog; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > item.TimeLog ? item.TimeLog : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < nextTamScanLog.TimeLog ? nextTamScanLog.TimeLog : workday.LastOutTime; workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); nextTamScanLog.Checked = true; isWrongShiftDetected = true; break;//chỉ hỗ trợ 1 ca } else { actualShiftID = null; } } else { listTimeLog.Add(item); } } else { if (!listTamScanLogByNextShift.Any(d => d.TimeLog == item.TimeLog)) { listTimeLog.Add(item); } listTimeLog = listTimeLog.Where(d => !listTamScanLogByNextShift.Contains(d)).ToList(); } } } if (!isWrongShiftDetected) { var listRemove = new List<Att_TAMScanLogEntity>(); if (listTimeLog.Count() >= 2) { var currentShiftDuration = shiftInfo.MinIn + shiftInfo.CoOut + shiftInfo.MaxOut; var timeLog1 = listTimeLog.OrderBy(d => d.TimeLog).FirstOrDefault(); var timeLog2 = listTimeLog.OrderBy(d => d.TimeLog).LastOrDefault(); if (isFromShift2) { workday.InTime2 = timeLog1.TimeLog; workday.OutTime2 = timeLog2.TimeLog; } else { workday.InTime1 = timeLog1.TimeLog; workday.OutTime1 = timeLog2.TimeLog; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > timeLog1.TimeLog ? timeLog1.TimeLog : workday.FirstInTime; workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < timeLog2.TimeLog ? timeLog2.TimeLog : workday.LastOutTime; isWrongShiftDetected = true; if (timeLog2.TimeLog.HasValue && timeLog1.TimeLog.HasValue && timeLog2.TimeLog.Value .Subtract(timeLog1.TimeLog.Value).TotalHours <= currentShiftDuration) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID = GetDetectedShiftID(timeLog1.TimeLog, timeLog2.TimeLog, listShift, null); var listTest = GetTamScanLogByShift(timeLog1.TimeLog.Value.Date, listShift, actualShiftID, listMonthShifts, new Att_TAMScanLogEntity[] { timeLog1, timeLog2 }); if (listTest != null && listTest.Count() >= 2 && listTest.Any(d => d.TimeLog.HasValue && d.TimeLog.Value.Date < date.Date)) { workday.Type = WorkdayType.E_WRONG_SHIFT.ToString(); } else { workday.Type = WorkdayType.E_LONGIN_SHIFT.ToString(); } } else { foreach (var item in listTimeLog.Where(d => d.TimeLog > timeLog1.TimeLog).OrderByDescending(d => d.TimeLog)) { if (isFromShift2) { workday.OutTime2 = item.TimeLog; } else { workday.OutTime1 = item.TimeLog; } workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < item.TimeLog ? item.TimeLog : workday.LastOutTime; if (item.TimeLog > timeLog1.TimeLog && item.TimeLog.HasValue && timeLog1.TimeLog.HasValue && item.TimeLog.Value.Subtract(timeLog1.TimeLog.Value).TotalHours <= currentShiftDuration) { workday.Type = WorkdayType.E_DETECTED_SHIFT.ToString(); break; } else { workday.Type = WorkdayType.E_LONGIN_SHIFT.ToString(); } } listRemove = listTimeLog.Where(d => d.TimeLog > workday.LastOutTime).ToList(); } } else if (listTimeLog.Count() == 1) { if (listTimeLog.Any(d => d.TimeLog < shiftInTime)) { var inTimeValue = listTimeLog.Select(d => d.TimeLog).FirstOrDefault(); if (isFromShift2) { workday.InTime2 = inTimeValue; } else { workday.InTime1 = inTimeValue; } workday.FirstInTime = !workday.FirstInTime.HasValue || workday.FirstInTime > inTimeValue ? inTimeValue : workday.FirstInTime; workday.Type = WorkdayType.E_MISS_OUT.ToString();//miss-in hay miss-out cũng như nhau } else { var outTimeValue = listTimeLog.Select(d => d.TimeLog).FirstOrDefault(); if (isFromShift2) { workday.OutTime2 = outTimeValue; } else { workday.OutTime1 = outTimeValue; } workday.LastOutTime = !workday.LastOutTime.HasValue || workday.LastOutTime < outTimeValue ? outTimeValue : workday.LastOutTime; workday.Type = WorkdayType.E_MISS_IN.ToString();//miss-in hay miss-out cũng như nhau } isWrongShiftDetected = true; } listTimeLog.Where(d => !listRemove.Contains(d)).ToList().ForEach(d => d.Checked = true); } if (!isWrongShiftDetected) { if (listHoliday.Any(d => d.DateOff.Date == date.Date)) { //Có ca mà không inout thì xem có phải holiday workday.Type = WorkdayType.E_HOLIDAY.ToString(); } else { workday.Type = WorkdayType.E_MISS_IN_OUT.ToString(); } } #endregion } } else if (inOutConfig.TypeLoadData == TypeLoadData.E_TYPEINOUT.ToString()) { //Xử lý cho các loại khác } return workday; #endregion }
private int ComputeWorkday(Guid asynTaskID, Guid userID, int totalProfile, int totalComputed, double timeoutMinutes, DateTime dateFrom, DateTime dateTo, out DataErrorCode dataErrorCode, params Hre_ProfileEntity[] listProfile) { List<Att_Workday> listWorkday = new List<Att_Workday>(); List<Att_Workday> listWorkdayChecked = new List<Att_Workday>(); List<Att_Workday> listWorkdayAnalyze = new List<Att_Workday>(); dateFrom = dateFrom <= DateTime.MinValue ? DateTime.Now : dateFrom; dateTo = dateTo <= DateTime.MinValue ? DateTime.Now : dateTo; DateTime dateStart = dateFrom.AddDays(-1); DateTime dateEnd = dateTo.AddDays(1); using (var context = new VnrHrmDataContext()) { var workHistoryServices = new Hre_WorkHistoryServices(); var leavedayServices = new Att_LeavedayServices(); var unitOfWork = new UnitOfWork(context); string waitStatus = ProfileStatusSyn.E_WAITING.ToString(); string rosterStatus = RosterStatus.E_APPROVED.ToString(); string leaveDayStatus = LeaveDayStatus.E_APPROVED.ToString(); String appConfigInfo = AppConfig.E_SERVER_TAM.ToString(); string E_LEAVE_EARLY = PregnancyType.E_LEAVE_EARLY.ToString(); string workdaySrcType = WorkdaySrcType.E_MANUAL.ToString(); string workdayStatus1 = WorkdayStatus.E_APPROVED.ToString(); string workdayStatus2 = WorkdayStatus.E_WAIT_APPROVED.ToString(); var listProfileID = listProfile.Select(d => d.ID).ToArray(); #region Delete Workday đã tổng hợp trước đó if (unitOfWork.CheckLock(typeof(Att_Workday), dateFrom, dateTo)) { dataErrorCode = DataErrorCode.Locked; CompleteComputingTask(asynTaskID, userID, totalComputed, totalProfile, dataErrorCode); return listWorkday.Count(); } else { Task task = Task.Run(() => DeleteWorkday(userID, dateFrom, dateTo, workdaySrcType, workdayStatus1, workdayStatus2, listProfileID)); } #endregion #region Khởi tạo dữ liệu cho lần tổng hợp var tamScanLogQueryable = unitOfWork.CreateQueryable<Att_TAMScanLog>(Guid.Empty, d => d.ProfileID.HasValue && listProfileID.Contains(d.ProfileID.Value) && d.TimeLog.HasValue && d.TimeLog >= dateStart && d.TimeLog <= dateEnd); //Danh sách quẹt thẻ theo điều kiện được chọn var listAllTamScanLog = tamScanLogQueryable.Select(d => new Att_TAMScanLogEntity { ID = d.ID, ProfileID = d.ProfileID, CardCode = d.CardCode, CodeEmp = d.CodeEmp, TimeLog = d.TimeLog, SrcType = d.SrcType, Type = d.Type }).ToList(); var listRoster = unitOfWork.CreateQueryable<Att_Roster>(Guid.Empty, d => d.Status == rosterStatus && d.DateStart <= dateEnd && d.DateEnd >= dateStart.Date && listProfileID.Contains(d.ProfileID)).Select(d => new Att_RosterEntity { ID = d.ID, ProfileID = d.ProfileID, RosterGroupName = d.RosterGroupName, Type = d.Type, Status = d.Status, DateEnd = d.DateEnd, DateStart = d.DateStart, MonShiftID = d.MonShiftID, TueShiftID = d.TueShiftID, WedShiftID = d.WedShiftID, ThuShiftID = d.ThuShiftID, FriShiftID = d.FriShiftID, SatShiftID = d.SatShiftID, SunShiftID = d.SunShiftID, MonShift2ID = d.MonShiftID, TueShift2ID = d.TueShift2ID, WedShift2ID = d.WedShift2ID, ThuShift2ID = d.ThuShift2ID, FriShift2ID = d.FriShift2ID, SatShift2ID = d.SatShift2ID, SunShift2ID = d.SunShift2ID }).ToList(); var listRosterGroup = unitOfWork.CreateQueryable<Att_RosterGroup>(Guid.Empty, m => m.DateStart != null && m.DateEnd != null && m.DateStart <= dateEnd && m.DateEnd >= dateStart.Date).Select(d => new Att_RosterGroupEntity { ID = d.ID, DateEnd = d.DateEnd, DateStart = d.DateStart, MonShiftID = d.MonShiftID, TueShiftID = d.TueShiftID, WedShiftID = d.WedShiftID, ThuShiftID = d.ThuShiftID, FriShiftID = d.FriShiftID, SatShiftID = d.SatShiftID, SunShiftID = d.SunShiftID, RosterGroupName = d.RosterGroupName }).ToList(); var listShift = unitOfWork.CreateQueryable<Cat_Shift>(Guid.Empty).ToList(); var listHoliday = unitOfWork.CreateQueryable<Cat_DayOff>(Guid.Empty, d => d.DateOff >= dateFrom.Date && d.DateOff <= dateTo).Select(d => new Cat_DayOffEntity { ID = d.ID, DateOff = d.DateOff, Type = d.Type }).ToList(); var listWorkdayExisting = unitOfWork.CreateQueryable<Att_Workday>(Guid.Empty, d => d.WorkDate >= dateStart && d.WorkDate <= dateEnd && (d.SrcType == workdaySrcType || d.Status == workdayStatus1 || d.Status == workdayStatus2) && listProfileID.Contains(d.ProfileID)).ToList(); var listLeaveDay = unitOfWork.CreateQueryable<Att_LeaveDay>(Guid.Empty, d => d.Status == leaveDayStatus && d.DateStart <= dateTo && d.DateEnd >= dateFrom.Date && listProfileID.Contains(d.ID)).Select(d => new { d.ID, d.ProfileID, d.LeaveDayTypeID, d.DateOvertimeOff, d.DateStart, d.DateEnd }).ToList(); var listLeaveDayType = unitOfWork.CreateQueryable<Cat_LeaveDayType>(Guid.Empty).Select(d => new { d.ID, d.Code, d.MissInOutReasonID }).ToList(); var listAllSetting = unitOfWork.CreateQueryable<Sys_AllSetting>(Guid.Empty, i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MAXHOURSONESHIFT.ToString() || i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MAXHOURSNEXTINOUT.ToString() || i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MINMINUTESSAMEATT.ToString() || i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_SYMBOL.ToString() || i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_DETECTSHIFT.ToString() || i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_TYPELOADDATA.ToString()).Select(d => new { d.Name, d.Value1, d.Value2 }).ToList(); var inOutConfigMaxHoursOneShift = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MAXHOURSONESHIFT.ToString()).FirstOrDefault(); var inOutConfigMaxHoursNextInOut = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MAXHOURSNEXTINOUT.ToString()).FirstOrDefault(); var inOutConfigMinMinutesSameAtt = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_MINMINUTESSAMEATT.ToString()).FirstOrDefault(); var inOutConfigSymbol = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_SYMBOL.ToString()).FirstOrDefault(); var inOutConfigDetectShift = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_DETECTSHIFT.ToString()).FirstOrDefault(); var inOutConfigTypeLoadData = listAllSetting.Where(i => i.Name == AppConfig.HRM_ATT_WORKDAY_SUMMARY_TYPELOADDATA.ToString()).FirstOrDefault(); var inOutConfig = new string[] { string.Empty }.Select(d => new WorkdayConfig { MaxHoursOneShift = inOutConfigMaxHoursOneShift != null ? inOutConfigMaxHoursOneShift.Value1 : string.Empty, MaxHoursNextInOut = inOutConfigMaxHoursNextInOut != null ? inOutConfigMaxHoursNextInOut.Value1 : string.Empty, MinMinutesSameAtt = inOutConfigMinMinutesSameAtt != null ? inOutConfigMinMinutesSameAtt.Value1 : string.Empty, TypeLoadData = inOutConfigTypeLoadData != null ? inOutConfigTypeLoadData.Value1 : string.Empty, SymbolIn = inOutConfigSymbol != null ? inOutConfigTypeLoadData.Value1 : string.Empty, SymbolOut = inOutConfigSymbol != null ? inOutConfigTypeLoadData.Value2 : string.Empty, DetectShift = inOutConfigDetectShift != null ? inOutConfigTypeLoadData.Value1 : string.Empty, DetectWrongShift = inOutConfigDetectShift != null ? inOutConfigTypeLoadData.Value2 : string.Empty, }).FirstOrDefault(); List<Att_Pregnancy> lstPrenancy = unitOfWork.CreateQueryable<Att_Pregnancy>(Guid.Empty, m => m.Type == E_LEAVE_EARLY && m.DateEnd >= dateFrom && m.DateStart < dateTo && listProfileID.Contains(m.ProfileID)).ToList(); List<Cat_LateEarlyRule> lstLateEarlyRule = unitOfWork.CreateQueryable<Cat_LateEarlyRule>(Guid.Empty).ToList(); List<Cat_GradeAttendance> lstGradeConfig = unitOfWork.CreateQueryable<Cat_GradeAttendance>(Guid.Empty).ToList(); List<Att_Grade> lstGrade = unitOfWork.CreateQueryable<Att_Grade>(Guid.Empty, m => m.ProfileID.HasValue && listProfileID.Contains(m.ProfileID.Value)).ToList(); List<DateTime> lstDayOff = unitOfWork.CreateQueryable<Cat_DayOff>(Guid.Empty, m => m.DateOff >= dateStart && m.DateOff <= dateEnd).Select(m => m.DateOff).ToList<DateTime>(); #endregion #region Bắt đầu xử lý tổng hợp in out string sameAttConfig = inOutConfig != null ? inOutConfig.MinMinutesSameAtt : string.Empty; var minMinutesSameAtt = VnResource.Helper.Data.DataHelper.TryGetValue<double>(sameAttConfig); //Loại bỏ những dòng quẹt thẻ liền kề nhau trong khoảng thời gian như cấu hình var listTamScanLog = RemoveSameTimeLog(listAllTamScanLog, minMinutesSameAtt); //Giữ danh sách những quẹt thẻ tạm thời được cho là trùng với những quẹt thẻ khác để xử lý sau var listTamScanLogRemove = listAllTamScanLog.Where(d => !listTamScanLog.Contains(d)).ToList(); using (var taskContext = new VnrHrmDataContext()) { var taskUnitOfWork = new UnitOfWork(taskContext); Sys_AsynTask asynTask = null; if (asynTaskID != Guid.Empty) { asynTask = taskUnitOfWork.CreateQueryable<Sys_AsynTask>(s => s.ID == asynTaskID).FirstOrDefault(); } int totalComputedProfileMustSubmitTask = 50; int totalComputedProfileMustSubmit = 200; int totalComputedProfileForSubmit = 0; int totalComputedProfileForTask = 0; totalComputedProfileMustSubmitTask = totalProfile * 5 / 100; if (totalComputedProfileMustSubmitTask > listProfile.Count()) { totalComputedProfileMustSubmitTask = listProfile.Count(); } foreach (var profile in listProfile) { #region Cập nhật thời gian tính timeout cho task if (asynTask != null) { bool mustSaveTask = false; if (asynTask.TimeEnd.HasValue) { var timeoutDate = DateTime.Now.AddMinutes(-timeoutMinutes); if (timeoutDate.AddMinutes(1) >= asynTask.TimeEnd.Value) { asynTask.TimeEnd = DateTime.Now; mustSaveTask = true; } } totalComputedProfileForTask++; double percent = totalComputedProfileForTask / (double)totalProfile; if (totalComputedProfileForTask >= totalComputedProfileMustSubmitTask) { var totalPercent = asynTask.PercentComplete + percent; asynTask.PercentComplete = totalPercent; asynTask.TimeEnd = DateTime.Now; mustSaveTask = true; } if (mustSaveTask) { taskUnitOfWork.SaveChanges(userID); totalComputedProfileForTask = 0; } } #endregion #region Những dữ liệu liên quan theo từng nhân viên var listRosterByProfile = listRoster.Where(d => d.ProfileID == profile.ID).ToList(); var listMonthShifts = Att_AttendanceLib.GetDailyShifts(dateStart, dateEnd, profile.ID, listRosterByProfile, listRosterGroup); #endregion #region Xử lý tổng hợp in out theo từng ngày for (DateTime date = dateFrom.Date; date <= dateTo; date = date.AddDays(1)) { Att_Workday workday = listWorkdayExisting.Where(d => d.ProfileID == profile.ID && d.WorkDate == date).FirstOrDefault(); var shiftByDate = listMonthShifts.Where(d => d.Key == date).Select(d => d.Value).FirstOrDefault(); Guid? shiftID1 = Guid.Empty; Guid? shiftID2 = Guid.Empty; if (shiftByDate != null) { if (shiftByDate.Count() > 0) { shiftID1 = shiftByDate[0]; } if (shiftByDate.Count() > 1) { shiftID2 = shiftByDate[1]; } } var shiftInfo1 = listShift.Where(d => d.ID == shiftID1).FirstOrDefault(); var shiftInfo2 = listShift.Where(d => d.ID == shiftID2).FirstOrDefault(); if ((profile.DateQuit.HasValue && profile.DateQuit.Value.Date <= date) || (profile.DateHire.HasValue && profile.DateHire.Value.Date > date)) { if (workday != null) { workday.IsDelete = true; } continue; } if (workday != null) { if (shiftByDate == null) { shiftByDate = new List<Guid?>(); } if ((!shiftID1.HasValue || shiftID1 == Guid.Empty)) { if (workday.ShiftActual.HasValue) { shiftByDate.Insert(0, workday.ShiftActual); } } if ((!shiftID2.HasValue || shiftID2 == Guid.Empty)) { if (workday.ShiftActual2.HasValue) { if (shiftByDate.Count() == 0) { shiftByDate.Add(Guid.Empty); } shiftByDate.Add(workday.ShiftActual2); } } if (listMonthShifts.ContainsKey(date)) { listMonthShifts[date] = shiftByDate; } else { listMonthShifts.Add(date, shiftByDate); } if ((workday.SrcType == workdaySrcType || workday.Status == workdayStatus1 || workday.Status == workdayStatus2)) { listWorkday.Add(workday); continue; } } Guid? actualShiftID1 = null; Guid? actualShiftID2 = null; bool isPreWorkday = false; var listTamScanLogByCardCode = listTamScanLog.Where(d => d.ProfileID == profile.ID).OrderBy(d => d.TimeLog).ToList(); var listTamScanLogByCardCodeUnchecked = listTamScanLogByCardCode.Where(d => !d.Checked && d.TimeLog.HasValue).ToList(); if (shiftID1.HasValue && shiftID1 != Guid.Empty) { #region Trường hợp có lịch làm việc - ca thứ nhất workday = CreateWorkday(unitOfWork, date, profile, inOutConfig, listHoliday, listWorkday, workday, false, shiftID1, shiftInfo1, listShift, listMonthShifts, out actualShiftID1, listTamScanLogByCardCode, listTamScanLogByCardCodeUnchecked); #endregion } else if (shiftID2.HasValue && shiftID2 != Guid.Empty) { #region Trường hợp có lịch làm việc - ca thứ hai workday = CreateWorkday(unitOfWork, date, profile, inOutConfig, listHoliday, listWorkday, workday, true, shiftID2, shiftInfo2, listShift, listMonthShifts, out actualShiftID2, listTamScanLogByCardCode, listTamScanLogByCardCodeUnchecked); #endregion } else if (inOutConfig != null && inOutConfig.DetectShift == Boolean.TrueString) { #region Trường hợp không có lịch làm việc var listTamScanLogByDate = listTamScanLogByCardCodeUnchecked.Where(d => d.TimeLog.Value.Date == date).ToList(); if (listTamScanLogByDate.Count() > 0) { var shiftInTime = date.Date.AddHours(12); var listTimeLog = new List<Att_TAMScanLogEntity>(); bool isWrongShiftDetected = false; foreach (var item in listTamScanLogByDate) { if (item.TimeLog < shiftInTime) { //Quẹt thẻ gần với thời gian vào của ca -> miss-out hoặc làm sai ca //Tìm ca làm việc trước gần nhất và dòng quẹt thẻ trước gần nhất của nhân viên đang xét var preShift = listMonthShifts.Where(d => d.Key >= date.AddDays(-1) && d.Key < date).OrderByDescending(d => d.Key).FirstOrDefault(); var preShiftValue = preShift.Value != null && preShift.Value.Count() > 0 ? preShift.Value.LastOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ phía trước gần nhất của nhân viên đang xét để kiểm tra ca trước var listPreTamScanLog = listTamScanLogByCardCode.Where(d => d.TimeLog <= item.TimeLog).OrderByDescending(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByPreShift = GetTamScanLogByShift(preShift.Key, listShift, preShiftValue, listMonthShifts, listPreTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ phía trước không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByPreShift == null || listTamScanLogByPreShift.Count() < 2) { var preTamScanLog = listPreTamScanLog.Where(d => d.TimeLog < item.TimeLog).FirstOrDefault(); var currentShiftDuration = 12;//cho ca tối đa được 12 tiếng đồng hồ if (preTamScanLog != null && listWorkday.Any(d => d.ProfileID == profile.ID && (d.InTime1 == preTamScanLog.TimeLog || d.InTime2 == preTamScanLog.TimeLog || d.InTime3 == preTamScanLog.TimeLog || d.InTime4 == preTamScanLog.TimeLog || d.OutTime1 == preTamScanLog.TimeLog || d.OutTime2 == preTamScanLog.TimeLog || d.OutTime3 == preTamScanLog.TimeLog || d.OutTime4 == preTamScanLog.TimeLog))) { //Trường hợp quẹt thẻ này đã sử dụng preTamScanLog = null; } //Nếu quẹt thẻ hiện tại kết với quẹt thẻ trước đó mà phù hợp duration thì ghép sai ca if (preTamScanLog != null && preTamScanLog.TimeLog.HasValue && item.TimeLog.Value .Subtract(preTamScanLog.TimeLog.Value).TotalHours <= currentShiftDuration) { if (preTamScanLog.TimeLog < date) { if (preShiftValue.HasValue) { workday = listWorkday.Where(d => d.ProfileID == profile.ID && d.WorkDate == date.AddDays(-1)).FirstOrDefault(); if (workday == null) { if (preTamScanLog.TimeLog.Value.Date >= dateFrom.Date && preTamScanLog.TimeLog.Value.Date <= dateTo.Date) { workday = new Att_Workday(); unitOfWork.AddObject(typeof(Att_Workday), workday); workday.WorkDate = preTamScanLog.TimeLog.Value.Date; workday.FirstInTime = workday.InTime1 = preTamScanLog.TimeLog; workday.LastOutTime = workday.OutTime1 = item.TimeLog; workday.Type = WorkdayType.E_DETECTED_SHIFT.ToString(); isPreWorkday = true; preTamScanLog.Checked = true; isWrongShiftDetected = true; break;//chỉ hỗ trợ 1 ca } } else { listTimeLog.Add(item); } } else { listTimeLog.Add(item); } } else { if (workday == null) { workday = new Att_Workday(); unitOfWork.AddObject(typeof(Att_Workday), workday); } workday.FirstInTime = workday.InTime1 = preTamScanLog.TimeLog; workday.LastOutTime = workday.OutTime1 = item.TimeLog; workday.Type = WorkdayType.E_DETECTED_SHIFT.ToString(); preTamScanLog.Checked = true; isWrongShiftDetected = true; break;//chỉ hỗ trợ 1 ca } } else { listTimeLog.Add(item); } } else { if (!listTamScanLogByPreShift.Any(d => d.TimeLog == item.TimeLog)) { listTimeLog.Add(item); } listTimeLog = listTimeLog.Where(d => !listTamScanLogByPreShift.Contains(d)).ToList(); } } else if (item.TimeLog > shiftInTime) { //Quẹt thẻ gần với thời gian ra của ca -> miss-in hoặc làm sai ca //Tìm ca làm việc tiếp theo gần nhất và dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét var nextShift = listMonthShifts.Where(d => d.Key > date && d.Key <= date.AddDays(1)).OrderBy(d => d.Key).FirstOrDefault(); var nextShiftValue = nextShift.Value != null && nextShift.Value.Count() > 0 ? nextShift.Value.FirstOrDefault() : null; //Lấy dòng quẹt thẻ hiện tại và 2 dòng quẹt thẻ tiếp theo gần nhất của nhân viên đang xét để kiểm tra ca tiếp theo var listNextTamScanLog = listTamScanLogByCardCodeUnchecked.Where(d => d.TimeLog >= item.TimeLog).OrderBy(d => d.TimeLog).Take(3).ToList(); var listTamScanLogByNextShift = GetTamScanLogByShift(nextShift.Key, listShift, nextShiftValue, listMonthShifts, listNextTamScanLog.ToArray()); //Nếu 2 dòng quẹt thẻ tiếp theo không thuộc một ca khác trong lịch của nhân viên if (listTamScanLogByNextShift == null || listTamScanLogByNextShift.Count() < 2) { listTimeLog.Add(item); foreach (var nextTamScanLog in listNextTamScanLog.Where(d => d.TimeLog > item.TimeLog)) { var currentShiftDuration = 12;//cho ca tối đa được 12 tiếng đồng hồ //Nếu quẹt thẻ hiện tại kết với quẹt thẻ tiếp theo mà phù hợp duration thì ghép sai ca if (nextTamScanLog != null && nextTamScanLog.TimeLog.HasValue && nextTamScanLog .TimeLog.Value.Subtract(item.TimeLog.Value).TotalHours <= currentShiftDuration) { listTimeLog.Add(nextTamScanLog); } } } else { if (!listTamScanLogByNextShift.Any(d => d.TimeLog == item.TimeLog)) { listTimeLog.Add(item); } listTimeLog = listTimeLog.Where(d => !listTamScanLogByNextShift.Contains(d)).ToList(); } } } if (!isWrongShiftDetected) { if (listTimeLog.Count() > 0) { var listRemove = new List<Att_TAMScanLogEntity>(); if (workday == null) { workday = new Att_Workday(); unitOfWork.AddObject(typeof(Att_Workday), workday); } if (listTimeLog.Count() >= 2) { workday.FirstInTime = workday.InTime1 = listTimeLog.OrderBy(d => d.TimeLog).Select(d => d.TimeLog).FirstOrDefault(); workday.LastOutTime = workday.OutTime1 = listTimeLog.OrderBy(d => d.TimeLog).Select(d => d.TimeLog).LastOrDefault(); var currentShiftDuration = 16;//cho ca tối đa được 12 tiếng đồng hồ isWrongShiftDetected = true; if (workday.LastOutTime.HasValue && workday.FirstInTime.HasValue && workday.LastOutTime.Value .Subtract(workday.FirstInTime.Value).TotalHours <= currentShiftDuration) { workday.Type = WorkdayType.E_DETECTED_SHIFT.ToString(); } else { foreach (var item in listTimeLog.Where(d => d.TimeLog > workday.FirstInTime).OrderByDescending(d => d.TimeLog)) { workday.LastOutTime = workday.OutTime1 = item.TimeLog; if (item.TimeLog > workday.FirstInTime && item.TimeLog.HasValue && workday.FirstInTime.HasValue && item.TimeLog.Value.Subtract(workday.FirstInTime.Value).TotalHours <= currentShiftDuration) { workday.Type = WorkdayType.E_DETECTED_SHIFT.ToString(); break; } else { workday.Type = WorkdayType.E_LONGIN_SHIFT.ToString(); } } listRemove = listTimeLog.Where(d => d.TimeLog > workday.LastOutTime).ToList(); } } else if (listTimeLog.Count() == 1) { if (listTimeLog.Any(d => d.TimeLog < shiftInTime)) { workday.FirstInTime = workday.InTime1 = listTimeLog.Select(d => d.TimeLog).FirstOrDefault(); workday.Type = WorkdayType.E_MISS_OUT.ToString();//miss-in hay miss-out cũng như nhau } else { workday.LastOutTime = workday.OutTime1 = listTimeLog.Select(d => d.TimeLog).FirstOrDefault(); workday.Type = WorkdayType.E_MISS_IN.ToString();//miss-in hay miss-out cũng như nhau } isWrongShiftDetected = true; } listTimeLog.Where(d => !listRemove.Contains(d)).ToList().ForEach(d => d.Checked = true); } } if (workday != null) { //Trường hợp wrong-shift và detected-shift thì phải check lại actualShiftID actualShiftID1 = GetDetectedShiftID(workday.InTime1, workday.OutTime1, listShift, null); } } #endregion } if (workday != null) { if (string.IsNullOrWhiteSpace(workday.Type)) { workday.Type = WorkdayType.E_NORMAL.ToString(); } workday.SrcType = WorkdaySrcType.E_NORMAL.ToString(); workday.ProfileID = profile.ID; listTamScanLogByCardCode = listTamScanLogRemove.Where(d => d.ProfileID == profile.ID).OrderBy(d => d.TimeLog).ToList(); listTamScanLogByCardCodeUnchecked = listTamScanLogByCardCode.Where(d => !d.Checked && d.TimeLog.HasValue).ToList(); workday.FirstInTime = workday.InTime1 = FindTimeLogAvailable(listTamScanLogByCardCode, workday.InTime1, minMinutesSameAtt, false); workday.LastOutTime = workday.OutTime1 = FindTimeLogAvailable(listTamScanLogByCardCode, workday.OutTime1, minMinutesSameAtt, true); if (!isPreWorkday) { workday.WorkDate = date; workday.InTimeRoot = workday.InTime1; workday.OutTimeRoot = workday.OutTime1; } if (shiftID1 != null && shiftID1 != Guid.Empty) { workday.ShiftID = shiftID1.Value; workday.ShiftActual = shiftID1.Value; workday.ShiftApprove = shiftID1.Value; } if (shiftID2 != null && shiftID2 != Guid.Empty) { workday.Shift2ID = shiftID2.Value; workday.ShiftActual2 = shiftID2.Value; workday.ShiftApprove2 = shiftID2.Value; } if (actualShiftID1.HasValue && actualShiftID1 != Guid.Empty) { workday.ShiftActual = actualShiftID1; workday.ShiftApprove = actualShiftID1; } if (actualShiftID2.HasValue && actualShiftID2 != Guid.Empty) { workday.ShiftActual2 = actualShiftID2; workday.ShiftApprove2 = actualShiftID2; } var listLeaveDayByProfile = listLeaveDay.Where(d => d.ProfileID == profile.ID).ToList(); var leaveDayID1 = listLeaveDayByProfile.Where(d => workday.WorkDate >= d.DateStart && workday.WorkDate <= d.DateEnd).Select(d => d.ID).FirstOrDefault(); var leaveDayID2 = listLeaveDayByProfile.Where(d => d.ID != workday.LeaveDayID1 && workday.WorkDate >= d.DateStart && workday.WorkDate <= d.DateEnd).Select(d => d.ID).FirstOrDefault(); workday.LeaveDayID1 = leaveDayID1 != Guid.Empty ? (Guid?)leaveDayID1 : null; workday.LeaveDayID2 = leaveDayID2 != Guid.Empty ? (Guid?)leaveDayID2 : null; workday.MissInOutReason = listLeaveDayType.Where(d => listLeaveDayByProfile.Any(p => p.LeaveDayTypeID == d.ID) && d.MissInOutReasonID != null).Select(d => d.MissInOutReasonID).FirstOrDefault(); listWorkday.Add(workday); } } #endregion #region Chia thành nhiều giai đoạn lưu ngày công //Nên submit lần đầu tiên khi đã tính được 5 profile bool firstSubmit = listProfile.ToList().IndexOf(profile) == 5; firstSubmit = totalComputed >= 5 ? false : firstSubmit;//đã chạy 1 lần totalComputedProfileForSubmit++; totalComputed++; if (firstSubmit || totalComputedProfileForSubmit >= totalComputedProfileMustSubmit) { listWorkdayAnalyze = listWorkday.Where(d => !listWorkdayChecked.Contains(d)).ToList(); listWorkdayChecked.AddRange(listWorkdayAnalyze); leavedayServices.AnalyzeLeaveLate(listWorkdayAnalyze, lstPrenancy, lstLateEarlyRule, listShift, lstGrade, lstGradeConfig, lstDayOff); totalComputedProfileForSubmit = firstSubmit ? totalComputedProfileForSubmit : 0; dataErrorCode = unitOfWork.SaveChanges(userID); if (dataErrorCode == DataErrorCode.Locked) { break; } } #endregion } } #endregion #region Lưu kết quả tổng hợp in out listWorkdayAnalyze = listWorkday.Where(d => !listWorkdayChecked.Contains(d)).ToList(); listWorkdayChecked.AddRange(listWorkdayAnalyze); leavedayServices.AnalyzeLeaveLate(listWorkdayAnalyze, lstPrenancy, lstLateEarlyRule, listShift, lstGrade, lstGradeConfig, lstDayOff); unitOfWork.SetCorrectOrgStructureID(listWorkday); dataErrorCode = unitOfWork.SaveChanges(userID); #endregion } return listWorkday.Count(); }