diff --git a/CompanyManagment.App.Contracts/RollCall/ShiftList.cs b/CompanyManagment.App.Contracts/RollCall/ShiftList.cs index d1a20eb0..e405366e 100644 --- a/CompanyManagment.App.Contracts/RollCall/ShiftList.cs +++ b/CompanyManagment.App.Contracts/RollCall/ShiftList.cs @@ -6,4 +6,24 @@ public class ShiftList { public DateTime Start { get; set; } public DateTime End { get; set; } + /// + /// تاخیر در ورود (مدت زمانی که کارمند با تأخیر وارد شده است) + /// + public TimeSpan LateEntryDuration { get; set; } + + /// + /// تعجیل در ورود (مدت زمانی که کارمند زودتر از زمان مشخص وارد شده است) + /// + public TimeSpan EarlyEntryDuration { get; set; } + + /// + /// تاخیر در خروج (مدت زمانی که کارمند با تأخیر از کار خارج شده است) + /// + public TimeSpan LateExitDuration { get; set; } + + /// + /// تعجیل در خروج (مدت زمانی که کارمند زودتر از زمان مشخص از کار خارج شده است) + /// + public TimeSpan EarlyExitDuration { get; set; } + } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs b/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs index 7f109b31..7c1c2ace 100644 --- a/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs @@ -40,6 +40,7 @@ public class RollCallMandatoryRepository : RepositoryBase, IRoll private readonly ILeftWorkRepository _leftWorkRepository; private readonly ILeaveRepository _leaveRepository; + public RollCallMandatoryRepository(CompanyContext context, IYearlySalaryRepository yearlySalaryRepository, ILeftWorkRepository leftWorkRepository, ILeaveRepository leaveRepository) : base(context) { @@ -1610,7 +1611,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) - public CustomizeCheckoutMandatoryViewModel CustomizeCheckoutMandatoryComputeForKebabMahdi(long employeeId, long workshopId, + public CustomizeCheckoutMandatoryViewModel CustomizeCheckoutMandatoryComputeForKebabMahdi(long employeeId, + long workshopId, DateTime contractStart, DateTime contractEnd) { var checkoutEnd = contractEnd; @@ -1619,11 +1621,13 @@ CreateWorkingHoursTemp command, bool holidayWorking) { return CheckoutWithoutCalculationForKebabMahdi(workshopId, employeeId, contractStart, contractEnd); } + var firstDayOfMonth = $"{(contractStart.ToFarsi())[..8]}/01".ToGeorgianDateTime(); #region LeftWork - var leftWork = _leftWorkRepository.GetByWorkshopIdEmployeeIdInDates(workshopId, employeeId, contractStart, contractEnd); + var leftWork = + _leftWorkRepository.GetByWorkshopIdEmployeeIdInDates(workshopId, employeeId, contractStart, contractEnd); if (leftWork.StartWorkDateGr > contractStart) { @@ -1635,7 +1639,9 @@ CreateWorkingHoursTemp command, bool holidayWorking) contractEnd = leftWork.LeftWorkDateGr.AddDays(-1); } - TimeSpan leftWorkDurationTimeSpan = leftWork.HasLeft ? leftWork.LeftWorkDateGr.AddDays(-1) - leftWork.StartWorkDateGr : contractEnd - leftWork.StartWorkDateGr; + TimeSpan leftWorkDurationTimeSpan = leftWork.HasLeft + ? leftWork.LeftWorkDateGr.AddDays(-1) - leftWork.StartWorkDateGr + : contractEnd - leftWork.StartWorkDateGr; #endregion @@ -1657,10 +1663,12 @@ CreateWorkingHoursTemp command, bool holidayWorking) TimeSpan contractDuration = contractEnd - contractStart; var employee = _context.Employees.FirstOrDefault(x => x.id == employeeId); var personnelCode = - _context.PersonnelCodeSet.FirstOrDefault(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId)?.PersonnelCode ?? 0; + _context.PersonnelCodeSet.FirstOrDefault(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId) + ?.PersonnelCode ?? 0; var contract = _context.Contracts.Where(x => x.WorkshopIds == workshopId && x.EmployeeId == employeeId && x.ContractEnd.Date >= contractStart.Date && - x.ContarctStart.Date <= contractEnd.Date).ToList()?.MaxBy(x => x.ContarctStart); + x.ContarctStart.Date <= contractEnd.Date).ToList() + ?.MaxBy(x => x.ContarctStart); var totalDays = (int)(contractEnd - contractStart).TotalDays + 1; mandatoryDays = totalDays; @@ -1670,8 +1678,9 @@ CreateWorkingHoursTemp command, bool holidayWorking) #region CustomizeSettings - CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings = _context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().FirstOrDefault(x => - x.WorkshopId == workshopId && x.EmployeeId == employeeId); + CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings = _context.CustomizeWorkshopEmployeeSettings + .AsSplitQuery().FirstOrDefault(x => + x.WorkshopId == workshopId && x.EmployeeId == employeeId); CustomizeWorkshopSettings customizeWorkshopSettings = _context.CustomizeWorkshopSettings.FirstOrDefault(x => x.WorkshopId == workshopId); //ToDo handel exception if is null @@ -1702,8 +1711,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) #endregion List rollCallResult = _context.RollCalls.Where(x => - x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.ShiftDate.Date >= contractStart.Date && - x.ShiftDate.Date <= contractEnd.Date && x.EndDate != null) + x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.ShiftDate.Date >= contractStart.Date && + x.ShiftDate.Date <= contractEnd.Date && x.EndDate != null) .Select(x => new RollCallViewModel() { StartDate = x.StartDate, @@ -1721,28 +1730,43 @@ CreateWorkingHoursTemp command, bool holidayWorking) - List groupedRollCall = rollCallResult.GroupBy(x => x.ShiftDate.Date).Select(x => new GroupedRollCalls() - { - CreationDate = x.Key, - ShiftList = x.Select(s => new ShiftList() { Start = s.StartDate!.Value, End = s.EndDate!.Value }).ToList(), - HasFriday = x.Any(s => s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value.DayOfWeek == DayOfWeek.Friday), + List groupedRollCall = rollCallResult.GroupBy(x => x.ShiftDate.Date).Select(x => + new GroupedRollCalls() + { + CreationDate = x.Key, + ShiftList = x.Select(s => new ShiftList() + { + Start = s.StartDate!.Value, + End = s.EndDate!.Value, + EarlyEntryDuration = s.EarlyEntryDuration, + EarlyExitDuration = s.EarlyExitDuration, + LateEntryDuration = s.LateEntryDuration, + LateExitDuration = s.LateExitDuration + }).ToList(), + HasFriday = x.Any(s => + s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value.DayOfWeek == DayOfWeek.Friday), - SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)) - CalculateBreakTime(customizeWorkshopEmployeeSettings.BreakTime, - new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))), + SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)) - CalculateBreakTime( + customizeWorkshopEmployeeSettings.BreakTime, + new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))), - BreakTime = CalculateBreakTime(customizeWorkshopEmployeeSettings.BreakTime, new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))), - ShiftDate = x.Key, - TotalEarlyEntryDuration = new TimeSpan(x.Sum(rollCall => rollCall.EarlyEntryDuration.Ticks)), - TotalLateEntryDuration = new TimeSpan(x.Sum(rollCall => rollCall.LateEntryDuration.Ticks)), - TotalEarlyExitDuration = new TimeSpan(x.Sum(rollCall => rollCall.EarlyExitDuration.Ticks)), - TotalLateExitDuration = new TimeSpan(x.Sum(rollCall => rollCall.LateExitDuration.Ticks)), - TotalShiftDurationTimeSpan = x.FirstOrDefault() == null ? TimeSpan.Zero : x.First().ShiftDurationTimeSpan - }).ToList(); + BreakTime = CalculateBreakTime(customizeWorkshopEmployeeSettings.BreakTime, + new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))), + ShiftDate = x.Key, + TotalEarlyEntryDuration = new TimeSpan(x.Sum(rollCall => rollCall.EarlyEntryDuration.Ticks)), + TotalLateEntryDuration = new TimeSpan(x.Sum(rollCall => rollCall.LateEntryDuration.Ticks)), + TotalEarlyExitDuration = new TimeSpan(x.Sum(rollCall => rollCall.EarlyExitDuration.Ticks)), + TotalLateExitDuration = new TimeSpan(x.Sum(rollCall => rollCall.LateExitDuration.Ticks)), + TotalShiftDurationTimeSpan = + x.FirstOrDefault() == null ? TimeSpan.Zero : x.First().ShiftDurationTimeSpan + }).ToList(); - var sumOfEmployeeShiftSpan = groupedRollCall.Any() ? groupedRollCall.First().TotalShiftDurationTimeSpan : TimeSpan.Zero; + var sumOfEmployeeShiftSpan = + groupedRollCall.Any() ? groupedRollCall.First().TotalShiftDurationTimeSpan : TimeSpan.Zero; - if (customizeWorkshopEmployeeSettings.BreakTime.BreakTimeType == BreakTimeType.WithTime && sumOfEmployeeShiftSpan != TimeSpan.Zero) + if (customizeWorkshopEmployeeSettings.BreakTime.BreakTimeType == BreakTimeType.WithTime && + sumOfEmployeeShiftSpan != TimeSpan.Zero) { sumOfEmployeeShiftSpan -= customizeWorkshopEmployeeSettings.BreakTime.BreakTimeValue.ToTimeSpan(); } @@ -1804,6 +1828,7 @@ CreateWorkingHoursTemp command, bool holidayWorking) mandatoryDays -= holiday; } + TimeSpan absentTimeSpans = new(); if ((mandatoryDays * sumOfEmployeeShiftSpan) > sumSpans) @@ -1814,11 +1839,14 @@ CreateWorkingHoursTemp command, bool holidayWorking) dailyWage = monthySalary / monthDays; - var minuteWage = sumOfEmployeeShiftSpan.TotalMinutes == 0 ? 0 : (dailyWage / sumOfEmployeeShiftSpan.TotalMinutes); + var minuteWage = sumOfEmployeeShiftSpan.TotalMinutes == 0 + ? 0 + : (dailyWage / sumOfEmployeeShiftSpan.TotalMinutes); // یافتن مرخصی ساعتی + #region LeavHourse LeaveSearchModel leaveHourseSearch = new LeaveSearchModel() @@ -1836,6 +1864,7 @@ CreateWorkingHoursTemp command, bool holidayWorking) #endregion //****افزودن مرخصی پرسنل به مجموع ساعات کار*** + #region AddEmployeeLeaves //TimeSpan workingPerDayAve = sumSpans / numberOfWorkingDay;//میانگین ساعت کار در روز @@ -1902,7 +1931,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) - sumSpans = CalculateLeavePay(sumOfEmployeeShiftSpan, absentTimeSpans, leavePermittedDays, monthDays, contractDays, sumSpans + sumSpans = CalculateLeavePay(sumOfEmployeeShiftSpan, absentTimeSpans, leavePermittedDays, monthDays, + contractDays, sumSpans , leaveValue, minuteWage, contractStart, contractEnd, out leavePayAmount, out absentsDeductionAmount); if (customizeWorkshopEmployeeSettings.LeavePay.LeavePayType != LeavePayType.None) @@ -1955,6 +1985,7 @@ CreateWorkingHoursTemp command, bool holidayWorking) Console.WriteLine(sumSpans); + #endregion //***********************************// @@ -1974,22 +2005,27 @@ CreateWorkingHoursTemp command, bool holidayWorking) //حق بیمه + #region InsurancePay InsuranceDeduction insuranceDeduction = customizeWorkshopEmployeeSettings.InsuranceDeduction; //farokhiChange - double insuranceDeductionAmount = InsurancePayCalculation(employeeId, contractStart, contractEnd, insuranceDeduction, monthySalary); + double insuranceDeductionAmount = + InsurancePayCalculation(employeeId, contractStart, contractEnd, insuranceDeduction, monthySalary); + #endregion + #region SalaryAidDeduction var salaryAidViewModel = _context.SalaryAids - .Where(x => x.SalaryAidDateTime >= checkoutStart && x.SalaryAidDateTime <= checkoutEnd && x.EmployeeId == employeeId && x.WorkshopId == workshopId).Select(x => new SalaryAidViewModel() - { - Amount = x.Amount.ToMoney(), - AmountDouble = x.Amount, - SalaryAidDateTimeFa = x.SalaryAidDateTime.ToFarsi(), - SalaryAidDateTimeGe = x.SalaryAidDateTime, - }).ToList(); + .Where(x => x.SalaryAidDateTime >= checkoutStart && x.SalaryAidDateTime <= checkoutEnd && + x.EmployeeId == employeeId && x.WorkshopId == workshopId).Select(x => new SalaryAidViewModel() + { + Amount = x.Amount.ToMoney(), + AmountDouble = x.Amount, + SalaryAidDateTimeFa = x.SalaryAidDateTime.ToFarsi(), + SalaryAidDateTimeGe = x.SalaryAidDateTime, + }).ToList(); double salaryAidDeduction = salaryAidViewModel.Sum(x => x.AmountDouble); #endregion @@ -1999,7 +2035,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) var loanInstallments = _context.Loans .Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId) .SelectMany(x => x.LoanInstallments) - .Where(i => i.InstallmentDate >= contractStart && i.InstallmentDate <= contractEnd && i.IsActive == IsActive.True) + .Where(i => i.InstallmentDate >= contractStart && i.InstallmentDate <= contractEnd && + i.IsActive == IsActive.True) .Select(x => new LoanInstallmentViewModel() { Month = x.Month, @@ -2007,7 +2044,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) Amount = x.AmountForMonth.ToMoney(), Year = x.Year, AmountDouble = x.AmountForMonth, - RemainingAmount = _context.Loans.SelectMany(l => l.LoanInstallments).Where(i => i.LoanId == x.LoanId && i.IsActive == IsActive.True && i.InstallmentDate > x.InstallmentDate) + RemainingAmount = _context.Loans.SelectMany(l => l.LoanInstallments).Where(i => + i.LoanId == x.LoanId && i.IsActive == IsActive.True && i.InstallmentDate > x.InstallmentDate) .Sum(i => i.AmountForMonth).ToMoney(), LoanAmount = _context.Loans.FirstOrDefault(l => l.id == x.LoanId).Amount.ToMoney() }).ToList(); @@ -2039,7 +2077,9 @@ CreateWorkingHoursTemp command, bool holidayWorking) #region Payments + //اضافه کاری + #region OvertimePay double overtimePayAmount = 0; @@ -2048,7 +2088,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) TimeSpan overtimeTimeSpan; - if (customizeWorkshopSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular && customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular) + if (customizeWorkshopSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular && + customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular) { overtimeTimeSpan = CalculateOvertimeSpanWithSumSpan(sumSpans, mandatoryDays, shiftSettings); } @@ -2072,7 +2113,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) groupedRollCall, mandatoryDays, sumSpans); } - overtimePayAmount = CalculateOvertimePay(overtimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage); + overtimePayAmount = + CalculateOvertimePay(overtimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage); if (overtimePayAmount >= absentsDeductionAmount) { @@ -2112,34 +2154,42 @@ CreateWorkingHoursTemp command, bool holidayWorking) x.FineAbsenceDeduction > 0); bool absentInEid = !_context.RollCalls.Any(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.ShiftDate == new DateTime(2025, 3, 20)); - if ( hasAbsents && absentInEid) + if (hasAbsents && absentInEid) { - CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, new DateTime(2025, 3, 21), RewardType.Eid, "بابت تعطیلی آخر سال"); + CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, + new DateTime(2025, 3, 21), RewardType.Eid, "بابت تعطیلی آخر سال"); } + if (absentDates.Any(x => x == new DateTime(2025, 4, 2) && createReward > 0)) { - CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, new DateTime(2025, 4, 2), RewardType.SinzdahBedar, "بابت تعطیلی روز 13 فروردین"); + CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, + new DateTime(2025, 4, 2), RewardType.SinzdahBedar, "بابت تعطیلی روز 13 فروردین"); createReward--; } if (absentDates.Any(x => x == new DateTime(2025, 4, 3) && createReward > 0)) { - CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, new DateTime(2025, 4, 3), RewardType.ChahardahFarvardin, "بابت تعطیلی روز 14 فروردین"); + CreateReward(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, + new DateTime(2025, 4, 3), RewardType.ChahardahFarvardin, "بابت تعطیلی روز 14 فروردین"); createReward--; } } #region FridayPay + double fridayPayAmount = 0; - fridayPayAmount = FridayPayCalculation(customizeWorkshopEmployeeSettings, rollCallResult, dailyWage, shiftSettings, overtimePayAmount); + fridayPayAmount = FridayPayCalculation(customizeWorkshopEmployeeSettings, rollCallResult, dailyWage, + shiftSettings, overtimePayAmount); #endregion //حق تاهل + #region MaritalAllownace + double maritalAllowancePay = 0; if (employee.MaritalStatus == "متاهل") { @@ -2159,10 +2209,13 @@ CreateWorkingHoursTemp command, bool holidayWorking) // } } } + #endregion //شب کاری + #region NightWorkPay + double nightworkPayAmount = 0; List rotatingResultList = RotatingShiftCheck(groupedRollCall); @@ -2191,17 +2244,24 @@ CreateWorkingHoursTemp command, bool holidayWorking) } } + #endregion //سنوات + #region BaseYearsPay - double baseYearsPayAmount = CalculateYearsPayAmount(employeeId, workshopId, monthySalary, contractStart, contractEnd - , customizeWorkshopEmployeeSettings.BaseYearsPay, customizeWorkshopSettings.BaseYearsPayInEndOfYear, customizeWorkshopSettings.MaxMonthDays); + + double baseYearsPayAmount = CalculateYearsPayAmount(employeeId, workshopId, monthySalary, contractStart, + contractEnd + , customizeWorkshopEmployeeSettings.BaseYearsPay, customizeWorkshopSettings.BaseYearsPayInEndOfYear, + customizeWorkshopSettings.MaxMonthDays); #endregion + //حق اولاد #region FamilyAllowancePay + double familyAllowancePay = 0; switch (customizeWorkshopEmployeeSettings.FamilyAllowance.FamilyAllowanceType) { @@ -2215,27 +2275,31 @@ CreateWorkingHoursTemp command, bool holidayWorking) case FamilyAllowanceType.Percentage: { double multiplier = customizeWorkshopEmployeeSettings.FamilyAllowance.Value / 100; - familyAllowancePay = CalculateFamilyAllowancePayAmount(employeeId, multiplier * monthySalary, contractEnd); + familyAllowancePay = + CalculateFamilyAllowancePayAmount(employeeId, multiplier * monthySalary, contractEnd); break; } } + #endregion + #region Reward var rewardViewModels = _context.Rewards.Where(x => - x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.GrantDate <= checkoutEnd && - x.GrantDate >= checkoutStart).Select(x => new RewardViewModel - { - Title = x.Title, - Amount = x.Amount.ToMoney(), - AmountDouble = x.Amount, - Description = x.Description, - GrantDateGr = x.GrantDate, - GrantDateFa = x.GrantDate.ToFarsi(), - IsActive = x.IsActive, - }).ToList(); + x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.GrantDate <= checkoutEnd && + x.GrantDate >= checkoutStart).Select(x => new RewardViewModel + { + Title = x.Title, + Amount = x.Amount.ToMoney(), + AmountDouble = x.Amount, + Description = x.Description, + GrantDateGr = x.GrantDate, + GrantDateFa = x.GrantDate.ToFarsi(), + IsActive = x.IsActive, + }).ToList(); double rewardPay = rewardViewModels.Sum(x => x.AmountDouble); + #endregion #region LeavePay @@ -2266,6 +2330,7 @@ CreateWorkingHoursTemp command, bool holidayWorking) bonusesPayAmount = (monthySalary * customizeWorkshopEmployeeSettings.BonusesPay.Value) / 100; break; } + double bonusesPerMonth = bonusesPayAmount / 12; if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.YearlyPay) @@ -2274,7 +2339,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) if (monthOfCheckout == 12 && (contractEndFarsi.EndsWith("29")) || contractEndFarsi.EndsWith("30")) { } - else if (customizeWorkshopSettings.BonusesPaysInEndOfMonth == BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft) + else if (customizeWorkshopSettings.BonusesPaysInEndOfMonth == + BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft) { TimeSpan bonusDuration; DateTime startOfYear = new PersianCalendar().ToDateTime(yearOfCheckout, 1, 1, 0, 0, 0, 0); @@ -2296,7 +2362,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) if (customizeWorkshopSettings.BonusesPaysInEndOfMonth == BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft && contractDays < monthDays) - bonusesPayAmount = (bonusesPerMonth / contractEnd.CountPersianMonthDays()) * contractDuration.TotalDays + 1; + bonusesPayAmount = (bonusesPerMonth / contractEnd.CountPersianMonthDays()) * + contractDuration.TotalDays + 1; bonusesPayAmount = bonusesPerMonth; @@ -2383,20 +2450,56 @@ CreateWorkingHoursTemp command, bool holidayWorking) double lateToWorkDeduction = 0; TimeSpan totalLateToWorkSpan = TimeSpan.Zero; - foreach (var rollCall in groupedRollCall) + + + + if (customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating) { - var rollCallShift = rollCall.TotalShiftDurationTimeSpan; - var dayMinuteWage = rollCallShift.TotalMinutes == 0 ? 0 : (dailyWage / rollCallShift.TotalMinutes); - var minutes = rollCall.TotalLateEntryDuration.TotalMinutes; - lateToWorkDeduction += dayMinuteWage * minutes; - totalLateToWorkSpan = totalLateToWorkSpan.Add(rollCall.TotalLateEntryDuration); + foreach (var rollCall in groupedRollCall) + { + + var rollCallShift = rollCall.TotalShiftDurationTimeSpan; + var dayMinuteWage = rollCallShift.TotalMinutes == 0 ? 0 : (dailyWage / rollCallShift.TotalMinutes); + (DateTime start, DateTime end)? firstShift = null; + foreach (var rc in rollCall.ShiftList.OrderBy(x => x.Start)) + { + double minutes = 0; + var shift = FindRotatingShift(rc.Start, rc.End, customizeWorkshopEmployeeSettings.CustomizeRotatingShifts); + if (firstShift == null) + { + firstShift = shift; + } + + if (shift.start == firstShift.Value.start && shift.end == firstShift.Value.end) + { + minutes += rc.LateEntryDuration.TotalMinutes; + totalLateToWorkSpan = totalLateToWorkSpan.Add(rc.LateEntryDuration); + } + lateToWorkDeduction += dayMinuteWage * minutes; + } + + } + + } + else + { + foreach (var rollCall in groupedRollCall) + { + var rollCallShift = rollCall.TotalShiftDurationTimeSpan; + var dayMinuteWage = rollCallShift.TotalMinutes == 0 ? 0 : (dailyWage / rollCallShift.TotalMinutes); + var minutes = rollCall.TotalLateEntryDuration.TotalMinutes; + lateToWorkDeduction += dayMinuteWage * minutes; + totalLateToWorkSpan = totalLateToWorkSpan.Add(rollCall.TotalLateEntryDuration); + + } + } #endregion - return new CustomizeCheckoutMandatoryViewModel + return new CustomizeCheckoutMandatoryViewModel { InsuranceDeduction = Math.Truncate(insuranceDeductionAmount), FridayPay = Math.Truncate(fridayPayAmount), @@ -2424,7 +2527,7 @@ CreateWorkingHoursTemp command, bool holidayWorking) EmployeeId = employeeId, SumOfWorkingDays = totalDays.ToString(), ContractNo = contract?.ContractNo ?? "-", - MonthlySalary = dailyWage * mandatoryDays, + MonthlySalary = dailyWage * mandatoryDays, PersonnelCode = personnelCode, FineViewModels = fineViewModels, InstallmentViewModels = loanInstallments, @@ -3424,10 +3527,9 @@ CreateWorkingHoursTemp command, bool holidayWorking) #endregion - private static (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, ICollection rotatingShifts) + public static (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, + ICollection rotatingShifts) { - - DateTime startDate = startRollCall.Date; DateTime endDate = endRollCall.Date; @@ -3447,7 +3549,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) var shifts = new List<(DateTime Start, DateTime End)>(); for (int i = -1; i <= 1; i++) { - var shiftStart = startDate.AddDays(i).Date.Add(shift.StartTime.ToTimeSpan()); + var shiftStart = startDate.AddDays(i).Date; + shiftStart = shiftStart.Add(shift.StartTime.ToTimeSpan()); var shiftEnd = shift.StartTime < shift.EndTime ? startDate.AddDays(i).Date.Add(shift.EndTime.ToTimeSpan()) : startDate.AddDays(i + 1).Date.Add(shift.EndTime.ToTimeSpan()); @@ -3457,6 +3560,8 @@ CreateWorkingHoursTemp command, bool holidayWorking) return shifts; }).ToList(); + #region مقایسه شروع حضور غیاب با شیفت + var startFilteredTimes = shiftDateTimes.Where(shift => (oneHourBeforeStart <= shift.Start && oneHourAfterStart >= shift.Start) || (oneHourBeforeStart <= shift.End && oneHourAfterStart >= shift.End)).ToList(); @@ -3475,8 +3580,14 @@ CreateWorkingHoursTemp command, bool holidayWorking) return startChosenShift; } - var endFilteredTimes = shiftDateTimes.Where(shift => (oneHourBeforeEnd <= shift.Start && oneHourAfterEnd >= shift.Start) || - (oneHourBeforeEnd <= shift.End && oneHourAfterEnd >= shift.End)).ToList(); + + #endregion + + #region مقایسه پایان حضورغیاب با شیفت + + var endFilteredTimes = shiftDateTimes.Where(shift => + (oneHourBeforeEnd <= shift.Start && oneHourAfterEnd >= shift.Start) || + (oneHourBeforeEnd <= shift.End && oneHourAfterEnd >= shift.End)).ToList(); if (endFilteredTimes.Count == 0) { endFilteredTimes = startFilteredTimes; @@ -3488,21 +3599,27 @@ CreateWorkingHoursTemp command, bool holidayWorking) } - var overlapChosenShift = endFilteredTimes.Select(shift => new + #endregion + + #region اشتراک حضور غیاب و شیفت + + var overlapShifts = endFilteredTimes.Select(shift => new { Shift = shift, Overlap = new TimeSpan(Math.Max(0, Math.Min(shift.End.Ticks, oneHourAfterEnd.Ticks) - - Math.Max(shift.Start.Ticks, oneHourBeforeEnd.Ticks))) - }).MaxBy(s => s.Overlap); - + Math.Max(shift.Start.Ticks, oneHourBeforeStart.Ticks))) + }); + var overlapChosenShift = overlapShifts.MaxBy(s => s.Overlap); var end = overlapChosenShift.Shift.End; if (overlapChosenShift.Shift.End < overlapChosenShift.Shift.Start) end = overlapChosenShift.Shift.End.AddDays(1); return (overlapChosenShift.Shift.Start, end); + + #endregion } #endregion } diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index b3a8ecef..5ec6d2a5 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -3,6 +3,7 @@ using _0_Framework.Domain.CustomizeCheckoutShared.Base; using _0_Framework.Domain.CustomizeCheckoutShared.Enums; using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects; using _0_Framework.InfraStructure; +using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg.Entities; using Company.Domain.EmployeeAgg; using Company.Domain.RollCallAgg; using Company.Domain.RollCallEmployeeAgg; @@ -364,6 +365,32 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos var orderedRollcalls = x.OrderBy(y => y.StartDate!.Value).ToList(); var firstRollCall = orderedRollcalls.FirstOrDefault(); var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault(); + //این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت + //منطق کباب مهدی!!!! + + #region SecondTimeDiff + var hasSecondTimeDiff = false; + if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating) + { + if (firstRollCall != null && secondRollCall != null) + { + var firstShift = FindRotatingShift(firstRollCall.StartDate.Value, firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + var secondShift = FindRotatingShift(secondRollCall.StartDate.Value, secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + if (firstShift.start == secondShift.start && firstShift.end == secondShift.end) + { + hasSecondTimeDiff = true; + } + } + + } + else + { + hasSecondTimeDiff = true; + } + + + + #endregion return new CheckoutDailyRollCallViewModel() { @@ -386,7 +413,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos : "", ExitDifferencesMinutes1 = "", - EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170 + EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170 && hasSecondTimeDiff ? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration, secondRollCall.LateEntryDuration) : "", @@ -1636,6 +1663,32 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos var orderedRollcalls = x.OrderBy(y => y.ShiftDate).ToList(); var firstRollCall = orderedRollcalls.FirstOrDefault(); var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault(); + //این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت + //منطق کباب مهدی!!!! + + #region SecondTimeDiff + var hasSecondTimeDiff = false; + if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating) + { + if (firstRollCall !=null && secondRollCall != null) + { + var firstShift = FindRotatingShift(firstRollCall.StartDate.Value, firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + var secondShift = FindRotatingShift(secondRollCall.StartDate.Value, secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + if (firstShift.start == secondShift.start && firstShift.end == secondShift.end) + { + hasSecondTimeDiff = true; + } + } + + } + else + { + hasSecondTimeDiff = true; + } + + + + #endregion return new CheckoutDailyRollCallViewModel() { StartDate1 = firstRollCall?.StartDate?.ToString("HH:mm"), @@ -1660,7 +1713,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos : "", ExitDifferencesMinutes1 = "", - EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170 + EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170&& hasSecondTimeDiff ? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration, secondRollCall.LateEntryDuration) : "", @@ -1796,7 +1849,34 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos var orderedRollcalls = x.OrderBy(y => y.StartDate!.Value).ToList(); var firstRollCall = orderedRollcalls.FirstOrDefault(); var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault(); - return new CheckoutDailyRollCallViewModel() + + //این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت + //منطق کباب مهدی!!!! + + #region SecondTimeDiff + var hasSecondTimeDiff = false; + if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating) + { + if (firstRollCall != null && secondRollCall != null) + { + var firstShift = FindRotatingShift(firstRollCall.StartDate.Value, firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + var secondShift = FindRotatingShift(secondRollCall.StartDate.Value, secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts); + if (firstShift.start == secondShift.start && firstShift.end == secondShift.end) + { + hasSecondTimeDiff = true; + } + } + + } + else + { + hasSecondTimeDiff = true; + } + + + + #endregion + return new CheckoutDailyRollCallViewModel() { StartDate1 = orderedRollcalls.FirstOrDefault()?.StartDate?.ToString("HH:mm"), EndDate1 = orderedRollcalls.FirstOrDefault()?.EndDate?.ToString("HH:mm"), @@ -1819,11 +1899,11 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos : "", ExitDifferencesMinutes1 = "", - EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170 - ? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration, - secondRollCall.LateEntryDuration) - : "", - ExitDifferencesMinutes2 = "" + EnterDifferencesMinutes2 = secondRollCall != null && secondRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170 && hasSecondTimeDiff + ? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration, + secondRollCall.LateEntryDuration) + : "", + ExitDifferencesMinutes2 = "" }; }); presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel @@ -1866,6 +1946,101 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return result; + + } + public static (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, + ICollection rotatingShifts) + { + DateTime startDate = startRollCall.Date; + DateTime endDate = endRollCall.Date; + + + + DateTime startEntryWithDate = startDate.Add(startRollCall.TimeOfDay); + DateTime endEntryWithDate = endDate.Add(endRollCall.TimeOfDay); + + DateTime oneHourBeforeStart = startEntryWithDate.AddHours(-1); + DateTime oneHourAfterStart = startEntryWithDate.AddHours(1); + DateTime oneHourBeforeEnd = endEntryWithDate.AddHours(-1); + DateTime oneHourAfterEnd = endEntryWithDate.AddHours(1); + + + var shiftDateTimes = rotatingShifts.SelectMany(shift => + { + var shifts = new List<(DateTime Start, DateTime End)>(); + for (int i = -1; i <= 1; i++) + { + var shiftStart = startDate.AddDays(i).Date; + shiftStart = shiftStart.Add(shift.StartTime.ToTimeSpan()); + var shiftEnd = shift.StartTime < shift.EndTime + ? startDate.AddDays(i).Date.Add(shift.EndTime.ToTimeSpan()) + : startDate.AddDays(i + 1).Date.Add(shift.EndTime.ToTimeSpan()); + shifts.Add((shiftStart, shiftEnd)); + } + + return shifts; + }).ToList(); + + #region مقایسه شروع حضور غیاب با شیفت + + var startFilteredTimes = shiftDateTimes.Where(shift => + (oneHourBeforeStart <= shift.Start && oneHourAfterStart >= shift.Start) || + (oneHourBeforeStart <= shift.End && oneHourAfterStart >= shift.End)).ToList(); + + if (startFilteredTimes.Count == 0) + { + startFilteredTimes = shiftDateTimes; + } + else if (startFilteredTimes.Count == 1) + { + var startChosenShift = startFilteredTimes.First(); + + if (startChosenShift.End < startChosenShift.Start) + startChosenShift.End = startChosenShift.End.AddDays(1); + + return startChosenShift; + } + + + #endregion + + #region مقایسه پایان حضورغیاب با شیفت + + var endFilteredTimes = shiftDateTimes.Where(shift => + (oneHourBeforeEnd <= shift.Start && oneHourAfterEnd >= shift.Start) || + (oneHourBeforeEnd <= shift.End && oneHourAfterEnd >= shift.End)).ToList(); + if (endFilteredTimes.Count == 0) + { + endFilteredTimes = startFilteredTimes; + } + else if (endFilteredTimes.Count == 1) + { + var endChosenShift = endFilteredTimes.First(); + return endChosenShift; + } + + + #endregion + + #region اشتراک حضور غیاب و شیفت + + var overlapShifts = endFilteredTimes.Select(shift => new + { + Shift = shift, + Overlap = new TimeSpan(Math.Max(0, + Math.Min(shift.End.Ticks, oneHourAfterEnd.Ticks) - + Math.Max(shift.Start.Ticks, oneHourBeforeStart.Ticks))) + }); + + var overlapChosenShift = overlapShifts.MaxBy(s => s.Overlap); + var end = overlapChosenShift.Shift.End; + if (overlapChosenShift.Shift.End < overlapChosenShift.Shift.Start) + end = overlapChosenShift.Shift.End.AddDays(1); + + + return (overlapChosenShift.Shift.Start, end); + + #endregion } }