Files
Backend-Api/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs
2024-12-22 18:42:51 +03:30

2053 lines
72 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 _0_Framework.Domain.CustomizeCheckoutShared.Base;
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
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;
}
#region OfficialChckout
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
//گرفتن ساعت استراحت پرسنل از تنظیمات
#region breakTime
BaseCustomizeEntity settings = _context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().FirstOrDefault(x =>
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
//اگر ساعت استراحت پرسنل وجود نداشت صفر است
var breakTime = settings == null ? new BreakTime(false, new TimeOnly()) : settings.BreakTime;
#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)) - CalculateBreakTime(breakTime,
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(groupedRollCall.Sum(x => x.SumOneDaySpan.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 / groupedRollCall.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;
}
private TimeSpan CalculateBreakTime(BreakTime breakTime, TimeSpan sumOneDaySpan)
{
if (breakTime.BreakTimeType != BreakTimeType.WithTime)
return TimeSpan.Zero;
var breakTimeSpan = breakTime.BreakTimeValue.ToTimeSpan();
if (breakTimeSpan * 2 >= sumOneDaySpan)
return TimeSpan.Zero;
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 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;
}
#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 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));
TimeSpan contractDuration = contractEnd - contractStart;
var employee = _context.Employees.FirstOrDefault(x => x.id == employeeId);
#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();
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 = "استحقاقی",
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 = customizeWorkshopSettings.LeavePermittedDays;
double leaveValue = customizeWorkshopEmployeeSettings.LeavePay.Value;
sumSpans = CalculateLeavePay(sumOfEmployeeShiftSpan, absentsDays, permittedDays, monthDays, contractDays, sumSpans
, leaveValue, dailyWage, leaveList, contractStart, contractEnd, out leavePayAmount, out absentsDeductionAmount);
}
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;
double insuranceDeductionAmount = InsurancePayCalculation(employeeId, contractEnd, insuranceDeduction, monthySalary);
#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);
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;
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 = 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
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 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 Test
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 * dailyWagePerMinute,
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 * dailyWagePerMinute,
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,
};
}
#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 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);
return overtimePayAmount;
break;
}
default:
break;
}
return fridayPayAmount;
}
public double InsurancePayCalculation(long employeeId, DateTime contractEnd,
InsuranceDeduction insuranceDeduction, double monthySalary)
{
double insurancePayAmount = 0;
switch (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 = 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, int absentsDays,
int permittedLeaveDay, int monthDays, int contractDays, TimeSpan sumSpans,
double leaveValue, double dailyWage, List<LeaveViewModel> leaveList, DateTime startDate, DateTime endDate, out double leavePayAmount, out double absentsDeduction)
{
#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
// مقدار ساعت های غیبت
TimeSpan absentsTimeSpan = sumOfEmployeeShiftSpan * absentsDays;
// زمان مجاز مرخصی
TimeSpan permittedLeaveTimeSpan = sumOfEmployeeShiftSpan * permittedLeaveDay;
// زمان مرخصی مجاز برای یک روز
TimeSpan leaveTimePerDay = (permittedLeaveTimeSpan / monthDays);
//اگر ترک کار کرده بود
if (contractDays < monthDays)
{
permittedLeaveTimeSpan = leaveTimePerDay * contractDays;
}
//اگر قراردادش کامل بود
else
{
}
//اختلاف غیبت و مرخصی
(TimeSpan Diffrence, AbsentOrLeave absentOrLeave) absentAndLeaveDifference;
//مقدار مبلغ مرخصی
leavePayAmount = 0;
//مقدار مبلغ غیبت
absentsDeduction = 0;
if (permittedLeaveTimeSpan >= usedLeavesCheckout)
permittedLeaveTimeSpan = permittedLeaveTimeSpan - usedLeavesCheckout;
else
{
absentsTimeSpan = usedLeavesCheckout - permittedLeaveTimeSpan;
permittedLeaveTimeSpan = new TimeSpan();
}
//اگر مقدار مرخصی بیشتر از غیبت یا مساوی باشد
if (permittedLeaveTimeSpan >= absentsTimeSpan)
{
//محاسبه مقدار باقی مانده مزد مرخصی
absentAndLeaveDifference.Diffrence = absentsTimeSpan - permittedLeaveTimeSpan;
absentAndLeaveDifference.absentOrLeave = AbsentOrLeave.LeavePay;
//صفر کردن مقدار غیبت
absentsTimeSpan = new TimeSpan(0);
absentsDays = 0;
//برگرداندن ساعت کاری باقی مونده از مزد مرخصی به ساعت کاری
sumSpans += absentAndLeaveDifference.Diffrence;
//مقدار مزد مرخصی برای هرروز استفاده نشده
double leavePayPerDayWage = (leaveValue * 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;
}
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;
}
#region سنوات
/// <summary>
/// فرمول اصلی محاسبه سنوات برای پرسنل در بازه زمانی با تنظیمات پیشرفته
/// </summary>
/// <param name="monthlySalary">حقوق ماهیانه پرسنل</param>
/// <param name="baseYearsSettings">تنظیمات سنوات</param>
/// <param name="payOnLeave">تنظیم مربوط به پرداخت هنگام ترک کار</param>
private 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);
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)
{
//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 groupedRollCalls = rollCalls.GroupBy(x => x.StartDate!.Value.Date);
var mandatoryPerDayTimeSpan = new TimeSpan(shiftSettings.Sum(x => (x.EndTime - x.StartTime).Ticks));
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;
}
/// <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 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>
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);
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
}).ToList();
int fridaysCount = preprocessedRollCalls.GroupBy(x => x.Start.Date).Count();
return fridaysCount;
}
#endregion
#endregion
#endregion
}
enum AbsentOrLeave
{
LeavePay,
AbsentDeduction
}