//Quy tắc phép bù của honda cập nhật trong file tài liệu /// <summary> /// Hàm tính ra số phép bù của nhân viên hiện tại /// </summary> /// <param name="ProfileID">ID của nhân viên</param> /// <param name="lstTimeOff4Ago">Ds trong bảng Att_TimeOffInLieu của nhân viên từ 3 tháng trước cho đến hiện tại</param> /// <param name="lstTimeOffByMonth3Ago">Ds trong bảng Att_TimeOffInLieuMonth của nhân viên tính theo 3 tháng trước tháng hiện tại</param> /// <param name="monthYear">Tháng Hiện tại</param> /// <param name="lstTimeOffByMonthNEW">Ds sẽ phát sinh ra thi tính công thì sẽ lưu Ds này</param> /// <param name="isFromValidateLeaveDay">Nếu validate từ ngày nghỉ thì TRUE ngươc lại từ tính công thi FALSE</param> /// <param name="dateStartOfMonth">Ngày bắt đầu của Tháng, Honda là ngày 1</param> /// <returns></returns> public double? CalculateTotalHourTimeOff(Guid ProfileID, List<Att_TimeOffInLieu> lstTimeOff4Ago, List<Att_TimeOffInLieuMonth> lstTimeOffByMonth3Ago, DateTime monthYear, int dateStartOfMonth) { monthYear = new DateTime(monthYear.Year, monthYear.Month, 1); lstTimeOffByMonth3Ago = lstTimeOffByMonth3Ago.Where(m => m.Month != monthYear).ToList(); if (lstTimeOffByMonth3Ago.Where(m => m.Month != null).ToList().Count == 0) return null; List<Att_TimeOffInLieuMonth> lstTimeOffByMonth_Auto_NEW = new List<Att_TimeOffInLieuMonth>(); Att_TimeOffInLieuMonth TimeOffInLieuMonthNew = lstTimeOffByMonth3Ago.OrderByDescending(m => m.Month).FirstOrDefault(); DateTime monthInLastTimeOff_inMonth = TimeOffInLieuMonthNew.Month ?? monthYear; for (DateTime MonthCheck = monthInLastTimeOff_inMonth.AddMonths(1); MonthCheck <= monthYear; MonthCheck = MonthCheck.AddMonths(1)) { DateTime beginMonth = new DateTime(MonthCheck.Year, MonthCheck.Month, dateStartOfMonth); DateTime endMonth = beginMonth.AddMonths(1).AddMinutes(-1); //DK.m = IF(Giam(m-1)>=DK(m-1), CK(m-1), IF(Giam(m-1) < DK(m-1),Tang(m-1),CK(m-1)) DateTime monthTimeOff_Inmonth = MonthCheck.AddMonths(-1); Att_TimeOffInLieuMonth TimeOffInLieuLast = lstTimeOffByMonth3Ago.Where(m => m.Month == monthTimeOff_Inmonth).FirstOrDefault(); if (TimeOffInLieuLast == null) { TimeOffInLieuLast = lstTimeOffByMonth_Auto_NEW.Where(m => m.Month == monthTimeOff_Inmonth).FirstOrDefault(); } if (TimeOffInLieuLast == null) return null; double Balance = 0; if ((TimeOffInLieuLast.TakenLeaves ?? 0) >= (TimeOffInLieuLast.BalanceLeaves ?? 0)) { Balance = TimeOffInLieuLast.RemainLeaves ?? 0; } else { Balance = TimeOffInLieuLast.UnusualLeaves ?? 0; } Att_TimeOffInLieuMonth LieuMonth_New = new Att_TimeOffInLieuMonth(); LieuMonth_New.ProfileID = ProfileID; LieuMonth_New.Month = MonthCheck; LieuMonth_New.BalanceLeaves = Balance; LieuMonth_New.UnusualLeaves = lstTimeOff4Ago.Where(m => m.ProfileID == ProfileID && m.Date >= beginMonth && m.Date < endMonth).Sum(m => m.UnusualLeaves); LieuMonth_New.TakenLeaves = lstTimeOff4Ago.Where(m => m.ProfileID == ProfileID && m.Date >= beginMonth && m.Date < endMonth).Sum(m => m.TakenLeaves); LieuMonth_New.RemainLeaves = LieuMonth_New.BalanceLeaves + LieuMonth_New.UnusualLeaves - LieuMonth_New.TakenLeaves; lstTimeOffByMonth_Auto_NEW.Add(LieuMonth_New); } //if (!isFromValidateLeaveDay) //{ // lstTimeOffByMonthNEW = lstTimeOffByMonth_Auto_NEW; //} if (lstTimeOffByMonth_Auto_NEW.Where(m => m.Month == monthYear).ToList().Count > 0) { return lstTimeOffByMonth_Auto_NEW.Where(m => m.Month == monthYear).FirstOrDefault().RemainLeaves; } return null; }
private int ComputeAttendance(Guid userID, Guid asynTaskID, DateTime monthYear, Guid cutOffDurationID, out DataErrorCode dataErrorCode, int totalProfile, int totalComputed, params Hre_ProfileEntity[] listProfile) { using (var context = new VnrHrmDataContext()) { IUnitOfWork unitOfWork = new UnitOfWork(context); int attendanceTableCount = 0; List<Guid> listProfileID = listProfile.Select(s => s.ID).ToList(); totalProfile = totalProfile <= 0 ? listProfileID.Count() : totalProfile; #region Xóa bảng công cũ đã tính trước đó dataErrorCode = DeleteAttendance(monthYear, cutOffDurationID, listProfileID); if (dataErrorCode == DataErrorCode.Locked || dataErrorCode == DataErrorCode.Error) { return attendanceTableCount; } #endregion #region Tính khoảng thời gian theo cutOffDurationID DateTime attendanceFrom = monthYear.AddDays(1 - monthYear.Day).Date; DateTime attendanceTo = attendanceFrom.AddMonths(1).AddSeconds(-1); var cutOffDuration = unitOfWork.CreateQueryable<Att_CutOffDuration>(Guid.Empty, d => d.ID == cutOffDurationID).Select(d => new { d.DateStart, d.DateEnd, d.OvertimeStart, d.OvertimeEnd, d.LeavedayStart, d.LeavedayEnd, }).FirstOrDefault(); if (cutOffDuration != null) { attendanceFrom = cutOffDuration.DateStart; attendanceTo = cutOffDuration.DateEnd; } #endregion #region Tải các thông tin danh mục có liên quan string overTimeMethod = MethodOption.E_CASHOUT.ToString(); string overTimeStatus = OverTimeStatus.E_APPROVED.ToString(); string pregnancyType = PregnancyType.E_LEAVE_EARLY.ToString(); string leaveStatus = LeaveDayStatus.E_APPROVED.ToString(); string hdtJobStatus = HDTJobStatus.E_APPROVE.ToString(); string leavedayTypeNOPAY = LeavedayTypeCode.NOPAY.ToString(); string leavedayTypeABS = LeavedayTypeCode.ABS.ToString(); string leavedayTypeHLD = LeavedayTypeCode.HLD.ToString(); string rosterStatus = RosterStatus.E_APPROVED.ToString(); string NOTAUTOREGISTERHOLIDAYLEAVE = AppConfig.HRM_ATT_NOTAUTOREGISTERHOLIDAYLEAVE.ToString(); string OT_HOLIDAYSCOMPUTE400 = AppConfig.HRM_ATT_OT_HOLIDAYSCOMPUTE400.ToString(); string MISSTAM_LEAVETYPE = AppConfig.HRM_ATT_MISSTAM_LEAVETYPE.ToString(); string HRM_ATT_OT_OVERTIMESTATUS = AppConfig.HRM_ATT_OT_OVERTIMESTATUS.ToString(); var standardWorkdayConfig = unitOfWork.CreateQueryable<Sys_AllSetting>(d => d.Name == NOTAUTOREGISTERHOLIDAYLEAVE || d.Name == OT_HOLIDAYSCOMPUTE400 || d.Name == MISSTAM_LEAVETYPE || d.Name == HRM_ATT_OT_OVERTIMESTATUS).ToList(); var notAutoRegHolidayLeave = standardWorkdayConfig.Where(s => s.Name == NOTAUTOREGISTERHOLIDAYLEAVE).FirstOrDefault(); var otholidayscompute400 = standardWorkdayConfig.Where(s => s.Name == OT_HOLIDAYSCOMPUTE400).FirstOrDefault(); var missTAM_LeaveType = standardWorkdayConfig.Where(s => s.Name == MISSTAM_LEAVETYPE).FirstOrDefault(); var statusOT = standardWorkdayConfig.Where(s => s.Name == HRM_ATT_OT_OVERTIMESTATUS).FirstOrDefault(); if (statusOT != null) { overTimeStatus = statusOT.Value1; } DateTime startYear = new DateTime(monthYear.Year, 1, 1).AddMonths(-1);//đầu năm DateTime endYear = new DateTime(monthYear.Year, 12, 31).Date.AddDays(1).AddSeconds(-1); DateTime preMonthYear = monthYear.AddMonths(-1); List<Cat_DayOff> listHoliday = unitOfWork.CreateQueryable<Cat_DayOff>(d => d.DateOff >= startYear && d.DateOff <= endYear).ToList(); //Tất cả roster từ đầu năm đến thời điểm tính công - cần cho mục tính tính phép năm còn lại cho từng nhân viên. var listRoster = unitOfWork.CreateQueryable<Att_Roster>(d => d.DateStart <= attendanceTo && d.DateEnd >= startYear && d.Status == rosterStatus && 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>(m => m.DateStart != null && m.DateEnd != null && m.DateStart <= attendanceTo && m.DateEnd >= attendanceFrom).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 listWorkHistory = unitOfWork.CreateQueryable<Hre_WorkHistory>(d => d.DateEffective <= attendanceTo && listProfileID.Contains(d.ProfileID)).ToList(); List<Att_Roster> lstRosterTypeGroup = new List<Att_Roster>(); List<Att_RosterGroup> lstRosterGroup = new List<Att_RosterGroup>(); GetRosterGroup(listProfileID, startYear, attendanceTo, out lstRosterTypeGroup, out lstRosterGroup); var listLateEarlyRule = unitOfWork.CreateQueryable<Cat_LateEarlyRule>().ToList<Cat_LateEarlyRule>(); var listShift = unitOfWork.CreateQueryable<Cat_Shift>().ToList<Cat_Shift>(); var currentYear = unitOfWork.CreateQueryable<Att_AnnualDetail>(d => monthYear == d.MonthYear).Select(d => d.Year).FirstOrDefault(); var monthStart = unitOfWork.CreateQueryable<Att_AnnualDetail>(d => d.Year == currentYear).OrderBy(d => d.MonthYear).Select(d => d.MonthYear).FirstOrDefault(); var listAnnualDetail = unitOfWork.CreateQueryable<Att_AnnualDetail>(d => d.MonthYear == monthStart && d.ProfileID.HasValue && listProfileID.Contains(d.ProfileID.Value)); var listPreAttendanceTable = unitOfWork.CreateQueryable<Att_AttendanceTable>(d => d.MonthYear.HasValue && d.MonthYear == preMonthYear && listProfileID.Contains(d.ProfileID)).Select(d => new Att_AttendanceTableEntity { ID = d.ID, AnlDayTaken = d.AnlDayTaken, AnlDayAdjacent = d.AnlDayAdjacent, SickDayTaken = d.SickDayTaken, SickDayAdjacent = d.SickDayAdjacent, AnlDayAvailable = d.AnlDayAvailable, SickDayAvailable = d.SickDayAvailable, ProfileID = d.ProfileID }).ToList<Att_AttendanceTableEntity>(); var listPregnancy = unitOfWork.CreateQueryable<Att_Pregnancy>(d => d.DateEnd >= attendanceFrom && d.DateStart <= attendanceTo && d.Type == pregnancyType && listProfileID.Contains(d.ProfileID)).Select(d => new Att_PregnancyEntity { ID = d.ID, ProfileID = d.ProfileID, DateStart = d.DateStart, DateEnd = d.DateEnd, TypePregnancyEarly = d.TypePregnancyEarly }).ToList<Att_PregnancyEntity>(); var listOvertime = unitOfWork.CreateQueryable<Att_Overtime>(d => d.Status == overTimeStatus && (d.MethodPayment == null || d.MethodPayment == overTimeMethod) && d.WorkDateRoot >= attendanceFrom && d.WorkDateRoot <= attendanceTo && listProfileID.Contains(d.ProfileID)).Select(d => new Att_OvertimeEntity { ID = d.ID, ProfileID = d.ProfileID, OvertimeTypeID = d.OvertimeTypeID, DurationType = d.DurationType, WorkDateRoot = d.WorkDateRoot, WorkDate = d.WorkDate, ApproveHours = d.ApproveHours, ConfirmHours = d.ConfirmHours, RegisterHours = d.RegisterHours }).ToList<Att_OvertimeEntity>(); List<Guid> listOvertimeTypeID = listOvertime.Select(o => o.OvertimeTypeID).Distinct().ToList(); var listOvertimeType = unitOfWork.CreateQueryable<Cat_OvertimeType>(d => listOvertimeTypeID.Contains(d.ID)).ToList(); var listLeaveDay = unitOfWork.CreateQueryable<Att_LeaveDay>(d => d.Status == leaveStatus && ((d.DateStart <= attendanceTo && d.DateEnd >= attendanceFrom) || d.DateOvertimeOff >= attendanceFrom && d.DateOvertimeOff <= attendanceTo) && listProfileID.Contains(d.ProfileID)).Select(d => new Att_LeaveDayEntity { ID = d.ID, ProfileID = d.ProfileID, DateStart = d.DateStart, DateEnd = d.DateEnd, DateOvertimeOff = d.DateOvertimeOff, LeaveDayTypeID = d.LeaveDayTypeID, DurationType = d.DurationType, LeaveHours = d.LeaveHours, LeaveDays = d.LeaveDays }).ToList<Att_LeaveDayEntity>(); List<Guid> listLeaveDayTypeID = listLeaveDay.Select(o => o.LeaveDayTypeID).Distinct().ToList(); var listLeaveDayType = unitOfWork.CreateQueryable<Cat_LeaveDayType>(d => listLeaveDayTypeID.Contains(d.ID) || d.Code == leavedayTypeABS || d.Code == leavedayTypeNOPAY || d.Code == leavedayTypeHLD).ToList(); List<Hre_HDTJob> listHDTJob = new List<Hre_HDTJob>(); foreach (var templstProfileIds in listProfileID.Chunk(1000)) { listHDTJob.AddRange(unitOfWork.CreateQueryable<Hre_HDTJob>(d => d.Status == hdtJobStatus && ((d.DateFrom <= attendanceTo && d.DateTo == null) || (d.DateTo != null && d.DateFrom <= attendanceTo && d.DateTo >= attendanceFrom)) && templstProfileIds.Contains(d.ProfileID.Value)).ToList()); } //var listHDTJob = unitOfWork.CreateQueryable<Hre_HDTJob>(d => d.Status == hdtJobStatus && ((d.DateFrom <= attendanceTo && d.DateTo == null) // || (d.DateTo != null && d.DateFrom <= attendanceTo && d.DateTo >= attendanceFrom)) && listProfileID.Contains(d.ProfileID.Value)).ToList(); //Danh sách cấu hình grade theo danh sách nhân viên có trong danh sách mã thẻ var listGrade = unitOfWork.CreateQueryable<Att_Grade>(d => d.MonthStart.HasValue && d.MonthStart <= attendanceTo && listProfileID.Contains(d.ProfileID.Value)).Select(d => new { d.ProfileID, d.MonthStart, d.GradeAttendanceID }).ToList(); listGrade = listGrade.GroupBy(d => d.ProfileID).Select(d => d.OrderByDescending(p => p.MonthStart).FirstOrDefault()).ToList(); //Danh sách cấu hình gradeCfg theo danh sách grade tìm được ở trên var listGradeCfgID = listGrade.Select(d => d.GradeAttendanceID).Distinct().ToList(); var listGradeCfg = unitOfWork.CreateQueryable<Cat_GradeAttendance>(d => listGradeCfgID.Contains(d.ID)).ToList(); var lstTimeOffInLieu = unitOfWork.CreateQueryable<Att_TimeOffInLieu>(d => d.Date != null && d.Date >= attendanceFrom && d.Date <= attendanceTo).Select(m => new { m.ProfileID, m.UnusualLeaves, m.TakenLeaves }).ToList(); DateTime month3Ago = new DateTime(attendanceTo.Year, attendanceTo.Month, 1); month3Ago = month3Ago.AddMonths(-3); List<Att_TimeOffInLieuMonth> lstTimeOffInLieu_ByMonth_3Month = unitOfWork.CreateQueryable<Att_TimeOffInLieuMonth>(d => d.Month != null && d.Month >= month3Ago && d.Month <= attendanceTo && listProfileID.Contains(d.ProfileID)).ToList(); List<Att_TimeOffInLieuMonth> lstTimeOffInLieuMonth = lstTimeOffInLieu_ByMonth_3Month.Where(d => d.Month != null && d.Month >= attendanceFrom && d.Month <= attendanceTo).ToList<Att_TimeOffInLieuMonth>(); List<Att_TimeOffInLieuMonth> lstTimeOffInLieuMonthInsert = new List<Att_TimeOffInLieuMonth>(); DateTime beginYear = new DateTime(attendanceTo.Year, 1, 1); #endregion #region Bắt đầu tính công cho từng người var listWorkDay = unitOfWork.CreateQueryable<Att_Workday>(d => d.WorkDate >= attendanceFrom && d.WorkDate <= attendanceTo && listProfileID.Contains(d.ProfileID)).ToList(); List<Att_TimeOffInLieu> lstTimeOffInLieu_3Month = unitOfWork.CreateQueryable<Att_TimeOffInLieu>(d => d.Date >= month3Ago && d.Date <= attendanceTo && listProfileID.Contains(d.ProfileID)).ToList(); var listTimeOffInLieu = lstTimeOffInLieu_3Month.Where(s => listProfileID.Contains(s.ProfileID) && attendanceFrom <= s.Date && s.Date <= attendanceTo).Select(s => new Att_TimeOffInLieuEntity { ID = s.ID, Date = s.Date, ProfileID = s.ProfileID, OvertimeID = s.OvertimeID, LeaveDayID = s.LeaveDayID, UnusualLeaves = s.UnusualLeaves, LeaveHours = s.LeaveHours, TakenLeaves = s.TakenLeaves }).ToList<Att_TimeOffInLieuEntity>(); using (var taskContext = new VnrHrmDataContext()) { IUnitOfWork 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 = 50; int totalComputedProfileForSubmit = 0; int totalComputedProfileForTask = 0; totalComputedProfileMustSubmitTask = totalProfile * 5 / 100; if (totalComputedProfileMustSubmitTask > listProfile.Count()) { totalComputedProfileMustSubmitTask = listProfile.Count(); } foreach (var profileId in listProfileID) { try { #region Những dữ liệu liên quan tính công theo từng nhân viên var profile = listProfile.Where(d => d.ID == profileId).FirstOrDefault(); var listAnnualDetailByProfile = listAnnualDetail.Where(d => d.ProfileID == profileId).ToList(); var listPreAttendanceTableByProfile = listPreAttendanceTable.Where(d => d.ProfileID == profileId).ToList(); var listWorkDayByProfile = listWorkDay.Where(d => d.ProfileID == profileId).OrderBy(d => d.WorkDate).ToList(); var listTimeOffInLieuByProfile = listTimeOffInLieu.Where(d => d.ProfileID == profileId).ToList(); var listHDTJobByProfile = listHDTJob.Where(d => d.ProfileID == profileId).ToList(); var listPregnancyByProfile = listPregnancy.Where(prg => prg.ProfileID == profileId && prg.DateEnd >= attendanceFrom && prg.DateStart <= attendanceTo).ToList(); var listLeaveDayByProfile = listLeaveDay.Where(d => d.ProfileID == profileId && ((d.DateStart <= attendanceTo && d.DateEnd >= attendanceFrom) || (d.DateOvertimeOff.HasValue && d.DateOvertimeOff >= attendanceFrom && d.DateOvertimeOff <= attendanceTo))).ToList(); var listOvertimeByProfile = listOvertime.Where(d => d.ProfileID == profileId && d.WorkDate >= attendanceFrom && d.WorkDate <= attendanceTo).ToList(); var gradeCfgIDByProfile = listGrade.Where(d => d.ProfileID == profileId && d.MonthStart <= attendanceTo).Select(d => d.GradeAttendanceID).FirstOrDefault(); var gradeCfgByProfile = listGradeCfg.Where(d => d.ID == gradeCfgIDByProfile).FirstOrDefault(); List<Hre_WorkHistory> listWorkHistoryByProfile = listWorkHistory.Where(d => d.ProfileID == profileId).ToList(); var listRosterByProfile = listRoster.Where(d => d.ProfileID == profileId && d.DateStart <= attendanceTo && d.DateEnd >= attendanceFrom).ToList(); var listMonthShifts = Att_AttendanceLib.GetDailyShifts(attendanceFrom, attendanceTo, profile.ID, listRosterByProfile, listRosterGroup); #endregion attendanceTableCount += ComputeAttendance(unitOfWork, userID, monthYear, cutOffDurationID, attendanceFrom, attendanceTo, profile, gradeCfgByProfile, listShift, listAnnualDetailByProfile, listHDTJobByProfile, listLeaveDayByProfile, listLeaveDayType, listOvertimeByProfile, listOvertimeType, listPregnancyByProfile, listLateEarlyRule, listWorkDayByProfile, listPreAttendanceTableByProfile, listTimeOffInLieuByProfile, notAutoRegHolidayLeave, otholidayscompute400, missTAM_LeaveType, listMonthShifts, listHoliday); #region Cập Nhật Dữ Liệu Cho Việc Tính TimeOffInLieuMonth and Year double? balanceLeaves = (new Att_LeavedayServices()).CalculateTotalHourTimeOff(profileId, lstTimeOffInLieu_3Month.Where(m => m.ProfileID == profileId).ToList(), lstTimeOffInLieu_ByMonth_3Month.Where(m => m.ProfileID == profileId).ToList(), monthYear, 1); double UnusualLeaves = lstTimeOffInLieu.Where(m => m.ProfileID == profileId).Sum(m => m.UnusualLeaves ?? 0); double TakenLeaves = lstTimeOffInLieu.Where(m => m.ProfileID == profileId).Sum(m => m.TakenLeaves ?? 0); double RemainLeaves = UnusualLeaves - TakenLeaves + (balanceLeaves ?? 0); var timeOffInLieuMonth_ByProfile = lstTimeOffInLieuMonth.Where(m => m.ProfileID == profileId).FirstOrDefault(); if (timeOffInLieuMonth_ByProfile == null) { //tạo mới timeOffInLieuMonth_ByProfile = new Att_TimeOffInLieuMonth(); timeOffInLieuMonth_ByProfile.ID = Guid.NewGuid(); timeOffInLieuMonth_ByProfile.ProfileID = profileId; timeOffInLieuMonth_ByProfile.BalanceLeaves = balanceLeaves ?? 0; timeOffInLieuMonth_ByProfile.UnusualLeaves = UnusualLeaves; timeOffInLieuMonth_ByProfile.TakenLeaves = TakenLeaves; timeOffInLieuMonth_ByProfile.RemainLeaves = RemainLeaves; timeOffInLieuMonth_ByProfile.Month = new DateTime(attendanceTo.Year, attendanceTo.Month, 1); unitOfWork.AddObject(typeof(Att_TimeOffInLieuMonth), timeOffInLieuMonth_ByProfile); } else { //chinh sua timeOffInLieuMonth_ByProfile.BalanceLeaves = balanceLeaves ?? 0; timeOffInLieuMonth_ByProfile.UnusualLeaves = UnusualLeaves; timeOffInLieuMonth_ByProfile.TakenLeaves = TakenLeaves; timeOffInLieuMonth_ByProfile.RemainLeaves = RemainLeaves; } #endregion #region Chia thành nhiều giai đoạn lưu bảng công if (asynTask != null) { totalComputedProfileForTask++; double percent = (double)totalComputedProfileForTask / (double)totalProfile; if (totalComputedProfileForTask >= totalComputedProfileMustSubmitTask) { asynTask.PercentComplete = asynTask.PercentComplete + percent; dataErrorCode = taskUnitOfWork.SaveChanges(userID); totalComputedProfileForTask = 0; if (dataErrorCode == DataErrorCode.Locked) { break; } } } //Nên submit lần đầu tiên khi đã tính được 5 profile bool firstSubmit = listProfileID.ToList().IndexOf(profileId) == 5; firstSubmit = totalComputed >= 5 ? false : firstSubmit;//đã chạy 1 lần totalComputedProfileForSubmit++; if (firstSubmit || totalComputedProfileForSubmit >= totalComputedProfileMustSubmit) { totalComputedProfileForSubmit = firstSubmit ? totalComputedProfileForSubmit : 0; dataErrorCode = unitOfWork.SaveChanges(userID); if (dataErrorCode == DataErrorCode.Locked) { break; } } #endregion } catch { throw new Exception(profileId.ToString()); } } } #endregion //Lưu tất cả kết quả tính công dataErrorCode = unitOfWork.SaveChanges(userID); return attendanceTableCount; } }