Пример #1
0
 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;
 }
Пример #2
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;
            }
        }
Пример #3
0
        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
        }
Пример #4
0
        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;
        }
Пример #5
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;
            }
        }
Пример #6
0
        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;
        }
Пример #7
0
        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;
        }
Пример #8
0
        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;
        }
Пример #9
0
        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
        }
Пример #10
0
        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();
        }