Files
Backend-Api/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs

5078 lines
176 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using _0_Framework.Application;
using _0_Framework.InfraStructure;
using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg.Entities;
using Company.Domain.CustomizeWorkshopSettingsAgg.Entities;
using Company.Domain.LeaveAgg;
using Company.Domain.LeftWorkAgg;
using Company.Domain.RollCallAgg;
using Company.Domain.YearlySalaryAgg;
using CompanyManagment.App.Contracts.Contract;
using CompanyManagment.App.Contracts.CustomizeCheckout;
using CompanyManagment.App.Contracts.CustomizeWorkshopSettings;
using CompanyManagment.App.Contracts.Leave;
using CompanyManagment.App.Contracts.LeftWork;
using CompanyManagment.App.Contracts.RollCall;
using CompanyManagment.App.Contracts.WorkingHoursTemp;
using System;
using System.Collections.Generic;
using System.Linq;
using CompanyManagment.App.Contracts.Fine;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using _0_Framework.Domain.CustomizeCheckoutShared.Base;
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
using Microsoft.EntityFrameworkCore;
using Company.Domain.EmployeeAgg;
using CompanyManagment.App.Contracts.Loan;
using CompanyManagment.App.Contracts.Reward;
using CompanyManagment.App.Contracts.SalaryAid;
using Company.Domain.RewardAgg;
using CompanyManagment.App.Contracts.Reward.Enums;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using Company.Domain.HolidayItemAgg;
using Company.Domain.RollCallEmployeeAgg;
using PersianTools.Core;
namespace CompanyManagment.EFCore.Repository;
public class RollCallMandatoryRepository : RepositoryBase<long, RollCall>, IRollCallMandatoryRepository
{
private readonly CompanyContext _context;
private readonly IYearlySalaryRepository _yearlySalaryRepository;
private readonly ILeftWorkRepository _leftWorkRepository;
private readonly ILeaveRepository _leaveRepository;
private readonly IHolidayItemRepository _holidayItemRepository;
private readonly TestDbContext _testDbContext;
public RollCallMandatoryRepository(CompanyContext context, IYearlySalaryRepository yearlySalaryRepository,
ILeftWorkRepository leftWorkRepository, ILeaveRepository leaveRepository, IHolidayItemRepository holidayItemRepository, TestDbContext testDbContext) : base(context)
{
_context = context;
_yearlySalaryRepository = yearlySalaryRepository;
_leftWorkRepository = leftWorkRepository;
_leaveRepository = leaveRepository;
_holidayItemRepository = holidayItemRepository;
_testDbContext = testDbContext;
}
#region OfficialChckout
public ComputingViewModel MandatoryCompute(long employeeId, long workshopId, DateTime contractStart,
DateTime contractEnd,
CreateWorkingHoursTemp command, bool holidayWorking, bool isStaticCheckout)
{
#region Entities
string SumWorkeTime = string.Empty;
var weeklyTime = new TimeSpan();
string shift1Hourse = "0";
string overMandatoryHours = "0";
string overMandatoryMinuts = "0";
string shiftOver22Hours = "0";
string shiftOver22Minuts = "0";
double ShiftPayResult = 0;
int numberOfFridays = 0;
#endregion
int TotalContractDays = (int)(contractEnd - contractStart).TotalDays + 1;
int fridays = 0;
int holiday = _context.HolidayItems.Count(x => x.Holidaydate >= contractStart && x.Holidaydate <= contractEnd);
;
for (var gDate = contractStart; gDate <= contractEnd; gDate = gDate.AddDays(1))
{
if (gDate.DayOfWeek == DayOfWeek.Friday)
{
fridays += 1;
}
}
int TotalDaysNoFriday = TotalContractDays - fridays;
int mandatorDays = TotalContractDays - (fridays + holiday);
if (command.ShiftWork != "4" && isStaticCheckout)
mandatorDays = TotalDaysNoFriday;
//if (holidayWorking)
// mandatorDays = TotalContractDays - fridays;
//***********************************//
//This Time Mandatory Hourse
double mandatoryHours = Math.Round((mandatorDays * 7.33), 2);
//گرفتن ساعت استراحت پرسنل از تنظیمات
#region breakTime
BaseCustomizeEntity settings = _context.CustomizeWorkshopEmployeeSettings.AsSplitQuery()
.Include(x => x.CustomizeWorkshopGroupSettings).FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
//اگر ساعت استراحت پرسنل وجود نداشت صفر است
var breakTimeEntity = settings == null ? new BreakTime(false, new TimeOnly()) : settings.BreakTime;
var endOfFarvardin = "1404/01/31".ToGeorgianDateTime();
#endregion
List<RollCallViewModel> rollCallResult;
List<GroupedRollCalls> groupedRollCall;
if (isStaticCheckout)
{
command.WorkshopId = workshopId;
command.EmployeeId = employeeId;
command.ContractStartGr = contractStart;
command.ContractEndGr = contractEnd;
rollCallResult = ConvertStaticHoursToRollCall(command, holidayWorking);
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,EndWithOutResTime = s.ShiftEndWithoutRest.Value}).ToList(),
HasFriday = x.Any(s => s.StartDate != null && s.EndDate != null && (s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value!.DayOfWeek == DayOfWeek.Friday)),
SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)),
BreakTime = x.First().BreakTimeSpan
}).OrderBy(x => x.CreationDate).ToList();
}
else
{
rollCallResult = _context.RollCalls.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate.Value.Date >= contractStart.Date &&
x.StartDate.Value.Date <= contractEnd.Date && x.EndDate != null).Select(x => new RollCallViewModel()
{
StartDate = x.StartDate,
EndDate = x.EndDate,
ShiftSpan = (x.EndDate.Value - x.StartDate.Value),
CreationDate = x.ShiftDate,
BreakTimeSpan = x.BreakTimeSpan
}).ToList();
groupedRollCall = rollCallResult.GroupBy(x => x.CreationDate.Date).Select(x =>
{
TimeSpan breakTime;
if (contractStart > endOfFarvardin)
{
breakTime = CalculateBreakTime(
x.First().BreakTimeSpan,
new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)));
}
else
{
breakTime = CalculateBreakTime(breakTimeEntity, new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)));
}
return new GroupedRollCalls()
{
CreationDate = x.Key,
ShiftList = x.Select(s => new ShiftList() { Start = s.StartDate!.Value, End = s.EndDate!.Value, EndWithOutResTime = s.EndDate.Value })
.ToList(),
HasFriday = x.Any(s =>
s.StartDate != null && s.EndDate != null && (s.StartDate.Value.DayOfWeek == DayOfWeek.Friday ||
s.EndDate.Value!.DayOfWeek == DayOfWeek.Friday)),
SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)) - breakTime,
BreakTime = breakTime,
};
}).OrderBy(x => x.CreationDate).ToList();
}
numberOfFridays = groupedRollCall.Count(x => x.HasFriday);
////*****کسر ساعاعت استراحت پرسنل از ساعت کار
//List<GroupedRollCalls> rollCallSubtractSpan = groupedRollCall.Select(x => new GroupedRollCalls()
//{
// CreationDate = x.CreationDate,
// AfterSubtractRestSpan = AfterSubtract(command, x.SumOneDaySpan, x.CreationDate),
//}).ToList();
TimeSpan sumSpans = new TimeSpan(groupedRollCall.Sum(x => x.SumOneDaySpan.Ticks));
TimeSpan sumSpansWhitOutleaves = new TimeSpan(groupedRollCall.Sum(x => x.SumOneDaySpan.Ticks));
//بدست آوردن مرخصی ساعتی
LeaveSearchModel hoursleaveSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
PaidLeaveType = "ساعتی",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
var hoursesleave = _leaveRepository.search(hoursleaveSearch);
var hoursesleaveTimeSpansList = hoursesleave.Count > 0
? hoursesleave.Select(x => TimeSpan.Parse(x.LeaveHourses)).ToList()
: new List<TimeSpan>();
// مجموع مرخصی ساعتی
var hoursesleaveTimeSpans = new TimeSpan(hoursesleaveTimeSpansList.Sum(x => x.Ticks));
//کسر مرخصی ساعتی از فیش استاتیک
if (isStaticCheckout && command.ShiftWork != "4")
{
// کم کردن از مجموع ساعت کار پرسنل
sumSpans = sumSpans.Subtract(hoursesleaveTimeSpans);
}
//****افزودن مرخصی پرسنل به مجموع ساعات کار***
#region AddEmployeeLeavs
LeaveSearchModel leaveSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
PaidLeaveType = "روزانه",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
var leaveSearchResult = _leaveRepository.search(leaveSearch);
// {مقدار ساعت مجاز مرخصی در برای یک روز{کامل
var leaveHoursesPerDay = 190.58 / 365;
// {مقدار ساعت مجاز مرخصی در مدت این فیش حقوقی{کامل
var starndardHoursesPerTotalDays = leaveHoursesPerDay * TotalContractDays;
// جدا کردن ساعت و دقیقه
int hours = (int)starndardHoursesPerTotalDays;
double minutesDecimal = (starndardHoursesPerTotalDays - hours) * 60;
int minutes = (int)minutesDecimal;
TimeSpan totalLeaveSpan = TimeSpan.Zero;
TimeSpan starndardHoursesPerTotalDaysSapn = new TimeSpan(hours, minutes, 0);
if (leaveSearchResult.Count > 0 || hoursesleave.Count > 0)
{
if (leaveSearchResult.Any(x => x.HasShiftDuration))
{
var sumSpansDouble = (sumSpans.TotalMinutes) / 60;
if (sumSpansDouble < mandatoryHours)
{
starndardHoursesPerTotalDays = (sumSpansDouble * starndardHoursesPerTotalDays) / mandatoryHours;
// جدا کردن ساعت و دقیقه
hours = (int)starndardHoursesPerTotalDays;
minutesDecimal = (starndardHoursesPerTotalDays - hours) * 60;
minutes = (int)minutesDecimal;
starndardHoursesPerTotalDaysSapn = new TimeSpan(hours, minutes, 0);
}
TimeSpan totalLeave = new TimeSpan(leaveSearchResult.Sum(x => x.ShiftDuration.Ticks));
totalLeave = totalLeave.Add(hoursesleaveTimeSpans);
var totalLeaveDouble = (totalLeave.TotalMinutes) / 60;
if (totalLeaveDouble > starndardHoursesPerTotalDays)
{
sumSpans = sumSpans.Add(starndardHoursesPerTotalDaysSapn);
}
else
{
sumSpans = sumSpans.Add(totalLeave);
}
totalLeaveSpan = totalLeave;
}
else
{
int leavingDayCout = 0;
//مرخصی های مابین
List<LeaveViewModel> beatweenCheckout = leaveSearchResult.Where(x => x.StartLeaveGr >= contractStart && x.EndLeaveGr <= contractEnd).Select(x => new LeaveViewModel()
{
DayCounter = Convert.ToInt32(x.LeaveHourses),
}).ToList();
leavingDayCout += beatweenCheckout.Sum(x => x.DayCounter);
// مرخصی که شروعش قبل از شروع تصفیه حساب است
List<LeaveViewModel> beforeCheckout = leaveSearchResult.Where(x => x.StartLeaveGr < contractStart).Select(x => new LeaveViewModel()
{
DayCounter = (int)(contractStart - x.EndLeaveGr).TotalDays + 1,
}).ToList();
leavingDayCout += beforeCheckout.Sum(x => x.DayCounter);
// مرخصی که پایانش بعد از پایان تصفیه حساب است
List<LeaveViewModel> afterCheckout = leaveSearchResult.Where(x => x.EndLeaveGr > contractEnd).Select(x => new LeaveViewModel()
{
DayCounter = (int)(x.StartLeaveGr - contractEnd).TotalDays + 1,
}).ToList();
leavingDayCout += afterCheckout.Sum(x => x.DayCounter);
Console.WriteLine(leavingDayCout);
TimeSpan workingPerDayAve = sumSpans / groupedRollCall.Count;//میانگین ساعت کار در روز
TimeSpan sumLeave = new TimeSpan();
if (workingPerDayAve <= new TimeSpan(7, 20, 0))
{
sumLeave = leavingDayCout * workingPerDayAve;
sumLeave = sumLeave.Add(hoursesleaveTimeSpans);
}
else
{
sumLeave = leavingDayCout * new TimeSpan(7, 20, 0);
}
if (sumLeave > starndardHoursesPerTotalDaysSapn)
{
sumSpans = sumSpans.Add(starndardHoursesPerTotalDaysSapn);
}
else
{
sumSpans = sumSpans.Add(sumLeave);
}
totalLeaveSpan = sumLeave;
}
}
//اگر مرخصی روزانه نداشت و فقط مرخصی ساعتی داشت
if (leaveSearchResult.Count == 0 && hoursesleave.Count > 0)
{
if (hoursesleaveTimeSpans > starndardHoursesPerTotalDaysSapn)
{
sumSpans = sumSpans.Add(starndardHoursesPerTotalDaysSapn);
}
else
{
sumSpans = sumSpans.Add(hoursesleaveTimeSpans);
}
}
Console.WriteLine(sumSpans);
#endregion
//***********************************//
//ToTalHourse Employe eWorked
double totalHourses = (sumSpans.TotalMinutes) / 60;
int totalHolidaysAndNotH = (int)sumSpans.TotalHours;
int totalHolidaysAndNotM = (int)(sumSpans.TotalMinutes % 60);
//***********************************//
//********** محاسبه مدت اضافه کاری ***********//
#region ComputeMandatoryAtThisTime
//***********************************//
//var dailyFix = TimeSpan.Parse("07:20");
//TimeSpan mandatoryHoursTimeSpan = new TimeSpan(7, 20, 0).Multiply(mandatorDays);
//TimeSpan Mandatory = sumSpansWhitOutleaves.Subtract(mandatoryHoursTimeSpan);
double mandatoryWorkWithOutleaves = (sumSpansWhitOutleaves.TotalMinutes) / 60;
double overTimeWork = 0;
if (mandatoryWorkWithOutleaves > mandatoryHours)
{
overTimeWork = mandatoryWorkWithOutleaves - mandatoryHours;
}
#endregion
//******* دستمزد روزانه *******//
#region DailyFeeCompute
var searchModel = new LeftWorkSearchModel()
{
EmployeeId = command.EmployeeId,
WorkshopId = command.WorkshopId,
};
var leftworkList = _leftWorkRepository.search(searchModel);
var basic = "0";
double dayliFeeComplete = 0;
var GetWorkStartDate = command.GetWorkDateHide.ToEnglishNumber();
var styear = Convert.ToInt32(GetWorkStartDate.Substring(0, 4));
var startDate = command.GetWorkDateHide.ToGeorgianDateTime();
var dayliFee = "خطای تاریخ";
double dayliFeeDouble = 0;
if (styear >= 1370)
{
if (leftworkList == null)
leftworkList = new List<LeftWorkViewModel>();
var dayliFeeResult = _yearlySalaryRepository.DayliFeeComputing(startDate, contractStart, contractEnd,
command.EmployeeId, command.WorkshopId, leftworkList);
dayliFee = dayliFeeResult.DayliFee;
dayliFeeDouble = dayliFeeResult.DayliFeeDouble;
dayliFeeComplete = dayliFeeResult.DayliFee.MoneyToDouble();
basic = dayliFeeResult.Basic;
}
#endregion
#region ConsumableItemsAndHousingAndFamily
var ConsumableItems = _yearlySalaryRepository.ConsumableItems(contractEnd);
var HousingAllowance = _yearlySalaryRepository.HousingAllowance(contractEnd);
var familyAllowance = _yearlySalaryRepository.FamilyAllowance(command.EmployeeId, contractStart, contractEnd);
var MarriedAllowance = _yearlySalaryRepository.MarriedAllowance(contractEnd, command.EmployeeId);
// حق تاهل
string MarriedAllowanceStr = MarriedAllowance > 0 ? MarriedAllowance.ToMoney() : "0";
#endregion
var totalWeek = (int)(TotalContractDays / 6);
#region Fix44Compute
int TotalContractdaysUnder30 = TotalContractDays > 30 ? 30 : TotalContractDays;
if (totalHourses < mandatoryHours)
{
if (!string.IsNullOrWhiteSpace(command.ShiftWork))
{
var workedHoursePerDay = totalHourses / mandatorDays;
var result = (dayliFeeDouble / 7.33) * workedHoursePerDay;
dayliFee = result.ToMoney();
var HousingAllowonceNumberType = HousingAllowance.MoneyToDouble();
var HousingStep1 = HousingAllowonceNumberType / 30;
var HousingStep2 = HousingStep1 / 7.33;
var HousingStep3 = HousingStep2 * workedHoursePerDay;
var HousingStep4 = HousingStep3 * TotalContractdaysUnder30;
HousingAllowance = HousingStep4.ToMoney();
var ConsumableItemsNumberType = ConsumableItems.MoneyToDouble();
var consumableItemsStep1 = ConsumableItemsNumberType / 30;
var consumableItemsStep2 = consumableItemsStep1 / 7.33;
var consumableItemsStep3 = consumableItemsStep2 * workedHoursePerDay;
var consumableItemsStep4 = consumableItemsStep3 * TotalContractdaysUnder30;
ConsumableItems = consumableItemsStep4.ToMoney();
//حق تاهل
if (MarriedAllowance > 0)
{
var MarriedStep1 = MarriedAllowance / 30;
var MarriedStep2 = MarriedStep1 / 7.33;
var MarriedStep3 = MarriedStep2 * workedHoursePerDay;
var MarriedStep4 = MarriedStep3 * TotalContractdaysUnder30;
MarriedAllowanceStr = MarriedStep4.ToMoney();
}
if (familyAllowance != "0")
{
var familyAllowanceNumberType = familyAllowance.MoneyToDouble();
var familyAllowanceStep1 = familyAllowanceNumberType / 30;
var familyAllowanceStep2 = familyAllowanceStep1 / 7.33;
var familyAllowanceStep3 = familyAllowanceStep2 * workedHoursePerDay;
var familyAllowanceStep4 = familyAllowanceStep3 * TotalContractdaysUnder30;
familyAllowance = familyAllowanceStep4.ToMoney();
}
if (totalWeek > 1)
{
double weekAvrage = 0;
if (totalHourses < 44.00)
{
weekAvrage = (totalHourses * 6) / TotalContractDays;
}
else
{
weekAvrage = (totalHourses * 6) / TotalDaysNoFriday;
}
//var oneday = weekAvrage * 6;
var totalShiftRound = Math.Round(weekAvrage, 2);
SumWorkeTime = $"{totalShiftRound}";
}
else if (totalWeek <= 1 && TotalDaysNoFriday <= 6)
{
var totalShiftRound = Math.Round(totalHourses, 2);
SumWorkeTime = $"{totalShiftRound}";
}
else if (totalWeek <= 1 && TotalDaysNoFriday > 6)
{
var perDyeWorked = totalHourses / TotalDaysNoFriday;
var weekAvrage = perDyeWorked * 6;
var totalShiftRound = Math.Round(weekAvrage, 2);
SumWorkeTime = $"{totalShiftRound}";
}
weeklyTime = sumSpans;
}
}
else // اگر بیشتر از 44 بود
{
var HousingAllowonceNumberType = HousingAllowance.MoneyToDouble();
var ConsumableItemsNumberType = ConsumableItems.MoneyToDouble();
var familyAllowanceNumberType = familyAllowance.MoneyToDouble();
var HousingStep1 = HousingAllowonceNumberType / 30;
var HousingStep4 = HousingStep1 * TotalContractdaysUnder30;
HousingAllowance = HousingStep4.ToMoney();
var consumableItemsStep1 = ConsumableItemsNumberType / 30;
var consumableItemsStep4 = consumableItemsStep1 * TotalContractdaysUnder30;
ConsumableItems = consumableItemsStep4.ToMoney();
//حق تاهل
if (MarriedAllowance > 0)
{
var MarriedStep1 = MarriedAllowance / 30;
var MarriedStep4 = MarriedStep1 * TotalContractdaysUnder30;
MarriedAllowanceStr = MarriedStep4.ToMoney();
}
if (familyAllowance != "0")
{
var familyAllowanceStep1 = familyAllowanceNumberType / 30;
var familyAllowanceStep4 = familyAllowanceStep1 * TotalContractdaysUnder30;
familyAllowance = familyAllowanceStep4.ToMoney();
}
SumWorkeTime = $"{44}";
//اضافه کار
if (overTimeWork > 0)
{
//int mandatoryH = (int)Mandatory.TotalHours;
//int mandatoryM = (int)(Mandatory.TotalMinutes % 60);
int mandatoryH = (int)overTimeWork;
int mandatoryM = (int)Math.Round((overTimeWork - mandatoryH) * 60);
overMandatoryHours = mandatoryH.ToString();
overMandatoryMinuts = mandatoryM.ToString();
}
}
#endregion
//****** نوبت کاری و شب کاری ****
#region RotatingShiftCheckAndNightWorkOver22
string shiftPayValue = "0";
List<RotatingShiftViewModel> rotatingResultList = RotatingShiftCheck(groupedRollCall);
// شبکاری
TimeSpan over22 = new TimeSpan(rotatingResultList.Sum(x => x.NightWorkSpan.Ticks));
var RotatingfaName = new List<string>();
//if (command.ShiftWork != "1" && command.ShiftWork != "2" && command.ShiftWork != "4")//اگر چرخشی بود و منظم نبود
//{
// if (moriningCount > 0)
// RotatingfaName.Add("صبح");
// if (eveningCount > 0)
// RotatingfaName.Add("عصر");
// if (nightCount > 0)
// RotatingfaName.Add("شب");
//}
//else// اگر منظم و شیفتی بود
//{
// var totalDays = (int)(command.ContractEndGr - command.ContractStartGr).TotalDays + 1;
// int validCount = 0;
// if (totalDays <= 7) // زیر 7 روز باید حد اقل 2 تغییر شیفت داشته باشد
// {
// validCount = 2;
// }
// else if (totalDays >= 28) // بالای 28 روز حد اقل 8 تغییر شیفت
// {
// validCount = 8;
// }
// else
// {
// // تناسب گیری - اگر برای 28 روز 8 تغییر پس برای ایکس روز چند تغییر لازم است
// validCount = (int)((totalDays * 8) / 28);
// }
// if (moriningCount >= validCount)
// RotatingfaName.Add("صبح");
// if (eveningCount >= validCount)
// RotatingfaName.Add("عصر");
// if (nightCount >= validCount)
// RotatingfaName.Add("شب");
//}
int moriningCount = 0;
int eveningCount = 0;
int nightCount = 0;
int moriningWinRate = rotatingResultList.Where(x => x.IsMorningShift).Sum(x => x.WinRate);
int eveningWinRate = rotatingResultList.Where(x => x.IsEveningShift).Sum(x => x.WinRate);
int nightWinRate = rotatingResultList.Where(x => x.IsNightShift).Sum(x => x.WinRate);
if (moriningWinRate > eveningWinRate && moriningWinRate > nightWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift && x.WinRate > 55);
nightCount = rotatingResultList.Count(x => x.IsNightShift && x.WinRate > 55);
}
if (eveningWinRate > moriningWinRate && eveningWinRate > nightWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift && x.WinRate > 55);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift);
nightCount = rotatingResultList.Count(x => x.IsNightShift && x.WinRate > 55);
}
if (nightWinRate > moriningWinRate && nightWinRate > eveningWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift && x.WinRate > 55);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift && x.WinRate > 55);
nightCount = rotatingResultList.Count(x => x.IsNightShift);
}
var totalDays = (int)(command.ContractEndGr - command.ContractStartGr).TotalDays + 1;
int validCount = 0;
if (totalDays <= 7) // زیر 7 روز باید حد اقل 2 تغییر شیفت داشته باشد
{
validCount = 2;
}
else if (totalDays >= 28) // بالای 28 روز حد اقل 8 تغییر شیفت
{
validCount = 8;
}
else
{
// تناسب گیری - اگر برای 28 روز 8 تغییر پس برای ایکس روز چند تغییر لازم است
validCount = (int)((totalDays * 8) / 28);
}
if (moriningCount >= validCount)
RotatingfaName.Add("صبح");
if (eveningCount >= validCount)
RotatingfaName.Add("عصر");
if (nightCount >= validCount)
RotatingfaName.Add("شب");
var rotatingFaResult = "";
if (RotatingfaName.Count > 1)// اگر تعداد شیفت های محاسبه شده بیش از یک بود
{
shiftOver22Hours = "0";
shiftOver22Minuts = "0";
for (var rotateNumber = 0; rotateNumber < RotatingfaName.Count; rotateNumber++)
{
if (rotateNumber == 0)
rotatingFaResult = $"{RotatingfaName[rotateNumber]}";
if (rotateNumber == 1)
rotatingFaResult += $" و {RotatingfaName[rotateNumber]}";
if (rotateNumber == 2)
rotatingFaResult += $" و {RotatingfaName[rotateNumber]}";
}
}
else if (RotatingfaName.Count <= 1)
{
rotatingFaResult = "نوبت کاری ندارد";
var over22Hours = (int)over22.TotalHours;
var over22Minuts = (int)(over22.TotalMinutes % 60);
shiftOver22Hours = over22Hours.ToString();
shiftOver22Minuts = over22Minuts.ToString();
}
#endregion
//******* محاسبه مبلغ نوبت کاری *************
#region ShiftPayPercent
if (rotatingFaResult != "نوبت کاری ندارد" || rotatingFaResult != "")
{
var TotalDays = (command.ContractEndGr - command.ContractStartGr).TotalDays + 1;
var DailyFeeNumberType = dayliFee.MoneyToDouble();
if (rotatingFaResult == "صبح و عصر")
{
var shiftPyaPercent = DailyFeeNumberType * 10 / 100;
ShiftPayResult = shiftPyaPercent * TotalDays;
shiftPayValue = "10";
}
else if (rotatingFaResult == "صبح و عصر و شب")
{
var shiftPyaPercent = DailyFeeNumberType * 15 / 100;
ShiftPayResult = shiftPyaPercent * TotalDays;
shiftPayValue = "15";
}
else if (rotatingFaResult == "صبح و شب" || rotatingFaResult == "عصر و شب")
{
var shiftPyaPercent = DailyFeeNumberType * 22.5 / 100;
ShiftPayResult = shiftPyaPercent * TotalDays;
shiftPayValue = "22.5";
}
}
#endregion
#region Result
LeaveSearchModel sickLeaveSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استعلاجی",
PaidLeaveType = "روزانه",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
var sickLeaveSearchResult = _leaveRepository.search(sickLeaveSearch);
var sickLeaveTimeSpans = sickLeaveSearchResult.Select(x =>
{
var startLeave = contractStart > x.StartLeaveGr ? contractStart : x.StartLeaveGr;
var endLeave = contractEnd < x.EndLeaveGr ? contractEnd : x.EndLeaveGr;
return (endLeave - startLeave).Add(TimeSpan.FromDays(1));
});
var totalBreakTime = new TimeSpan(groupedRollCall.Sum(x => x.BreakTime.Ticks));
var res = new ComputingViewModel()
{
NumberOfWorkingDays = $"{groupedRollCall.Count}",
NumberOfFriday = $"{numberOfFridays}",
TotalHoursesH = totalHolidaysAndNotH.ToString(),
TotalHoursesM = totalHolidaysAndNotM.ToString(),
OverTimeWorkH = overMandatoryHours,
OverTimeWorkM = overMandatoryMinuts,
OverNightWorkH = shiftOver22Hours,
OverNightWorkM = shiftOver22Minuts,
ComplexNumberOfWorkingDays = $"{groupedRollCall.Count}",
SalaryCompute = dayliFee,
SumTime44 = SumWorkeTime,
ConsumableItems = ConsumableItems,
HousingAllowance = HousingAllowance,
FamilyAllowance = familyAllowance,
OfficialHoliday = holiday,
weeklyTime = weeklyTime,
RotatingResultList = rotatingResultList,
RotatingStatus = rotatingFaResult,
ShiftPay = ShiftPayResult,
Basic = basic,
FridayStartToEnd = fridays,
TotalHolidayAndNotH = totalHolidaysAndNotH.ToString(),
TotalHolidayAndNotM = totalHolidaysAndNotM.ToString(),
DayliFeeComplete = dayliFeeComplete,
MarriedAllowance = MarriedAllowanceStr,
RotatingShiftValue = shiftPayValue,
#region SaveRollCall
GroupedRollCalls = groupedRollCall,
TotalWorkingTimeSpan = sumSpansWhitOutleaves,
TotalBreakTimeSpan = totalBreakTime,
TotalPresentTimeSpan = sumSpansWhitOutleaves + totalBreakTime,
TotalPaidLeave = totalLeaveSpan,
TotalSickLeave = new TimeSpan(sickLeaveTimeSpans.Sum(x=>x.Ticks)),
#endregion
};
#endregion
return res;
}
/// <summary>
/// محاسبه ساعات کارکرد پرسنل در صورت داشتن حضور غیاب
/// </summary>
/// <param name="employeeId"></param>
/// <param name="workshopId"></param>
/// <param name="contractStart"></param>
/// <param name="contractEnd"></param>
/// <returns></returns>
public (bool hasRollCall, TimeSpan sumOfSpan) GetRollCallWorkingSpan(long employeeId, long workshopId,
DateTime contractStart, DateTime contractEnd)
{
//bool hasRollcall =
// _rollCallEmployeeRepository.HasRollCallRecord(employeeId, workshopId, contractStart, contractEnd);
//if (!hasRollcall)
// return (false, new TimeSpan());
List<RollCallViewModel> rollCallResult;
List<GroupedRollCalls> groupedRollCall;
rollCallResult = _context.RollCalls.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate.Value.Date >= contractStart.Date &&
x.StartDate.Value.Date <= contractEnd.Date && x.EndDate != null).Select(x => new RollCallViewModel()
{
StartDate = x.StartDate,
EndDate = x.EndDate,
ShiftSpan = (x.EndDate.Value - x.StartDate.Value),
CreationDate = x.ShiftDate,
BreakTimeSpan = x.BreakTimeSpan
}).ToList();
groupedRollCall = rollCallResult.GroupBy(x => x.CreationDate.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 != null && s.EndDate != null && (s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value!.DayOfWeek == DayOfWeek.Friday)),
SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)) - CalculateBreakTime(x.First().BreakTimeSpan,
new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))),
BreakTime = CalculateBreakTime(x.First().BreakTimeSpan, new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))),
}).OrderBy(x => x.CreationDate).ToList();
TimeSpan sumSpans = new TimeSpan(groupedRollCall.Sum(x => x.SumOneDaySpan.Ticks));
return (true, sumSpans);
}
public async Task<ComputingViewModel> RotatingShiftReport(long workshopId, long employeeId, DateTime contractStart, DateTime contractEnd, string shiftwork, bool hasRollCall, CreateWorkingHoursTemp command, bool holidayWorking)
{
List<RollCallViewModel> rollCallResult = new List<RollCallViewModel>();
List<GroupedRollCalls> groupedRollCall = new List<GroupedRollCalls>();
if (hasRollCall)
{
rollCallResult = await _context.RollCalls.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate.Value.Date >= contractStart.Date &&
x.StartDate.Value.Date <= contractEnd.Date && x.EndDate != null).Select(x => new RollCallViewModel()
{
StartDate = x.StartDate,
EndDate = x.EndDate,
ShiftSpan = (x.EndDate.Value - x.StartDate.Value),
CreationDate = x.ShiftDate,
}).ToListAsync();
groupedRollCall = rollCallResult.GroupBy(x => x.CreationDate.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 != null && s.EndDate != null && (s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value!.DayOfWeek == DayOfWeek.Friday)),
}).OrderBy(x => x.CreationDate).ToList();
}
else
{
command.WorkshopId = workshopId;
command.EmployeeId = employeeId;
command.ContractStartGr = contractStart;
command.ContractEndGr = contractEnd;
rollCallResult = ConvertStaticHoursToRollCall(command, holidayWorking);
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 != null && s.EndDate != null && (s.StartDate.Value.DayOfWeek == DayOfWeek.Friday || s.EndDate.Value!.DayOfWeek == DayOfWeek.Friday)),
SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))
}).OrderBy(x => x.CreationDate).ToList();
}
//****** نوبت کاری و شب کاری ****
#region RotatingShiftCheckAndNightWorkOver22
string shiftPayValue = "0";
List<RotatingShiftViewModel> rotatingResultList = RotatingShiftCheck(groupedRollCall);
int moriningCount = 0;
int eveningCount = 0;
int nightCount = 0;
int moriningWinRate = rotatingResultList.Where(x => x.IsMorningShift).Sum(x => x.WinRate);
int eveningWinRate = rotatingResultList.Where(x => x.IsEveningShift).Sum(x => x.WinRate);
int nightWinRate = rotatingResultList.Where(x => x.IsNightShift).Sum(x => x.WinRate);
if (moriningWinRate > eveningWinRate && moriningWinRate > nightWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift && x.WinRate > 55);
nightCount = rotatingResultList.Count(x => x.IsNightShift && x.WinRate > 55);
}
if (eveningWinRate > moriningWinRate && eveningWinRate > nightWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift && x.WinRate > 55);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift);
nightCount = rotatingResultList.Count(x => x.IsNightShift && x.WinRate > 55);
}
if (nightWinRate > moriningWinRate && nightWinRate > eveningWinRate)
{
moriningCount = rotatingResultList.Count(x => x.IsMorningShift && x.WinRate > 55);
eveningCount = rotatingResultList.Count(x => x.IsEveningShift && x.WinRate > 55);
nightCount = rotatingResultList.Count(x => x.IsNightShift);
}
// شبکاری
TimeSpan over22 = new TimeSpan(rotatingResultList.Sum(x => x.NightWorkSpan.Ticks));
var RotatingfaName = new List<string>();
//if (shiftwork != "1" && shiftwork != "2" && shiftwork != "4")//اگر چرخشی بود و منظم نبود
//{
// if (moriningCount > 0)
// RotatingfaName.Add("صبح");
// if (eveningCount > 0)
// RotatingfaName.Add("عصر");
// if (nightCount > 0)
// RotatingfaName.Add("شب");
//}
//else// اگر منظم و شیفتی بود
//{
//}
var totalDays = (int)(contractEnd - contractStart).TotalDays + 1;
int validCount = 0;
if (totalDays <= 7) // زیر 7 روز باید حد اقل 2 تغییر شیفت داشته باشد
{
validCount = 2;
}
else if (totalDays >= 28) // بالای 28 روز حد اقل 8 تغییر شیفت
{
validCount = 6;
}
else
{
// تناسب گیری - اگر برای 28 روز 8 تغییر پس برای ایکس روز چند تغییر لازم است
validCount = (int)((totalDays * 6) / 28);
}
Console.WriteLine(validCount);
if (moriningCount >= validCount)
RotatingfaName.Add("صبح");
if (eveningCount >= validCount)
RotatingfaName.Add("عصر");
if (nightCount >= validCount)
RotatingfaName.Add("شب");
var rotatingFaResult = "";
if (RotatingfaName.Count > 1)// اگر تعداد شیفت های محاسبه شده بیش از یک بود
{
for (var rotateNumber = 0; rotateNumber < RotatingfaName.Count; rotateNumber++)
{
if (rotateNumber == 0)
rotatingFaResult = $"{RotatingfaName[rotateNumber]}";
if (rotateNumber == 1)
rotatingFaResult += $" و {RotatingfaName[rotateNumber]}";
if (rotateNumber == 2)
rotatingFaResult += $" و {RotatingfaName[rotateNumber]}";
}
}
else if (RotatingfaName.Count <= 1)
{
rotatingFaResult = "نوبت کاری ندارد";
}
return new ComputingViewModel
{
RotatingStatus = rotatingFaResult,
RotatingResultList = rotatingResultList
};
#endregion
}
public static TimeSpan CalculateBreakTime(BreakTime breakTime, TimeSpan sumOneDaySpan)
{
if (breakTime.BreakTimeType != BreakTimeType.WithTime)
return new TimeSpan();
var breakTimeSpan = breakTime.BreakTimeValue.ToTimeSpan();
if (breakTimeSpan * 2 >= sumOneDaySpan)
return new TimeSpan();
return breakTimeSpan; ;
}
public static TimeSpan CalculateBreakTime(TimeSpan breakTimeSpan, TimeSpan sumOneDaySpan)
{
if (breakTimeSpan * 2 >= sumOneDaySpan)
return new TimeSpan();
return breakTimeSpan; ;
}
public TimeSpan AfterSubtract(CreateWorkingHoursTemp command, TimeSpan sumOneDaySpan, DateTime creationDate)
{
#region RestTimes
var rest0 = new TimeSpan();
var rest1 = new TimeSpan();
var rest2 = new TimeSpan();
var rest3 = new TimeSpan();
var rest4 = new TimeSpan();
var rest5 = new TimeSpan();
var rest6 = new TimeSpan();
switch (command.ShiftWork)
{
case "1":
case "2":
command.RestTime = command.RestTime == "0" ? "00" : command.RestTime;
command.RestTimeYekshanbeh = command.RestTimeYekshanbeh == "0" ? "00" : command.RestTimeYekshanbeh;
command.RestTimeDoshanbeh = command.RestTimeDoshanbeh == "0" ? "00" : command.RestTimeDoshanbeh;
command.RestTimeSeshanbeh = command.RestTimeSeshanbeh == "0" ? "00" : command.RestTimeSeshanbeh;
command.RestTimeCheharshanbeh =
command.RestTimeCheharshanbeh == "0" ? "00" : command.RestTimeCheharshanbeh;
command.RestTimePanjshanbeh = command.RestTimePanjshanbeh == "0" ? "00" : command.RestTimePanjshanbeh;
command.RestTimeJomeh = command.RestTimeJomeh == "0" ? "00" : command.RestTimeJomeh;
command.RestTimeMin = command.RestTimeMin == "0" ? "00" : command.RestTimeMin;
command.RestTimeYekshanbehMin =
command.RestTimeYekshanbehMin == "0" ? "00" : command.RestTimeYekshanbehMin;
command.RestTimeDoshanbehMin =
command.RestTimeDoshanbehMin == "0" ? "00" : command.RestTimeDoshanbehMin;
command.RestTimeSeshanbehMin =
command.RestTimeSeshanbehMin == "0" ? "00" : command.RestTimeSeshanbehMin;
command.RestTimeCheharshanbehMin =
command.RestTimeCheharshanbehMin == "0" ? "00" : command.RestTimeCheharshanbehMin;
command.RestTimePanjshanbehMin =
command.RestTimePanjshanbehMin == "0" ? "00" : command.RestTimePanjshanbehMin;
command.RestTimeJomehMin = command.RestTimeJomehMin == "0" ? "00" : command.RestTimeJomehMin;
rest0 = TimeSpan.Parse($"{command.RestTime}:{command.RestTimeMin}");
rest1 = TimeSpan.Parse($"{command.RestTimeYekshanbeh}:{command.RestTimeYekshanbehMin}");
rest2 = TimeSpan.Parse($"{command.RestTimeDoshanbeh}:{command.RestTimeDoshanbehMin}");
rest3 = TimeSpan.Parse($"{command.RestTimeSeshanbeh}:{command.RestTimeSeshanbehMin}");
rest4 = TimeSpan.Parse($"{command.RestTimeCheharshanbeh}:{command.RestTimeCheharshanbehMin}");
rest5 = TimeSpan.Parse($"{command.RestTimePanjshanbeh}:{command.RestTimePanjshanbehMin}");
rest6 = TimeSpan.Parse($"{command.RestTimeJomeh}:{command.RestTimeJomehMin}");
break;
case "4":
command.RestTimeShanbe1 = command.RestTimeShanbe1 == "0" ? "00" : command.RestTimeShanbe1;
command.RestTimeShanbe1Min = command.RestTimeShanbe1Min == "0" ? "00" : command.RestTimeShanbe1Min;
command.RestTimeYekShanbe1 = command.RestTimeYekShanbe1 == "0" ? "00" : command.RestTimeYekShanbe1;
command.RestTimeYekShanbe1Min =
command.RestTimeYekShanbe1Min == "0" ? "00" : command.RestTimeYekShanbe1Min;
command.RestTimeDoShanbe1 = command.RestTimeDoShanbe1 == "0" ? "00" : command.RestTimeDoShanbe1;
command.RestTimeDoShanbe1Min =
command.RestTimeDoShanbe1Min == "0" ? "00" : command.RestTimeDoShanbe1Min;
command.RestTimeSeShanbe1 = command.RestTimeSeShanbe1 == "0" ? "00" : command.RestTimeSeShanbe1;
command.RestTimeSeShanbe1Min =
command.RestTimeSeShanbe1Min == "0" ? "00" : command.RestTimeSeShanbe1Min;
command.RestTimeCheharShanbe1 =
command.RestTimeCheharShanbe1 == "0" ? "00" : command.RestTimeCheharShanbe1;
command.RestTimeCheharShanbe1Min =
command.RestTimeCheharShanbe1Min == "0" ? "00" : command.RestTimeCheharShanbe1Min;
command.RestTimePanjShanbe1 = command.RestTimePanjShanbe1 == "0" ? "00" : command.RestTimePanjShanbe1;
command.RestTimePanjShanbe1Min =
command.RestTimePanjShanbe1Min == "0" ? "00" : command.RestTimePanjShanbe1Min;
command.RestTimeJome1 = command.RestTimeJome1 == "0" ? "00" : command.RestTimeJome1;
command.RestTimeJome1Min = command.RestTimeJome1Min == "0" ? "00" : command.RestTimeJome1Min;
// sumrest week1
rest0 = TimeSpan.Parse($"{command.RestTimeShanbe1}:{command.RestTimeShanbe1Min}");
rest1 = TimeSpan.Parse($"{command.RestTimeYekShanbe1}:{command.RestTimeYekShanbe1Min}");
rest2 = TimeSpan.Parse($"{command.RestTimeDoShanbe1}:{command.RestTimeDoShanbe1Min}");
rest3 = TimeSpan.Parse($"{command.RestTimeSeShanbe1}:{command.RestTimeSeShanbe1Min}");
rest4 = TimeSpan.Parse($"{command.RestTimeCheharShanbe1}:{command.RestTimeCheharShanbe1Min}");
rest5 = TimeSpan.Parse($"{command.RestTimePanjShanbe1}:{command.RestTimePanjShanbe1Min}");
rest6 = TimeSpan.Parse($"{command.RestTimeJome1}:{command.RestTimeJome1Min}");
break;
}
//week1
#endregion
var result = new TimeSpan();
switch (creationDate.DayOfWeek)
{
case DayOfWeek.Saturday:
if (sumOneDaySpan >= rest0)
result = sumOneDaySpan.Subtract(rest0);
break;
case DayOfWeek.Sunday:
if (sumOneDaySpan >= rest1)
result = sumOneDaySpan.Subtract(rest1);
break;
case DayOfWeek.Monday:
if (sumOneDaySpan >= rest2)
result = sumOneDaySpan.Subtract(rest2);
break;
case DayOfWeek.Tuesday:
if (sumOneDaySpan >= rest3)
result = sumOneDaySpan.Subtract(rest3);
break;
case DayOfWeek.Wednesday:
if (sumOneDaySpan >= rest4)
result = sumOneDaySpan.Subtract(rest4);
break;
case DayOfWeek.Thursday:
if (sumOneDaySpan >= rest5)
result = sumOneDaySpan.Subtract(rest5);
break;
case DayOfWeek.Friday:
if (sumOneDaySpan >= rest6)
result = sumOneDaySpan.Subtract(rest6);
break;
}
return result;
}
public List<RotatingShiftViewModel> RotatingShiftCheck(List<GroupedRollCalls> rollCallList)
{
List<RotatingShiftViewModel> finalResult = new List<RotatingShiftViewModel>();
var nullDateTme = new DateTime(0001, 01, 01);
foreach (var item in rollCallList)
{
#region Entityes
var morningWorkingTime = new TimeSpan();
var eveningWorkingTime = new TimeSpan();
var nightWorkingTime = new TimeSpan();
#endregion
foreach (var shift in item.ShiftList)
{
#region DatePeriod
var shiftDate = item.CreationDate;
if (shift.Start.Date < shiftDate.Date)
shiftDate = shiftDate.AddDays(-1);
DateTime midNight24 = new DateTime(shiftDate.Year, shiftDate.Month, shiftDate.Day, 0, 0, 0);
DateTime morningStart = new DateTime(shiftDate.Year, shiftDate.Month, shiftDate.Day, 6, 0, 0);
DateTime morningEnd = new DateTime(shiftDate.Year, shiftDate.Month, shiftDate.Day, 14, 0, 0);
DateTime eveningStart = morningEnd;
DateTime eveningEnd = new DateTime(shiftDate.Year, shiftDate.Month, shiftDate.Day, 22, 0, 0);
DateTime nightStart = eveningEnd;
DateTime nightEnd = morningStart;
DateTime nightEndNextday = nightEnd.AddDays(1);
DateTime morningEndNextday = morningEnd.AddDays(1);
DateTime eveningEndNextday = eveningEnd.AddDays(1);
#endregion
#region MidNight Enter 00:00 ---> 6
if (shift.Start >= midNight24 // 00:00 >---> 6
&& shift.End <= morningStart)
{
nightWorkingTime = nightWorkingTime.Add(shift.End - shift.Start);
}
else if (shift.Start >= midNight24 && shift.Start < morningStart // 00:00---6--->14
&& shift.End > morningStart && shift.End <= morningEnd)
{
nightWorkingTime = nightWorkingTime.Add(morningStart - shift.Start);
morningWorkingTime = morningWorkingTime.Add(shift.End - morningStart);
}
else if (shift.Start >= midNight24 && shift.Start < morningStart// 00:00---6---14--->22
&& shift.End > morningEnd && shift.End <= eveningEnd)
{
nightWorkingTime = nightWorkingTime.Add(morningStart - shift.Start);
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
eveningWorkingTime = eveningWorkingTime.Add(shift.End - eveningStart);
}
else if (shift.Start >= midNight24 // 00:00---6---14----22---->6
&& shift.Start < morningStart
&& shift.End > eveningEnd && shift.End <= nightEndNextday)
{
nightWorkingTime = nightWorkingTime.Add(morningStart - shift.Start);
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
eveningWorkingTime = eveningWorkingTime.Add(new TimeSpan(8, 0, 0));
nightWorkingTime = nightWorkingTime.Add(shift.End - eveningEnd);
}
#endregion
#region morning enter 14 <- 6
if (shift.Start >= morningStart // 14<---<6
&& shift.End <= morningEnd)
{
morningWorkingTime = morningWorkingTime.Add(shift.End - shift.Start);
}
else if (shift.Start >= morningStart && shift.Start < morningEnd // 22<---14---6
&& shift.End > eveningStart && shift.End <= eveningEnd)
{
morningWorkingTime = morningWorkingTime.Add(morningEnd - shift.Start);
eveningWorkingTime = eveningWorkingTime.Add(shift.End - eveningStart);
}
else if (shift.Start >= morningStart && shift.Start < morningEnd// // 6<---22---14---6
&& shift.End > eveningEnd && shift.End <= nightEndNextday)
{
morningWorkingTime = morningWorkingTime.Add(morningEnd - shift.Start);
eveningWorkingTime = eveningWorkingTime.Add(new TimeSpan(8, 0, 0));
nightWorkingTime = nightWorkingTime.Add(shift.End - eveningEnd);
}
else if (shift.Start >= morningStart // 14<---6<---22---14---6
&& shift.Start < morningEnd
&& shift.End > nightEndNextday && shift.End <= morningEndNextday)
{
morningWorkingTime = morningWorkingTime.Add(morningEnd - shift.Start);
eveningWorkingTime = eveningWorkingTime.Add(new TimeSpan(8, 0, 0));
nightWorkingTime = nightWorkingTime.Add(new TimeSpan(8, 0, 0));
TimeSpan nextDayMorningSpan = (shift.End - nightEndNextday);
morningWorkingTime = morningWorkingTime.Add(nextDayMorningSpan);
}
else if (shift.Start >= morningStart // 22<---14<---6<---22---14---6
&& shift.Start < morningEnd
&& shift.End > morningEndNextday && shift.End <= eveningEndNextday)
{
morningWorkingTime = morningWorkingTime.Add(morningEnd - shift.Start);
eveningWorkingTime = eveningWorkingTime.Add(new TimeSpan(8, 0, 0));
nightWorkingTime = nightWorkingTime.Add(new TimeSpan(8, 0, 0));
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
TimeSpan nextDayEveningSpan = (shift.End - morningEndNextday);
eveningWorkingTime = eveningWorkingTime.Add(nextDayEveningSpan);
}
#endregion
#region evening enter 22 <- 14
if (shift.Start >= eveningStart // 22<---<14
&& shift.End <= eveningEnd)
{
eveningWorkingTime = eveningWorkingTime.Add(shift.End - shift.Start);
}
else if (shift.Start >= eveningStart && shift.Start < eveningEnd // 6<---22---14
&& shift.End > nightStart && shift.End <= nightEndNextday)
{
eveningWorkingTime = eveningWorkingTime.Add(eveningEnd - shift.Start);
nightWorkingTime = nightWorkingTime.Add(shift.End - eveningEnd);
}
else if (shift.Start >= eveningStart && shift.Start < eveningEnd// // 14<---6---22---14
&& shift.End > nightEndNextday && shift.End <= morningEndNextday)
{
eveningWorkingTime = eveningWorkingTime.Add(eveningEnd - shift.Start);
nightWorkingTime = nightWorkingTime.Add(new TimeSpan(8, 0, 0));
morningWorkingTime = morningWorkingTime.Add(shift.End - nightEndNextday);
}
else if (shift.Start >= eveningStart // 22<---14<---6---22---14
&& shift.Start < eveningEnd
&& shift.End > morningEndNextday && shift.End <= eveningEndNextday)
{
eveningWorkingTime = eveningWorkingTime.Add(morningEnd - shift.Start);
nightWorkingTime = nightWorkingTime.Add(new TimeSpan(8, 0, 0));
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
TimeSpan nextDayEveningSpan = (shift.End - morningEndNextday);
eveningWorkingTime = eveningWorkingTime.Add(nextDayEveningSpan);
}
#endregion
#region night enter 6 <- 22
if (shift.Start >= nightStart // 6<---<22
&& shift.End <= nightEndNextday)
{
nightWorkingTime = nightWorkingTime.Add(shift.End - shift.Start);
}
else if (shift.Start >= nightStart && shift.Start < nightEndNextday // 14<---6---22
&& shift.End > nightEndNextday && shift.End <= morningEndNextday)
{
nightWorkingTime = nightWorkingTime.Add(nightEndNextday - shift.Start);
morningWorkingTime = morningWorkingTime.Add(shift.End - nightEndNextday);
}
else if (shift.Start >= nightStart && shift.Start < nightEndNextday// // 22<---14---6---22
&& shift.End > morningEndNextday && shift.End <= eveningEndNextday)
{
nightWorkingTime = nightWorkingTime.Add(nightEndNextday - shift.Start); ;
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
eveningWorkingTime = eveningWorkingTime.Add(shift.End - morningEndNextday);
}
else if (shift.Start >= nightStart // 6<---22<---14---6---22
&& shift.Start < nightEndNextday
&& shift.End > eveningEndNextday)
{
nightWorkingTime = nightWorkingTime.Add(nightEndNextday - shift.Start);
morningWorkingTime = morningWorkingTime.Add(new TimeSpan(8, 0, 0));
eveningWorkingTime = eveningWorkingTime.Add(new TimeSpan(8, 0, 0));
TimeSpan nextDayNightSpan = (shift.End - eveningEndNextday);
nightWorkingTime = nightWorkingTime.Add(nextDayNightSpan);
}
#endregion
}
#region Result
var result = new RotatingShiftViewModel();
result.RotatingDate = item.CreationDate.ToFarsi();
result.MorningWorkSpan = morningWorkingTime;
result.EveningWorkSpan = eveningWorkingTime;
result.NightWorkSpan = nightWorkingTime;
var nullWorkspan = new TimeSpan(0, 0, 0);
var totalTime = result.TotalWorkingTime.Add(result.MorningWorkSpan);
totalTime = totalTime.Add(result.EveningWorkSpan);
totalTime = totalTime.Add(result.NightWorkSpan);
result.TotalWorkingTime = totalTime;
var morningH = (int)result.MorningWorkSpan.TotalHours;
var morningM = result.MorningWorkSpan.Minutes % 60;
var morningMS = "00";
if (morningM < 10 && morningM > 0)
morningMS = $"0{morningM}";
if (morningM > 10)
morningMS = $"{morningM}";
result.MorningString = $"0{morningH}:{morningMS}";
var eveningH = (int)result.EveningWorkSpan.TotalHours;
var eveningM = result.EveningWorkSpan.Minutes % 60;
var eveningMS = "00";
if (eveningM < 10 && eveningM > 0)
eveningMS = $"0{eveningM}";
if (eveningM > 10)
eveningMS = $"{eveningM}";
result.EveningString = $"0{eveningH}:{eveningMS}";
var nightH = (int)result.NightWorkSpan.TotalHours;
var nightM = result.NightWorkSpan.Minutes % 60;
var nightMS = "00";
if (nightM < 10 && nightM > 0)
nightMS = $"0{nightM}";
if (nightM > 10)
nightMS = $"{nightM}";
result.NightString = $"0{nightH}:{nightMS}";
if (result.MorningWorkSpan > result.EveningWorkSpan
|| result.MorningWorkSpan == result.EveningWorkSpan) // if morning bigerThan evening or equal
{
if (result.MorningWorkSpan != nullWorkspan)
{
var sumSpan = result.MorningWorkSpan.Add(result.EveningWorkSpan);
var sumSpanDouble = sumSpan.TotalMinutes;
var winRate = (result.MorningWorkSpan.TotalMinutes * 100) / sumSpanDouble;
result.WinRate = Convert.ToInt32(winRate);
result.IsMorningShift = true;
result.IsNightShift = false;
result.IsEveningShift = false;
result.RotatingShiftStatus = "صبح";
}
if (result.MorningWorkSpan < result.NightWorkSpan
|| result.MorningWorkSpan == result.NightWorkSpan) // if night bigerThan morning or equal
if (result.NightWorkSpan != nullWorkspan)
{
var sumSpan = result.MorningWorkSpan.Add(result.NightWorkSpan);
var sumSpanDouble = sumSpan.TotalMinutes;
var winRate = (result.NightWorkSpan.TotalMinutes * 100) / sumSpanDouble;
result.WinRate = Convert.ToInt32(winRate);
result.IsMorningShift = false;
result.IsNightShift = true;
result.IsEveningShift = false;
result.RotatingShiftStatus = "شب";
}
}
else if (result.MorningWorkSpan < result.EveningWorkSpan) // if evening bigerThan morning
{
if (result.EveningWorkSpan != nullWorkspan)
{
var sumSpan = result.MorningWorkSpan.Add(result.EveningWorkSpan);
var sumSpanDouble = sumSpan.TotalMinutes;
var winRate = (result.EveningWorkSpan.TotalMinutes * 100) / sumSpanDouble;
result.WinRate = Convert.ToInt32(winRate);
result.IsEveningShift = true;
result.IsMorningShift = false;
result.IsNightShift = false;
result.RotatingShiftStatus = "عصر";
}
if (result.EveningWorkSpan < result.NightWorkSpan
|| result.EveningWorkSpan == result.NightWorkSpan) // if night bigerThan evening or equal
if (result.NightWorkSpan != nullWorkspan)
{
var sumSpan = result.EveningWorkSpan.Add(result.NightWorkSpan);
var sumSpanDouble = sumSpan.TotalMinutes;
var winRate = (result.NightWorkSpan.TotalMinutes * 100) / sumSpanDouble;
result.WinRate = Convert.ToInt32(winRate);
result.IsMorningShift = false;
result.IsEveningShift = false;
result.IsNightShift = true;
result.RotatingShiftStatus = "شب";
}
}
finalResult.Add(result);
#endregion
}
return finalResult;
}
public List<RollCallViewModel> ConvertStaticHoursToRollCall(CreateWorkingHoursTemp command, bool workshopHolidyWorking)
{
var rollCallList = new List<RollCallViewModel>();
#region Entities
var sdate = command.ContarctStart.ToEnglishNumber();
var edate = command.ContractEnd.ToEnglishNumber();
var syear = Convert.ToInt32(sdate.Substring(0, 4));
var smonth = Convert.ToInt32(sdate.Substring(5, 2));
var sday = Convert.ToInt32(sdate.Substring(8, 2));
var eyear = Convert.ToInt32(edate.Substring(0, 4));
var emonth = Convert.ToInt32(edate.Substring(5, 2));
var eday = Convert.ToInt32(edate.Substring(8, 2));
var d1 = new PersianDateTime(syear, smonth, sday);
var d2 = new PersianDateTime(eyear, emonth, eday);
//بدست آوردن مرخصی
LeaveSearchModel leaveSearch = new LeaveSearchModel()
{
EmployeeId = command.EmployeeId,
WorkshopId = command.WorkshopId,
StartLeaveGr = command.ContractStartGr,
EndLeaveGr = command.ContractEndGr,
IsAccepted = true,
};
var leaveSearchResult = _leaveRepository.search(leaveSearch);
//بدس آوردن تعطیلات رسمی
var holidayList = _holidayItemRepository.GetHolidayItem(sdate.Substring(0, 4));
bool isHoliday = false;
#endregion
#region SumRestTimesOneShift
var rest0 = new TimeSpan();
var rest1 = new TimeSpan();
var rest2 = new TimeSpan();
var rest3 = new TimeSpan();
var rest4 = new TimeSpan();
var rest5 = new TimeSpan();
var rest6 = new TimeSpan();
var rest0w1 = new TimeSpan();
var rest1w1 = new TimeSpan();
var rest2w1 = new TimeSpan();
var rest3w1 = new TimeSpan();
var rest4w1 = new TimeSpan();
var rest5w1 = new TimeSpan();
var rest6w1 = new TimeSpan();
var rest0w2 = new TimeSpan();
var rest1w2 = new TimeSpan();
var rest2w2 = new TimeSpan();
var rest3w2 = new TimeSpan();
var rest4w2 = new TimeSpan();
var rest5w2 = new TimeSpan();
var rest6w2 = new TimeSpan();
var rest0w3 = new TimeSpan();
var rest1w3 = new TimeSpan();
var rest2w3 = new TimeSpan();
var rest3w3 = new TimeSpan();
var rest4w3 = new TimeSpan();
var rest5w3 = new TimeSpan();
var rest6w3 = new TimeSpan();
var rest0w4 = new TimeSpan();
var rest1w4 = new TimeSpan();
var rest2w4 = new TimeSpan();
var rest3w4 = new TimeSpan();
var rest4w4 = new TimeSpan();
var rest5w4 = new TimeSpan();
var rest6w4 = new TimeSpan();
if (command.ShiftWork == "4")
{
//week1
command.RestTimeShanbe1 = command.RestTimeShanbe1 == "0" ? "00" : command.RestTimeShanbe1;
command.RestTimeShanbe1Min = command.RestTimeShanbe1Min == "0" ? "00" : command.RestTimeShanbe1Min;
command.RestTimeYekShanbe1 = command.RestTimeYekShanbe1 == "0" ? "00" : command.RestTimeYekShanbe1;
command.RestTimeYekShanbe1Min =
command.RestTimeYekShanbe1Min == "0" ? "00" : command.RestTimeYekShanbe1Min;
command.RestTimeDoShanbe1 = command.RestTimeDoShanbe1 == "0" ? "00" : command.RestTimeDoShanbe1;
command.RestTimeDoShanbe1Min =
command.RestTimeDoShanbe1Min == "0" ? "00" : command.RestTimeDoShanbe1Min;
command.RestTimeSeShanbe1 = command.RestTimeSeShanbe1 == "0" ? "00" : command.RestTimeSeShanbe1;
command.RestTimeSeShanbe1Min =
command.RestTimeSeShanbe1Min == "0" ? "00" : command.RestTimeSeShanbe1Min;
command.RestTimeCheharShanbe1 =
command.RestTimeCheharShanbe1 == "0" ? "00" : command.RestTimeCheharShanbe1;
command.RestTimeCheharShanbe1Min =
command.RestTimeCheharShanbe1Min == "0" ? "00" : command.RestTimeCheharShanbe1Min;
command.RestTimePanjShanbe1 = command.RestTimePanjShanbe1 == "0" ? "00" : command.RestTimePanjShanbe1;
command.RestTimePanjShanbe1Min =
command.RestTimePanjShanbe1Min == "0" ? "00" : command.RestTimePanjShanbe1Min;
command.RestTimeJome1 = command.RestTimeJome1 == "0" ? "00" : command.RestTimeJome1;
command.RestTimeJome1Min = command.RestTimeJome1Min == "0" ? "00" : command.RestTimeJome1Min;
//week2
command.RestTimeShanbe2 = command.RestTimeShanbe2 == "0" ? "00" : command.RestTimeShanbe2;
command.RestTimeShanbe2Min = command.RestTimeShanbe2Min == "0" ? "00" : command.RestTimeShanbe2Min;
command.RestTimeYekShanbe2 = command.RestTimeYekShanbe2 == "0" ? "00" : command.RestTimeYekShanbe2;
command.RestTimeYekShanbe2Min =
command.RestTimeYekShanbe2Min == "0" ? "00" : command.RestTimeYekShanbe2Min;
command.RestTimeDoShanbe2 = command.RestTimeDoShanbe2 == "0" ? "00" : command.RestTimeDoShanbe2;
command.RestTimeDoShanbe2Min =
command.RestTimeDoShanbe2Min == "0" ? "00" : command.RestTimeDoShanbe2Min;
command.RestTimeSeShanbe2 = command.RestTimeSeShanbe2 == "0" ? "00" : command.RestTimeSeShanbe2;
command.RestTimeSeShanbe2Min =
command.RestTimeSeShanbe2Min == "0" ? "00" : command.RestTimeSeShanbe2Min;
command.RestTimeCheharShanbe2 =
command.RestTimeCheharShanbe2 == "0" ? "00" : command.RestTimeCheharShanbe2;
command.RestTimeCheharShanbe2Min =
command.RestTimeCheharShanbe2Min == "0" ? "00" : command.RestTimeCheharShanbe2Min;
command.RestTimePanjShanbe2 = command.RestTimePanjShanbe2 == "0" ? "00" : command.RestTimePanjShanbe2;
command.RestTimePanjShanbe2Min =
command.RestTimePanjShanbe2Min == "0" ? "00" : command.RestTimePanjShanbe2Min;
command.RestTimeJome2 = command.RestTimeJome2 == "0" ? "00" : command.RestTimeJome2;
command.RestTimeJome2Min = command.RestTimeJome2Min == "0" ? "00" : command.RestTimeJome2Min;
//week3
command.RestTimeShanbe3 = command.RestTimeShanbe3 == "0" ? "00" : command.RestTimeShanbe3;
command.RestTimeShanbe3Min = command.RestTimeShanbe3Min == "0" ? "00" : command.RestTimeShanbe3Min;
command.RestTimeYekShanbe3 = command.RestTimeYekShanbe3 == "0" ? "00" : command.RestTimeYekShanbe3;
command.RestTimeYekShanbe3Min =
command.RestTimeYekShanbe3Min == "0" ? "00" : command.RestTimeYekShanbe3Min;
command.RestTimeDoShanbe3 = command.RestTimeDoShanbe3 == "0" ? "00" : command.RestTimeDoShanbe3;
command.RestTimeDoShanbe3Min =
command.RestTimeDoShanbe3Min == "0" ? "00" : command.RestTimeDoShanbe3Min;
command.RestTimeSeShanbe3 = command.RestTimeSeShanbe3 == "0" ? "00" : command.RestTimeSeShanbe3;
command.RestTimeSeShanbe3Min =
command.RestTimeSeShanbe3Min == "0" ? "00" : command.RestTimeSeShanbe3Min;
command.RestTimeCheharShanbe3 =
command.RestTimeCheharShanbe3 == "0" ? "00" : command.RestTimeCheharShanbe3;
command.RestTimeCheharShanbe3Min =
command.RestTimeCheharShanbe3Min == "0" ? "00" : command.RestTimeCheharShanbe3Min;
command.RestTimePanjShanbe3 = command.RestTimePanjShanbe3 == "0" ? "00" : command.RestTimePanjShanbe3;
command.RestTimePanjShanbe3Min =
command.RestTimePanjShanbe3Min == "0" ? "00" : command.RestTimePanjShanbe3Min;
command.RestTimeJome3 = command.RestTimeJome3 == "0" ? "00" : command.RestTimeJome3;
command.RestTimeJome3Min = command.RestTimeJome3Min == "0" ? "00" : command.RestTimeJome3Min;
//week4
command.RestTimeShanbe4 = command.RestTimeShanbe4 == "0" ? "00" : command.RestTimeShanbe4;
command.RestTimeShanbe4Min = command.RestTimeShanbe4Min == "0" ? "00" : command.RestTimeShanbe4Min;
command.RestTimeYekShanbe4 = command.RestTimeYekShanbe4 == "0" ? "00" : command.RestTimeYekShanbe4;
command.RestTimeYekShanbe4Min =
command.RestTimeYekShanbe4Min == "0" ? "00" : command.RestTimeYekShanbe4Min;
command.RestTimeDoShanbe4 = command.RestTimeDoShanbe4 == "0" ? "00" : command.RestTimeDoShanbe4;
command.RestTimeDoShanbe4Min =
command.RestTimeDoShanbe4Min == "0" ? "00" : command.RestTimeDoShanbe4Min;
command.RestTimeSeShanbe4 = command.RestTimeSeShanbe4 == "0" ? "00" : command.RestTimeSeShanbe4;
command.RestTimeSeShanbe4Min =
command.RestTimeSeShanbe4Min == "0" ? "00" : command.RestTimeSeShanbe4Min;
command.RestTimeCheharShanbe4 =
command.RestTimeCheharShanbe4 == "0" ? "00" : command.RestTimeCheharShanbe4;
command.RestTimeCheharShanbe4Min =
command.RestTimeCheharShanbe4Min == "0" ? "00" : command.RestTimeCheharShanbe4Min;
command.RestTimePanjShanbe4 = command.RestTimePanjShanbe4 == "0" ? "00" : command.RestTimePanjShanbe4;
command.RestTimePanjShanbe4Min =
command.RestTimePanjShanbe4Min == "0" ? "00" : command.RestTimePanjShanbe4Min;
command.RestTimeJome4 = command.RestTimeJome4 == "0" ? "00" : command.RestTimeJome4;
command.RestTimeJome4Min = command.RestTimeJome4Min == "0" ? "00" : command.RestTimeJome4Min;
// sumrest week1
rest0w1 = TimeSpan.Parse($"{command.RestTimeShanbe1}:{command.RestTimeShanbe1Min}");
rest1w1 = TimeSpan.Parse($"{command.RestTimeYekShanbe1}:{command.RestTimeYekShanbe1Min}");
rest2w1 = TimeSpan.Parse($"{command.RestTimeDoShanbe1}:{command.RestTimeDoShanbe1Min}");
rest3w1 = TimeSpan.Parse($"{command.RestTimeSeShanbe1}:{command.RestTimeSeShanbe1Min}");
rest4w1 = TimeSpan.Parse($"{command.RestTimeCheharShanbe1}:{command.RestTimeCheharShanbe1Min}");
rest5w1 = TimeSpan.Parse($"{command.RestTimePanjShanbe1}:{command.RestTimePanjShanbe1Min}");
rest6w1 = TimeSpan.Parse($"{command.RestTimeJome1}:{command.RestTimeJome1Min}");
// sumrest week2
rest0w2 = TimeSpan.Parse($"{command.RestTimeShanbe2}:{command.RestTimeShanbe2Min}");
rest1w2 = TimeSpan.Parse($"{command.RestTimeYekShanbe2}:{command.RestTimeYekShanbe2Min}");
rest2w2 = TimeSpan.Parse($"{command.RestTimeDoShanbe2}:{command.RestTimeDoShanbe2Min}");
rest3w2 = TimeSpan.Parse($"{command.RestTimeSeShanbe2}:{command.RestTimeSeShanbe2Min}");
rest4w2 = TimeSpan.Parse($"{command.RestTimeCheharShanbe2}:{command.RestTimeCheharShanbe2Min}");
rest5w2 = TimeSpan.Parse($"{command.RestTimePanjShanbe2}:{command.RestTimePanjShanbe2Min}");
rest6w2 = TimeSpan.Parse($"{command.RestTimeJome2}:{command.RestTimeJome2Min}");
// sumrest week3
rest0w3 = TimeSpan.Parse($"{command.RestTimeShanbe3}:{command.RestTimeShanbe3Min}");
rest1w3 = TimeSpan.Parse($"{command.RestTimeYekShanbe3}:{command.RestTimeYekShanbe3Min}");
rest2w3 = TimeSpan.Parse($"{command.RestTimeDoShanbe3}:{command.RestTimeDoShanbe3Min}");
rest3w3 = TimeSpan.Parse($"{command.RestTimeSeShanbe3}:{command.RestTimeSeShanbe3Min}");
rest4w3 = TimeSpan.Parse($"{command.RestTimeCheharShanbe3}:{command.RestTimeCheharShanbe3Min}");
rest5w3 = TimeSpan.Parse($"{command.RestTimePanjShanbe3}:{command.RestTimePanjShanbe3Min}");
rest6w3 = TimeSpan.Parse($"{command.RestTimeJome3}:{command.RestTimeJome3Min}");
// sumrest week4
rest0w4 = TimeSpan.Parse($"{command.RestTimeShanbe4}:{command.RestTimeShanbe4Min}");
rest1w4 = TimeSpan.Parse($"{command.RestTimeYekShanbe4}:{command.RestTimeYekShanbe4Min}");
rest2w4 = TimeSpan.Parse($"{command.RestTimeDoShanbe4}:{command.RestTimeDoShanbe4Min}");
rest3w4 = TimeSpan.Parse($"{command.RestTimeSeShanbe4}:{command.RestTimeSeShanbe4Min}");
rest4w4 = TimeSpan.Parse($"{command.RestTimeCheharShanbe4}:{command.RestTimeCheharShanbe4Min}");
rest5w4 = TimeSpan.Parse($"{command.RestTimePanjShanbe4}:{command.RestTimePanjShanbe4Min}");
rest6w4 = TimeSpan.Parse($"{command.RestTimeJome4}:{command.RestTimeJome4Min}");
}
#endregion
#region Complex
//[12-24 : 5] [24-24 : 6] [12-36 : 7] [24-48 : 8]
if (command.ShiftWork is "5" or "6" or "7" or "8")
{
int addHours = command.ShiftWork switch
{
"5" => 36,
"6" => 48,
"7" => 48,
"8" => 72,
_ => 0
};
var start = Convert.ToDateTime(command.StartComplex);
var end = Convert.ToDateTime(command.EndComplex);
var startDateAndTime = new PersianDateTime(syear, smonth, sday, start.Hour, start.Minute);
var startContract = new PersianDateTime(syear, smonth, sday, start.Hour, start.Minute);
var endContract = new PersianDateTime(eyear, emonth, eday, 23, 59);
for (var da = startDateAndTime; da <= endContract; da = da.AddHours(addHours))
{
var currentDateFa = $"{da}";
var currentDateGr = da.ToGregorianDateTime();
if (da == startContract)
{
start = new DateTime(currentDateGr.Year, currentDateGr.Month, currentDateGr.Day, start.Hour, start.Minute, 0);
end = new DateTime(currentDateGr.Year, currentDateGr.Month, currentDateGr.Day, end.Hour, end.Minute, 0);
if (start.Date == end.Date && start.TimeOfDay > end.TimeOfDay)
end = end.AddDays(1);
if ((command.ShiftWork is "6" or "8") && start == end)
end = end.AddDays(1);
}
var startComplex = new DateTime(start.Year, start.Month, start.Day, start.Hour, start.Minute,
start.Second);
var endComplex = new DateTime(end.Year, end.Month, end.Day, end.Hour, end.Minute,
end.Second);
Console.WriteLine($"{currentDateFa} - {currentDateGr.Date} - start : {startComplex} end : {endComplex}");
rollCallList.Add(new RollCallViewModel()
{
StartDate = startComplex,
EndDate = endComplex,
ShiftSpan = (endComplex - startComplex),
ShiftDate = currentDateGr,
});
var endCal = end - start;
start = startComplex.AddHours(addHours);
end = start.Add(endCal);
}
var countLeves = leaveSearchResult.Where(x => x.PaidLeaveType == "روزانه").ToList();
if (countLeves.Count > 0)
{
int totalDays = countLeves.Sum(x => int.Parse(x.LeaveHourses));
int countRollCall = rollCallList.Count();
int takRollCall = totalDays < countRollCall ? (countRollCall - totalDays) : 0;
rollCallList = rollCallList.Take(takRollCall).ToList();
}
}
#endregion
#region ShiftWork4Compute
if (command.ShiftWork == "4")
{
//DateTime currentDay = ($"{da}").ToGeorgianDateTime();
var hasSickLeave = false;
for (var da = d1; da <= d2; da.AddDays(1))
{
var FirstDayOfMonth = new PersianDateTime(da.Year, da.Month, 1);
var w1 = 0;
var w2 = 0;
var w3 = 0;
var w4 = 0;
var w5 = 0;
var w6 = 0;
var currentDateFa = $"{da}";
DateTime currntDateGr = currentDateFa.ToGeorgianDateTime();
if (!workshopHolidyWorking)
{
isHoliday = holidayList.Any(x => x == currentDateFa);
}
switch (FirstDayOfMonth.DayOfWeek)
{
case "شنبه":
w1 = 7;
w2 = 14;
w3 = 28;
w4 = 31;
break;
case "یکشنبه":
w1 = 6;
w2 = 13;
w3 = 20;
w4 = 27;
w5 = 31;
break;
case "دوشنبه":
w1 = 5;
w2 = 12;
w3 = 19;
w4 = 26;
w5 = 31;
break;
case "سه شنبه":
w1 = 4;
w2 = 11;
w3 = 18;
w4 = 25;
w5 = 31;
break;
case "چهارشنبه":
w1 = 3;
w2 = 10;
w3 = 17;
w4 = 24;
w5 = 31;
break;
case "پنج شنبه":
w1 = 2;
w2 = 9;
w3 = 16;
w4 = 23;
w5 = 30;
w6 = 31;
break;
case "جمعه":
w1 = 1;
w2 = 8;
w3 = 15;
w4 = 22;
w5 = 29;
w6 = 31;
break;
}
switch (da.DayOfWeek)
{
case "شنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.Shanbe1 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Shanbe1,
command.SingleShift2Shanbe1,
command.TowShifts1Shanbe1,
command.TowShifts2Shanbe1, currntDateGr, rest0w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.Shanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Shanbe2,
command.SingleShift2Shanbe2,
command.TowShifts1Shanbe2,
command.TowShifts2Shanbe2, currntDateGr, rest0w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.Shanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Shanbe3,
command.SingleShift2Shanbe3,
command.TowShifts1Shanbe3,
command.TowShifts2Shanbe3, currntDateGr, rest0w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.Shanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Shanbe4,
command.SingleShift2Shanbe4,
command.TowShifts1Shanbe4,
command.TowShifts2Shanbe4, currntDateGr, rest0w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "یکشنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.YekShanbe1 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1YekShanbe1,
command.SingleShift2YekShanbe1,
command.TowShifts1YekShanbe1,
command.TowShifts2YekShanbe1, currntDateGr, rest1w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.YekShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1YekShanbe2,
command.SingleShift2YekShanbe2,
command.TowShifts1YekShanbe2,
command.TowShifts2YekShanbe2, currntDateGr, rest1w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.YekShanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1YekShanbe3,
command.SingleShift2YekShanbe3,
command.TowShifts1YekShanbe3,
command.TowShifts2YekShanbe3, currntDateGr, rest1w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.YekShanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1YekShanbe4,
command.SingleShift2YekShanbe4,
command.TowShifts1YekShanbe4,
command.TowShifts2YekShanbe4, currntDateGr, rest1w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "دوشنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.DoShanbe1 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1DoShanbe1,
command.SingleShift2DoShanbe1,
command.TowShifts1DoShanbe1,
command.TowShifts2DoShanbe1, currntDateGr, rest2w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.DoShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1DoShanbe2,
command.SingleShift2DoShanbe2,
command.TowShifts1DoShanbe2,
command.TowShifts2DoShanbe2, currntDateGr, rest2w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.DoShanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1DoShanbe3,
command.SingleShift2DoShanbe3,
command.TowShifts1DoShanbe3,
command.TowShifts2DoShanbe3, currntDateGr, rest2w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.DoShanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1DoShanbe4,
command.SingleShift2DoShanbe4,
command.TowShifts1DoShanbe4,
command.TowShifts2DoShanbe4, currntDateGr, rest2w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "سه شنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.SeShanbe1 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1SeShanbe1,
command.SingleShift2SeShanbe1,
command.TowShifts1SeShanbe1,
command.TowShifts2SeShanbe1, currntDateGr, rest3w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.SeShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1SeShanbe2,
command.SingleShift2SeShanbe2,
command.TowShifts1SeShanbe2,
command.TowShifts2SeShanbe2, currntDateGr, rest3w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.SeShanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1SeShanbe3,
command.SingleShift2SeShanbe3,
command.TowShifts1SeShanbe3,
command.TowShifts2SeShanbe3, currntDateGr, rest3w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.SeShanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1SeShanbe4,
command.SingleShift2SeShanbe4,
command.TowShifts1SeShanbe4,
command.TowShifts2SeShanbe4, currntDateGr, rest3w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "چهارشنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.CheharShanbe1 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1CheharShanbe1,
command.SingleShift2CheharShanbe1,
command.TowShifts1CheharShanbe1,
command.TowShifts2CheharShanbe1, currntDateGr, rest4w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.CheharShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1CheharShanbe2,
command.SingleShift2CheharShanbe2,
command.TowShifts1CheharShanbe2,
command.TowShifts2CheharShanbe2, currntDateGr, rest4w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.CheharShanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1CheharShanbe3,
command.SingleShift2CheharShanbe3,
command.TowShifts1CheharShanbe3,
command.TowShifts2CheharShanbe3, currntDateGr, rest4w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.CheharShanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1CheharShanbe4,
command.SingleShift2CheharShanbe4,
command.TowShifts1CheharShanbe4,
command.TowShifts2CheharShanbe4, currntDateGr, rest4w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "پنج شنبه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.PanjShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1PanjShanbe1,
command.SingleShift2PanjShanbe1,
command.TowShifts1PanjShanbe1,
command.TowShifts2PanjShanbe1, currntDateGr, rest5w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.PanjShanbe2 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1PanjShanbe2,
command.SingleShift2PanjShanbe2,
command.TowShifts1PanjShanbe2,
command.TowShifts2PanjShanbe2, currntDateGr, rest5w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.PanjShanbe3 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1PanjShanbe3,
command.SingleShift2PanjShanbe3,
command.TowShifts1PanjShanbe3,
command.TowShifts2PanjShanbe3, currntDateGr, rest5w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.PanjShanbe4 && isHoliday == false)
{
var res = FindStaticShiftsStatus(
command.SingleShift1PanjShanbe4,
command.SingleShift2PanjShanbe4,
command.TowShifts1PanjShanbe4,
command.TowShifts2PanjShanbe4, currntDateGr, rest5w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
case "جمعه":
if (((da.Day <= w1) || (da.Day > w4 && da.Day <= w5)) && command.Jome1)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Jome1,
command.SingleShift2Jome1,
command.TowShifts1Jome1,
command.TowShifts2Jome1, currntDateGr, rest6w1, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (((da.Day > w1 && da.Day <= w2) || (da.Day > w5 && da.Day <= w6)) && command.Jome2)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Jome2,
command.SingleShift2Jome2,
command.TowShifts1Jome2,
command.TowShifts2Jome2, currntDateGr, rest6w2, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w2 && da.Day <= w3 && command.Jome3)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Jome3,
command.SingleShift2Jome3,
command.TowShifts1Jome3,
command.TowShifts2Jome3, currntDateGr, rest6w3, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
else if (da.Day > w3 && da.Day <= w4 && command.Jome4)
{
var res = FindStaticShiftsStatus(
command.SingleShift1Jome4,
command.SingleShift2Jome4,
command.TowShifts1Jome4,
command.TowShifts2Jome4, currntDateGr, rest6w4, leaveSearchResult);
if (res.Count > 0)
rollCallList.AddRange(res);
}
break;
}
}
}
#endregion
return rollCallList;
}
/// <summary>
/// جاگذاری شیفت های استاتیک در بازه تاریخ
/// </summary>
/// <returns></returns>
private List<RollCallViewModel> FindStaticShiftsStatus(string shift1Start, string shift1End, string shift2Start,
string shift2End, DateTime cuurentDate, TimeSpan restTime, List<LeaveViewModel> leaveSearchResult)
{
var result = new List<RollCallViewModel>();
var shift1StartGr = new DateTime();
var shift1EndGr = new DateTime();
var shift2StartGr = new DateTime();
var shift2EndGr = new DateTime();
if (leaveSearchResult.Count > 0)
{
leaveSearchResult = leaveSearchResult.Select(x => new LeaveViewModel()
{
LeaveHourses = x.LeaveHourses,
LeaveType = x.LeaveType,
PaidLeaveType = x.PaidLeaveType,
StartLeaveGr = x.StartLeaveGr,
EndLeaveGr = x.PaidLeaveType == "روزانه" ? new DateTime(x.EndLeaveGr.Year, x.EndLeaveGr.Month, x.EndLeaveGr.Day, 23, 59, 59) : x.EndLeaveGr,
}).ToList();
}
#region Shift1
if (!string.IsNullOrWhiteSpace(shift1Start) && !string.IsNullOrWhiteSpace(shift1End))
{
try
{
var starTimeSingel1 = Convert.ToDateTime(shift1Start);
var endTimeSingel2 = Convert.ToDateTime(shift1End);
bool hasRestTime = false;
shift1StartGr = new DateTime(cuurentDate.Year, cuurentDate.Month, cuurentDate.Day, starTimeSingel1.Hour, starTimeSingel1.Minute, 0);
shift1EndGr = new DateTime(cuurentDate.Year, cuurentDate.Month, cuurentDate.Day, endTimeSingel2.Hour, endTimeSingel2.Minute, 0);
if (shift1EndGr.TimeOfDay < shift1StartGr.TimeOfDay)
shift1EndGr = shift1EndGr.AddDays(1);
var shiftEndWithoutRest = shift1EndGr;
var shiftSpan = (shift1EndGr - shift1StartGr);
if (restTime > TimeSpan.Zero && shiftSpan >= restTime)
{
hasRestTime = true;
shift1EndGr = shift1EndGr.Subtract(restTime);
shiftSpan = (shift1EndGr - shift1StartGr);
}
if (!leaveSearchResult.Any(x => x.StartLeaveGr < shift1EndGr && x.EndLeaveGr > shift1StartGr && x.PaidLeaveType == "روزانه"))
{
var hourseLeaveTypeResult = leaveSearchResult.FirstOrDefault(x =>
x.StartLeaveGr < shift1EndGr && x.EndLeaveGr > shift1StartGr && x.PaidLeaveType == "ساعتی");
if (hourseLeaveTypeResult == null)
{
result.Add(new RollCallViewModel()
{
BreakTimeSpan = hasRestTime ? restTime : TimeSpan.Zero,
StartDate = shift1StartGr,
EndDate = shift1EndGr,
ShiftSpan = shiftSpan,
ShiftDate = shift1StartGr,
ShiftEndWithoutRest = shiftEndWithoutRest
});
}
else
{
if (hourseLeaveTypeResult.StartLeaveGr <= shift1StartGr && hourseLeaveTypeResult.EndLeaveGr < shift1EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
BreakTimeSpan = hasRestTime ? restTime : TimeSpan.Zero,
StartDate = hourseLeaveTypeResult.EndLeaveGr,
EndDate = shift1EndGr,
ShiftSpan = (shift1EndGr - hourseLeaveTypeResult.EndLeaveGr),
ShiftDate = shift1StartGr,
ShiftEndWithoutRest = shiftEndWithoutRest
});
}
else if (hourseLeaveTypeResult.StartLeaveGr > shift1StartGr && hourseLeaveTypeResult.EndLeaveGr < shift1EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
BreakTimeSpan = hasRestTime ? restTime : TimeSpan.Zero,
StartDate = shift1StartGr,
EndDate = hourseLeaveTypeResult.StartLeaveGr,
ShiftSpan = (hourseLeaveTypeResult.StartLeaveGr - shift1StartGr),
ShiftDate = shift1StartGr,
ShiftEndWithoutRest = hourseLeaveTypeResult.StartLeaveGr
});
result.Add(new RollCallViewModel()
{
BreakTimeSpan = hasRestTime ? restTime : TimeSpan.Zero,
StartDate = hourseLeaveTypeResult.EndLeaveGr,
EndDate = shift1EndGr,
ShiftSpan = (shift1EndGr - hourseLeaveTypeResult.EndLeaveGr),
ShiftDate = shift1StartGr,
ShiftEndWithoutRest = shiftEndWithoutRest
});
}
else if (hourseLeaveTypeResult.StartLeaveGr > shift1StartGr && hourseLeaveTypeResult.EndLeaveGr >= shift1EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
BreakTimeSpan = hasRestTime ? restTime : TimeSpan.Zero,
StartDate = shift1StartGr,
EndDate = hourseLeaveTypeResult.StartLeaveGr,
ShiftSpan = (hourseLeaveTypeResult.StartLeaveGr - shift1StartGr),
ShiftDate = shift1StartGr,
ShiftEndWithoutRest = hourseLeaveTypeResult.StartLeaveGr
});
}
}
}
}
catch (Exception e)
{
// ignored
}
}
#endregion
#region Shift2
if (!string.IsNullOrWhiteSpace(shift2Start) && !string.IsNullOrWhiteSpace(shift2End))
{
try
{
var startTimeTowSh1 = Convert.ToDateTime(shift2Start);
var endTimeTowSh2 = Convert.ToDateTime(shift2End);
//اگر شیفت 1 وجود داشت تاریخ جاری را از شیف 1 میگیریم
//زیرا ممکن پایان شیف 1 در روز بعد باشد
var shift1 = result.MaxBy(x => x.EndDate);
if (shift1 != null)
if (shift1.EndDate != null)
cuurentDate = shift1.EndDate.Value;
shift2StartGr = new DateTime(cuurentDate.Year, cuurentDate.Month, cuurentDate.Day, startTimeTowSh1.Hour, startTimeTowSh1.Minute, 0);
shift2EndGr = new DateTime(cuurentDate.Year, cuurentDate.Month, cuurentDate.Day, endTimeTowSh2.Hour, endTimeTowSh2.Minute, 0);
if (shift2EndGr.TimeOfDay < shift2StartGr.TimeOfDay)
shift2EndGr = shift2EndGr.AddDays(1);
if (!leaveSearchResult.Any(x => x.StartLeaveGr < shift2EndGr && x.EndLeaveGr > shift2StartGr && x.PaidLeaveType == "روزانه"))
{
var hourseLeaveTypeResult = leaveSearchResult.FirstOrDefault(x =>
x.StartLeaveGr < shift2EndGr && x.EndLeaveGr > shift2StartGr && x.PaidLeaveType == "ساعتی");
if (hourseLeaveTypeResult == null)
{
result.Add(new RollCallViewModel()
{
StartDate = shift2StartGr,
EndDate = shift2EndGr,
ShiftSpan = (shift2EndGr - shift2StartGr),
ShiftDate = shift1?.ShiftDate ?? shift2EndGr,
});
}
else
{
if (hourseLeaveTypeResult.StartLeaveGr <= shift2StartGr && hourseLeaveTypeResult.EndLeaveGr < shift2EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
StartDate = hourseLeaveTypeResult.EndLeaveGr,
EndDate = shift2EndGr,
ShiftSpan = (shift2EndGr - hourseLeaveTypeResult.EndLeaveGr),
ShiftDate = shift1?.EndDate ?? shift2EndGr,
});
}
else if (hourseLeaveTypeResult.StartLeaveGr > shift2StartGr && hourseLeaveTypeResult.EndLeaveGr < shift2EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
StartDate = shift2StartGr,
EndDate = hourseLeaveTypeResult.StartLeaveGr,
ShiftSpan = (hourseLeaveTypeResult.StartLeaveGr - shift2StartGr),
ShiftDate = shift1?.EndDate ?? shift2EndGr,
});
result.Add(new RollCallViewModel()
{
StartDate = hourseLeaveTypeResult.EndLeaveGr,
EndDate = shift2EndGr,
ShiftSpan = (shift2EndGr - hourseLeaveTypeResult.EndLeaveGr),
ShiftDate = shift1?.EndDate ?? shift2EndGr,
});
}
else if (hourseLeaveTypeResult.StartLeaveGr > shift2StartGr && hourseLeaveTypeResult.EndLeaveGr >= shift2EndGr)
{
//leave <-------------------->
//shift <---------------------------------->
result.Add(new RollCallViewModel()
{
StartDate = shift2StartGr,
EndDate = hourseLeaveTypeResult.StartLeaveGr,
ShiftSpan = (hourseLeaveTypeResult.StartLeaveGr - shift2StartGr),
ShiftDate = shift1?.EndDate ?? shift2EndGr,
});
}
}
}
}
catch (Exception e)
{
// ignored
}
}
#endregion
return result;
}
#endregion
#region CustomizeCheckout
/// <summary>
/// متد محاسبه فیش حقوقی دلخواه
/// </summary>
/// <param name="employeeId"></param>
/// <param name="workshopId"></param>
/// <param name="contractStart"></param>
/// <param name="contractEnd"></param>
/// <returns></returns>
public CustomizeCheckoutMandatoryViewModel CustomizeCheckoutMandatoryCompute(long employeeId, long workshopId, DateTime contractStart,
DateTime contractEnd)
{
var checkoutEnd = contractEnd;
var checkoutStart = contractStart;
if (workshopId == 170)
return CustomizeCheckoutMandatoryComputeForKebabMahdi(employeeId, workshopId, contractStart, contractEnd);
var firstDayOfMonth = $"{(contractStart.ToFarsi())[..8]}/01".ToGeorgianDateTime();
#region LeftWork
var leftWork = _leftWorkRepository.GetByWorkshopIdEmployeeIdInDates(workshopId, employeeId, contractStart, contractEnd);
if (leftWork.StartWorkDateGr > contractStart)
{
contractStart = leftWork.StartWorkDateGr;
}
if (leftWork.LeftWorkDateGr.AddDays(-1) < contractEnd)
{
contractEnd = leftWork.LeftWorkDateGr.AddDays(-1);
}
TimeSpan leftWorkDurationTimeSpan = leftWork.HasLeft ? leftWork.LeftWorkDateGr.AddDays(-1) - leftWork.StartWorkDateGr : contractEnd - leftWork.StartWorkDateGr;
#endregion
#region Entities
int numberOfFridays = 0;
double monthySalary = 0;
int monthDays = 0;
double dailyWage = 0;
int numberOfWorkingDay = 0;
string endPersianDate = contractEnd.ToFarsi();
int monthOfCheckout = Convert.ToInt32(endPersianDate.Substring(5, 2));
int yearOfCheckout = Convert.ToInt32(endPersianDate.Substring(0, 4));
//روز هایی که پرسنل موظف بوده کار کند
var mandatoryDays = 0;
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;
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);
var totalDays = (int)(contractEnd - contractStart).TotalDays + 1;
mandatoryDays = totalDays;
#endregion
#region CustomizeSettings
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
monthySalary = customizeWorkshopEmployeeSettings?.Salary ?? 0;
monthDays = customizeWorkshopSettings.MaxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth
? 30
: firstDayOfMonth.CountMonthDays();
var shiftSettings = customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts;
var employeeShiftsSpans = shiftSettings.Select(x =>
{
var start = new DateTime(new DateOnly(), x.StartTime);
var end = new DateTime(new DateOnly(), x.EndTime);
if (x.EndTime < x.StartTime)
end = end.AddDays(1);
var span = end - start;
return new EmployeeShiftResult
{
Placement = x.Placement,
ShiftSpan = span
};
});
var sumOfEmployeeShiftSpan = new TimeSpan(employeeShiftsSpans.Sum(x => x.ShiftSpan.Ticks));
if (customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Irregular)
{
sumOfEmployeeShiftSpan = CalculateIrregularShift(customizeWorkshopEmployeeSettings.IrregularShift);
}
if (customizeWorkshopEmployeeSettings.BreakTime.BreakTimeType == BreakTimeType.WithTime)
{
sumOfEmployeeShiftSpan -= customizeWorkshopEmployeeSettings.BreakTime.BreakTimeValue.ToTimeSpan();
}
#endregion
List<RollCallViewModel> rollCallResult = _context.RollCalls.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate.Value.Date >= contractStart.Date &&
x.StartDate.Value.Date <= contractEnd.Date && x.EndDate != null)
.Select(x => new RollCallViewModel()
{
StartDate = x.StartDate,
EndDate = x.EndDate,
ShiftSpan = (x.EndDate.Value - x.StartDate.Value),
CreationDate = x.CreationDate,
BreakTimeSpan = x.BreakTimeSpan
}).ToList();
List<GroupedRollCalls> groupedRollCall = rollCallResult.GroupBy(x => x.StartDate!.Value.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),
SumOneDaySpan = new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)) - CalculateBreakTime(x.First().BreakTimeSpan,
new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))),
BreakTime = CalculateBreakTime(x.First().BreakTimeSpan, new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks)))
}).ToList();
TimeSpan sumSpans = new TimeSpan(groupedRollCall.Sum(x => x.SumOneDaySpan.Ticks));
numberOfFridays = groupedRollCall.Count(x => x.HasFriday);
numberOfWorkingDay = groupedRollCall.Count();
//تعداد روز های قرارداد
int contractDays = (int)contractDuration.TotalDays + 1;
//روز های غیبت
int fridays = 0;
int holiday = _context.HolidayItems.Count(x => x.Holidaydate >= contractStart && x.Holidaydate <= contractEnd);
for (var gDate = contractStart; gDate <= contractEnd; gDate = gDate.AddDays(1))
{
if (gDate.DayOfWeek == DayOfWeek.Friday)
{
fridays += 1;
}
}
if (customizeWorkshopEmployeeSettings.FridayWork == FridayWork.Default)
{
var fridayWorkingTotalDays = CalculateFridayWorkingTotalDays(rollCallResult);
fridays = fridays - fridayWorkingTotalDays;
mandatoryDays -= fridays;
}
if (customizeWorkshopEmployeeSettings.HolidayWork == HolidayWork.Default)
{
var groupStartDaysDates = groupedRollCall.Select(x => x.CreationDate.Date).ToList();
var holidayWorkingDays = _context.HolidayItems.Count(x =>
groupStartDaysDates.Any(r => r == x.Holidaydate.Date));
holiday = holiday - holidayWorkingDays;
mandatoryDays -= holiday;
}
TimeSpan absentTimeSpans = new();
if ((mandatoryDays * sumOfEmployeeShiftSpan) > sumSpans)
{
absentTimeSpans = (mandatoryDays * sumOfEmployeeShiftSpan) - sumSpans;
}
dailyWage = monthySalary / monthDays;
var minuteWage = sumOfEmployeeShiftSpan.TotalMinutes == 0 ? 0 : (dailyWage / sumOfEmployeeShiftSpan.TotalMinutes);
// یافتن مرخصی ساعتی
#region LeavHourse
LeaveSearchModel leaveHourseSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
List<LeaveViewModel> leaveList = _leaveRepository.search(leaveHourseSearch);
#endregion
//****افزودن مرخصی پرسنل به مجموع ساعات کار***
#region AddEmployeeLeaves
//TimeSpan workingPerDayAve = sumSpans / numberOfWorkingDay;//میانگین ساعت کار در روز
//if (workingPerDayAve <= new TimeSpan(7, 20, 0))
//{
// sumLeave = leavingDayCout * workingPerDayAve;
//}
//else
//{
// sumLeave = leavingDayCout * new TimeSpan(7, 20, 0);
//}
double leavePayAmount = 0;
double absentsDeductionAmount = 0;
if (customizeWorkshopEmployeeSettings.LeavePay.LeavePayType != LeavePayType.None)
{
int permittedDays = customizeWorkshopEmployeeSettings.LeavePermittedDays;
double leaveValue = customizeWorkshopEmployeeSettings.LeavePay.Value;
sumSpans = CalculateLeavePay(sumOfEmployeeShiftSpan, absentTimeSpans, permittedDays, monthDays, contractDays, sumSpans
, leaveValue, minuteWage, contractStart, contractEnd, out leavePayAmount, out absentsDeductionAmount);
}
else
{
absentsDeductionAmount = absentTimeSpans.TotalMinutes * minuteWage;
}
Console.WriteLine(sumSpans);
#endregion
//***********************************//
//ToTal Hours Employee Worked
double totalHours = (sumSpans.TotalMinutes) / 60;
int totalHolidaysAndNotH = (int)sumSpans.TotalHours;
int totalHolidaysAndNotM = (int)(sumSpans.TotalMinutes % 60);
//***********************************//
#region Deductions
//غیبت
//تاخیر و تعجیل
//حق بیمه
#region InsurancePay
InsuranceDeduction insuranceDeduction = customizeWorkshopEmployeeSettings.InsuranceDeduction;
//farokhiChange
double insuranceDeductionAmount = InsurancePayCalculation(employeeId, contractStart, contractEnd, insuranceDeduction, monthySalary);
#endregion
#region SalaryAidDeduction
var salaryAidViewModel = SalaryAidsForCheckout(employeeId, workshopId, checkoutStart, checkoutEnd);
double salaryAidDeduction = salaryAidViewModel.Sum(x => x.AmountDouble);
#endregion
#region Loan
var loanInstallments = LoanInstallmentForCheckout(employeeId, workshopId, contractStart, contractEnd);
double loanDeduction = loanInstallments.Sum(x => x.AmountDouble);
#endregion
#region Fine
var fineViewModels = FinesForCheckout(employeeId, workshopId, contractStart, contractEnd);
double fineDeduction = fineViewModels.Sum(x => x.Amount.MoneyToDouble());
#endregion
#endregion
#region Payments
//اضافه کاری
#region OvertimePay
double overtimePayAmount = 0;
TimeSpan overtimeTimeSpan;
if (customizeWorkshopSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular && customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular)
{
TimeOnly employeeOffSet = customizeWorkshopSettings.EndTimeOffSet;
overtimeTimeSpan = CalculateOvertimeTimeSpan(rollCallResult, shiftSettings, employeeOffSet);
}
else if (customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular)
{
var date = new DateOnly();
var firstStartShift = new DateTime(date, customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts.MinBy(x => x.Placement).StartTime);
var lastEndShift = new DateTime(date, customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts.MaxBy(x => x.Placement).EndTime);
if (lastEndShift > firstStartShift)
firstStartShift = firstStartShift.AddDays(1);
var offSet = (firstStartShift - lastEndShift).Divide(2);
var employeeOffSet = TimeOnly.FromDateTime(lastEndShift.Add(offSet));
overtimeTimeSpan = CalculateOvertimeTimeSpan(rollCallResult, shiftSettings, employeeOffSet);
}
else
{
var irregularShifts = customizeWorkshopEmployeeSettings.IrregularShift.WorkshopIrregularShifts;
overtimeTimeSpan = CalculateIrregularOverTime(rollCallResult, sumOfEmployeeShiftSpan, irregularShifts, mandatoryDays);
//Todo: fix for irregular and rotating shifts
}
overtimePayAmount = CalculateOvertimePay(overtimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage);
if (overtimePayAmount >= absentsDeductionAmount)
{
overtimePayAmount = overtimePayAmount - absentsDeductionAmount;
absentsDeductionAmount = 0;
}
else
{
absentsDeductionAmount = absentsDeductionAmount - overtimePayAmount;
overtimePayAmount = 0;
}
#endregion
#region FridayPay
double fridayPayAmount = 0;
fridayPayAmount = FridayPayCalculation(customizeWorkshopEmployeeSettings, rollCallResult, dailyWage, shiftSettings, overtimePayAmount);
#endregion
//حق تاهل
#region MaritalAllownace
double maritalAllowancePay = 0;
if (employee.MaritalStatus == "متاهل")
{
switch (customizeWorkshopEmployeeSettings.MarriedAllowance.MarriedAllowanceType)
{
case MarriedAllowanceType.Money:
{
maritalAllowancePay = customizeWorkshopEmployeeSettings.MarriedAllowance.Value;
break;
}
//case MarriedAllowanceType.PercentageFromSalary:
// {
// double multiplier = customizeWorkshopEmployeeSettings.MarriedAllowance.Value / 100;
// maritalAllowance = dailyWage * multiplier;
// break;
// }
}
}
#endregion
//شب کاری
#region NightWorkPay
double nightworkPayAmount = 0;
List<RotatingShiftViewModel> rotatingResultList = RotatingShiftCheck(groupedRollCall);
// شبکاری
TimeSpan nightWorks = new TimeSpan(rotatingResultList.Sum(x => x.NightWorkSpan.Ticks));
if (nightWorks > new TimeSpan())
{
switch (customizeWorkshopEmployeeSettings.NightWorkPay.NightWorkingType)
{
case NightWorkType.MoneyPerHour:
{
var baseAmount = customizeWorkshopEmployeeSettings.NightWorkPay.Value;
var nightWorkMinutes = (int)(nightWorks).TotalMinutes;
nightworkPayAmount += nightWorkMinutes * (baseAmount / 60);
break;
}
case NightWorkType.PercentageFromSalary:
{
double multiplier = customizeWorkshopEmployeeSettings.NightWorkPay.Value / 100;
var nightWorkMinutes = (int)(nightWorks).TotalMinutes;
nightworkPayAmount += ((dailyWage * multiplier) / 60) * nightWorkMinutes;
break;
}
}
}
#endregion
//سنوات
#region BaseYearsPay
double baseYearsPayAmount = CalculateYearsPayAmount(employeeId, workshopId, monthySalary, contractStart, contractEnd
, customizeWorkshopEmployeeSettings.BaseYearsPay, customizeWorkshopSettings.BaseYearsPayInEndOfYear, customizeWorkshopSettings.MaxMonthDays);
#endregion
//حق اولاد
#region FamilyAllowancePay
double familyAllowancePay = 0;
switch (customizeWorkshopEmployeeSettings.FamilyAllowance.FamilyAllowanceType)
{
case FamilyAllowanceType.Money:
{
double baseAmount = customizeWorkshopEmployeeSettings.FamilyAllowance.Value;
familyAllowancePay = CalculateFamilyAllowancePayAmount(employeeId, baseAmount, contractEnd);
break;
}
case FamilyAllowanceType.Percentage:
{
double multiplier = customizeWorkshopEmployeeSettings.FamilyAllowance.Value / 100;
familyAllowancePay = CalculateFamilyAllowancePayAmount(employeeId, multiplier * monthySalary, contractEnd);
break;
}
}
#endregion
#region Reward
var rewardViewModels = RewardForCheckout(employeeId, workshopId, checkoutEnd, checkoutStart);
double rewardPay = rewardViewModels.Sum(x => x.AmountDouble);
#endregion
#region LeavePay
#endregion
#region BonusesPay
double bonusesPayAmount = 0;
if (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType != BonusesType.None)
{
switch (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType)
{
case BonusesType.OneTimeOfSalary:
bonusesPayAmount = monthySalary;
break;
case BonusesType.TwoTimeOfSalary:
bonusesPayAmount = monthySalary * 2;
break;
case BonusesType.Money:
bonusesPayAmount = customizeWorkshopEmployeeSettings.BonusesPay.Value;
break;
case BonusesType.PercentageOfSalary:
bonusesPayAmount = (monthySalary * customizeWorkshopEmployeeSettings.BonusesPay.Value) / 100;
break;
}
double bonusesPerMonth = bonusesPayAmount / 12;
if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.YearlyPay)
{
var contractEndFarsi = Tools.FindeEndOfMonth(contractEnd.ToFarsi());
if (monthOfCheckout == 12 && (contractEndFarsi.EndsWith("29")) || contractEndFarsi.EndsWith("30"))
{
}
else if (customizeWorkshopSettings.BonusesPaysInEndOfMonth == BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft)
{
TimeSpan bonusDuration;
DateTime startOfYear = new PersianCalendar().ToDateTime(yearOfCheckout, 1, 1, 0, 0, 0, 0);
if (startOfYear < leftWork.StartWorkDateGr)
bonusDuration = leftWorkDurationTimeSpan;
else
bonusDuration = leftWork.LeftWorkDateGr - startOfYear;
//ToDo: Check if should be absolute 365!
bonusesPayAmount = (bonusesPayAmount / 365) * bonusDuration.TotalDays;
}
else
{
bonusesPayAmount = 0;
}
}
else if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.MonthlyPay)
{
if (customizeWorkshopSettings.BonusesPaysInEndOfMonth ==
BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft && contractDays < monthDays)
bonusesPayAmount = (bonusesPerMonth / contractEnd.CountPersianMonthDays()) * contractDuration.TotalDays + 1;
bonusesPayAmount = bonusesPerMonth;
}
else
{
throw new InvalidDataException();
}
}
#endregion
#endregion
#region LateToWork & EarlyExit
var lateToWorkEarlyExit = LateToWorkEarlyExit(groupedRollCall, shiftSettings, leaveList);
foreach (var i in lateToWorkEarlyExit)
{
Console.WriteLine(" start : " + i.StartSpan + " end : " + i.EndSpan + " spaning : " + i.Spanning + " Type : " + i.TypeOfSapn);
}
var lateToWoks = lateToWorkEarlyExit.Where(x => x.TypeOfSapn == "LateToWork");
var earlyExits = lateToWorkEarlyExit.Where(x => x.TypeOfSapn == "EarlyExist");
var lateToWork = new TimeSpan(lateToWoks.Sum(x => x.Spanning.Ticks));
var earlyExist = new TimeSpan(earlyExits.Sum(x => x.Spanning.Ticks));
var totalSpaning = new TimeSpan(lateToWorkEarlyExit.Sum(x => x.Spanning.Ticks));
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(" LateToWork H : " + (int)lateToWork.TotalHours + " M : " + (int)(lateToWork.TotalMinutes % 60));
Console.WriteLine(" EarlyExist H : " + (int)earlyExist.TotalHours + " M : " + (int)(earlyExist.TotalMinutes % 60));
Console.WriteLine(" TotalSpaning H : " + (int)totalSpaning.TotalHours + " M : " + (int)(totalSpaning.TotalMinutes % 60));
Console.ResetColor();
double earlyExitDeduction = 0;
double lateToWorkDeduction = 0;
////محاسبه مزد روزانه به ازای هر دقیقه
//double dailyWagePerMinute =
// (customizeWorkshopEmployeeSettings.Salary / monthDays) / sumOfEmployeeShiftSpan.TotalMinutes;
if (customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitType != EarlyExitType.None && earlyExist > new TimeSpan())
{
earlyExitDeduction = customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitType switch
{
EarlyExitType.Default => earlyExist.TotalMinutes * minuteWage,
EarlyExitType.MoneyPerMinute => earlyExist.TotalMinutes * customizeWorkshopEmployeeSettings.EarlyExit.Value,
_ => 0
};
}
if (customizeWorkshopEmployeeSettings.LateToWork.LateToWorkType != LateToWorkType.None && lateToWork > new TimeSpan())
{
lateToWorkDeduction = customizeWorkshopEmployeeSettings.LateToWork.LateToWorkType switch
{
LateToWorkType.Default => lateToWork.TotalMinutes * minuteWage,
LateToWorkType.MoneyPerMinute => lateToWork.TotalMinutes * customizeWorkshopEmployeeSettings.LateToWork.Value,
_ => 0
};
}
if (customizeWorkshopEmployeeSettings.LateToWork.LateToWorkTimeFines.Any())
{
lateToWorkDeduction +=
(from lateToWorkTimeFine in customizeWorkshopEmployeeSettings.LateToWork.LateToWorkTimeFines
let stepFine = lateToWoks.Count(x => x.Spanning.TotalMinutes >= Convert.ToInt32(lateToWorkTimeFine.Minute))
select stepFine * lateToWorkTimeFine.FineMoney).Sum();
}
if (customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitTimeFines.Any())
{
earlyExitDeduction +=
(from earlyExitFine in customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitTimeFines
let stepFine = earlyExits.Count(x => x.Spanning.TotalMinutes >= Convert.ToInt32(earlyExitFine.Minute))
select stepFine * earlyExitFine.FineMoney).Sum();
}
#endregion
return new CustomizeCheckoutMandatoryViewModel
{
InsuranceDeduction = insuranceDeductionAmount,
FridayPay = fridayPayAmount,
OverTimePay = overtimePayAmount,
BaseYearsPay = baseYearsPayAmount,
NightWorkPay = nightworkPayAmount,
MarriedAllowance = maritalAllowancePay,
FamilyAllowance = familyAllowancePay,
LeavePay = leavePayAmount,
FineAbsenceDeduction = absentsDeductionAmount,
BonusesPay = bonusesPayAmount,
ContractEndFa = contractEnd.ToFarsi(),
ContractStartFa = contractStart.ToFarsi(),
EmployeeName = employee.FullName,
InstallmentDeduction = loanDeduction,
SalaryAidDeduction = salaryAidDeduction,
FineDeduction = fineDeduction,
RewardPay = rewardPay,
Month = monthOfCheckout,
Year = yearOfCheckout,
LateToWorkDeduction = lateToWorkDeduction,
EarlyExitDeduction = earlyExitDeduction,
ShiftPay = 0,
TaxDeduction = 0,
EmployeeId = employeeId,
SumOfWorkingDays = totalDays.ToString(),
ContractNo = contract?.ContractNo ?? "-",
MonthlySalary = dailyWage * mandatoryDays,
PersonnelCode = personnelCode,
FineViewModels = fineViewModels,
InstallmentViewModels = loanInstallments,
SalaryAidViewModels = salaryAidViewModel,
RewardViewModels = rewardViewModels
};
}
public CustomizeCheckoutMandatoryViewModel CustomizeCheckoutMandatoryComputeForKebabMahdi(long employeeId,
long workshopId,
DateTime contractStart, DateTime contractEnd)
{
var checkoutEnd = contractEnd;
var checkoutStart = contractStart;
var exceptionEmployees = _context.CustomizeWorkshopGroupSettings.Where(x => x.id == 117)
.Include(x => x.CustomizeWorkshopEmployeeSettingsCollection).AsSplitQuery().FirstOrDefault()?.CustomizeWorkshopEmployeeSettingsCollection.Select(x => x.EmployeeId).ToList() ?? [];
if (exceptionEmployees.Contains(employeeId))
{
return CheckoutWithoutCalculationForKebabMahdi(workshopId, employeeId, contractStart, contractEnd);
}
var firstDayOfMonth = $"{(contractStart.ToFarsi())[..8]}/01".ToGeorgianDateTime();
#region LeftWork
var leftWork =
_leftWorkRepository.GetByWorkshopIdEmployeeIdInDates(workshopId, employeeId, contractStart, contractEnd);
if (leftWork.StartWorkDateGr > contractStart)
{
contractStart = leftWork.StartWorkDateGr;
}
if (leftWork.LeftWorkDateGr.AddDays(-1) < contractEnd)
{
contractEnd = leftWork.LeftWorkDateGr.AddDays(-1);
}
TimeSpan leftWorkDurationTimeSpan = leftWork.HasLeft
? leftWork.LeftWorkDateGr.AddDays(-1) - leftWork.StartWorkDateGr
: contractEnd - leftWork.StartWorkDateGr;
#endregion
#region Entities
int numberOfFridays = 0;
double monthySalary = 0;
int monthDays = 0;
double dailyWage = 0;
int numberOfWorkingDay = 0;
string endPersianDate = contractEnd.ToFarsi();
int monthOfCheckout = Convert.ToInt32(endPersianDate.Substring(5, 2));
int yearOfCheckout = Convert.ToInt32(endPersianDate.Substring(0, 4));
//روز هایی که پرسنل موظف بوده کار کند
var mandatoryDays = 0;
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;
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);
var totalDays = (int)(contractEnd - contractStart).TotalDays + 1;
mandatoryDays = totalDays;
#endregion
#region CustomizeSettings
CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings;
CustomizeWorkshopSettings customizeWorkshopSettings;
var endFarvarding = new DateTime(2025, 4, 20);
if (contractStart > endFarvarding)
{
customizeWorkshopEmployeeSettings = _context.CustomizeWorkshopEmployeeSettings
.AsSplitQuery().AsNoTracking().FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
customizeWorkshopSettings = _context.CustomizeWorkshopSettings.AsNoTracking().FirstOrDefault(x => x.WorkshopId == workshopId);
}
else
{
customizeWorkshopEmployeeSettings = _testDbContext.CustomizeWorkshopEmployeeSettings
.AsSplitQuery().AsNoTracking().FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
customizeWorkshopSettings = _testDbContext.CustomizeWorkshopSettings.AsNoTracking().FirstOrDefault(x => x.WorkshopId == workshopId);
}
//ToDo handel exception if is null
monthySalary = customizeWorkshopEmployeeSettings?.Salary ?? 0;
monthDays = customizeWorkshopSettings.MaxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth
? 30
: firstDayOfMonth.CountMonthDays();
var shiftSettings = customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts;
var employeeShiftsSpans = shiftSettings.Select(x =>
{
var start = new DateTime(new DateOnly(), x.StartTime);
var end = new DateTime(new DateOnly(), x.EndTime);
if (x.EndTime < x.StartTime)
end = end.AddDays(1);
var span = end - start;
return new EmployeeShiftResult
{
Placement = x.Placement,
ShiftSpan = span
};
});
#endregion
List<RollCallViewModel> rollCallResult = _context.RollCalls.AsNoTracking().Where(x =>
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,
EndDate = x.EndDate,
ShiftSpan = (x.EndDate.Value - x.StartDate.Value),
CreationDate = x.CreationDate,
ShiftDate = x.ShiftDate,
EarlyEntryDuration = x.EarlyEntryDuration,
LateEntryDuration = x.LateEntryDuration,
EarlyExitDuration = x.EarlyExitDuration,
LateExitDuration = x.LateExitDuration,
ShiftDurationTimeSpan = x.ShiftDurationTimeSpan,
BreakTimeSpan = x.BreakTimeSpan
}).ToList();
List<GroupedRollCalls> 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(
x.First().BreakTimeSpan,
new TimeSpan(x.Sum(shift => shift.ShiftSpan.Ticks))),
BreakTime = CalculateBreakTime(x.First().BreakTimeSpan,
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;
if (customizeWorkshopEmployeeSettings.BreakTime.BreakTimeType == BreakTimeType.WithTime &&
sumOfEmployeeShiftSpan != TimeSpan.Zero)
{
sumOfEmployeeShiftSpan -= customizeWorkshopEmployeeSettings.BreakTime.BreakTimeValue.ToTimeSpan();
}
// ساخت لیست همه تاریخ‌ها در بازه
List<DateTime> allDates = Enumerable.Range(0, (contractEnd - contractStart).Days + 1)
.Select(offset => contractStart.AddDays(offset))
.ToList();
// فیلتر تاریخ‌هایی که در لیست حضور نیستند
List<DateTime> absentDates = allDates
.Where(date => !groupedRollCall.Any(g => g.ShiftDate.Date == date.Date))
.ToList();
TimeSpan sumSpans = new TimeSpan(groupedRollCall.Sum(x => x.SumOneDaySpan.Ticks));
numberOfFridays = groupedRollCall.Count(x => x.HasFriday);
numberOfWorkingDay = groupedRollCall.Count();
//تعداد روز های قرارداد
int contractDays = (int)contractDuration.TotalDays + 1;
//روز های غیبت
var absenceDays = mandatoryDays - groupedRollCall.Count;
int fridays = 0;
int holiday = _context.HolidayItems.Count(x => x.Holidaydate >= contractStart && x.Holidaydate <= contractEnd);
for (var gDate = contractStart; gDate <= contractEnd; gDate = gDate.AddDays(1))
{
if (gDate.DayOfWeek == DayOfWeek.Friday)
{
fridays += 1;
}
}
if (customizeWorkshopEmployeeSettings.FridayWork == FridayWork.Default)
{
var fridayWorkingTotalDays = groupedRollCall.Count(x => x.ShiftDate.DayOfWeek == DayOfWeek.Friday);
var fridayWorking = fridays - fridayWorkingTotalDays;
//mandatoryDays -= fridayWorking;
}
if (customizeWorkshopEmployeeSettings.HolidayWork == HolidayWork.Default)
{
var groupStartDaysDates = groupedRollCall.Select(x => x.CreationDate.Date).ToList();
var holidayWorkingDays = _context.HolidayItems.Count(x =>
groupStartDaysDates.Any(r => r == x.Holidaydate.Date));
holiday = holiday - holidayWorkingDays;
mandatoryDays -= holiday;
}
TimeSpan absentTimeSpans = new();
if ((mandatoryDays * sumOfEmployeeShiftSpan) > sumSpans)
{
absentTimeSpans = (mandatoryDays * sumOfEmployeeShiftSpan) - sumSpans;
}
dailyWage = monthySalary / monthDays;
var minuteWage = sumOfEmployeeShiftSpan.TotalMinutes == 0
? 0
: (dailyWage / sumOfEmployeeShiftSpan.TotalMinutes);
// یافتن مرخصی ساعتی
#region LeavHourse
LeaveSearchModel leaveHourseSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
List<LeaveViewModel> leaveList = _leaveRepository.search(leaveHourseSearch);
#endregion
//****افزودن مرخصی پرسنل به مجموع ساعات کار***
#region AddEmployeeLeaves
//TimeSpan workingPerDayAve = sumSpans / numberOfWorkingDay;//میانگین ساعت کار در روز
//if (workingPerDayAve <= new TimeSpan(7, 20, 0))
//{
// sumLeave = leavingDayCout * workingPerDayAve;
//}
//else
//{
// sumLeave = leavingDayCout * new TimeSpan(7, 20, 0);
//}
double leavePayAmount = 0;
double absentsDeductionAmount = 0;
int leavePermittedDays = customizeWorkshopEmployeeSettings.LeavePermittedDays;
double leaveValue = customizeWorkshopEmployeeSettings.LeavePay.Value;
if (customizeWorkshopEmployeeSettings.CustomizeWorkshopGroupSettingId == 77)
{
var startMonth = contractStart;
var endMonth = contractStart.ToFarsi().FindeEndOfMonth().ToGeorgianDateTime();
int fridayInMonth = 0;
// Ensure the dates are in the correct order
if (startMonth > endMonth)
{
var temp = startMonth;
startMonth = endMonth;
endMonth = temp;
}
// Find the first Friday in the range
int daysUntilFriday = ((int)DayOfWeek.Friday - (int)startMonth.DayOfWeek + 7) % 7;
DateTime firstFriday = startMonth.AddDays(daysUntilFriday);
// If the first Friday is outside the range, there are no Fridays
if (firstFriday > endMonth)
{
fridayInMonth = 0;
}
// Calculate the total number of days between the first Friday and the end date
int totalFridayPeriod = (endMonth - firstFriday).Days;
// Count the Fridays by dividing the total days by 7 and adding 1 for the first Friday
fridayInMonth = totalFridayPeriod / 7 + 1;
leavePermittedDays = fridayInMonth;
}
sumSpans = CalculateLeavePay(sumOfEmployeeShiftSpan, absentTimeSpans, leavePermittedDays, monthDays,
contractDays, sumSpans
, leaveValue, minuteWage, contractStart, contractEnd, out leavePayAmount, out absentsDeductionAmount);
if (customizeWorkshopEmployeeSettings.LeavePay.LeavePayType != LeavePayType.None)
{
}
else
{
absentsDeductionAmount = absentTimeSpans.TotalMinutes * minuteWage;
}
leavePayAmount = 0;
absenceDays = (absenceDays - leavePermittedDays) < 0 ? 0 : (absenceDays - leavePermittedDays);
//اگر روز تولدش تاریخ فیش وجود داشت
var monthOfBirthDay = employee!.DateOfBirth.ToFarsi().Substring(5, 2);
var pc = new PersianCalendar();
var birthdayMonth = pc.GetMonth(employee.DateOfBirth);
var birthdayDay = pc.GetDayOfMonth(employee.DateOfBirth);
if (birthdayMonth == 12 && birthdayDay == 30)
{
//چک کن که آیا سال قرارداد کبیسه هست یا نه
var leap =
pc.IsLeapYear(pc.GetYear(contractStart));
if (!leap)
{
birthdayDay = 29;
}
}
var employeeBirthDay = $"{yearOfCheckout:0000}/{birthdayMonth:00}/{birthdayDay:00}".ToGeorgianDateTime();
if (employeeBirthDay >= contractStart && employeeBirthDay <= contractEnd && absenceDays > 0)
{
CreateRewardForBirthDay(employeeId, workshopId, dailyWage, monthOfCheckout, yearOfCheckout, contractStart);
}
Console.WriteLine(sumSpans);
#endregion
//***********************************//
//ToTal Hours Employee Worked
double totalHours = (sumSpans.TotalMinutes) / 60;
int totalHolidaysAndNotH = (int)sumSpans.TotalHours;
int totalHolidaysAndNotM = (int)(sumSpans.TotalMinutes % 60);
//***********************************//
#region Deductions
//غیبت
//تاخیر و تعجیل
//حق بیمه
#region InsurancePay
InsuranceDeduction insuranceDeduction = customizeWorkshopEmployeeSettings.InsuranceDeduction;
//farokhiChange
double insuranceDeductionAmount =
InsurancePayCalculation(employeeId, contractStart, contractEnd, insuranceDeduction, monthySalary);
#endregion
#region SalaryAidDeduction
var salaryAidViewModel = SalaryAidsForCheckout(employeeId, workshopId, checkoutStart, checkoutEnd);
double salaryAidDeduction = salaryAidViewModel.Sum(x => x.AmountDouble);
#endregion
#region Loan
var loanInstallments = LoanInstallmentForCheckout(employeeId, workshopId, contractStart, contractEnd);
double loanDeduction = loanInstallments.Sum(x => x.AmountDouble);
#endregion
#region Fine
var fineViewModels = FinesForCheckout(employeeId, workshopId, contractStart, contractEnd);
double fineDeduction = fineViewModels.Sum(x => x.Amount.MoneyToDouble());
#endregion
#endregion
#region Payments
//اضافه کاری
#region OvertimePay
double overtimePayAmount = 0;
TimeSpan overtimeTimeSpan;
if (customizeWorkshopSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular &&
customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular)
{
overtimeTimeSpan = CalculateOvertimeSpanWithSumSpan(sumSpans, mandatoryDays, shiftSettings);
}
else if (customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Regular)
{
//var date = new DateOnly();
//var firstStartShift = new DateTime(date, customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts.MinBy(x => x.Placement).StartTime);
//var lastEndShift = new DateTime(date, customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts.MaxBy(x => x.Placement).EndTime);
//if (lastEndShift > firstStartShift)
// firstStartShift = firstStartShift.AddDays(1);
//var offSet = (firstStartShift - lastEndShift).Divide(2);
//var employeeOffSet = TimeOnly.FromDateTime(lastEndShift.Add(offSet));
overtimeTimeSpan = CalculateOvertimeSpanWithSumSpan(sumSpans, mandatoryDays, shiftSettings);
}
else
{
var irregularShifts = customizeWorkshopEmployeeSettings.IrregularShift.WorkshopIrregularShifts;
overtimeTimeSpan = CalculateRotatingOvertime(customizeWorkshopEmployeeSettings.CustomizeRotatingShifts,
groupedRollCall, mandatoryDays, sumSpans);
}
overtimePayAmount =
CalculateOvertimePay(overtimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage);
if (overtimePayAmount >= absentsDeductionAmount)
{
overtimePayAmount = overtimePayAmount - absentsDeductionAmount;
absentsDeductionAmount = 0;
}
else
{
absentsDeductionAmount = absentsDeductionAmount - overtimePayAmount;
overtimePayAmount = 0;
}
overtimePayAmount = 0;
#endregion
#region KebabMahdiAbsentsCaclculation
var rollCallDays = groupedRollCall.Count > mandatoryDays ? mandatoryDays : groupedRollCall.Count;
absenceDays = mandatoryDays - rollCallDays;
absenceDays = absenceDays - leavePermittedDays < 0 ? 0 : absenceDays - leavePermittedDays;
absentsDeductionAmount = absenceDays * dailyWage;
#endregion
var createReward = absenceDays;
if (monthOfCheckout == 1 && yearOfCheckout == 1404)
{
bool hasAbsents = _context.CustomizeCheckouts.Any(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.MonthInt == 12 && x.YearInt == 1403 &&
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)
{
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--;
}
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--;
}
}
#region FridayPay
double fridayPayAmount = 0;
fridayPayAmount = FridayPayCalculation(customizeWorkshopEmployeeSettings, rollCallResult, dailyWage,
shiftSettings, overtimePayAmount);
#endregion
//حق تاهل
#region MaritalAllownace
double maritalAllowancePay = 0;
if (employee.MaritalStatus == "متاهل")
{
switch (customizeWorkshopEmployeeSettings.MarriedAllowance.MarriedAllowanceType)
{
case MarriedAllowanceType.Money:
{
maritalAllowancePay = customizeWorkshopEmployeeSettings.MarriedAllowance.Value;
break;
}
//case MarriedAllowanceType.PercentageFromSalary:
// {
// double multiplier = customizeWorkshopEmployeeSettings.MarriedAllowance.Value / 100;
// maritalAllowance = dailyWage * multiplier;
// break;
// }
}
}
#endregion
//شب کاری
#region NightWorkPay
double nightworkPayAmount = 0;
List<RotatingShiftViewModel> rotatingResultList = RotatingShiftCheck(groupedRollCall);
// شبکاری
TimeSpan nightWorks = new TimeSpan(rotatingResultList.Sum(x => x.NightWorkSpan.Ticks));
if (nightWorks > new TimeSpan())
{
switch (customizeWorkshopEmployeeSettings.NightWorkPay.NightWorkingType)
{
case NightWorkType.MoneyPerHour:
{
var baseAmount = customizeWorkshopEmployeeSettings.NightWorkPay.Value;
var nightWorkMinutes = (int)(nightWorks).TotalMinutes;
nightworkPayAmount += nightWorkMinutes * (baseAmount / 60);
break;
}
case NightWorkType.PercentageFromSalary:
{
double multiplier = customizeWorkshopEmployeeSettings.NightWorkPay.Value / 100;
var nightWorkMinutes = (int)(nightWorks).TotalMinutes;
nightworkPayAmount += ((dailyWage * multiplier) / 60) * nightWorkMinutes;
break;
}
}
}
#endregion
//سنوات
#region BaseYearsPay
double baseYearsPayAmount = CalculateYearsPayAmount(employeeId, workshopId, monthySalary, contractStart,
contractEnd
, customizeWorkshopEmployeeSettings.BaseYearsPay, customizeWorkshopSettings.BaseYearsPayInEndOfYear,
customizeWorkshopSettings.MaxMonthDays);
#endregion
//حق اولاد
#region FamilyAllowancePay
double familyAllowancePay = 0;
switch (customizeWorkshopEmployeeSettings.FamilyAllowance.FamilyAllowanceType)
{
case FamilyAllowanceType.Money:
{
double baseAmount = customizeWorkshopEmployeeSettings.FamilyAllowance.Value;
familyAllowancePay = CalculateFamilyAllowancePayAmount(employeeId, baseAmount, contractEnd);
break;
}
case FamilyAllowanceType.Percentage:
{
double multiplier = customizeWorkshopEmployeeSettings.FamilyAllowance.Value / 100;
familyAllowancePay =
CalculateFamilyAllowancePayAmount(employeeId, multiplier * monthySalary, contractEnd);
break;
}
}
#endregion
#region Reward
var rewardViewModels = RewardForCheckout(employeeId, workshopId, checkoutEnd, checkoutStart);
double rewardPay = rewardViewModels.Sum(x => x.AmountDouble);
#endregion
#region LeavePay
#endregion
#region BonusesPay
double bonusesPayAmount = 0;
if (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType != BonusesType.None)
{
switch (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType)
{
case BonusesType.OneTimeOfSalary:
bonusesPayAmount = monthySalary;
break;
case BonusesType.TwoTimeOfSalary:
bonusesPayAmount = monthySalary * 2;
break;
case BonusesType.Money:
bonusesPayAmount = customizeWorkshopEmployeeSettings.BonusesPay.Value;
break;
case BonusesType.PercentageOfSalary:
bonusesPayAmount = (monthySalary * customizeWorkshopEmployeeSettings.BonusesPay.Value) / 100;
break;
}
double bonusesPerMonth = bonusesPayAmount / 12;
if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.YearlyPay)
{
var contractEndFarsi = Tools.FindeEndOfMonth(contractEnd.ToFarsi());
if (monthOfCheckout == 12 && (contractEndFarsi.EndsWith("29")) || contractEndFarsi.EndsWith("30"))
{
}
else if (customizeWorkshopSettings.BonusesPaysInEndOfMonth ==
BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft)
{
TimeSpan bonusDuration;
DateTime startOfYear = new PersianCalendar().ToDateTime(yearOfCheckout, 1, 1, 0, 0, 0, 0);
if (startOfYear < leftWork.StartWorkDateGr)
bonusDuration = leftWorkDurationTimeSpan;
else
bonusDuration = leftWork.LeftWorkDateGr - startOfYear;
//ToDo: Check if should be absolute 365!
bonusesPayAmount = (bonusesPayAmount / 365) * bonusDuration.TotalDays;
}
else
{
bonusesPayAmount = 0;
}
}
else if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.MonthlyPay)
{
if (customizeWorkshopSettings.BonusesPaysInEndOfMonth ==
BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft && contractDays < monthDays)
bonusesPayAmount = (bonusesPerMonth / contractEnd.CountPersianMonthDays()) *
contractDuration.TotalDays + 1;
bonusesPayAmount = bonusesPerMonth;
}
else
{
throw new InvalidDataException();
}
}
#endregion
#endregion
#region LateToWork & EarlyExit
//var lateToWorkEarlyExit = LateToWorkEarlyExit(groupedRollCall, shiftSettings, leaveList);
//foreach (var i in lateToWorkEarlyExit)
//{
// Console.WriteLine(" start : " + i.StartSpan + " end : " + i.EndSpan + " spaning : " + i.Spanning + " Type : " + i.TypeOfSapn);
//}
//var lateToWoks = lateToWorkEarlyExit.Where(x => x.TypeOfSapn == "LateToWork");
//var earlyExits = lateToWorkEarlyExit.Where(x => x.TypeOfSapn == "EarlyExist");
//var lateToWork = new TimeSpan(lateToWoks.Sum(x => x.Spanning.Ticks));
//var earlyExist = new TimeSpan(earlyExits.Sum(x => x.Spanning.Ticks));
//var totalSpaning = new TimeSpan(lateToWorkEarlyExit.Sum(x => x.Spanning.Ticks));
//Console.ForegroundColor = ConsoleColor.Yellow;
//Console.WriteLine(" LateToWork H : " + (int)lateToWork.TotalHours + " M : " + (int)(lateToWork.TotalMinutes % 60));
//Console.WriteLine(" EarlyExist H : " + (int)earlyExist.TotalHours + " M : " + (int)(earlyExist.TotalMinutes % 60));
//Console.WriteLine(" TotalSpaning H : " + (int)totalSpaning.TotalHours + " M : " + (int)(totalSpaning.TotalMinutes % 60));
//Console.ResetColor();
//double earlyExitDeduction = 0;
//double lateToWorkDeduction = 0;
//////محاسبه مزد روزانه به ازای هر دقیقه
////double dailyWagePerMinute =
//// (customizeWorkshopEmployeeSettings.Salary / monthDays) / sumOfEmployeeShiftSpan.TotalMinutes;
//if (customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitType != EarlyExitType.None && earlyExist > new TimeSpan())
//{
// earlyExitDeduction = customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitType switch
// {
// EarlyExitType.Default => earlyExist.TotalMinutes * minuteWage,
// EarlyExitType.MoneyPerMinute => earlyExist.TotalMinutes * customizeWorkshopEmployeeSettings.EarlyExit.Value,
// _ => 0
// };
//}
//if (customizeWorkshopEmployeeSettings.LateToWork.LateToWorkType != LateToWorkType.None && lateToWork > new TimeSpan())
//{
// lateToWorkDeduction = customizeWorkshopEmployeeSettings.LateToWork.LateToWorkType switch
// {
// LateToWorkType.Default => lateToWork.TotalMinutes * minuteWage,
// LateToWorkType.MoneyPerMinute => lateToWork.TotalMinutes * customizeWorkshopEmployeeSettings.LateToWork.Value,
// _ => 0
// };
//}
//if (customizeWorkshopEmployeeSettings.LateToWork.LateToWorkTimeFines.Any())
//{
// lateToWorkDeduction +=
// (from lateToWorkTimeFine in customizeWorkshopEmployeeSettings.LateToWork.LateToWorkTimeFines
// let stepFine = lateToWoks.Count(x => x.Spanning.TotalMinutes >= Convert.ToInt32(lateToWorkTimeFine.Minute))
// select stepFine * lateToWorkTimeFine.FineMoney).Sum();
//}
//if (customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitTimeFines.Any())
//{
// earlyExitDeduction +=
// (from earlyExitFine in customizeWorkshopEmployeeSettings.EarlyExit.EarlyExitTimeFines
// let stepFine = earlyExits.Count(x => x.Spanning.TotalMinutes >= Convert.ToInt32(earlyExitFine.Minute))
// select stepFine * earlyExitFine.FineMoney).Sum();
//}
double lateToWorkDeduction = 0;
TimeSpan totalLateToWorkSpan = TimeSpan.Zero;
if (customizeWorkshopEmployeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating)
{
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);
}
}
if (mandatoryDays == 31)
{
mandatoryDays = 30;
}
#endregion
return new CustomizeCheckoutMandatoryViewModel
{
InsuranceDeduction = Math.Truncate(insuranceDeductionAmount),
FridayPay = Math.Truncate(fridayPayAmount),
OverTimePay = Math.Truncate(overtimePayAmount),
BaseYearsPay = Math.Truncate(baseYearsPayAmount),
NightWorkPay = Math.Truncate(nightworkPayAmount),
MarriedAllowance = Math.Truncate(maritalAllowancePay),
FamilyAllowance = Math.Truncate(familyAllowancePay),
LeavePay = Math.Truncate(leavePayAmount),
FineAbsenceDeduction = Math.Truncate(absentsDeductionAmount),
BonusesPay = Math.Truncate(bonusesPayAmount),
ContractEndFa = contractEnd.ToFarsi(),
ContractStartFa = contractStart.ToFarsi(),
EmployeeName = employee.FullName,
InstallmentDeduction = Math.Truncate(loanDeduction),
SalaryAidDeduction = Math.Truncate(salaryAidDeduction),
FineDeduction = Math.Truncate(fineDeduction),
RewardPay = Math.Truncate(rewardPay),
Month = monthOfCheckout,
Year = yearOfCheckout,
LateToWorkDeduction = Math.Truncate(lateToWorkDeduction),
EarlyExitDeduction = 0,
ShiftPay = 0,
TaxDeduction = 0,
EmployeeId = employeeId,
SumOfWorkingDays = totalDays.ToString(),
ContractNo = contract?.ContractNo ?? "-",
MonthlySalary = dailyWage * mandatoryDays,
PersonnelCode = personnelCode,
FineViewModels = fineViewModels,
InstallmentViewModels = loanInstallments,
SalaryAidViewModels = salaryAidViewModel,
RewardViewModels = rewardViewModels,
LateToWorkValue = totalLateToWorkSpan,
SettingSalary = customizeWorkshopEmployeeSettings.Salary,
DailyWage = dailyWage,
ShiftStatus = customizeWorkshopEmployeeSettings.WorkshopShiftStatus,
IrregularShift = customizeWorkshopEmployeeSettings.IrregularShift,
CustomizeRotatingShifts = customizeWorkshopEmployeeSettings.CustomizeRotatingShifts,
EmployeeSettingsShifts = customizeWorkshopEmployeeSettings.CustomizeWorkshopEmployeeSettingsShifts
.Select(x => (CustomizeSifts)x).ToList(),
};
}
private CustomizeCheckoutMandatoryViewModel CheckoutWithoutCalculationForKebabMahdi(long workshopId, long employeeId, DateTime contractStart, DateTime contractEnd)
{
var firstDayOfMonth = $"{(contractStart.ToFarsi())[..8]}/01".ToGeorgianDateTime();
CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings;
CustomizeWorkshopSettings customizeWorkshopSettings;
var endFarvarding = new DateTime(2025, 4, 20);
if (contractStart > endFarvarding)
{
customizeWorkshopEmployeeSettings = _context.CustomizeWorkshopEmployeeSettings
.AsSplitQuery().AsNoTracking().FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
customizeWorkshopSettings = _context.CustomizeWorkshopSettings.AsNoTracking().FirstOrDefault(x => x.WorkshopId == workshopId);
}
else
{
customizeWorkshopEmployeeSettings = _testDbContext.CustomizeWorkshopEmployeeSettings
.AsSplitQuery().AsNoTracking().FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
customizeWorkshopSettings = _testDbContext.CustomizeWorkshopSettings.AsNoTracking().FirstOrDefault(x => x.WorkshopId == workshopId);
}
//ToDo handel exception if is null
var monthySalary = customizeWorkshopEmployeeSettings?.Salary ?? 0;
var monthDays = customizeWorkshopSettings.MaxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth
? 30
: firstDayOfMonth.CountMonthDays();
double dailyWage = 0;
dailyWage = monthySalary / monthDays;
var totalDays = (int)(contractEnd - contractStart).TotalDays + 1;
var mandatoryDays = totalDays;
#region SalaryAidDeduction
var salaryAidViewModel = SalaryAidsForCheckout(employeeId, workshopId, contractStart, contractEnd);
double salaryAidDeduction = salaryAidViewModel.Sum(x => x.AmountDouble);
#endregion
#region Loan
var loanInstallments = LoanInstallmentForCheckout(employeeId, workshopId, contractStart, contractEnd);
double loanDeduction = loanInstallments.Sum(x => x.AmountDouble);
#endregion
#region Fine
var fineViewModels = FinesForCheckout(employeeId, workshopId, contractStart, contractEnd);
double fineDeduction = fineViewModels.Sum(x => x.Amount.MoneyToDouble());
#endregion
#region Reward
var rewardViewModels = RewardForCheckout(employeeId, workshopId, contractEnd, contractStart);
double rewardPay = rewardViewModels.Sum(x => x.AmountDouble);
#endregion
if (mandatoryDays == 31)
{
mandatoryDays = 30;
}
return new CustomizeCheckoutMandatoryViewModel()
{
MonthlySalary = dailyWage * mandatoryDays,
RewardPay = rewardPay,
RewardViewModels = rewardViewModels,
SalaryAidDeduction = salaryAidDeduction,
SalaryAidViewModels = salaryAidViewModel,
InstallmentDeduction = loanDeduction,
InstallmentViewModels = loanInstallments,
FineDeduction = fineDeduction,
FineViewModels = fineViewModels
};
}
private List<RewardViewModel> RewardForCheckout(long employeeId, long workshopId, DateTime checkoutEnd, DateTime checkoutStart)
{
return _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,
Id = x.id
}).ToList();
}
private List<FineViewModel> FinesForCheckout(long employeeId, long workshopId, DateTime contractStart, DateTime contractEnd)
{
return _context.Fines.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.FineDate >= contractStart &&
x.FineDate <= contractEnd && x.IsActive == IsActive.True).Select(x => new FineViewModel()
{
IsActive = x.IsActive,
Amount = x.Amount.ToMoney(),
FineDate = x.FineDate.ToFarsi(),
Id = x.id,
Title = x.Title,
EmployeeId = x.EmployeeId,
CreationDate = x.CreationDate.ToFarsi()
}).ToList();
}
public List<LoanInstallmentViewModel> LoanInstallmentForCheckout(long employeeId, long workshopId, DateTime contractStart, DateTime contractEnd)
{
return _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)
.Select(x => new LoanInstallmentViewModel()
{
Id = x.Id,
Month = x.Month,
IsActive = x.IsActive,
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)
.Sum(i => i.AmountForMonth).ToMoney(),
LoanAmount = _context.Loans.FirstOrDefault(l => l.id == x.LoanId).Amount.ToMoney()
}).ToList();
}
public List<SalaryAidViewModel> SalaryAidsForCheckout(long employeeId, long workshopId, DateTime checkoutStart, DateTime checkoutEnd)
{
return _context.SalaryAids
.Where(x => x.CalculationDate >= checkoutStart && x.CalculationDate <= 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,
CalculationDateTimeGe = x.CalculationDate,
CalculationDateTimeFa = x.CalculationDate.ToFarsi(),
Id = x.id
}).ToList();
}
private void CreateRewardForBirthDay(long employeeId, long workshopId, double amount, int month, int year,
DateTime contractStart)
{
var start = $"{year}/{month:00}/01".ToGeorgianDateTime();
var end = $"{year}/{month:00}/01".FindeEndOfMonth().ToGeorgianDateTime();
if (_context.Rewards.Any(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId
&& x.GrantDate >= start && x.GrantDate <= end
&& x.RewardType == RewardType.CreatedByCheckoutForBirthDay) == false)
{
var reward = new Reward(employeeId, workshopId, amount, "", 0, UserType.System, contractStart, "هدیه تولد",
RewardType.CreatedByCheckoutForBirthDay);
_context.Rewards.Add(reward);
_context.SaveChanges();
}
}
private void CreateReward(long employeeId, long workshopId, double amount, int month, int year,
DateTime contractStart, RewardType type, string title)
{
var start = $"{year}/{month:00}/01".ToGeorgianDateTime();
var end = $"{year}/{month:00}/01".FindeEndOfMonth().ToGeorgianDateTime();
if (_context.Rewards.Any(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId
&& x.GrantDate >= start && x.GrantDate <= end
&& x.RewardType == type) == false)
{
var reward = new Reward(employeeId, workshopId, amount, "", 0, UserType.System, contractStart, title, type);
_context.Rewards.Add(reward);
_context.SaveChanges();
}
}
//private void CreateRewardForChahardah(long employeeId, long workshopId, double amount, int month, int year,
// DateTime contractStart)
//{
// var start = $"{year}/{month:00}/01".ToGeorgianDateTime();
// var end = $"{year}/{month:00}/01".FindeEndOfMonth().ToGeorgianDateTime();
// if (_context.Rewards.Any(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId
// && x.GrantDate >= start && x.GrantDate <= end
// && x.RewardType == RewardType.ChahardahFarvardin) == false)
// {
// var reward = new Reward(employeeId, workshopId, amount, "", 0, contractStart, "بابت تعطیلی روز 14 فروردین",
// RewardType.ChahardahFarvardin);
// _context.Rewards.Add(reward);
// _context.SaveChanges();
// }
//}
private TimeSpan CalculateIrregularOverTime(List<RollCallViewModel> rollCalls, TimeSpan employeeShiftSpan, WorkshopIrregularShifts irregularShifts, int mandatoryDays)
{
var sumOfRollCallTicks = rollCalls.Sum(x => (x.EndDate.Value - x.StartDate.Value).Ticks);
var sumRollCall = new TimeSpan(sumOfRollCallTicks);
var sumOfShift = employeeShiftSpan * mandatoryDays;
if (sumOfShift > sumRollCall)
return TimeSpan.Zero;
return sumRollCall - sumOfShift;
}
public static TimeSpan CalculateIrregularShiftSpans(int totalDays, IrregularShift irregularShift)
{
//مبنای تقسیم که بر اساس جمع مقدار ساعت استراحت و ساعت کاری بدست میاد
double baseDivideTime = 0;
//مقدار ساعت کارکرد در هر شیفت
double workTime = 0;
switch (irregularShift.WorkshopIrregularShifts)
{
case WorkshopIrregularShifts.TwelveThirtySix:
baseDivideTime = 48;
workTime = 12;
break;
case WorkshopIrregularShifts.TwelveTwentyFour:
baseDivideTime = 36;
workTime = 12;
break;
case WorkshopIrregularShifts.TwentyFourFortyEight:
baseDivideTime = 72;
workTime = 24;
break;
case WorkshopIrregularShifts.TwentyFourTwentyFour:
baseDivideTime = 48;
workTime = 24;
break;
}
//کل ساعاتی داخلش ممکنه کار کرده باشه
var workingHour = totalDays * 24;
//مقدار تعداد خالصی که سر شیفت بوده است
int countOfWorking = (int)(workingHour / baseDivideTime);
//باقی مونده تعدادی که سر شیفت بوده است
double fractionalPart = (workingHour / baseDivideTime) - countOfWorking;
//مقدار ساعت خالصی که سر کار بوده است
TimeSpan sumOfEmployeeWorkingHours = TimeSpan.FromHours(countOfWorking * workTime);
//مقدار احتمال سر کار بودن بر حسب باقی مونده تقسیم
var workingTimesDiff = fractionalPart * workTime;
workingTimesDiff = workingTimesDiff >= workTime ? workTime : workingTimesDiff;
//جمع ساعات خالصی و احتمالی
sumOfEmployeeWorkingHours = sumOfEmployeeWorkingHours.Add(TimeSpan.FromHours(workingTimesDiff));
return sumOfEmployeeWorkingHours;
}
public static TimeSpan CalculateIrregularShift(IrregularShift irregularShift)
{
var workingTime = irregularShift.WorkshopIrregularShifts switch
{
WorkshopIrregularShifts.TwelveThirtySix => TimeSpan.FromHours(6),
WorkshopIrregularShifts.TwelveTwentyFour => TimeSpan.FromHours(8),
WorkshopIrregularShifts.TwentyFourFortyEight => TimeSpan.FromHours(8),
WorkshopIrregularShifts.TwentyFourTwentyFour => TimeSpan.FromHours(12),
_ => new TimeSpan()
};
return workingTime;
}
public static TimeSpan CalculateRotatingOvertime(ICollection<CustomizeRotatingShift> rotatingShifts,
List<GroupedRollCalls> rollCalls, int mandatoryDays, TimeSpan sumSpan)
{
TimeSpan mandatorySpan = TimeSpan.Zero;
foreach (var groupedRollCall in rollCalls)
{
var findRotatingShift = FindRotatingShift(groupedRollCall.ShiftList.Min(x => x.Start),
groupedRollCall.ShiftList.Max(x => x.End), rotatingShifts);
var span = findRotatingShift.end - findRotatingShift.start;
mandatorySpan += span;
}
var leftDays = mandatoryDays - rollCalls.Count;
if (leftDays > 0)
{
TimeSpan totalDuration = new TimeSpan(rotatingShifts.Sum(shift => Math.Abs(shift.EndTime.Ticks - shift.StartTime.Ticks)));
var averageDuration = totalDuration / rotatingShifts.Count;
mandatorySpan += averageDuration * leftDays;
}
if (mandatorySpan < sumSpan)
{
return sumSpan - mandatorySpan;
}
return TimeSpan.Zero;
}
#region CustomizeCheckoutCalculation
public static double FridayPayCalculation(CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings,
List<RollCallViewModel> rollCallResult, double dailyWage, ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings, double overtimePayAmount)
{
double fridayPayAmount = 0;
switch (customizeWorkshopEmployeeSettings.FridayPay.FridayPayType)
{
case (FridayPayType.MoneyPerFridayForDay):
{
int workedFridaysCount = CalculateFridayWorkingTotalDays(rollCallResult);
double baseAmount = customizeWorkshopEmployeeSettings.FridayPay.Value;
fridayPayAmount = baseAmount * workedFridaysCount;
break;
}
case (FridayPayType.MoneyPerFridayPerHour):
{
int workedFridaysMinutes = (int)CalculateFridayWorkingTimeSpan(rollCallResult).TotalMinutes;
double baseAmount = customizeWorkshopEmployeeSettings.FridayPay.Value;
fridayPayAmount = (baseAmount / 60) * workedFridaysMinutes;
break;
}
case (FridayPayType.PercentageFromSalaryPerHour):
{
int workedFridaysMinutes = (int)CalculateFridayWorkingTimeSpan(rollCallResult).TotalMinutes;
double percentageAmount = (customizeWorkshopEmployeeSettings.FridayPay.Value / 100 * dailyWage);
fridayPayAmount = (percentageAmount / 60) * workedFridaysMinutes;
break;
}
//case (FridayPayType.ExtraWorking):
// {
// var fridayOvertimeTimeSpan = CalculateFridayWorkingTimeSpanWithoutOvertime(rollCallResult, shiftSettings);
// overtimePayAmount += CalculateOvertimePay(fridayOvertimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage);
// return overtimePayAmount;
// break;
// }
default:
break;
}
return fridayPayAmount;
}
public double InsurancePayCalculation(long employeeId, DateTime contractStart, DateTime contractEnd,
InsuranceDeduction insuranceDeduction, double monthySalary)
{
double insurancePayAmount = 0;
switch (insuranceDeduction.InsuranceDeductionType)
{
case InsuranceDeductionType.BasedOnLaborLaw:
//farokhiChange
double familyAllowance = _yearlySalaryRepository.FamilyAllowance(employeeId, contractStart, contractEnd).MoneyToDouble();
double housingAllowance = _yearlySalaryRepository.HousingAllowance(contractEnd).MoneyToDouble();
double consumableItemsAllowance = _yearlySalaryRepository.ConsumableItems(contractEnd).MoneyToDouble();
double wage = _context.YearlySalaries.Include(x => x.YearlySalaryItemsList)
.FirstOrDefault(x => x.StartDate <= contractEnd && x.EndDate <= contractEnd).YearlySalaryItemsList
.FirstOrDefault(x => x.ItemName == "مزد روزانه").ItemValue;
insurancePayAmount = (familyAllowance + housingAllowance + consumableItemsAllowance + wage) * 7 / 100;
break;
case InsuranceDeductionType.PercentageOfSalary:
double multiplier = insuranceDeduction.Value / 100;
insurancePayAmount = monthySalary * multiplier;
break;
case InsuranceDeductionType.Money:
double baseAmount = insuranceDeduction.Value;
insurancePayAmount = baseAmount;
break;
case InsuranceDeductionType.None:
break;
default:
insurancePayAmount = 0;
break;
}
return insurancePayAmount;
}
public static TimeSpan CalculateLeavePay(TimeSpan sumOfEmployeeShiftSpan, TimeSpan absentsTimeSpan,
int permittedLeaveDay, int monthDays, int contractDays, TimeSpan sumSpans,
double leaveValue, double minuteWage, DateTime startDate, DateTime endDate, out double leavePayAmount, out double absentsDeduction)
{
// زمان مجاز مرخصی
TimeSpan permittedLeaveTimeSpan = sumOfEmployeeShiftSpan * permittedLeaveDay;
// زمان مرخصی مجاز برای یک روز
TimeSpan leaveTimePerDay = (permittedLeaveTimeSpan / monthDays);
//اگر ترک کار کرده بود
if (contractDays < monthDays)
{
permittedLeaveTimeSpan = leaveTimePerDay * contractDays;
}
//اگر قراردادش کامل بود
else
{
}
//اختلاف غیبت و مرخصی
(TimeSpan Diffrence, AbsentOrLeave absentOrLeave) absentAndLeaveDifference;
//مقدار مبلغ مرخصی
leavePayAmount = 0;
//مقدار مبلغ غیبت
absentsDeduction = 0;
//#region SumLeaves
//var usedLeavesCheckout = new TimeSpan();
//foreach (var item in leaveList)
//{
// var start = new DateTime();
// var end = new DateTime();
// start = item.StartLeaveGr < startDate ? startDate : item.StartLeaveGr;
// end = item.EndLeaveGr > endDate ? endDate : item.EndLeaveGr;
// if (item.PaidLeaveType == "روزانه")
// {
// var leaveSpan = (end - start);
// usedLeavesCheckout = usedLeavesCheckout.Add(leaveSpan);
// }
// else
// {
// var leavingHourses = TimeSpan.Parse(item.LeaveHourses);
// usedLeavesCheckout = usedLeavesCheckout.Add(leavingHourses);
// }
//}
//#endregion
//if (permittedLeaveTimeSpan >= usedLeavesCheckout)
//{
// permittedLeaveTimeSpan = permittedLeaveTimeSpan - usedLeavesCheckout;
// sumSpans += usedLeavesCheckout;
// usedLeavesCheckout = new TimeSpan();
//}
//else
//{
// sumSpans += permittedLeaveTimeSpan;
// absentsTimeSpan = (absentsTimeSpan - usedLeavesCheckout) - permittedLeaveTimeSpan;
// permittedLeaveTimeSpan = new TimeSpan();
//}
//اگر مقدار مجاز مرخصی بیشتر از غیبت یا مساوی باشد
if (permittedLeaveTimeSpan >= absentsTimeSpan)
{
//محاسبه مقدار باقی مانده مزد مرخصی
absentAndLeaveDifference.Diffrence = permittedLeaveTimeSpan - absentsTimeSpan;
absentAndLeaveDifference.absentOrLeave = AbsentOrLeave.LeavePay;
//صفر کردن مقدار غیبت
absentsTimeSpan = new TimeSpan(0);
////برگرداندن ساعت کاری باقی مونده از مزد مرخصی به ساعت کاری
//sumSpans += absentAndLeaveDifference.Diffrence;
//مقدار مزد مرخصی برای هرروز استفاده نشده
double leavePayPerDayWage = (leaveValue * (minuteWage * sumOfEmployeeShiftSpan.TotalMinutes));
if (permittedLeaveTimeSpan.TotalHours == 0)
return sumSpans;
leavePayAmount = (leavePayPerDayWage / permittedLeaveTimeSpan.TotalMinutes) * absentAndLeaveDifference.Diffrence.TotalMinutes;
}
//اگر مقدار غیبت بیشتر از مرخصی باشد
else
{
//محاسبه مقدار باقی مانده از غیبت
absentAndLeaveDifference.Diffrence = absentsTimeSpan - permittedLeaveTimeSpan;
absentAndLeaveDifference.absentOrLeave = AbsentOrLeave.AbsentDeduction;
//صفر کردن مقدار مزد مرخصی
permittedLeaveTimeSpan = new TimeSpan(0);
permittedLeaveDay = 0;
////برگرداندن ساعت کاری باقی مونده از مزد مرخصی به ساعت کاری
//sumSpans += permittedLeaveTimeSpan;
absentsDeduction = absentsTimeSpan.TotalMinutes * minuteWage;
}
return sumSpans;
}
/// <summary>
/// محاسبه تاخیر در ورورد و تعجیل در خروج
/// </summary>
/// <param name="groupedRollCall"></param>
/// <param name="shiftSettings"></param>
/// <returns></returns>
public List<LateToWorkEarlyExistSpannig> LateToWorkEarlyExit(List<GroupedRollCalls> groupedRollCall, ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings, List<LeaveViewModel> leavList)
{
List<LateToWorkEarlyExistSpannig> lateToWorkEarlyExistSpannig = new List<LateToWorkEarlyExistSpannig>();
foreach (var day in groupedRollCall)
{
foreach (var shift in shiftSettings)
{
//DateTime start = DateTime.Parse(shift.StartTime);
//DateTime end = DateTime.Parse(shift.EndTime);
DateTime startShift = new DateTime(day.CreationDate.Year, day.CreationDate.Month, day.CreationDate.Day, shift.StartTime.Hour, shift.StartTime.Minute, 0);
DateTime endShift = new DateTime(day.CreationDate.Year, day.CreationDate.Month, day.CreationDate.Day, shift.EndTime.Hour, shift.EndTime.Minute, 0);
if (shift.StartTime > shift.EndTime)
endShift = endShift.AddDays(1);
//اگر در بازه شیف تعیین شده حضور غیاب داشت
var hasRollCall = day.ShiftList.Where(x =>
(x.Start <= startShift && x.End > startShift) ||
(x.Start >= startShift && x.End <= endShift) ||
(x.Start > startShift && x.End > endShift)).ToList();
if (!hasRollCall.Any())// اگر در بازه شیفت هیچ حضور غیابی نداشت
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = startShift,
EndSpan = endShift,
Spanning = (endShift - startShift),
TypeOfSapn = shift.Placement == ShiftPlacement.First ? "LateToWork" : "EarlyExist"
});
}
else if (hasRollCall.Count() == 1)
{
var singleHasRollCall = hasRollCall.FirstOrDefault();
if (singleHasRollCall != null && singleHasRollCall.Start > startShift &&
singleHasRollCall.End >= endShift)
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = startShift,
EndSpan = singleHasRollCall.Start,
Spanning = (singleHasRollCall.Start - startShift),
TypeOfSapn = "LateToWork"
});
}
else if (singleHasRollCall != null && singleHasRollCall.Start <= startShift &&
singleHasRollCall.End < endShift)
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = singleHasRollCall.End,
EndSpan = endShift,
Spanning = (endShift - singleHasRollCall.End),
TypeOfSapn = "EarlyExist"
});
}
else if (singleHasRollCall != null && singleHasRollCall.Start > startShift &&
singleHasRollCall.End < endShift)
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = startShift,
EndSpan = singleHasRollCall.Start,
Spanning = (singleHasRollCall.Start - startShift),
TypeOfSapn = "LateToWork"
});
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = singleHasRollCall.End,
EndSpan = endShift,
Spanning = (endShift - singleHasRollCall.End),
TypeOfSapn = "EarlyExist"
});
}
}
else if (hasRollCall.Count() > 1)
{
var multiHasRollCall = hasRollCall.OrderBy(x => x.Start);
var firstRollcall = multiHasRollCall.First();
var lastRollCall = multiHasRollCall.Last();
if (firstRollcall.Start > startShift &&
firstRollcall.End >= endShift)
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = startShift,
EndSpan = firstRollcall.Start,
Spanning = (firstRollcall.Start - startShift),
TypeOfSapn = "LateToWork"
});
}
if (lastRollCall.Start <= startShift &&
lastRollCall.End < endShift)
{
lateToWorkEarlyExistSpannig.Add(new LateToWorkEarlyExistSpannig()
{
StartSpan = lastRollCall.End,
EndSpan = endShift,
Spanning = (endShift - lastRollCall.End),
TypeOfSapn = "EarlyExist"
});
}
}
}
}
leavList = leavList.Where(x => x.PaidLeaveType == "ساعتی").ToList();
// اگر تاخیر یا تعجیل به دلیل مرخصی ساعتی بود حساب نشود
if (leavList.Count > 0 && lateToWorkEarlyExistSpannig.Count > 0)
{
foreach (var el in lateToWorkEarlyExistSpannig.ToList())
{
var hasLeve = leavList.Any(x =>
(x.StartLeaveGr <= el.StartSpan && x.EndLeaveGr > el.StartSpan) ||
(x.StartLeaveGr >= el.StartSpan && x.EndLeaveGr <= el.EndSpan) ||
(x.StartLeaveGr > el.StartSpan && x.EndLeaveGr > el.EndSpan));
if (hasLeve)
lateToWorkEarlyExistSpannig.Remove(el);
}
}
return lateToWorkEarlyExistSpannig;
}
#region Pooya
public double CalculateFamilyAllowancePayAmount(long employeeId, double basePay, DateTime contractEnd)
{
int underageChildrenCount = _context.EmployeeChildrenSet.Where(x => x.EmployeeId == employeeId &&
x.DateOfBirth.AddYears(18) > contractEnd).Count();
return basePay * underageChildrenCount;
}
//Deprecated
private TimeSpan CalculateOvertimeTimeSpanWithThreshold(List<RollCallViewModel> rollCalls,
ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings, int overtimeThresholdMinutes)
{
var mandatoryTotalTimeSpan = new TimeSpan(shiftSettings.Sum(x => (x.EndTime - x.StartTime).Ticks));
mandatoryTotalTimeSpan += new TimeSpan(0, overtimeThresholdMinutes, 0);
var rollCallsTimeSpans = rollCalls.Select(x => x.EndDate.Value - x.StartDate.Value).Where(x => x > mandatoryTotalTimeSpan).ToList();
var rollCallTotalTimeSpan = new TimeSpan(rollCallsTimeSpans.Sum(x => x.Ticks));
if (rollCallTotalTimeSpan < mandatoryTotalTimeSpan)
return TimeSpan.Zero;
return rollCallTotalTimeSpan - mandatoryTotalTimeSpan;
}
#region سنوات
/// <summary>
/// فرمول اصلی محاسبه سنوات برای پرسنل در بازه زمانی با تنظیمات پیشرفته
/// </summary>
/// <param name="monthlySalary">حقوق ماهیانه پرسنل</param>
/// <param name="baseYearsSettings">تنظیمات سنوات</param>
/// <param name="payOnLeave">تنظیم مربوط به پرداخت هنگام ترک کار</param>
public double CalculateYearsPayAmount(long employeeId, long workshopId, double monthlySalary, DateTime contractStart, DateTime contractEnd,
BaseYearsPay baseYearsSettings, BaseYearsPayInEndOfYear payOnLeave, MaxMonthDays maxMonthDays)
{
double baseYearPayAmount = 0;
var leftWorks = _context.LeftWorkList
.Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId &&
x.LeftWorkDate.Date.AddDays(-1) >= contractStart && x.StartWorkDate.Date <= contractEnd).ToList();
if (!leftWorks.Any())
return 0;
int daysWorked = (int)new TimeSpan(leftWorks.Select(x => new
{
Start = x.StartWorkDate < contractStart ? contractStart : x.StartWorkDate
,
End = x.LeftWorkDate.AddDays(-1) > contractEnd ? contractEnd : x.LeftWorkDate.AddDays(-1)
}).Sum(x => (x.End - x.Start).Ticks)).TotalDays + 1;
bool hasLeftWork = leftWorks.MaxBy(x => x.LeftWorkDate).LeftWorkDate.AddDays(-1) < contractEnd;
//محاسبه سنوات سالیانه
switch (baseYearsSettings.BaseYearsPayType)
{
case BaseYearsPayType.PercentageOfSalary:
{
baseYearPayAmount = monthlySalary * baseYearsSettings.Value / 100;
break;
}
case BaseYearsPayType.Money:
{
baseYearPayAmount = baseYearsSettings.Value;
break;
}
case BaseYearsPayType.None:
{
return 0;
}
}
//در صورت ترک کار
if (hasLeftWork)
{
switch (payOnLeave)
{
//اگر سنوات در آخر سال تعلق می گیرد ترک کار قبل از پایان دوره موجب صفر شدن آن میشود
case BaseYearsPayInEndOfYear.EndOfYear:
return 0;
//اگر هنگام ترک کار سنوات تعلق می گیرد
case BaseYearsPayInEndOfYear.WhenEverEmployeeLeftWork:
{
//بر اساس نوع پرداخت سالیانه یا ماهیانه سنوات محاسبه می گردد
switch (baseYearsSettings.PaymentType)
{
case BaseYearsPaymentType.MonthlyPay:
{
return CalculateYearsPayMonthlyByDays(baseYearPayAmount, daysWorked, contractStart.CountPersianMonthDays(), maxMonthDays);
}
case BaseYearsPaymentType.YearlyPay:
{
return CalculateYearsPayYearlyByDays(baseYearPayAmount, daysWorked);
}
default:
return 0;
}
}
}
}
//در صورت عدم ترک کار
switch (baseYearsSettings.PaymentType)
{
case BaseYearsPaymentType.MonthlyPay:
{
return CalculateYearsPayMonthlyByDays(baseYearPayAmount, daysWorked, contractStart.CountPersianMonthDays(), maxMonthDays);
}
case BaseYearsPaymentType.YearlyPay:
{
string contractEndFa = contractEnd.ToFarsi();
bool isCheckoutForEsfand = contractEndFa.Substring(5, 2) == "12";
bool isContractEndOfMonth = contractEndFa.FindeEndOfMonth() == contractEndFa;
//اگر آخر ماه نبود یا اسفند نبود سنوات سالیانه محاسبه نمی گردد
if (isContractEndOfMonth == false || isCheckoutForEsfand == false)
return 0;
return CalculateYearsPayYearlyByDays(baseYearPayAmount, daysWorked);
}
default:
return 0;
}
}
/// <summary>
/// محاسبه سنوات ماهیانه بر اساس روز های کارکرد
/// </summary>
/// <param name="baseYears">سنوات در کل سال</param>
/// <param name="daysWorked">روز های کارکرد</param>
/// <param name="totalDaysInMonth">تعداد روز های ماه</param>
public static double CalculateYearsPayMonthlyByDays(double baseYears, int daysWorked, int totalDaysInMonth, MaxMonthDays maxMonthDays)
{
daysWorked = maxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth && daysWorked > 30 ? 30 : daysWorked;
totalDaysInMonth = maxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth ? 30 : totalDaysInMonth;
return baseYears / 12 / totalDaysInMonth * daysWorked;
}
/// <summary>
/// محاسبه سنوات سالیانه بر اساس روز های کارکرد
/// </summary>
/// <param name="baseYears">سنوات در کل سال</param>
/// <param name="daysWorked">روز های کارکرد</param>
/// <param name="totalDaysInMonth"></param>
/// <param name="maxMonthDays"></param>
public static double CalculateYearsPayYearlyByDays(double baseYears, int daysWorked)
{
return baseYears / 365 * daysWorked;
}
#endregion
//TODO: this must be updated with Mahan's method for leaves
/// <summary>
/// محاسبه مدت اضافه کاری
/// </summary>
public static TimeSpan CalculateOvertimeTimeSpan(List<RollCallViewModel> rollCalls,
ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings, TimeOnly employeeOffSet)
{
//for (DateTime offset = start; offset <= end; offset.AddDays(1))
//{
// DayOfWeek dayOfWeek = offset.DayOfWeek;
// switch (dayOfWeek)
// {
// case DayOfWeek.Thursday:
// shifts.Add(new ShiftViewModel { Start = offset.AddHours(9), End = offset.AddHours(14) });
// break;
// case DayOfWeek.Friday:
// break;
// default:
// shifts.Add(new ShiftViewModel { Start = offset.AddHours(8), End = offset.AddHours(16) });
// break;
// }
//}
//if (!rollCalls.Any())
// return TimeSpan.Zero;
//var startRollCall = rollCalls.MinBy(x => x.StartDate!.Value).StartDate!.Value;
//var endRollCall = rollCalls.Max(x => x.EndDate)!.Value;
//DateTime startDateTime = new DateTime(DateOnly.FromDateTime(startRollCall), employeeOffSet);
//DateTime endDateTime = new DateTime(DateOnly.FromDateTime(endRollCall), employeeOffSet);
//endDateTime = endDateTime == startDateTime ? endDateTime.AddDays(1) : endDateTime;
var mandatoryPerDayTimeSpan = new TimeSpan(shiftSettings.Sum(x => (x.EndTime - x.StartTime).Ticks));
//bool isFirst = true;
//var sumOfOverTime = TimeSpan.Zero;
//for (var startDateOffset = startDateTime; startDateOffset <= endDateTime; startDateOffset = startDateOffset.AddDays(1))
//{
// IEnumerable<RollCallViewModel> rollCallViewModels;
// var startPeriod = startDateOffset;
// var endPeriod = startDateOffset.AddDays(1);
// if (isFirst)
// {
// rollCallViewModels = rollCalls
// .Where(x => x.StartDate.Value > startPeriod.Date && x.EndDate.Value <= endPeriod);
// isFirst = false;
// }
// else
// {
// rollCallViewModels = rollCalls
// .Where(x => x.StartDate.Value > startPeriod && x.EndDate.Value <= endPeriod);
// }
// var sum = rollCallViewModels.Sum(x => (x.EndDate.Value - x.StartDate.Value).Ticks);
// var rollCallTimeSpan = new TimeSpan(sum);
// if (rollCallTimeSpan > mandatoryPerDayTimeSpan)
// {
// var overTime = rollCallTimeSpan - mandatoryPerDayTimeSpan;
// sumOfOverTime = sumOfOverTime.Add(overTime);
// }
//}
//return sumOfOverTime;
var groupedRollCalls = rollCalls.GroupBy(x => x.StartDate!.Value.Date);
var rollCallsTimeSpans = groupedRollCalls.Where(x =>
x.Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks) > mandatoryPerDayTimeSpan.Ticks)
.Select(x => x.Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks)).ToList();
var daysCount = rollCallsTimeSpans.Count();
var totalMandatoryTotalTimeSpan = mandatoryPerDayTimeSpan * daysCount;
var rollCallTotalTimeSpan = new TimeSpan(rollCallsTimeSpans.Sum(x => x));
if (rollCallTotalTimeSpan < totalMandatoryTotalTimeSpan)
return TimeSpan.Zero;
return rollCallTotalTimeSpan - totalMandatoryTotalTimeSpan;
}
public static TimeSpan CalculateOvertimeSpanWithSumSpan(TimeSpan sumSpan, int mandatoryDays,
ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings)
{
var mandatoryPerDayTimeSpan = new TimeSpan(shiftSettings.Sum(x => (x.EndTime - x.StartTime).Ticks));
var mandatoryWorkingTimeSpan = mandatoryPerDayTimeSpan * mandatoryDays;
if (mandatoryWorkingTimeSpan > sumSpan)
return TimeSpan.Zero;
return sumSpan - mandatoryWorkingTimeSpan;
}
/// <summary>
/// محاسبه مبلغ اضافه کاری با استفاده از تنظیمات
/// </summary>
/// <param name="overtimeTimeSpan">مدت اضافه کاری</param>
/// <param name="overTimePaySettings">تنظیمات اضافه کاری</param>
/// <param name="dailyWage">مزد روزانه</param>
/// <returns></returns>
public static double CalculateOvertimePay(TimeSpan overtimeTimeSpan, OverTimePay overTimePaySettings, double dailyWage)
{
double baseAmount = overTimePaySettings.Value;
double result = 0;
switch (overTimePaySettings.OverTimePayType)
{
case OverTimePayType.None:
break;
case OverTimePayType.MoneyPerHour:
{
int totalMinutes = (int)overtimeTimeSpan.TotalMinutes;
result = totalMinutes * (baseAmount / 60);
break;
}
case OverTimePayType.PercentagePerHourOfSalary:
{
int totalMinutes = (int)overtimeTimeSpan.TotalMinutes;
double multiplier = overTimePaySettings.Value / 100;
result = ((dailyWage * multiplier) / 60) * totalMinutes;
break;
}
}
return result;
}
/// <summary>
/// محاسبه مدت جمعه کاری بدون در نظر گرفتن اضافه کاری
/// </summary>
public static TimeSpan CalculateFridayWorkingTimeSpanWithoutOvertime(List<RollCallViewModel> rollCallsList, ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings)
{
var _rollCallsList = rollCallsList;
_rollCallsList = _rollCallsList.Where(x => x.StartDate.Value.DayOfWeek == DayOfWeek.Friday ||
x.EndDate.Value.DayOfWeek == DayOfWeek.Friday ||
(x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday && x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday)).ToList();
var preprocessedRollCalls = _rollCallsList.Select(x =>
new RollCallViewModel
{
StartDate = x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday ? x.StartDate.Value.AddDays(1).Date : x.StartDate.Value
,
EndDate = x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday ? x.EndDate.Value.Date : x.EndDate.Value
}).ToList();
//var timeSpan = new TimeSpan(preprocessedRollCalls.Sum(x => (x.EndDate.Value - x.StartDate.Value).Ticks));
var extraWorkingTimeSpan = CalculateOvertimeTimeSpan(preprocessedRollCalls, shiftSettings, new TimeOnly());
var rollCallTimeSpan = CalculateFridayWorkingTimeSpan(preprocessedRollCalls);
if (rollCallTimeSpan <= extraWorkingTimeSpan)
return TimeSpan.Zero;
return rollCallTimeSpan - extraWorkingTimeSpan;
}
/// <summary>
/// محاسبه مدت جمعه کاری
/// </summary>
public static TimeSpan CalculateFridayWorkingTimeSpan(List<RollCallViewModel> rollCallsList)
{
var _rollCallsList = rollCallsList;
_rollCallsList = _rollCallsList.Where(x => x.StartDate.Value.DayOfWeek == DayOfWeek.Friday ||
x.EndDate.Value.DayOfWeek == DayOfWeek.Friday ||
(x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday && x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday)).ToList();
var preprocessedRollCalls = _rollCallsList.Select(x =>
new
{
Start = x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday ? x.StartDate.Value.AddDays(1).Date : x.StartDate.Value
,
End = x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday ? x.EndDate.Value.Date : x.EndDate.Value
}).ToList();
var timeSpan = new TimeSpan(preprocessedRollCalls.Sum(x => (x.End - x.Start).Ticks));
return timeSpan;
}
/// <summary>
/// محاسبه روز های جمعه کاری
/// </summary>
public static int CalculateFridayWorkingTotalDays(List<RollCallViewModel> rollCallsList)
{
var _rollCallsList = rollCallsList;
_rollCallsList = _rollCallsList.Where(x => x.StartDate.Value.DayOfWeek == DayOfWeek.Friday ||
x.EndDate.Value.DayOfWeek == DayOfWeek.Friday ||
(x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday && x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday)).ToList();
var preprocessedRollCalls = _rollCallsList.Select(x =>
new
{
Start = x.StartDate.Value.DayOfWeek == DayOfWeek.Thursday ? x.StartDate.Value.AddDays(1).Date : x.StartDate.Value
,
End = x.EndDate.Value.DayOfWeek == DayOfWeek.Saturday ? x.StartDate.Value.Date : x.EndDate.Value,
ShiftDate = x.ShiftDate
}).ToList();
int fridaysCount = preprocessedRollCalls.GroupBy(x => x.ShiftDate).Count();
return fridaysCount;
}
#endregion
#endregion
public static (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall,
ICollection<CustomizeRotatingShift> rotatingShifts)
{
DateTime startDate = startRollCall.Date;
DateTime endDate = endRollCall.Date;
DateTime startEntryWithDate = startDate.Add(startRollCall.TimeOfDay);
DateTime endEntryWithDate = endDate.Add(endRollCall.TimeOfDay);
DateTime twoHourBeforeStart = startEntryWithDate.AddHours(-2);
DateTime twoHourAfterStart = startEntryWithDate.AddHours(2);
DateTime twoHourBeforeEnd = endEntryWithDate.AddHours(-2);
DateTime twoHourAfterEnd = endEntryWithDate.AddHours(2);
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 =>
// (twoHourBeforeStart <= shift.Start && twoHourAfterStart >= shift.Start) ||
// (twoHourBeforeStart <= shift.End && twoHourAfterStart >= 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 =>
// (twoHourBeforeEnd <= shift.Start && twoHourAfterEnd >= shift.Start) ||
// (twoHourBeforeEnd <= shift.End && twoHourAfterEnd >= shift.End)).ToList();
//if (endFilteredTimes.Count == 0)
//{
// endFilteredTimes = startFilteredTimes;
//}
//else if (endFilteredTimes.Count == 1)
//{
// var endChosenShift = endFilteredTimes.First();
// return endChosenShift;
//}
#endregion
#region اشتراک حضور غیاب و شیفت
var overlapShifts = shiftDateTimes
.Select(shift => new
{
Shift = shift,
Overlap = new TimeSpan(Math.Max(0,
Math.Min(shift.End.Ticks, endRollCall.Ticks) -
Math.Max(shift.Start.Ticks, startRollCall.Ticks))),
// زمان حضور فرد در شیفت (مجموع Overlap با شیفت)
TotalTimeInShift = new TimeSpan(Math.Max(0,
Math.Min(shift.End.Ticks, endRollCall.Ticks) -
Math.Max(shift.Start.Ticks, startRollCall.Ticks))),
StartDistance = Math.Abs((shift.Start - startRollCall).Ticks),
EndDistance = Math.Abs((shift.End - endRollCall).Ticks),
TotalDistance = Math.Abs((shift.Start - startRollCall).Ticks) + Math.Abs((shift.End - endRollCall).Ticks)
})
.OrderByDescending(s => s.TotalTimeInShift) // 1. بیشترین زمان حضور فرد
.ThenByDescending(s => s.Overlap) // 2. بیشترین Overlap
.ThenBy(s => s.TotalDistance)
.ThenBy(s => s.StartDistance)
.ThenBy(x => x.EndDistance); // 3. اگر برابر بود، Start نزدیک‌تر
var overlapChosenShift = overlapShifts.First();
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
}
enum AbsentOrLeave
{
LeavePay,
AbsentDeduction
}
internal class EmployeeShiftResult
{
public ShiftPlacement Placement { get; set; }
public TimeSpan ShiftSpan { get; set; }
}
internal class StaticShiftStartEnd
{
public DateTime StartShift { get; set; }
public DateTime EndShift { get; set; }
public TimeSpan ShiftSpanning { get; set; }
public bool HasValue { get; set; }
public string ShiftType { get; set; }
}