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

1705 lines
68 KiB
C#

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 _0_Framework.Domain.CustomizeCheckoutValueObjects;
using CompanyManagment.App.Contracts.Fine;
using System.Globalization;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Company.Domain.EmployeeAgg;
//
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;
public RollCallMandatoryRepository(CompanyContext context, IYearlySalaryRepository yearlySalaryRepository,
ILeftWorkRepository leftWorkRepository, ILeaveRepository leaveRepository) : base(context)
{
_context = context;
_yearlySalaryRepository = yearlySalaryRepository;
_leftWorkRepository = leftWorkRepository;
_leaveRepository = leaveRepository;
}
public ComputingViewModel MandatoryCompute(long employeeId, long workshopId, DateTime contractStart,
DateTime contractEnd,
CreateWorkingHoursTemp command, long leavId)
{
#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
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,
}).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)),
}).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(rollCallSubtractSpan.Sum(x => x.AfterSubtractRestSpan.Ticks));
//****افزودن مرخصی پرسنل به مجموع ساعات کار***
#region AddEmployeeLeavs
LeaveSearchModel leaveSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
PaidLeaveType = "روزانه",
StartLeaveGr = contractStart,
EndLeaveGr = contractEnd,
IsAccepted = true,
};
var leaveSearchResult = _leaveRepository.search(leaveSearch);
if (leaveSearchResult.Count > 0)
{
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 / rollCallSubtractSpan.Count;//میانگین ساعت کار در روز
TimeSpan sumLeave = new TimeSpan();
if (workingPerDayAve <= new TimeSpan(7, 20, 0))
{
sumLeave = leavingDayCout * workingPerDayAve;
}
else
{
sumLeave = leavingDayCout * new TimeSpan(7, 20, 0);
}
sumSpans = sumSpans.Add(sumLeave);
}
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
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);
//***********************************//
//This Time Mandatory Hourse
double mandatoryHours = Math.Round((mandatorDays * 7.33), 2);
//***********************************//
var dailyFix = TimeSpan.Parse("07:20");
TimeSpan mandatoryHoursTimeSpan = new TimeSpan(7, 20, 0).Multiply(mandatorDays);
TimeSpan Mandatory = sumSpans.Subtract(mandatoryHoursTimeSpan);
#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, 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 (command.ShiftWork == "1" || command.ShiftWork == "2" || command.ShiftWork == "4")
{
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 (totalHourses > mandatoryHours)
{
Console.WriteLine(Mandatory);
Console.WriteLine(Mandatory.Minutes);
int mandatoryH = (int)Mandatory.TotalHours;
int mandatoryM = (int)(Mandatory.TotalMinutes % 60);
overMandatoryHours = mandatoryH.ToString();
overMandatoryMinuts = mandatoryM.ToString();
}
}
#endregion
//****** نوبت کاری و شب کاری ****
#region RotatingShiftCheckAndNightWorkOver22
List<RotatingShiftViewModel> rotatingResultList = RotatingShiftCheck(groupedRollCall);
var moriningCount = rotatingResultList.Count(x => x.IsMorningShift);
var eveningCount = rotatingResultList.Count(x => x.IsEveningShift);
var nightCount = rotatingResultList.Count(x => x.IsNightShift);
// شبکاری
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("شب");
}
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;
}
else if (rotatingFaResult == "صبح و عصر و شب")
{
var shiftPyaPercent = DailyFeeNumberType * 15 / 100;
ShiftPayResult = shiftPyaPercent * TotalDays;
}
else if (rotatingFaResult == "صبح و شب" || rotatingFaResult == "عصر و شب")
{
var shiftPyaPercent = DailyFeeNumberType * 22.5 / 100;
ShiftPayResult = shiftPyaPercent * TotalDays;
}
}
#endregion
#region Result
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,
};
#endregion
return res;
}
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 midNight24 = new DateTime(item.CreationDate.Year, item.CreationDate.Month, item.CreationDate.Day, 0, 0, 0).AddDays(1);
var morningWorkingTime = new TimeSpan();
var eveningWorkingTime = new TimeSpan();
var nightWorkingTime = new TimeSpan();
DateTime morningStart = new DateTime(item.CreationDate.Year, item.CreationDate.Month, item.CreationDate.Day, 6, 0, 0);
DateTime morningEnd = new DateTime(item.CreationDate.Year, item.CreationDate.Month, item.CreationDate.Day, 14, 0, 0);
DateTime eveningStart = morningEnd;
DateTime eveningEnd = new DateTime(item.CreationDate.Year, item.CreationDate.Month, item.CreationDate.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
foreach (var shift in item.ShiftList)
{
#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 = morningWorkingTime.Add(eveningEnd - eveningStart);
}
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.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)
{
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)
{
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)
{
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)
{
result.IsMorningShift = false;
result.IsEveningShift = false;
result.IsNightShift = true;
result.RotatingShiftStatus = "شب";
}
}
finalResult.Add(result);
#endregion
}
return finalResult;
}
/// <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)
{
#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));
TimeSpan contractDuration = contractEnd - contractStart;
var employee = _context.Employees.FirstOrDefault(x => x.id == employeeId);
#endregion
#region LeftWork
var leftWork = _leftWorkRepository.GetByDateAndWorkshopIdAndEmployeeId(workshopId, employeeId, contractEnd);
TimeSpan leftWorkDurationTimeSpan = leftWork.HasLeft ? leftWork.LeftWorkDateGr - leftWork.StartWorkDateGr : contractEnd - leftWork.StartWorkDateGr;
#endregion
#region CustomizeSettings
CustomizeWorkshopEmployeeSettings customizeWorkshopEmployeeSettings = _context.CustomizeWorkshopEmployeeSettings.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
: contractStart.CountMonthDays();
dailyWage = monthySalary / monthDays;
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
{
Placement = x.Placement,
ShiftSpan = span
};
});
var sumOfEmployeeShiftSpan = new TimeSpan(employeeShiftsSpans.Sum(x => x.ShiftSpan.Ticks));
#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,
}).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)),
}).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 absentsDays = contractDays - numberOfWorkingDay;
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.WorkInFriday)
{
absentsDays -= fridays;
}
if (customizeWorkshopEmployeeSettings.HolidayWork != HolidayWork.WorkInHolidays)
{
absentsDays -= holiday;
}
// یافتن مرخصی ساعتی
#region LeavHourse
LeaveSearchModel leaveHourseSearch = new LeaveSearchModel()
{
EmployeeId = employeeId,
WorkshopId = workshopId,
LeaveType = "استحقاقی",
PaidLeaveType = "ساعتی",
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);
//}
if (customizeWorkshopEmployeeSettings.LeavePay.LeavePayType != LeavePayType.None)
{
// مقدار ساعت های غیبت
TimeSpan absentsTimeSpan = sumOfEmployeeShiftSpan * absentsDays;
//روزهای مجاز مرخصی
int permittedLeaveDay = customizeWorkshopSettings.LeavePermittedDays;
// زمان مجاز مرخصی
TimeSpan permittedLeaveTimeSpan = sumOfEmployeeShiftSpan * permittedLeaveDay;
// زمان مرخصی مجاز برای یک روز
TimeSpan leaveTimePerDay = (permittedLeaveTimeSpan / monthDays);
//اگر ترک کار کرده بود
if (contractDays < monthDays)
{
permittedLeaveTimeSpan = leaveTimePerDay * contractDays;
}
//اگر قراردادش کامل بود
else
{
}
//اختلاف غیبت و مرخصی
(TimeSpan Diffrence, AbsentOrLeave absentOrLeave) absentAndLeaveDifference;
//مقدار مبلغ مرخصی
double leavePayAmount = 0;
//مقدار مبلغ غیبت
double absentsDeduction = 0;
//اگر مقدار مرخصی بیشتر از غیبت یا مساوی باشد
if (permittedLeaveTimeSpan >= absentsTimeSpan)
{
//محاسبه مقدار باقی مانده مزد مرخصی
absentAndLeaveDifference.Diffrence = absentsTimeSpan - permittedLeaveTimeSpan;
absentAndLeaveDifference.absentOrLeave = AbsentOrLeave.LeavePay;
//صفر کردن مقدار غیبت
absentsTimeSpan = new TimeSpan(0);
absentsDays = 0;
//برگرداندن ساعت کاری باقی مونده از مزد مرخصی به ساعت کاری
sumSpans += absentAndLeaveDifference.Diffrence;
//مقدار مزد مرخصی برای هرروز استفاده نشده
double leavePayPerDayWage = (customizeWorkshopEmployeeSettings.LeavePay.Value * dailyWage);
leavePayAmount = (leavePayPerDayWage / permittedLeaveTimeSpan.TotalHours) * absentAndLeaveDifference.Diffrence.TotalHours;
}
//اگر مقدار غیبت بیشتر از مرخصی باشد
else
{
//محاسبه مقدار باقی مانده از غیبت
absentAndLeaveDifference.Diffrence = permittedLeaveTimeSpan - absentsTimeSpan;
absentAndLeaveDifference.absentOrLeave = AbsentOrLeave.AbsentDeduction;
//صفر کردن مقدار مزد مرخصی
permittedLeaveTimeSpan = new TimeSpan(0);
permittedLeaveDay = 0;
//برگرداندن ساعت کاری باقی مونده از مزد مرخصی به ساعت کاری
sumSpans += permittedLeaveTimeSpan;
absentsDeduction = absentsDays * dailyWage;
}
}
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
double insurancePayAmount = 0;
switch (customizeWorkshopEmployeeSettings.InsuranceDeduction.InsuranceDeductionType)
{
case InsuranceDeductionType.BasedOnLaborLaw:
double familyAllowance = _yearlySalaryRepository.FamilyAllowance(employeeId, 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 = customizeWorkshopEmployeeSettings.InsuranceDeduction.Value / 100;
insurancePayAmount = monthySalary * multiplier;
break;
case InsuranceDeductionType.Money:
double baseAmount = customizeWorkshopEmployeeSettings.InsuranceDeduction.Value;
insurancePayAmount = baseAmount;
break;
}
#endregion
#region SalaryAidDeduction
double salaryAidDeduction = _context.SalaryAids.Where(x => x.SalaryAidDateTime > contractStart && x.SalaryAidDateTime < contractEnd).Sum(x => x.Amount);
#endregion
#region Loan
double loanInstallments = _context.Loans
.Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId)
.SelectMany(x => x.LoanInstallments)
.Where(i => i.Month == monthOfCheckout.ToString("00") && i.Year == yearOfCheckout.ToString("0000")).Select(x => x.AmountForMonth).Sum(x => x);
double loanDeduction = loanInstallments;
#endregion
#region Fine
var fineViewModels = _context.Fines.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.FineDate > contractStart &&
x.FineDate < contractStart && x.IsActive == IsActive.True).Select(x => new EditFineViewModel()
{
IsActive = x.IsActive,
Amount = x.Amount.ToMoney(),
FineDate = x.FineDate.ToFarsi(),
Id = x.id,
Title = x.Title
}).ToList();
double fineDeduction = fineViewModels.Sum(x => x.Amount.MoneyToDouble());
#endregion
#endregion
#region Payments
//اضافه کاری
#region OvertimePay
double overtimePayAmount = 0;
overtimePayAmount = CalculateOvertimePay(sumSpans, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage);
#endregion
#region FridayPay
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 workedFridaysHours = (int)CalculateFridayWorkingTimeSpan(rollCallResult).TotalHours;
double baseAmount = customizeWorkshopEmployeeSettings.FridayPay.Value;
fridayPayAmount = baseAmount * workedFridaysHours;
break;
}
case (FridayPayType.PercentageFromSalaryPerHour):
{
int workedFridaysHours = (int)CalculateFridayWorkingTimeSpan(rollCallResult).TotalHours;
double percentageAmount = (customizeWorkshopEmployeeSettings.FridayPay.Value / 100 * dailyWage);
fridayPayAmount = percentageAmount * workedFridaysHours;
break;
}
case (FridayPayType.ExtraWorking):
{
var fridayOvertimeTimeSpan = CalculateFridayWorkingTimeSpanWithoutOvertime(rollCallResult, shiftSettings);
overtimePayAmount += CalculateOvertimePay(fridayOvertimeTimeSpan, customizeWorkshopEmployeeSettings.OverTimePay, dailyWage);
break;
}
default:
break;
}
#endregion
//حق تاهل
#region MaritalAllownace
double maritalAllowance = 0;
if (employee.MaritalStatus == "متاهل")
{
switch (customizeWorkshopEmployeeSettings.MarriedAllowance.MarriedAllowanceType)
{
case MarriedAllowanceType.Money:
{
maritalAllowance = customizeWorkshopEmployeeSettings.MarriedAllowance.Value;
break;
}
//case MarriedAllowanceType.PercentageFromSalary:
// {
// double multiplier = customizeWorkshopEmployeeSettings.MarriedAllowance.Value / 100;
// maritalAllowance = dailyWage * multiplier;
// break;
// }
}
}
#endregion
//شب کاری
#region NightWorkPay
double nightworkPayAmount = 0;
var nightWorks = RotatingShiftCheck(groupedRollCall).Where(x => x.IsNightShift);
if (nightWorks.Any())
{
switch (customizeWorkshopEmployeeSettings.NightWorkPay.NightWorkingType)
{
case NightWorkType.MoneyPerHour:
{
var baseAmount = customizeWorkshopEmployeeSettings.NightWorkPay.Value;
var nightWorkHours = (int)(new TimeSpan(nightWorks.Sum(x => x.NightWorkSpan.Ticks))).TotalHours;
nightworkPayAmount += nightWorkHours * baseAmount;
break;
}
case NightWorkType.PercentageFromSalary:
{
double multiplier = customizeWorkshopEmployeeSettings.NightWorkPay.Value / 100;
var nightWorkHours = (int)(new TimeSpan(nightWorks.Sum(x => x.NightWorkSpan.Ticks))).TotalHours;
nightworkPayAmount += dailyWage * multiplier * nightWorkHours;
break;
}
}
}
#endregion
//سنوات
#region BaseYearsPay
double baseYearsPayAmount = 0;
switch (customizeWorkshopEmployeeSettings.BaseYearsPay.BaseYearsPayType)
{
case BaseYearsPayType.PercentageOfSalary:
{
double multiplier = customizeWorkshopEmployeeSettings.BaseYearsPay.Value / 100;
baseYearsPayAmount = CalculateYearsPayAmount(multiplier * monthySalary, contractStart, contractEnd, customizeWorkshopSettings.MaxMonthDays);
break;
}
case BaseYearsPayType.Money:
{
double baseAmount = customizeWorkshopEmployeeSettings.BaseYearsPay.Value;
baseYearsPayAmount = CalculateYearsPayAmount(baseAmount, contractStart, contractEnd, customizeWorkshopSettings.MaxMonthDays);
break;
}
}
#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
double rewardPay = _context.Rewards.Where(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.CreationDate < contractEnd &&
x.CreationDate > contractStart).Sum(x => x.Amount);
#endregion
#region LeavePay
#endregion
#region BonusesPay
double bonusesPay = 0;
if (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType != BonusesType.None)
{
switch (customizeWorkshopEmployeeSettings.BonusesPay.BonusesPayType)
{
case BonusesType.OneTimeOfSalary:
bonusesPay = monthySalary;
break;
case BonusesType.TwoTimeOfSalary:
bonusesPay = monthySalary * 2;
break;
case BonusesType.Money:
bonusesPay = customizeWorkshopEmployeeSettings.BonusesPay.Value;
break;
case BonusesType.PercentageOfSalary:
bonusesPay = (monthySalary * customizeWorkshopEmployeeSettings.BonusesPay.Value) / 100;
break;
}
double bonusesPerMonth = bonusesPay / 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!
bonusesPay = (bonusesPay / 365) * bonusDuration.TotalDays;
}
else
{
bonusesPay = 0;
}
}
else if (customizeWorkshopEmployeeSettings.BonusesPay.PaymentType == BonusesPaymentType.MonthlyPay)
{
if (customizeWorkshopSettings.BonusesPaysInEndOfMonth ==
BonusesPaysInEndOfYear.WhenEverEmployeeLeftWork && leftWork.HasLeft && contractDays < monthDays)
bonusesPay = (bonusesPerMonth / contractEnd.CountPersianMonthDays()) * contractDuration.TotalDays + 1;
bonusesPay = bonusesPerMonth;
}
else
{
throw new InvalidDataException();
}
}
#endregion
#endregion
return new();
}
/// <summary>
/// محاسبه تاخیر در ورورد و تعجیل در خروج
/// </summary>
/// <param name="groupedRollCall"></param>
/// <param name="shiftSettings"></param>
/// <returns></returns>
public (double lateToWorkSapn, double earlyExit) 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"
});
}
}
}
}
// اگر تاخیر یا تعجیل به دلیل مرخصی ساعتی بود حساب نشود
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 (0, 0);
}
#region Pooya
private 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;
}
private double CalculateYearsPayAmount(double basePay, DateTime contractStart, DateTime contractEnd, MaxMonthDays maxMonthDays)
{
int days = (int)((contractEnd - contractStart).TotalDays);
int totalMonthDays = contractEnd.CountPersianMonthDays();
if (maxMonthDays == MaxMonthDays.ThirtyDaysForAllMonth)
{
if (days >= 30 || days == totalMonthDays)
return basePay;
else
return (basePay * days / 30);
}
else
{
return (basePay * days / totalMonthDays);
}
}
//TODO: this must be updated with Mahan's method for leaves
/// <summary>
/// محاسبه مدت اضافه کاری
/// </summary>
private TimeSpan CalculateOvertimeTimeSpan(List<RollCallViewModel> rollCalls, ICollection<CustomizeWorkshopEmployeeSettingsShift> shiftSettings)
{
//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;
// }
//}
var rollCallsTimeSpans = rollCalls.Select(x => x.EndDate.Value - x.StartDate.Value).ToList();
var mandatoryTotalTimeSpan = new TimeSpan(shiftSettings.Sum(x => (x.EndTime - x.StartTime).Ticks));
var rollCallTotalTimeSpan = new TimeSpan(rollCallsTimeSpans.Sum(x => x.Ticks));
if (rollCallTotalTimeSpan < mandatoryTotalTimeSpan)
return TimeSpan.Zero;
return rollCallTotalTimeSpan - mandatoryTotalTimeSpan;
}
/// <summary>
/// محاسبه مبلغ اضافه کاری با استفاده از تنظیمات
/// </summary>
/// <param name="overtimeTimeSpan">مدت اضافه کاری</param>
/// <param name="overTimePaySettings">تنظیمات اضافه کاری</param>
/// <param name="dailyWage">مزد روزانه</param>
/// <returns></returns>
private 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 totalHours = (int)overtimeTimeSpan.TotalHours;
result = totalHours * baseAmount;
break;
}
case OverTimePayType.PercentagePerHourOfSalary:
{
int totalHours = (int)overtimeTimeSpan.TotalHours;
double multiplier = overTimePaySettings.Value / 100;
result = dailyWage * totalHours * multiplier;
break;
}
}
return result;
}
/// <summary>
/// محاسبه مدت جمعه کاری بدون در نظر گرفتن اضافه کاری
/// </summary>
private 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.StartDate.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);
var rollCallTimeSpan = CalculateFridayWorkingTimeSpan(preprocessedRollCalls);
return rollCallTimeSpan - extraWorkingTimeSpan;
}
/// <summary>
/// محاسبه مدت جمعه کاری
/// </summary>
private 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.StartDate.Value.Date : x.EndDate.Value
}).ToList();
var timeSpan = new TimeSpan(preprocessedRollCalls.Sum(x => (x.End - x.Start).Ticks));
return timeSpan;
}
/// <summary>
/// محاسبه روز های جمعه کاری
/// </summary>
private 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
}).ToList();
int fridaysCount = preprocessedRollCalls.GroupBy(x => x.Start.Date).Count();
return fridaysCount;
}
#endregion
}
public class LateToWorkEarlyExistSpannig()
{
public DateTime StartSpan { get; set; }
public DateTime EndSpan { get; set; }
public TimeSpan Spanning { get; set; }
public string TypeOfSapn { get; set; }
}
enum AbsentOrLeave
{
LeavePay,
AbsentDeduction
}