1705 lines
68 KiB
C#
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
|
|
} |