Пример #1
0
 public Att_LeaveDayModel Post([Bind]Att_LeaveDayModel model)
 {
     Att_LeavedayServices services = new Att_LeavedayServices();
     model.ActionStatus = services.UpdateTotalDuration(model.lstLeaveIDs);
     return model;
 }
Пример #2
0
        public List<Sal_HoldSalaryEntity> ComputeHoldSalary(Guid? cutOffDurationID, Guid[] ProfileIDs, string orgStructureID, Guid TimeAnalyze, string userLoginName)
        {
            using (var context = new VnrHrmDataContext())
            {
                #region Get Data
                string status = string.Empty;
                List<Sal_HoldSalaryEntity> lstHoldSalaryEntity = new List<Sal_HoldSalaryEntity>();

                //ds kỳ công
                var cutOffServies = new Att_CutOffDurationServices();
                var lstObjCutOff = new List<object>();
                lstObjCutOff.Add(null);
                lstObjCutOff.Add(1);
                lstObjCutOff.Add(int.MaxValue - 1);
                var lstCutOff = cutOffServies.GetData<Att_CutOffDurationEntity>(Common.DotNetToOracle(cutOffDurationID.Value.ToString()), ConstantSql.hrm_att_sp_get_CutOffDurationById, userLoginName, ref status).FirstOrDefault();

                //ds nv
                var hrService = new Hre_ProfileServices();
                List<object> strOrgIDs = new List<object>();
                strOrgIDs.AddRange(new object[3]);
                strOrgIDs[0] = (object)orgStructureID;
                var lstProfile = hrService.GetData<Hre_ProfileEntity>(strOrgIDs, ConstantSql.hrm_hr_sp_get_ProfileIdsByOrg, userLoginName, ref status);

                if (ProfileIDs != null)
                {
                    lstProfile = lstProfile.Where(s => ProfileIDs.Contains(s.ID)).ToList();
                }

                //ds ngày nghỉ
                var leaveDayServices = new Att_LeavedayServices();
                var lstObjLeaveDay = new List<object>();
                lstObjLeaveDay.AddRange(new object[11]);
                lstObjLeaveDay[4] = lstCutOff.DateStart;
                lstObjLeaveDay[5] = lstCutOff.DateEnd;
                lstObjLeaveDay[9] = 1;
                lstObjLeaveDay[10] = int.MaxValue - 1;
                var lstLeaveDay = leaveDayServices.GetData<Att_LeaveDayEntity>(lstObjLeaveDay, ConstantSql.hrm_att_sp_get_Leaveday,userLoginName, ref status);

                //ds loại ngày nghỉ
                var leavedayTypeServices = new Cat_LeaveDayTypeServices();
                var lstObjLeavedayType = new List<object>();
                lstObjLeavedayType.Add(null);
                lstObjLeavedayType.Add(null);
                lstObjLeavedayType.Add(1);
                lstObjLeavedayType.Add(int.MaxValue - 1);
                var lstLeavedayType = leavedayTypeServices.GetData<Cat_LeaveDayTypeEntity>(lstObjLeavedayType, ConstantSql.hrm_cat_sp_get_LeaveDayType,userLoginName, ref status);

                lstObjLeavedayType = new List<object>();
                lstObjLeavedayType.Add(null);
                lstObjLeavedayType.Add(EnumDropDown.EntityType.E_CountAnalyzeHoldSalary.ToString());
                lstObjLeavedayType.Add(1);
                lstObjLeavedayType.Add(int.MaxValue - 1);
                var ListNameEntity = leavedayTypeServices.GetData<Cat_NameEntityEntity>(lstObjLeavedayType, ConstantSql.hrm_cat_sp_get_NameEntityByKPI,userLoginName, ref status);

                ////ds chế độ lương
                //var Sal_GradeServices = new Sal_GradeServices();
                //var lstObjSal_Grade = new List<object>();
                //lstObjSal_Grade.AddRange(new object[7]);
                //lstObjSal_Grade[3] = lstCutOff.DateStart;
                //lstObjSal_Grade[4] = lstCutOff.DateEnd;//sửa lại store lấy lên tất cả các grade mà ko có ngày kết thúc
                //lstObjSal_Grade[5] = 1;
                //lstObjSal_Grade[6] = int.MaxValue - 1;
                //var lstSal_Grade = Sal_GradeServices.GetData<Sal_GradeEntity>(lstObjSal_Grade, ConstantSql.hrm_sal_sp_get_Sal_Grade, ref status).ToList();

                Sys_AttOvertimePermitConfigServices Sys_Services = new Sys_AttOvertimePermitConfigServices();
                double DATECLOSE_SALARY = Sys_Services.GetConfigValue<double>(AppConfig.HRM_SAL_DATECLOSE_SALARY);

                foreach (var profile in lstProfile)
                {

                    Sal_HoldSalaryEntity entity = new Sal_HoldSalaryEntity();

                    entity.ProfileID = profile.ID;
                    entity.CodeEmp = profile.CodeEmp;
                    entity.ProfileName = profile.ProfileName;
                    entity.CodeAttendance = profile.CodeAttendance;
                    entity.EmployeeTypeName = profile.EmployeeTypeName;
                    entity.WorkPlaceName = profile.WorkPlaceName;
                    entity.IDNo = profile.IDNo;
                    entity.MonthSalary = lstCutOff.MonthYear;
                    entity.TimeAnalyzeID = TimeAnalyze;
                    entity.CatNameEntity = ListNameEntity.FirstOrDefault(m => m.ID == TimeAnalyze) != null ? ListNameEntity.FirstOrDefault(m => m.ID == TimeAnalyze).NameEntityName : "";
                    var lstLeavedayByProfileID = lstLeaveDay.Where(s => profile.ID == s.ProfileID).ToList();

                    #region NV Nghỉ việc trước ngày 18
                    if (profile.DateQuit != null)
                    {
                        if (profile.DateQuit.Value <= lstCutOff.DateEnd && profile.IsSettlement != true)
                        {
                            //if (profile.DateQuit.Value.Day <= 18)
                            //{
                            entity.Terminate = true;
                            lstHoldSalaryEntity.Add(entity);
                            continue;
                            //}
                        }
                    }
                    #endregion

                    #region kiểm tra nghỉ quá 12 ngày
                    if (lstLeavedayByProfileID.Count > 0)
                    {
                        var lstLeavedayTypeBy12 = lstLeavedayType.Where(m => m.Code == "SP" || m.Code == "SC" || m.Code == "DSP" || m.Code == "DL" || m.Code == "M").ToList();
                        var _tmp = lstLeavedayByProfileID.Where(m => !lstLeavedayTypeBy12.Any(t => t.ID == m.LeaveDayTypeID)).ToList();
                        double count = 0;
                        foreach (var i in _tmp)
                        {
                            count += i.LeaveDays != null ? (double)i.LeaveDays : 0;
                        }
                        if (count >= 12)
                        {
                            entity.DayLeave = (int)count;
                            lstHoldSalaryEntity.Add(entity);
                            continue;
                        }
                    }
                    #endregion

                    #region trường hợp đăng ký thai sản trước ngày 18
                    if (lstLeavedayByProfileID.Count > 0)
                    {
                        var lstLeavedayTypeBy12 = lstLeavedayType.Where(m => m.Code == "M").ToList();
                        var _tmp = lstLeavedayByProfileID.FirstOrDefault(m => lstLeavedayTypeBy12.Any(t => t.ID == m.LeaveDayTypeID) && m.DateStart.Day < 18);
                        if (_tmp != null)
                        {
                            entity.IsLeaveM = true;
                            lstHoldSalaryEntity.Add(entity);
                            continue;
                        }
                    }
                    #endregion

                    #region Nghỉ liên tục 3 ngày
                    if (lstLeavedayByProfileID.Count > 0)
                    {
                        var lstLeavedayTypeBy3 = lstLeavedayType.Where(m => m.Code == "D").ToList();
                        //lấy ngày nghỉ theo loại ngày nghỉ D
                        var lstLeavedayByProfileID3 = lstLeavedayByProfileID.Where(m => lstLeavedayTypeBy3.Any(t => t.ID == m.LeaveDayTypeID)).ToList();

                        lstLeavedayByProfileID3 = lstLeavedayByProfileID3.Where(m => m.DateEnd.Day <= DATECLOSE_SALARY).ToList();
                        double count = 0;
                        //còn 1 bug đó là khi đăng ký 3 dòng  liền kế ngày nhau
                        foreach (var i in lstLeavedayByProfileID3)
                        {
                            count = i.LeaveDays != null ? (double)i.LeaveDays : 0;
                            if (count >= 3)
                            {
                                entity.IsLeaveContinuous = true;
                                break;
                            }
                        }
                        if (entity.IsLeaveContinuous != null && entity.IsLeaveContinuous == true)
                        {
                            lstHoldSalaryEntity.Add(entity);
                            continue;
                        }
                    }

                    #endregion
                }
                return lstHoldSalaryEntity;
                #endregion



            }

        }
Пример #3
0
        public Att_LeaveDayModel Post([Bind]Att_LeaveDayModel model)
        {
            string status = "";
            string message = string.Empty;
            //truong hop edit 1 nhan vien
            if (model.ProfileID != Guid.Empty)
            {
                model.ProfileIds = model.ProfileID.ToString();
            }
            BaseService baseService = new BaseService();
            List<Guid> lstProfileIDs = new List<Guid>();
            #region Xu ly lay lst nhan vien cuoi cung
            //xu ly chon nhan vien hay chon phong ban
            if (!string.IsNullOrEmpty(model.ProfileIds))
            {
                List<Guid> lstMulti = new List<Guid>();
                var lst = model.ProfileIds.Split(',');
                foreach (var item in lst)
                {
                    Guid _Id = new Guid(item);
                    lstMulti.Add(_Id);
                }
                lstProfileIDs = lstMulti;
            }
            else
            {
                if (model.strOrgStructureIDs == "")
                {
                    model.strOrgStructureIDs = null;
                }
                List<object> lstObj = new List<object>();
                lstObj.Add(model.strOrgStructureIDs);
                lstObj.Add(null);
                lstObj.Add(null);
                List<Hre_ProfileEntity> lstOrg = baseService.GetData<Hre_ProfileEntity>(lstObj, ConstantSql.hrm_hr_sp_get_ProfileIdsByOrg, UserLogin, ref status).ToList();
                lstProfileIDs = lstOrg.Select(d => d.ID).ToList();
                //neu co loai tru
                if(!string.IsNullOrEmpty(model.ProfileIDsExclude) && lstProfileIDs.Count>0)
                {
                    List<Guid> lstProfileIDsExclude = new List<Guid>();
                    var lst = model.ProfileIDsExclude.Split(',');
                    foreach (var item in lst)
                    {
                        Guid _Id = new Guid(item);
                        lstProfileIDsExclude.Add(_Id);
                    }
                    lstProfileIDs = lstProfileIDs.Where(d => !lstProfileIDsExclude.Contains(d)).ToList();
                }
            }
            if (lstProfileIDs.Count()==0)
            {
                message = string.Format(ConstantMessages.FieldNotAllowNull.TranslateString(), ("ProfileID").TranslateString());
                model.ActionStatus = message;
                return model;
            }
            #endregion
            if (model.HoursFrom != null)
            {
                model.DateStart = new DateTime(model.DateStart.Year, model.DateStart.Month, model.DateStart.Day, model.HoursFrom.Value.Hour, model.HoursFrom.Value.Minute, 0);

            }
            if (model.HoursTo != null)
            {
                model.DateEnd = new DateTime(model.DateStart.Year, model.DateStart.Month, model.DateStart.Day, model.HoursTo.Value.Hour, model.HoursTo.Value.Minute, 0);
            }
            #region Validate

         
            var checkValidate = true;
            if(model.IsPortal ==true)
            {
                checkValidate = HRM.Business.Main.Domain.ValidatorService.OnValidateData<Att_LeaveDayModel>(model, "Att_LeaveDayPortal", ref message);
            }
            else
            {
                checkValidate = HRM.Business.Main.Domain.ValidatorService.OnValidateData<Att_LeaveDayModel>(model, "Att_LeaveDay", ref message);
            }
            if (!checkValidate)
            {
                model.ActionStatus = message;
                return model;
            }
            if (model.LeaveDays == 0 && model.LeaveHours == 0)
            {
                model.ActionStatus = ConstantMessages.AccessDenied.TranslateString();
                return model;
            }
            #endregion



            //TimeSpan ts = new TimeSpan(model.HoursFrom.Value.Hour, model.HoursFrom.Value.Minute, 0);
            //model.DateStart = model.DateStart + ts;


            if (model.DurationType != LeaveDayDurationType.E_FULLSHIFT.ToString())
            {
                if (model.HoursFrom.HasValue)
                    model.DateStart = new DateTime(model.DateStart.Year, model.DateStart.Month, model.DateStart.Day, model.HoursFrom.Value.Hour, model.HoursFrom.Value.Minute, model.HoursFrom.Value.Second);
                if (model.HoursTo.HasValue)
                    model.DateEnd = new DateTime(model.DateEnd.Year, model.DateEnd.Month, model.DateEnd.Day, model.HoursTo.Value.Hour, model.HoursTo.Value.Minute, model.HoursTo.Value.Second);

                if (model.DurationType == LeaveDayDurationType.E_FIRSTHALFSHIFT.ToString() || model.DurationType == LeaveDayDurationType.E_LASTHALFSHIFT.ToString())
                {
                    model.LeaveDays = 0.5;
                }
            }

            ActionService service = new ActionService(UserLogin);
            List<object> lstobject = new List<object>();
            lstobject.AddRange(new object[11]);
            //lstobject[4] = DateTime.MinValue; //DateFrom
            //lstobject[5] = DateTime.MaxValue; //DateTo
            lstobject[9] = 1;
            //lstobject[10] = int.MaxValue;
            lstobject[10] = Int32.MaxValue - 1;
      
            string strMessages = "";
            var _catLeaveDay = new Att_LeavedayServices();
            List<Att_LeaveDayEntity> lstLeaveDayInDbUpdate = _catLeaveDay.GetData<Att_LeaveDayEntity>(lstobject, ConstantSql.hrm_att_sp_get_Leaveday, UserLogin, ref status);

            #region [Hien.Nguyen] - Kiểm tra trùng khi đăng kí cùng một ngày và cùng loại ngày nghỉ

            //if (lstLeaveDayInDbUpdate != null)
            //{
            //    if (model.ID == Guid.Empty)
            //    {
            //        if (lstLeaveDayInDbUpdate.Any(m => m.ProfileID == model.ProfileID && m.DateStart <= model.DateEnd && m.DateEnd >= model.DateStart && m.LeaveDayTypeID == model.LeaveDayTypeID))
            //        {
            //            model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
            //            return model;
            //        }
            //    }
            //    else
            //    {
            //        var leaveDay = _catLeaveDay.GetData<Att_LeaveDayEntity>(model.ID, ConstantSql.hrm_att_sp_get_LeaveDayById, ref status).FirstOrDefault();
            //        if (leaveDay != null)
            //        {
            //            if (leaveDay.LeaveDayTypeID != model.LeaveDayTypeID || leaveDay.DateStart != model.DateStart || leaveDay.DateEnd != model.DateEnd || leaveDay.ProfileID != model.ProfileID)
            //            {
            //                if (lstLeaveDayInDbUpdate.Any(m => m.ProfileID == model.ProfileID && m.DateStart <= model.DateEnd && m.DateEnd >= model.DateStart && m.LeaveDayTypeID == model.LeaveDayTypeID))
            //                {
            //                    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
            //                    return model;
            //                }
            //            }
            //        }
            //    }
            //}

            #endregion

            #region Kiểm tra đăng ký trùng 1 ngày chỉ 1 loại ngày nghỉ nếu là Loại Toàn Ca, Còn lại thì 2 loại ngày nghỉ
            if (model.ID != Guid.Empty)//nếu là chỉnh sửa thì loại bỏ dòng đó ra khỏi list tổng
            {
                lstLeaveDayInDbUpdate = lstLeaveDayInDbUpdate.Where(m => m.ID != model.ID).ToList();
            }
            if (model.DurationType == LeaveDayDurationType.E_FULLSHIFT.ToString())//Toàn ca chỉ được dk 1 dòng
            {
                if (lstLeaveDayInDbUpdate.Any(m => lstProfileIDs.Contains(m.ProfileID) && m.DateStart <= model.DateEnd && m.DateEnd >= model.DateStart))
                {
                    //model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
                    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + string.Format(ConstantMessages.FieldDuplicate.TranslateString(), ConstantDisplay.HRM_Evaluation_Information.TranslateString()));
                    return model;
                }
            }
            else//Ngược lại thì đk 2 dòng
            {
                if (lstLeaveDayInDbUpdate.Any(m => lstProfileIDs.Contains(m.ProfileID) && m.DateStart <= model.DateEnd && m.DateEnd >= model.DateStart && m.DurationType == LeaveDayDurationType.E_FULLSHIFT.ToString()))
                {
                    //  model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
                    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + string.Format(ConstantMessages.FieldDuplicate.TranslateString(), ConstantDisplay.HRM_Evaluation_Information.TranslateString()));
                    return model;
                }
                else if (lstLeaveDayInDbUpdate.Where(m => lstProfileIDs.Contains(m.ProfileID) && m.DateStart <= model.DateEnd && m.DateEnd >= model.DateStart && m.DurationType != LeaveDayDurationType.E_FULLSHIFT.ToString()).Count() > 1)
                {
                    // model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
                    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + string.Format(ConstantMessages.FieldDuplicate.TranslateString(), ConstantDisplay.HRM_Evaluation_Information.TranslateString()));
                    return model;
                }
            }


            #endregion

            #region Triet.Mai Kiểm tra vượt giới hạn cho 1 tháng
            //string[] ProfileArr = model.ProfileIds.Split(',');
            //List<Guid> lstProfileID = new List<Guid>();
            //foreach (var item in lstProfileIDs)
            //{
            //    Guid ProfileID = item;
            //    //Guid.TryParse(item, out ProfileID);
            //    if (ProfileID != Guid.Empty)
            //        lstProfileID.Add(ProfileID);
            //}
            var LeaveDayEntity = model.CopyData<Att_LeaveDayEntity>();
            string Error = (new Att_LeavedayServices()).ValidateOverDayInMonth(LeaveDayEntity, lstProfileIDs);
            if (Error != string.Empty)
            {
                model.SetPropertyValue(Constant.ActionStatus, Error);
                return model;
            }
            #endregion

            List<Att_LeaveDayEntity> lstSM = new List<Att_LeaveDayEntity>();
            Att_ProcessApprovedServices smService = new Att_ProcessApprovedServices();

            if (!string.IsNullOrEmpty(model.ProfileIds))
            {
            
                //string[] arrProfileIds = model.ProfileIds.Split(',');
                strMessages = "";
                if (strMessages != "")
                {
                    // model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
                    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + string.Format(ConstantMessages.FieldDuplicate.TranslateString(), ConstantDisplay.HRM_Evaluation_Information.TranslateString()));
                    return model;
                }
                else
                {
                    var leavedayTypeServices = new Cat_LeaveDayTypeServices();
                    var lstLeavedayType = leavedayTypeServices.GetData<Cat_LeaveDayTypeEntity>(model.LeaveDayTypeID, ConstantSql.hrm_cat_sp_get_LeaveDayTypeById, UserLogin, ref status).FirstOrDefault();


                    if (lstProfileIDs.Count()==1)
                    {

                        var guiId = lstProfileIDs[0];
                        Att_LeaveDayModel modelSave = model.CopyData<Att_LeaveDayModel>();
                        modelSave.ProfileID = guiId;
                        #region Kiểm tra Tổng Số Ngày Nghỉ
                        if (lstLeavedayType != null)
                        {
                            if (model.LeaveDays > lstLeavedayType.MaxPerTimes)
                            {
                                modelSave.ActionStatus = "ErrorTotalLeave";
                                return modelSave;
                            }
                            if (model.LeaveDays > lstLeavedayType.MaxPerYear)
                            {
                                modelSave.ActionStatus = "ErrorTotalLeave";
                                return modelSave;
                            }
                        }
                        #endregion

                        modelSave = service.UpdateOrCreate<Att_LeaveDayEntity, Att_LeaveDayModel>(modelSave);
                        if (modelSave.ActionStatus == NotificationType.Success.ToString())
                        {
                            lstSM.Add(modelSave.Copy<Att_LeaveDayEntity>());
                        }
                        smService.GetEmailToSend_LeaveDay(lstSM, UserLogin);
                        return modelSave;
                    }
                  
                    foreach (var ProfileId in lstProfileIDs)
                    {
                        var guiId = ProfileId;
                        Att_LeaveDayModel modelSave = model.CopyData<Att_LeaveDayModel>();
                        modelSave.ProfileID = guiId;

                        #region Kiểm tra Tổng Số Ngày Nghỉ
                        if (lstLeavedayType != null)
                        {
                            if (model.LeaveDays > lstLeavedayType.MaxPerTimes)
                            {
                                modelSave.ActionStatus = "ErrorTotalLeave";
                                return modelSave;
                            }
                            if (model.LeaveDays > lstLeavedayType.MaxPerYear)
                            {
                                modelSave.ActionStatus = "ErrorTotalLeave";
                                return modelSave;
                            }
                        }
                        #endregion

                        modelSave = service.UpdateOrCreate<Att_LeaveDayEntity, Att_LeaveDayModel>(modelSave);
                        if (modelSave.ActionStatus == NotificationType.Success.ToString())
                        {
                            lstSM.Add(modelSave.Copy<Att_LeaveDayEntity>());
                        }
                        else
                        {
                            smService.GetEmailToSend_LeaveDay(lstSM, UserLogin);
                            return modelSave;
                        }
                    }
                }
                smService.GetEmailToSend_LeaveDay(lstSM, UserLogin);

                model.SetPropertyValue(Constant.ActionStatus, NotificationType.Success.ToString());
                return model;
            }
            else
            {
                //Đã kiểm tra ở trên , nên không cần kt dưới này - [hien.nguyen]
                //if (lstLeaveDayInDbUpdate != null && lstLeaveDayInDbUpdate.Any(d => d.ID != model.ID && d.ProfileID == model.ProfileID && d.DateStart <= model.DateEnd && d.DateEnd >= model.DateStart))
                //{
                //    strMessages = lstLeaveDayInDbUpdate.Where(d => d.ProfileID == model.ProfileID).FirstOrDefault().ProfileName;
                //    model.SetPropertyValue(Constant.ActionStatus, NotificationType.Error + "," + strMessages + ConstantMessages.FieldDuplicate);
                //    return model;
                //}
                //else
                model = service.UpdateOrCreate<Att_LeaveDayEntity, Att_LeaveDayModel>(model);
                if (model.ActionStatus == NotificationType.Success.ToString())
                {
                    lstSM.Add(model.Copy<Att_LeaveDayEntity>());
                    smService.GetEmailToSend_LeaveDay(lstSM, UserLogin);
                }
                return model;
            }
        }
Пример #4
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;
            }
        }
Пример #5
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();
        }