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