2396 lines
110 KiB
C#
2396 lines
110 KiB
C#
using _0_Framework.Application;
|
||
using _0_Framework.Domain.CustomizeCheckoutShared.Base;
|
||
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
||
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
|
||
using _0_Framework.InfraStructure;
|
||
using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg.Entities;
|
||
using Company.Domain.EmployeeAgg;
|
||
using Company.Domain.RollCallAgg;
|
||
using Company.Domain.RollCallEmployeeAgg;
|
||
using Company.Domain.WorkshopAgg;
|
||
using CompanyManagment.App.Contracts.HolidayItem;
|
||
using CompanyManagment.App.Contracts.RollCall;
|
||
using MD.PersianDateTime.Standard;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel.DataAnnotations.Schema;
|
||
using System.Globalization;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading.Tasks;
|
||
using _0_Framework.Exceptions;
|
||
using OfficeOpenXml.Packaging.Ionic.Zip;
|
||
|
||
|
||
namespace CompanyManagment.EFCore.Repository;
|
||
|
||
public class RollCallRepository : RepositoryBase<long, RollCall>, IRollCallRepository
|
||
{
|
||
private readonly CompanyContext _context;
|
||
private readonly IHolidayItemApplication _holidayItemApplication;
|
||
private readonly IWorkshopRepository _workshopRepository;
|
||
private readonly IRollCallMandatoryRepository _rollCallMandatoryRepository;
|
||
|
||
public RollCallRepository(CompanyContext context, IHolidayItemApplication holidayItemApplication,
|
||
IAuthHelper authHelper, IWorkshopRepository workshopRepository,
|
||
IRollCallMandatoryRepository rollCallMandatoryRepository) : base(context)
|
||
{
|
||
_context = context;
|
||
_holidayItemApplication = holidayItemApplication;
|
||
_workshopRepository = workshopRepository;
|
||
_rollCallMandatoryRepository = rollCallMandatoryRepository;
|
||
}
|
||
|
||
|
||
#region Pooya
|
||
|
||
//حضور غیاب گروهی از پرسنل برای پرینت گروهی فیش حقوقی غیر رسمی موقت
|
||
public List<PersonnelCheckoutDailyRollCallViewModel> GetEmployeeRollCallsInDates(IEnumerable<long> employeeIds,
|
||
long workshopId, DateTime start, DateTime end)
|
||
{
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
employeeIds.Contains(x.EmployeeId) && workshopId == x.WorkshopId && x.StartDate != null &&
|
||
x.EndDate != null &&
|
||
x.ShiftDate.Date >= start && x.ShiftDate.Date <= end).ToList();
|
||
|
||
int dateRange = (int)(end - start).TotalDays + 1;
|
||
|
||
var completeDaysList = Enumerable.Range(0, dateRange).Select(offset => start.AddDays(offset).Date);
|
||
|
||
List<PersonnelCheckoutDailyRollCallViewModel> result = new();
|
||
foreach (var employeeId in employeeIds)
|
||
{
|
||
var absentRecords = completeDaysList.Where(x =>
|
||
!rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date))
|
||
.Select(x => new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = null,
|
||
EndDate1 = null,
|
||
DateTimeGr = x.Date.Date,
|
||
DayOfWeek = x.Date.DayOfWeek.ToString(),
|
||
RollCallDateFa = x.Date.ToFarsi()
|
||
});
|
||
var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date)
|
||
.Select(x =>
|
||
{
|
||
var orderedRollcalls = x.OrderBy(y => y.ShiftDate);
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = orderedRollcalls.FirstOrDefault().StartDate.Value.ToString("HH:mm"),
|
||
EndDate1 = orderedRollcalls.FirstOrDefault().EndDate.Value.ToString("HH:mm"),
|
||
|
||
StartDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.StartDate?.ToString("HH:mm") ?? "",
|
||
EndDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.EndDate?.ToString("HH:mm") ?? "",
|
||
|
||
TotalhourseSpan =
|
||
new TimeSpan(x.Where(y => y.EndDate != null)
|
||
.Sum(y => (y.EndDate - y.StartDate)!.Value.Ticks)),
|
||
DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
RollCallDateFa = x.Key.Date.ToFarsi(),
|
||
DateTimeGr = x.Key.Date,
|
||
IsSliced = x.Count() > 2
|
||
};
|
||
});
|
||
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
|
||
{
|
||
StartDate1 = x.StartDate1,
|
||
EndDate1 = x.EndDate1,
|
||
EndDate2 = x.EndDate2,
|
||
StartDate2 = x.StartDate2,
|
||
TotalWorkingHours = $"{(int)(x.TotalhourseSpan.TotalHours)}:{x.TotalhourseSpan.Minutes.ToString("00")}",
|
||
DayOfWeek = x.DayOfWeek,
|
||
RollCallDateFa = x.RollCallDateFa,
|
||
DateTimeGr = x.DateTimeGr,
|
||
IsSliced = x.IsSliced
|
||
});
|
||
|
||
List<CheckoutDailyRollCallViewModel> checkoutDailyRollCalls =
|
||
presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
|
||
|
||
|
||
var resultItem = new PersonnelCheckoutDailyRollCallViewModel()
|
||
{
|
||
EmployeeId = employeeId,
|
||
WorkshopId = workshopId,
|
||
DailyRollCalls = checkoutDailyRollCalls
|
||
};
|
||
result.Add(resultItem);
|
||
}
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
//قطع شده توسط سیستم
|
||
public List<RollCallsByDateViewModel> GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start,
|
||
DateTime end)
|
||
{
|
||
var personnelCode = _context.PersonnelCodeSet.Where(x => x.WorkshopId == workshopId);
|
||
|
||
var rollCalls = _context.RollCalls
|
||
.Where(x => personnelCode.Any(y => y.EmployeeId == x.EmployeeId) &&
|
||
x.RollCallModifyType == RollCallModifyType.CutByBgService && x.WorkshopId == workshopId &&
|
||
x.ShiftDate.Date >= start.Date && x.ShiftDate.Date <= end.Date).ToList();
|
||
|
||
var names = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId)
|
||
.Select(x => new { x.EmployeeId, x.WorkshopId, x.EmployeeFullName }).ToList();
|
||
|
||
|
||
return rollCalls.GroupBy(x => x.ShiftDate.Date)
|
||
.Select(g => new RollCallsByDateViewModel()
|
||
{
|
||
DateGr = g.Key,
|
||
DateFa = g.Key.ToFarsi(),
|
||
ActiveEmployees = g.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeId = x.EmployeeId,
|
||
EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.EmployeeFullName ?? "",
|
||
WorkshopId = x.WorkshopId,
|
||
Id = x.id,
|
||
StartDate = x.StartDate,
|
||
EndDate = x.EndDate
|
||
})
|
||
})
|
||
.ToList();
|
||
}
|
||
|
||
//حضور غیاب در پرینت فیش حقوقی رسمی
|
||
public List<CheckoutDailyRollCallViewModel> GetEmployeeRollCallsForMonth(long employeeId, long workshopId,
|
||
DateTime startMonthDay, DateTime endMonthDay)
|
||
{
|
||
var firstDayOfMonth = $"{startMonthDay.ToFarsi().Substring(0, 8)}01".ToGeorgianDateTime();
|
||
var endFarvardin = "1404/01/31".ToGeorgianDateTime();
|
||
//گرفتن ساعت استراحت پرسنل از تنظیمات
|
||
|
||
#region breakTime
|
||
|
||
BaseCustomizeEntity settings = _context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().FirstOrDefault(x =>
|
||
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
|
||
//اگر ساعت استراحت پرسنل وجود نداشت صفر است
|
||
var breakTime = settings == null ? new BreakTime(false, new TimeOnly()) : settings.BreakTime;
|
||
|
||
#endregion
|
||
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate != null && x.EndDate != null &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined &&
|
||
x.ShiftDate.Date >= startMonthDay && x.ShiftDate.Date <= endMonthDay).ToList();
|
||
|
||
|
||
var leaves = _context.LeaveList.Where(x =>
|
||
x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.EndLeave.Date >= startMonthDay.Date &&
|
||
x.StartLeave.Date <= endMonthDay.Date).ToList();
|
||
|
||
var year = Convert.ToInt32(firstDayOfMonth.ToFarsi().Substring(0, 4));
|
||
var month = Convert.ToInt32(firstDayOfMonth.ToFarsi().Substring(5, 2));
|
||
var firstDayOfCurrentMonth = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
|
||
if (month == 12)
|
||
{
|
||
year += 1;
|
||
month = 1;
|
||
}
|
||
else
|
||
month += 1;
|
||
|
||
var nextMonthDate = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
var lastDayOfCurrentMonth = nextMonthDate.AddDays(-1);
|
||
|
||
int dateRange = (int)(lastDayOfCurrentMonth - firstDayOfCurrentMonth).TotalDays + 1;
|
||
|
||
var holidays = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = startMonthDay.ToFarsiYear()
|
||
});
|
||
//all the dates from start to end, to be compared with present days to get absent dates
|
||
var completeDaysList = Enumerable.Range(0, dateRange)
|
||
.Select(offset => firstDayOfCurrentMonth.AddDays(offset).Date).ToList();
|
||
|
||
var absentRecords = completeDaysList
|
||
.ExceptBy(rollCalls.Select(x => x.ShiftDate.Date), y => y.Date)
|
||
.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y =>
|
||
y.EmployeeId == employeeId && y.EndLeave.Date >= x.Date && y.StartLeave.Date <= x.Date);
|
||
var isHoliday = holidays.Any(y => y.HolidaydateGr == x.Date);
|
||
var isFriday = x.Date.DayOfWeek == DayOfWeek.Friday;
|
||
var isNormalWorkingDay = isHoliday == false && isFriday == false;
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = null,
|
||
EndDate1 = null,
|
||
DateTimeGr = x.Date,
|
||
DayOfWeek = x.Date.DayOfWeek.ToString(),
|
||
RollCallDateFa = x.Date.ToFarsi(),
|
||
LeaveType = leave != null ? leave.LeaveType : "",
|
||
IsAbsent = leave == null && isNormalWorkingDay
|
||
};
|
||
});
|
||
|
||
var presentDays = rollCalls.GroupBy(x => x.ShiftDate.Date).Select(x =>
|
||
{
|
||
var orderedRollcalls = x.OrderBy(y => y.ShiftDate);
|
||
|
||
var rollCallTimeSpanPerDay =
|
||
new TimeSpan(x.Where(y => y.EndDate != null).Sum(y => (y.EndDate - y.StartDate)!.Value.Ticks));
|
||
TimeSpan breakTimePerDay;
|
||
if (startMonthDay > endFarvardin)
|
||
breakTimePerDay =
|
||
RollCallMandatoryRepository.CalculateBreakTime(x.First().BreakTimeSpan, rollCallTimeSpanPerDay);
|
||
else
|
||
breakTimePerDay = RollCallMandatoryRepository.CalculateBreakTime(breakTime, rollCallTimeSpanPerDay);
|
||
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = orderedRollcalls.FirstOrDefault().StartDate.Value.ToString("HH:mm"),
|
||
EndDate1 = orderedRollcalls.FirstOrDefault().EndDate.Value.ToString("HH:mm"),
|
||
|
||
StartDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.StartDate?.ToString("HH:mm") ?? "",
|
||
EndDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.EndDate?.ToString("HH:mm") ?? "",
|
||
|
||
TotalhourseSpan = rollCallTimeSpanPerDay - breakTimePerDay,
|
||
|
||
BreakTimeTimeSpan = breakTimePerDay,
|
||
|
||
DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
RollCallDateFa = x.Key.Date.ToFarsi(),
|
||
DateTimeGr = x.Key.Date,
|
||
IsSliced = x.Count() > 2,
|
||
IsAbsent = false
|
||
};
|
||
});
|
||
|
||
|
||
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
|
||
{
|
||
StartDate1 = x.StartDate1,
|
||
EndDate1 = x.EndDate1,
|
||
EndDate2 = x.EndDate2,
|
||
StartDate2 = x.StartDate2,
|
||
TotalWorkingHours = $"{(int)(x.TotalhourseSpan.TotalHours)}:{x.TotalhourseSpan.Minutes.ToString("00")}",
|
||
BreakTimeString = $"{(int)(x.BreakTimeTimeSpan.TotalHours)}:{x.BreakTimeTimeSpan.Minutes.ToString("00")}",
|
||
TotalhourseSpan = x.TotalhourseSpan,
|
||
BreakTimeTimeSpan = x.BreakTimeTimeSpan,
|
||
DayOfWeek = x.DayOfWeek,
|
||
RollCallDateFa = x.RollCallDateFa,
|
||
DateTimeGr = x.DateTimeGr,
|
||
IsSliced = x.IsSliced,
|
||
IsAbsent = false
|
||
});
|
||
|
||
var result = presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
|
||
result.ForEach(x =>
|
||
{
|
||
x.IsHoliday = holidays.Any(y => x.DateTimeGr.Date == y.HolidaydateGr.Date);
|
||
x.IsFriday = x.DateTimeGr.DayOfWeek == DayOfWeek.Friday;
|
||
});
|
||
|
||
return result;
|
||
}
|
||
|
||
//محاسبه کارکرد پرسنل در هنگام جستجو
|
||
public TimeSpan GetEmployeeRollCallTimeSpanForDuration(long employeeId, long workshopId, DateTime start,
|
||
DateTime end)
|
||
{
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate != null && x.EndDate != null &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined &&
|
||
x.ShiftDate.Date >= start && x.ShiftDate.Date <= end).ToList();
|
||
|
||
|
||
return new TimeSpan(rollCalls.Sum(x => (x.EndDate - x.StartDate).Value.Ticks));
|
||
}
|
||
|
||
//حضور غیاب گروهی از پرسنل برای پرینت گروهی فیش حقوقی غیر رسمی نهایی
|
||
public List<PersonnelCheckoutDailyRollCallViewModel> GetEmployeeRollCallsForMonth(IEnumerable<long> employeeIds,
|
||
long workshopId, DateTime start, DateTime end)
|
||
{
|
||
if (workshopId == 170)
|
||
return GetEmployeeRollCallsForMonthForKababMahdi(employeeIds, workshopId, start, end);
|
||
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
employeeIds.Contains(x.EmployeeId) && workshopId == x.WorkshopId && x.StartDate != null &&
|
||
x.EndDate != null && x.RollCallModifyType != RollCallModifyType.Undefined &&
|
||
x.ShiftDate.Date >= start && x.ShiftDate.Date <= end).ToList();
|
||
|
||
var leaves = _context.LeaveList.Where(x =>
|
||
x.WorkshopId == workshopId && employeeIds.Contains(x.EmployeeId) && x.EndLeave.Date >= start.Date &&
|
||
x.StartLeave.Date <= end.Date).ToList();
|
||
|
||
var year = Convert.ToInt32(start.ToFarsi().Substring(0, 4));
|
||
var month = Convert.ToInt32(start.ToFarsi().Substring(5, 2));
|
||
var firstDayOfCurrentMonth = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
|
||
if (month == 12)
|
||
{
|
||
year += 1;
|
||
month = 1;
|
||
}
|
||
else
|
||
month += 1;
|
||
|
||
var nextMonthDate = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
var lastDayOfCurrentMonth = nextMonthDate.AddDays(-1);
|
||
|
||
int dateRange = (int)(lastDayOfCurrentMonth - firstDayOfCurrentMonth).TotalDays + 1;
|
||
var employeeSettingsList =
|
||
_context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().Where(x => x.WorkshopId == workshopId).ToList();
|
||
var holidays = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = start.ToFarsiYear()
|
||
});
|
||
//all the dates from start to end, to be compared with present days to get absent dates
|
||
var completeDaysList = Enumerable.Range(0, dateRange).Select(offset => start.AddDays(offset).Date).ToList();
|
||
|
||
|
||
List<PersonnelCheckoutDailyRollCallViewModel> result = new();
|
||
foreach (var employeeId in employeeIds)
|
||
{
|
||
var settings = employeeSettingsList.FirstOrDefault(x => x.EmployeeId == employeeId);
|
||
var worksInFriday = settings.FridayWork != FridayWork.Default;
|
||
var worksInHolidays = settings.HolidayWork != HolidayWork.Default;
|
||
var absentRecords = completeDaysList.Where(x =>
|
||
!rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date))
|
||
.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y =>
|
||
y.EmployeeId == employeeId && y.EndLeave.Date >= x.Date && y.StartLeave.Date <= x.Date);
|
||
var isHoliday = holidays.Any(y => y.HolidaydateGr == x.Date);
|
||
var isFriday = x.Date.DayOfWeek == DayOfWeek.Friday;
|
||
var isNormalWorkingDay = isHoliday == false && isFriday == false;
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = null,
|
||
EndDate1 = null,
|
||
DateTimeGr = x.Date,
|
||
DayOfWeek = x.Date.DayOfWeek.ToString(),
|
||
RollCallDateFa = x.Date.ToFarsi(),
|
||
LeaveType = leave != null ? leave.LeaveType : "",
|
||
IsAbsent = leave == null && (isNormalWorkingDay ||
|
||
(worksInFriday && x.Date.DayOfWeek == DayOfWeek.Friday) ||
|
||
(worksInHolidays && isHoliday))
|
||
};
|
||
});
|
||
var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date)
|
||
.Select(x =>
|
||
{
|
||
var orderedRollcalls = x.OrderBy(y => y.StartDate!.Value).ToList();
|
||
var firstRollCall = orderedRollcalls.FirstOrDefault();
|
||
var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault();
|
||
//این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت
|
||
//منطق کباب مهدی!!!!
|
||
|
||
#region SecondTimeDiff
|
||
|
||
var hasSecondTimeDiff = false;
|
||
if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating)
|
||
{
|
||
if (firstRollCall != null && secondRollCall != null)
|
||
{
|
||
var firstShift = FindRotatingShift(firstRollCall.StartDate.Value,
|
||
firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
var secondShift = FindRotatingShift(secondRollCall.StartDate.Value,
|
||
secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
if (firstShift.start == secondShift.start && firstShift.end == secondShift.end)
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = firstRollCall?.StartDate?.ToString("HH:mm"),
|
||
EndDate1 = firstRollCall?.EndDate?.ToString("HH:mm"),
|
||
|
||
StartDate2 = secondRollCall?.StartDate?.ToString("HH:mm") ?? "",
|
||
EndDate2 = secondRollCall?.EndDate?.ToString("HH:mm") ?? "",
|
||
|
||
TotalhourseSpan =
|
||
new TimeSpan(x.Where(y => y.EndDate != null)
|
||
.Sum(y => (y.EndDate - y.StartDate)!.Value.Ticks)),
|
||
DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
RollCallDateFa = x.Key.Date.ToFarsi(),
|
||
DateTimeGr = x.Key.Date,
|
||
IsSliced = x.Count() > 2,
|
||
IsAbsent = false,
|
||
EnterDifferencesMinutes1 =
|
||
firstRollCall != null && firstRollCall.LateEntryDuration > TimeSpan.Zero
|
||
? CalculateEntryMinuteDifference(firstRollCall.EarlyEntryDuration,
|
||
firstRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes1 =
|
||
firstRollCall != null && firstRollCall.EarlyExitDuration > TimeSpan.Zero
|
||
? CalculateExitMinuteDifference(firstRollCall.EarlyExitDuration,
|
||
firstRollCall.LateExitDuration)
|
||
: "",
|
||
|
||
EnterDifferencesMinutes2 = secondRollCall != null &&
|
||
secondRollCall.LateEntryDuration > TimeSpan.Zero && hasSecondTimeDiff
|
||
? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration,
|
||
secondRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes2 = secondRollCall != null &&
|
||
secondRollCall.EarlyExitDuration > TimeSpan.Zero && hasSecondTimeDiff
|
||
? CalculateExitMinuteDifference(secondRollCall.EarlyExitDuration,
|
||
secondRollCall.LateExitDuration)
|
||
: ""
|
||
};
|
||
});
|
||
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
|
||
{
|
||
StartDate1 = x.StartDate1,
|
||
EndDate1 = x.EndDate1,
|
||
EndDate2 = x.EndDate2,
|
||
StartDate2 = x.StartDate2,
|
||
TotalWorkingHours = $"{(int)(x.TotalhourseSpan.TotalHours)}:{x.TotalhourseSpan.Minutes.ToString("00")}",
|
||
DayOfWeek = x.DayOfWeek,
|
||
RollCallDateFa = x.RollCallDateFa,
|
||
DateTimeGr = x.DateTimeGr,
|
||
IsSliced = x.IsSliced,
|
||
IsAbsent = false,
|
||
EnterDifferencesMinutes1 = x.EnterDifferencesMinutes1,
|
||
ExitDifferencesMinutes1 = x.ExitDifferencesMinutes1,
|
||
EnterDifferencesMinutes2 = x.EnterDifferencesMinutes2,
|
||
ExitDifferencesMinutes2 = x.ExitDifferencesMinutes2
|
||
});
|
||
|
||
List<CheckoutDailyRollCallViewModel> checkoutDailyRollCalls =
|
||
presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
|
||
|
||
checkoutDailyRollCalls.ForEach(x =>
|
||
{
|
||
x.IsFriday = x.DateTimeGr.DayOfWeek == DayOfWeek.Friday;
|
||
x.IsHoliday = holidays.Any(y => y.HolidaydateGr == x.DateTimeGr);
|
||
});
|
||
var resultItem = new PersonnelCheckoutDailyRollCallViewModel()
|
||
{
|
||
EmployeeId = employeeId,
|
||
WorkshopId = workshopId,
|
||
DailyRollCalls = checkoutDailyRollCalls
|
||
};
|
||
result.Add(resultItem);
|
||
}
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return "-";
|
||
}
|
||
else if (late != TimeSpan.Zero)
|
||
{
|
||
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
|
||
return $"{minutes}+";
|
||
}
|
||
else if (early != TimeSpan.Zero)
|
||
{
|
||
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
|
||
return $"{minutes}-";
|
||
}
|
||
else
|
||
{
|
||
return $"";
|
||
}
|
||
}
|
||
|
||
private string CalculateEntryMinuteDifference(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return "-";
|
||
}
|
||
else if (late != TimeSpan.Zero)
|
||
{
|
||
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
|
||
return $"{minutes}-";
|
||
}
|
||
else if (early != TimeSpan.Zero)
|
||
{
|
||
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
|
||
return $"{minutes}+";
|
||
}
|
||
else
|
||
{
|
||
return $"";
|
||
}
|
||
}
|
||
|
||
//خواسته کارفرما: هنگام جستجوی کارمند حضور غیاب های فرد در قالب های یک ماهه ظاهر شوند
|
||
//این قالب ها متناسب با جستجوی کاربر، یا حضور غیاب های موجود، ممکن است بازه ای کمتر از یک ماه را شامل باشد
|
||
//صورت گیرد AJAX ضمنا چون دیتا سینگین است
|
||
// میدهد و سپس در جواب سرور ایندکس تاریخ بعدی را بدست می آورد و در ایجکس بعدی قرار میدهد NULL پیاده سازی: فرانت بار اول ایندکس تاریخ را
|
||
// باشد یعنی قبل از این تاریخ دیگر فعالیتی نداشته NULL اگر در جواب سرور ایندکس تاریخ
|
||
/// <summary>
|
||
/// جستجوی سوابق حضور غیاب بر اساس کارمند
|
||
/// </summary>
|
||
public EmployeeRollCallsByMonthViewModel GetEmployeeRollCallsHistory(long employeeId, long workshopId,
|
||
DateTime? startDateTime, DateTime? endDateTime, DateTime? exactDateTime, DateTime? dateIndex)
|
||
{
|
||
// اگر کد پرسنلی نداشت نباید چیزی نشان ندهد
|
||
if (!_context.PersonnelCodeSet.Any(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId))
|
||
return new();
|
||
|
||
//get RollCallEmployee and RollCallEmployeeStatus for that employee in that workshop
|
||
var employeeRollCallStatuses = _context.RollCallEmployees.Include(x => x.EmployeesStatus)
|
||
.FirstOrDefault(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId);
|
||
|
||
//if no status was found return empty
|
||
if (employeeRollCallStatuses == null || employeeRollCallStatuses.EmployeesStatus == null ||
|
||
!employeeRollCallStatuses.EmployeesStatus.Any())
|
||
return new();
|
||
|
||
//this list will have all the months which employee was active in, remember this doesn't have statuses,
|
||
//just the list of months which user had activity in
|
||
var activeMonths = new List<PersianDateTime>();
|
||
|
||
//filling the list
|
||
foreach (var status in employeeRollCallStatuses.EmployeesStatus)
|
||
{
|
||
var persianEndDate = new PersianDateTime(status.EndDate.Date);
|
||
var persianStartDate = new PersianDateTime(status.StartDate.Date);
|
||
|
||
var persianStartFirstDayOfMonth = new PersianDateTime(persianStartDate.Year, persianStartDate.Month, 1);
|
||
|
||
for (PersianDateTime start = persianStartFirstDayOfMonth;
|
||
start <= persianEndDate && start < PersianDateTime.Today.Date;
|
||
start = start.AddMonths(1))
|
||
{
|
||
activeMonths.Add(start);
|
||
}
|
||
}
|
||
|
||
//might have duplicated records, this is the reason for distinct
|
||
var activeMonthsList = activeMonths.OrderByDescending(x => x.Date).Distinct().ToList();
|
||
|
||
PersianDateTime startSearch = new();
|
||
PersianDateTime endSearch = new();
|
||
|
||
//if search has these parameters below
|
||
if (startDateTime.HasValue && endDateTime.HasValue)
|
||
{
|
||
//change them to persian date time and store them
|
||
startSearch = new PersianDateTime(startDateTime.Value);
|
||
endSearch = new PersianDateTime(endDateTime.Value);
|
||
|
||
//get the months that include these dates
|
||
activeMonthsList = activeMonthsList.Where(x =>
|
||
x.Year >= startSearch.Year && x.Month >= startSearch.Month && x.Year <= endSearch.Year &&
|
||
x.Month <= endSearch.Month).ToList();
|
||
}
|
||
|
||
//if exact datetime is given start and end will be the same date
|
||
if (exactDateTime.HasValue)
|
||
{
|
||
startSearch = new PersianDateTime(exactDateTime.Value);
|
||
endSearch = startSearch;
|
||
activeMonthsList = activeMonthsList.Where(x =>
|
||
x.Year >= startSearch.Year && x.Month >= startSearch.Month && x.Year <= endSearch.Year &&
|
||
x.Month <= endSearch.Month).ToList();
|
||
}
|
||
|
||
//dateIndex is a kind of selector which moves
|
||
if (dateIndex != null)
|
||
{
|
||
var persianDateIndex = new PersianDateTime(dateIndex.Value);
|
||
|
||
//gets first of month, if the day is 21st of month, first of month is 21-21 +1 = 1 or 21 + (-(21-1)) = 1
|
||
var dateIndexFirstOfMonth = persianDateIndex.AddDays(-(persianDateIndex.Day - 1));
|
||
|
||
activeMonthsList = activeMonthsList.Where(x => dateIndexFirstOfMonth >= x).ToList();
|
||
}
|
||
|
||
if (!activeMonthsList.Any()) return new();
|
||
|
||
//get the first month which user was active in
|
||
PersianDateTime selectedMonthPersian = activeMonthsList.First();
|
||
|
||
DateTime selectedMonthFirstDay = selectedMonthPersian;
|
||
DateTime nextMonthFirstDay = selectedMonthPersian.AddMonths(1);
|
||
|
||
//get statuses which were active in the selected month
|
||
var statusesOfMonth = employeeRollCallStatuses.EmployeesStatus.Where(x => x.EndDate >= selectedMonthFirstDay &&
|
||
x.StartDate < nextMonthFirstDay);
|
||
|
||
|
||
//get leaves in the specified month
|
||
var leavesQuery =
|
||
_context.LeaveList.Where(x =>
|
||
(x.LeaveType == "استعلاجی" || (x.LeaveType == "استحقاقی" && x.PaidLeaveType == "روزانه")) &&
|
||
x.IsAccepted &&
|
||
x.EndLeave >= selectedMonthFirstDay && x.StartLeave < nextMonthFirstDay &&
|
||
x.WorkshopId == workshopId && x.EmployeeId == employeeId);
|
||
|
||
//get employee rollcalls where there is no leave in that day,
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
x.EmployeeId == employeeId && !leavesQuery.Any(y =>
|
||
y.StartLeave.Date <= x.ShiftDate.Date && y.EndLeave.Date >= x.ShiftDate.Date) &&
|
||
x.WorkshopId == workshopId && x.StartDate != null &&
|
||
x.ShiftDate >= selectedMonthFirstDay && x.ShiftDate < nextMonthFirstDay &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined);
|
||
|
||
|
||
var personnelCode =
|
||
_context.PersonnelCodeSet.FirstOrDefault(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId)
|
||
?.PersonnelCode;
|
||
|
||
var employeeName = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId)
|
||
.Select(x => new { x.EmployeeId, x.EmployeeFullName })
|
||
.FirstOrDefault(x => x.EmployeeId == employeeId);
|
||
|
||
var rollCallsList = rollCalls.ToList();
|
||
var leavesList = leavesQuery.ToList();
|
||
|
||
//number of days in period, since we are subtracting from next month's first day,there is no need for ".TotalDays() - 1"
|
||
int dateRange = (int)(nextMonthFirstDay - selectedMonthFirstDay).TotalDays;
|
||
|
||
var todayDate = DateTime.Now.Date;
|
||
|
||
//all the dates from start to end, to be compared with present days to get absent dates
|
||
var completeDaysList = Enumerable.Range(0, dateRange)
|
||
.Select(offset => selectedMonthFirstDay.AddDays(offset).Date).Where(x => x.Date < todayDate);
|
||
|
||
//if user search range is within a month for example, we dont want 30/31/29 days for month, we want it to be the size of the search range
|
||
//user input = 2024/04/15~2024/04/21, output days count is 21-15+1=6 days from 15th to 21st
|
||
if (exactDateTime.HasValue || (startDateTime.HasValue && endDateTime.HasValue))
|
||
completeDaysList = completeDaysList.Where(x => x.Date >= startSearch.Date && x.Date <= endSearch.Date);
|
||
|
||
//get the days in which user was active and no rollcall with enddate==null is present
|
||
//(im thinking about removing the rollcall condition)
|
||
var result = completeDaysList.Where(x =>
|
||
!rollCallsList.Any(y => y.ShiftDate.Date == x.Date.Date && y.EndDate == null) &&
|
||
statusesOfMonth.Any(y => x >= y.StartDate.Date && x <= y.EndDate.Date))
|
||
.Select(x =>
|
||
{
|
||
//iterating day by day
|
||
|
||
//get the leaves for this day so we can find out if employee was on a permitted absence
|
||
var leave = leavesList.FirstOrDefault(y => y.EndLeave >= x.Date && y.StartLeave <= x.Date);
|
||
return new RollCallViewModel()
|
||
{
|
||
DateGr = x.Date,
|
||
DateFa = x.Date.ToFarsi(),
|
||
|
||
//all the roll calls which have a start date in this day
|
||
RollCallTimesList = rollCallsList.Where(y => x.Date == y.ShiftDate.Date).Select(y =>
|
||
new RollCallTimeViewModel()
|
||
{
|
||
StartDate = y.StartDate.Value.ToString("HH:mm"),
|
||
EndDate = y.EndDate!.Value.ToString("HH:mm"),
|
||
StartDateGr = y.StartDate.Value,
|
||
EndDateGr = y.EndDate.Value,
|
||
EntryTimeDifferences =
|
||
CalculateEntryTimeDifferences(y.EarlyEntryDuration, y.LateEntryDuration),
|
||
ExitTimeDifferences = CalculateExitTimeDifferences(y.EarlyExitDuration, y.LateExitDuration)
|
||
}),
|
||
TotalWorkingHoursSpan = new TimeSpan(rollCallsList.Where(y => x.Date == y.ShiftDate.Date)
|
||
.Sum(y => (y.EndDate!.Value - y.StartDate.Value).Ticks)),
|
||
Reason = leave?.LeaveType ?? "",
|
||
HasLeave = (leave?.PaidLeaveType == "روزانه" || leave?.LeaveType == "استعلاجی") ? true : false
|
||
};
|
||
});
|
||
|
||
//filling TotalWorkingHours string from TimeSpans we filled in the last step and other info
|
||
result = result.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeFullName = employeeName.EmployeeFullName,
|
||
EmployeeId = employeeId,
|
||
PersonnelCode = personnelCode.ToString(),
|
||
DateGr = x.DateGr,
|
||
DateFa = x.DateFa,
|
||
|
||
DayOfWeekFa = x.DateGr.DayOfWeek.DayOfWeeKToPersian(),
|
||
IsHoliday = _holidayItemApplication.IsHoliday(x.DateGr),
|
||
IsAbsent = !x.RollCallTimesList.Any(),
|
||
RollCallTimesList = x.RollCallTimesList.OrderBy(r => r.StartDateGr),
|
||
HasLeave = x.HasLeave,
|
||
TotalWorkingHoursSpan = x.TotalWorkingHoursSpan,
|
||
TotalWorkingHours =
|
||
$"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}"
|
||
}).ToList();
|
||
|
||
//total working hours in the whole month or duration
|
||
var totalWorkingHours = new TimeSpan(result.Sum(x => x.TotalWorkingHoursSpan.Ticks));
|
||
|
||
//if there are any other months available that the selector
|
||
return new EmployeeRollCallsByMonthViewModel()
|
||
{
|
||
PersianMonthName = selectedMonthPersian.ToString("MMMM"),
|
||
PersianYear = selectedMonthPersian.ToString("yyyy"),
|
||
DateGr = selectedMonthFirstDay,
|
||
RollCalls = result.OrderByDescending(x => x.DateGr),
|
||
DateIndex = activeMonthsList.Count > 1 ? activeMonthsList.Skip(1).First().ToString("yyyy/MM/dd") : null,
|
||
TotalWorkingHours = new TimeSpan(result.Sum(x => x.TotalWorkingHoursSpan.Ticks)).ToFarsiHoursAndMinutes(),
|
||
TotalWorkingHoursTimeSpan = $"{(int)totalWorkingHours.TotalHours}:{totalWorkingHours.Minutes:00}"
|
||
};
|
||
}
|
||
|
||
private string CalculateExitTimeDifferences(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return "-";
|
||
}
|
||
else if (late != TimeSpan.Zero)
|
||
{
|
||
return $"{late.Hours}:{late.Minutes:00}+";
|
||
}
|
||
else if (early != TimeSpan.Zero)
|
||
{
|
||
return $"{early.Hours}:{early.Minutes:00}-";
|
||
}
|
||
else
|
||
{
|
||
return $"";
|
||
}
|
||
}
|
||
|
||
private string CalculateEntryTimeDifferences(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return "-";
|
||
}
|
||
else if (late != TimeSpan.Zero)
|
||
{
|
||
return $"{late.Hours}:{late.Minutes:00}-";
|
||
}
|
||
else if (early != TimeSpan.Zero)
|
||
{
|
||
return $"{early.Hours}:{early.Minutes:00}+";
|
||
}
|
||
else
|
||
{
|
||
return $"";
|
||
}
|
||
}
|
||
|
||
private TimeSpan CalculateExitTimeDifferencesTimeSpan(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return TimeSpan.Zero;
|
||
}
|
||
|
||
if (late != TimeSpan.Zero)
|
||
{
|
||
return late * 1;
|
||
}
|
||
|
||
if (early != TimeSpan.Zero)
|
||
{
|
||
return early * -1;
|
||
}
|
||
|
||
return TimeSpan.Zero;
|
||
}
|
||
|
||
private TimeSpan CalculateEntryTimeDifferencesTimeSpan(TimeSpan early, TimeSpan late)
|
||
{
|
||
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||
{
|
||
return TimeSpan.Zero;
|
||
}
|
||
|
||
if (late != TimeSpan.Zero)
|
||
{
|
||
return late * -1;
|
||
}
|
||
|
||
if (early != TimeSpan.Zero)
|
||
{
|
||
return early * 1;
|
||
}
|
||
|
||
return TimeSpan.Zero;
|
||
}
|
||
|
||
//Without Paginate, With EndDate==null, without undefined, Ordered Descending By StartDate
|
||
public List<RollCallViewModel> GetEmployeeRollCallsHistoryAllInDates(long workshopId, long employeeId,
|
||
DateTime start, DateTime end)
|
||
{
|
||
var withPersonnelCode = _context.PersonnelCodeSet.Where(x => x.WorkshopId == workshopId);
|
||
|
||
return _context.RollCalls.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId &&
|
||
withPersonnelCode.Any(y => y.EmployeeId == x.EmployeeId) &&
|
||
(x.EndDate == null || x.EndDate.Value.Date >= start.Date) &&
|
||
x.ShiftDate.Date <= end.Date)
|
||
.OrderByDescending(x => x.StartDate.Value)
|
||
.Select(x => new RollCallViewModel
|
||
{
|
||
EmployeeId = employeeId,
|
||
WorkshopId = workshopId,
|
||
StartDate = x.StartDate,
|
||
EndDate = x.EndDate,
|
||
DateGr = x.ShiftDate,
|
||
ShiftDate = x.ShiftDate
|
||
}).ToList();
|
||
}
|
||
|
||
|
||
//سوابق حضور غیاب کارگاه
|
||
public RollCallsByDateViewModel GetWorkshopRollCallHistory(RollCallSearchModel searchModel)
|
||
{
|
||
//initialize
|
||
DateTime searchDurationEnd = DateTime.Now.AddDays(-1).Date;
|
||
DateTime searchDurationStart = DateTime.MinValue;
|
||
|
||
|
||
//override if user has entered inputs (dates must be validated in the application layer)
|
||
if (!string.IsNullOrWhiteSpace(searchModel.StarDateFa) && !string.IsNullOrWhiteSpace(searchModel.StarDateFa))
|
||
{
|
||
searchDurationEnd = searchModel.EndDateFa.ToGeorgianDateTime().Date;
|
||
searchDurationStart = searchModel.StarDateFa.ToGeorgianDateTime().AddDays(-1).Date;
|
||
}
|
||
|
||
|
||
else if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa))
|
||
{
|
||
searchDurationEnd = searchModel.ExactDateFa.ToGeorgianDateTime().Date;
|
||
searchDurationStart = searchModel.ExactDateFa.ToGeorgianDateTime().AddDays(-1).Date;
|
||
}
|
||
|
||
|
||
if (searchDurationEnd < searchDurationStart)
|
||
return new();
|
||
|
||
|
||
DateTime dateIndex = searchDurationEnd.AddDays(-1 * (searchModel.DateIndex)).Date;
|
||
|
||
if (dateIndex <= searchDurationStart)
|
||
return new();
|
||
|
||
|
||
//get leaves for workshop that have been activated in dateIndex date
|
||
var leavesQuery = _context.LeaveList.Where(x => x.WorkshopId == searchModel.WorkshopId &&
|
||
x.IsAccepted &&
|
||
(x.LeaveType == "استعلاجی" || (x.LeaveType == "استحقاقی" &&
|
||
x.PaidLeaveType == "روزانه")) &&
|
||
x.EndLeave.Date >= dateIndex && x.StartLeave.Date <= dateIndex);
|
||
|
||
//roll calls for current workshop where shift start is in dateIndex date (filters today's shifts)
|
||
var rollCallsQuery = _context.RollCalls
|
||
.Where(x => x.WorkshopId == searchModel.WorkshopId && x.StartDate.HasValue &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined && x.ShiftDate < DateTime.Now.Date &&
|
||
x.ShiftDate.Date == dateIndex.Date);
|
||
|
||
var personnelCodeQuery = _context.PersonnelCodeSet.Where(x => x.WorkshopId == searchModel.WorkshopId);
|
||
|
||
//get active employees of workshop in dateIndex date
|
||
var activeEmployeesQuery =
|
||
_context.RollCallEmployees.Include(x => x.EmployeesStatus)
|
||
.Where(x => x.WorkshopId == searchModel.WorkshopId &&
|
||
personnelCodeQuery.Any(y => y.EmployeeId == x.EmployeeId) &&
|
||
x.EmployeesStatus.Any(y => y.EndDate.Date >= dateIndex && y.StartDate.Date <= dateIndex)
|
||
&& !rollCallsQuery.Any(rc => rc.EmployeeId == x.EmployeeId && !rc.EndDate.HasValue));
|
||
|
||
if (searchModel.EmployeeId > 0)
|
||
{
|
||
rollCallsQuery = rollCallsQuery.Where(x => x.EmployeeId == searchModel.EmployeeId);
|
||
activeEmployeesQuery = activeEmployeesQuery.Where(x => x.EmployeeId == searchModel.EmployeeId);
|
||
leavesQuery = leavesQuery.Where(x => x.EmployeeId == searchModel.EmployeeId);
|
||
}
|
||
|
||
|
||
var personnelCodeList = personnelCodeQuery.ToList();
|
||
var activatedEmployeesList = activeEmployeesQuery.ToList();
|
||
rollCallsQuery = rollCallsQuery.Where(x => x.EndDate.HasValue);
|
||
var rollCallsList = rollCallsQuery.ToList();
|
||
var leavesList = leavesQuery.ToList();
|
||
|
||
rollCallsList = rollCallsList.Where(x => leavesList.All(y => y.EmployeeId != x.EmployeeId)).ToList();
|
||
var result = new RollCallsByDateViewModel()
|
||
{
|
||
DateGr = dateIndex,
|
||
DayOfWeekFa = dateIndex.DayOfWeek.DayOfWeeKToPersian(),
|
||
IsHoliday = _holidayItemApplication.IsHoliday(dateIndex),
|
||
DateFa = dateIndex.ToFarsi(),
|
||
ActiveEmployees = activatedEmployeesList.Select(x =>
|
||
{
|
||
var leave = leavesList.FirstOrDefault(y => y.EmployeeId == x.EmployeeId);
|
||
var employeeRollCallsForDate = rollCallsList.Where(y => y.EmployeeId == x.EmployeeId).ToList();
|
||
|
||
return new RollCallViewModel()
|
||
{
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId,
|
||
Reason = leave == null ? "" : $"{leave.LeaveType}-{leave.PaidLeaveType}",
|
||
RollCallTimesList = employeeRollCallsForDate.OrderBy(r => r.StartDate).Select(y =>
|
||
new RollCallTimeViewModel()
|
||
{
|
||
EndDate = y.EndDate!.Value.ToString("HH:mm"),
|
||
StartDate = y.StartDate!.Value.ToString("HH:mm"),
|
||
EntryTimeDifferences =
|
||
CalculateEntryTimeDifferences(y.EarlyEntryDuration, y.LateEntryDuration),
|
||
ExitTimeDifferences = CalculateExitTimeDifferences(y.EarlyExitDuration, y.LateExitDuration)
|
||
}),
|
||
HasLeave = leave != null,
|
||
IsAbsent = !employeeRollCallsForDate.Any(),
|
||
TotalWorkingHoursSpan =
|
||
new TimeSpan(employeeRollCallsForDate.Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks)),
|
||
PersonnelCode = personnelCodeList.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.PersonnelCode
|
||
.ToString(),
|
||
};
|
||
})
|
||
};
|
||
result.ActiveEmployees = result.ActiveEmployees.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId,
|
||
Reason = x.Reason,
|
||
RollCallTimesList = x.RollCallTimesList,
|
||
HasLeave = x.HasLeave,
|
||
IsAbsent = x.IsAbsent,
|
||
PersonnelCode = x.PersonnelCode,
|
||
TotalWorkingHours =
|
||
$"{(int)x.TotalWorkingHoursSpan.TotalHours}:{(x.TotalWorkingHoursSpan.Minutes).ToString("00")}"
|
||
});
|
||
return result;
|
||
}
|
||
|
||
//برای دریافت سوابق به صورت collapsed
|
||
public RollCallsByDateViewModel GetWorkshopRollCallHistoryCollapsed(RollCallSearchModel searchModel)
|
||
{
|
||
//initialize
|
||
|
||
DateTime searchDurationEnd = DateTime.Now.AddDays(-1).Date;
|
||
DateTime searchDurationStart = searchDurationEnd.AddDays(-16);
|
||
|
||
|
||
//override if user has entered inputs (dates must be validated in the application layer)
|
||
if (!string.IsNullOrWhiteSpace(searchModel.StarDateFa) && !string.IsNullOrWhiteSpace(searchModel.StarDateFa))
|
||
{
|
||
searchDurationEnd = searchModel.EndDateFa.ToGeorgianDateTime().Date;
|
||
searchDurationStart = searchModel.StarDateFa.ToGeorgianDateTime().AddDays(-1).Date;
|
||
}
|
||
|
||
|
||
else if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa))
|
||
{
|
||
searchDurationEnd = searchModel.ExactDateFa.ToGeorgianDateTime().Date;
|
||
searchDurationStart = searchModel.ExactDateFa.ToGeorgianDateTime().AddDays(-1).Date;
|
||
}
|
||
|
||
|
||
if (searchDurationEnd < searchDurationStart)
|
||
return new();
|
||
|
||
|
||
DateTime dateIndex = searchDurationEnd.AddDays(-1 * (searchModel.DateIndex)).Date;
|
||
|
||
if (dateIndex <= searchDurationStart)
|
||
return new();
|
||
|
||
var activeEmployeesList =
|
||
_context.RollCallEmployees.Include(x => x.EmployeesStatus)
|
||
.Where(x => x.WorkshopId == searchModel.WorkshopId &&
|
||
x.EmployeesStatus.Any(y => y.EndDate.Date >= dateIndex && y.StartDate.Date <= dateIndex))
|
||
.ToList();
|
||
|
||
var result = new RollCallsByDateViewModel()
|
||
{
|
||
DateGr = dateIndex,
|
||
DayOfWeekFa = dateIndex.DayOfWeek.DayOfWeeKToPersian(),
|
||
IsHoliday = _holidayItemApplication.IsHoliday(dateIndex),
|
||
DateFa = dateIndex.ToFarsi(),
|
||
ActiveEmployeesCount = activeEmployeesList.Count()
|
||
};
|
||
return result;
|
||
}
|
||
|
||
//سوابق غیبت
|
||
public List<RollCallsByDateViewModel> GetWorkshopAbsentHistory(long workshopId, DateTime startSearch,
|
||
DateTime endSearch)
|
||
{
|
||
if (endSearch.Date == DateTime.Now.Date)
|
||
endSearch = endSearch.AddDays(-1);
|
||
//get leaves for workshop that have been activated in dateIndex date
|
||
var leavesQuery = _context.LeaveList.AsSplitQuery().Where(x => x.WorkshopId == workshopId &&
|
||
x.IsAccepted &&
|
||
(x.LeaveType == "استعلاجی" ||
|
||
(x.LeaveType == "استحقاقی" &&
|
||
x.PaidLeaveType == "روزانه")) &&
|
||
x.EndLeave.Date >= startSearch.Date &&
|
||
x.StartLeave.Date <= endSearch.Date);
|
||
|
||
//roll calls for current workshop where shift start is in dateIndex date (filters today's shifts)
|
||
var rollCallsQuery = _context.RollCalls.AsSplitQuery()
|
||
.Where(x => x.WorkshopId == workshopId && x.StartDate.HasValue &&
|
||
x.ShiftDate.Date >= startSearch.Date && x.ShiftDate.Date <= endSearch.Date &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined);
|
||
|
||
|
||
var withPersonnelCode = _context.PersonnelCodeSet.AsSplitQuery().Where(x => x.WorkshopId == workshopId);
|
||
|
||
//get active employees of workshop in dateIndex date
|
||
var activeEmployeesQuery =
|
||
_context.RollCallEmployees.AsSplitQuery().Include(x => x.EmployeesStatus)
|
||
.Where(x => x.WorkshopId == workshopId &&
|
||
x.EmployeesStatus.Any(y =>
|
||
y.EndDate.Date >= startSearch && y.StartDate.Date <= endSearch) &&
|
||
withPersonnelCode.Any(y => y.EmployeeId == x.EmployeeId));
|
||
|
||
var employeeSettingsList =
|
||
_context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().Where(x => x.WorkshopId == workshopId).ToList();
|
||
var rollCallsList = rollCallsQuery.ToList();
|
||
var activatedEmployeesList = activeEmployeesQuery.ToList();
|
||
var leavesList = leavesQuery.ToList();
|
||
|
||
//start of search year may be different to end of search year
|
||
var holidays1 = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = startSearch.ToFarsiYear()
|
||
});
|
||
var holidays2 = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = endSearch.ToFarsiYear()
|
||
});
|
||
var totalHolidays = holidays1.Concat(holidays2).Distinct().ToList();
|
||
int daysCount = (int)((endSearch.Date - startSearch.Date).TotalDays + 1);
|
||
List<DateTime> days = Enumerable.Range(0, daysCount).Select(x => startSearch.Date.AddDays(x)).ToList();
|
||
List<RollCallsByDateViewModel> result = new();
|
||
foreach (var day in days)
|
||
{
|
||
bool isHoliday = totalHolidays.Any(x => x.HolidaydateGr == day);
|
||
|
||
List<RollCallEmployee> activatedEmployeesListInDay = new();
|
||
|
||
activatedEmployeesListInDay = activatedEmployeesList
|
||
.Join(employeeSettingsList.Where(x =>
|
||
x.WeeklyOffDays == null || !x.WeeklyOffDays.Select(w => w.DayOfWeek).Contains(day.DayOfWeek))
|
||
, x => x.EmployeeId, y => y.EmployeeId,
|
||
(x, _) => x).ToList();
|
||
|
||
if (isHoliday)
|
||
{
|
||
activatedEmployeesListInDay = activatedEmployeesListInDay
|
||
.Join(employeeSettingsList.Where(x =>
|
||
x.WeeklyOffDays == null || x.HolidayWork != HolidayWork.Default)
|
||
, x => x.EmployeeId, y => y.EmployeeId,
|
||
(x, _) => x).ToList();
|
||
}
|
||
|
||
////in working days everyone should be present
|
||
//if (day.DayOfWeek != DayOfWeek.Friday && isHoliday == false)
|
||
//{
|
||
// activatedEmployeesListInDay = activatedEmployeesList;
|
||
//}
|
||
|
||
////in fridays, friday workers should be present
|
||
//else if (day.DayOfWeek == DayOfWeek.Friday)
|
||
//{
|
||
// activatedEmployeesListInDay = activatedEmployeesList
|
||
// .Join(employeeSettingsList.Where(x => x.FridayWork != FridayWork.Default)
|
||
// , x => x.EmployeeId, y => y.EmployeeId,
|
||
// (x, y) => x).ToList();
|
||
//}
|
||
|
||
////in holidays holiday workers should be present
|
||
//else
|
||
//{
|
||
// activatedEmployeesListInDay = activatedEmployeesList
|
||
// .Join(employeeSettingsList.Where(x => x.HolidayWork != HolidayWork.Default)
|
||
// , x => x.EmployeeId, y => y.EmployeeId,
|
||
// (x, y) => x).ToList();
|
||
//}
|
||
var item = new RollCallsByDateViewModel()
|
||
{
|
||
DateGr = day,
|
||
DayOfWeekFa = day.DayOfWeek.DayOfWeeKToPersian(),
|
||
DateFa = day.ToFarsi(),
|
||
ActiveEmployees = activatedEmployeesListInDay.Where(x =>
|
||
x.EmployeesStatus.Any(y => y.StartDate.Date <= day && y.EndDate.AddDays(-1).Date >= day) &&
|
||
!leavesList.Any(y =>
|
||
y.EmployeeId == x.EmployeeId && y.StartLeave.Date <= day && y.EndLeave.Date >= day) &&
|
||
!rollCallsList.Any(rc => rc.EmployeeId == x.EmployeeId && rc.ShiftDate.Date == day.Date))
|
||
.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeId = x.EmployeeId,
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
Id = x.id,
|
||
WorkshopId = x.WorkshopId
|
||
}),
|
||
IsHoliday = isHoliday,
|
||
IsFriday = day.DayOfWeek == DayOfWeek.Friday
|
||
};
|
||
result.Add(item);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
//گزارش آنلاین حضور غیاب کارگاه
|
||
public CurrentDayRollCall GetWorkshopCurrentDayRollCalls(long workshopId)
|
||
{
|
||
var date = DateTime.Now.Date;
|
||
|
||
|
||
//get active leaves for workshop which are active today and accepted and are either روزانه and استحقاقی or استعلاجی
|
||
var leaves = _context.LeaveList
|
||
.Where(x =>
|
||
(x.WorkshopId == workshopId && x.EndLeave.Date >= date && x.StartLeave.Date <= date && x.IsAccepted) &&
|
||
((x.LeaveType == "استعلاجی" || (x.LeaveType == "استحقاقی" && x.PaidLeaveType == "روزانه")) ||
|
||
(x.LeaveType == "استحقاقی" && x.PaidLeaveType == "ساعتی" && x.StartLeave <= DateTime.Now &&
|
||
x.EndLeave >= DateTime.Now))
|
||
);
|
||
|
||
var personnelCodes = _context.PersonnelCodeSet.Where(x => x.WorkshopId == workshopId);
|
||
|
||
//get currently working employees with leftWork table
|
||
//var workingEmployees =
|
||
// _context.LeftWorkList.Where(x => x.WorkshopId == workshopId && x.StartWorkDate < date && x.LeftWorkDate.Date > date);
|
||
|
||
|
||
//get activated employees
|
||
var activeEmployees =
|
||
_context.RollCallEmployees.Include(x => x.EmployeesStatus)
|
||
.Where(x => x.WorkshopId == workshopId && personnelCodes.Any(y => y.EmployeeId == x.EmployeeId) &&
|
||
x.EmployeesStatus.Any(y => y.StartDate.Date <= date && y.EndDate.Date >= date));
|
||
|
||
|
||
//get today's roll calls
|
||
var rollCallsQuery = _context.RollCalls.Where(x =>
|
||
x.WorkshopId == workshopId && (x.ShiftDate.Date == date || x.EndDate == null) &&
|
||
x.RollCallModifyType != RollCallModifyType.Undefined);
|
||
|
||
|
||
var mustBePresent = activeEmployees.Where(x => !leaves.Any(y => y.EmployeeId == x.EmployeeId));
|
||
|
||
|
||
var filteredRollCallQuery = rollCallsQuery.Where(x => mustBePresent
|
||
.Any(y => x.EmployeeId == y.EmployeeId)).ToList();
|
||
|
||
|
||
var nameReferences = activeEmployees.ToList();
|
||
|
||
//presents list is ready
|
||
var presentEmployees = filteredRollCallQuery.GroupBy(x => x.EmployeeId).Select(x => new RollCallViewModel()
|
||
{
|
||
PersonnelCode = personnelCodes
|
||
.FirstOrDefault(y => y.EmployeeId == x.Key)?
|
||
.PersonnelCode.ToString(),
|
||
EmployeeFullName = nameReferences.FirstOrDefault(y => x.Key == y.EmployeeId).EmployeeFullName,
|
||
EmployeeId = x.FirstOrDefault()!.EmployeeId,
|
||
TotalWorkingHoursSpan =
|
||
new TimeSpan(x.Where(y => y.EndDate != null).Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks)),
|
||
RollCallTimesList = x.OrderBy(r => r.StartDate).Select(y => new RollCallTimeViewModel()
|
||
{
|
||
StartDate = y.StartDate!.Value.ToString("HH:mm"),
|
||
EndDate = y.EndDate?.ToString("HH:mm"),
|
||
EntryTimeDifferences = CalculateEntryTimeDifferences(y.EarlyEntryDuration, y.LateEntryDuration),
|
||
ExitTimeDifferences = CalculateExitTimeDifferences(y.EarlyExitDuration, y.LateExitDuration)
|
||
}).ToList()
|
||
});
|
||
|
||
presentEmployees = presentEmployees.Select(x => new RollCallViewModel()
|
||
{
|
||
PersonnelCode = x.PersonnelCode,
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId,
|
||
TotalWorkingHours =
|
||
$"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}",
|
||
RollCallTimesList = x.RollCallTimesList
|
||
}).OrderBy(x => x.RollCallTimesList.Any(y => y.EndDate != null)).ToList();
|
||
|
||
//absent ones are those who are active and not on the roll call list
|
||
var absentsQuery = activeEmployees.AsEnumerable()
|
||
.ExceptBy(presentEmployees.Select(x => x.EmployeeId), e => e.EmployeeId).ToList();
|
||
|
||
|
||
//get today's active leaves
|
||
var employeesWithLeave = leaves.AsEnumerable()
|
||
.Where(x => absentsQuery.Any(y => y.EmployeeId == x.EmployeeId))
|
||
.Select(x => new { x.EmployeeId, x.LeaveType }).ToList();
|
||
|
||
var personnelCodesList = personnelCodes.ToList();
|
||
|
||
//join leave and absents
|
||
var absentsViewModel = absentsQuery.Select(x => new AbsentEmployeeViewModel()
|
||
{
|
||
PersonnelCode = personnelCodesList
|
||
.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?
|
||
.PersonnelCode.ToString(),
|
||
EmployeeId = x.EmployeeId,
|
||
EmployeeFullName = nameReferences.FirstOrDefault(y => x.EmployeeId == y.EmployeeId).EmployeeFullName,
|
||
HasLeave = employeesWithLeave.Any(y => y.EmployeeId == x.EmployeeId),
|
||
Reason = employeesWithLeave.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.LeaveType
|
||
}).ToList();
|
||
|
||
return new CurrentDayRollCall()
|
||
{
|
||
AbsentEmployees = absentsViewModel.ToList(),
|
||
PresentEmployees = presentEmployees
|
||
.OrderByDescending(x => x.RollCallTimesList.Any(y => string.IsNullOrWhiteSpace(y.EndDate)))
|
||
.ThenByDescending(x => x.RollCallTimesList.Max(y => y.StartDate)).ToList()
|
||
};
|
||
}
|
||
|
||
|
||
public void AddRange(List<RollCall> rollCalls)
|
||
{
|
||
_context.RollCalls.AddRange(rollCalls);
|
||
}
|
||
|
||
|
||
//تداخل مرخصی در کارپوشه
|
||
public EditRollCall GetByEmployeeIdAndWorkshopId(long employeeId, long workshopId)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
|
||
public EditRollCall GetById(long id)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
|
||
public List<OverlappedRollCallWithLeave> GetOverlappedRollCallsWithLeaveInDates(long workshopId, DateTime start,
|
||
DateTime end)
|
||
{
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
x.WorkshopId == workshopId && x.ShiftDate.Date >= start.Date && x.EndDate.HasValue &&
|
||
x.ShiftDate.Date <= end).ToList();
|
||
|
||
var leaves =
|
||
_context.LeaveList.Where(x => x.WorkshopId == workshopId && x.EndLeave >= start && x.StartLeave <= end)
|
||
.ToList();
|
||
|
||
var dailyLeaves = leaves.Where(x => x.PaidLeaveType == "روزانه").ToList();
|
||
var hourlyLeaves = leaves.Where(x => x.PaidLeaveType == "ساعتی").ToList();
|
||
|
||
var hourlyOverlappedRollCalls = rollCalls.Where(x =>
|
||
hourlyLeaves.Any(y =>
|
||
x.EmployeeId == y.EmployeeId && x.EndDate.Value >= y.StartLeave && x.StartDate.Value <= y.EndLeave));
|
||
|
||
var dailyOverlappedRollCalls = rollCalls.Where(x =>
|
||
dailyLeaves.Any(y => x.EmployeeId == y.EmployeeId && x.ShiftDate.Date == y.StartLeave.Date));
|
||
|
||
var hourlyOverlappedRollCallsResult = hourlyOverlappedRollCalls.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y => x.EmployeeId == y.EmployeeId &&
|
||
x.EndDate.Value >= y.StartLeave &&
|
||
x.StartDate.Value <= y.EndLeave);
|
||
return new OverlappedRollCallWithLeave()
|
||
{
|
||
RollCallId = x.id,
|
||
LeaveId = leave.id,
|
||
StartOfOverlapDateTime = leave.StartLeave > x.StartDate.Value ? leave.StartLeave : x.StartDate.Value,
|
||
EndOfOverlapDateTime = leave.EndLeave < x.EndDate ? leave.EndLeave : x.EndDate.Value,
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId
|
||
};
|
||
}).ToList();
|
||
|
||
var dailyOverlappedRollCallsResult = dailyOverlappedRollCalls.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y => x.EmployeeId == y.EmployeeId &&
|
||
x.ShiftDate.Date == y.StartLeave.Date);
|
||
return new OverlappedRollCallWithLeave()
|
||
{
|
||
RollCallId = x.id,
|
||
LeaveId = leave.id,
|
||
StartOfOverlapDateTime = leave.StartLeave > x.StartDate.Value ? leave.StartLeave : x.StartDate.Value,
|
||
EndOfOverlapDateTime = leave.EndLeave < x.EndDate ? leave.EndLeave : x.EndDate.Value,
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId
|
||
};
|
||
}).ToList();
|
||
|
||
var result = hourlyOverlappedRollCallsResult.Concat(dailyOverlappedRollCallsResult);
|
||
|
||
return result.Select(x => new OverlappedRollCallWithLeave()
|
||
{
|
||
RollCallId = x.RollCallId,
|
||
LeaveId = x.LeaveId,
|
||
StartOfOverlapDateTime = x.StartOfOverlapDateTime,
|
||
EndOfOverlapDateTime = x.EndOfOverlapDateTime,
|
||
StartOfOverlapDateFa = x.StartOfOverlapDateTime.ToFarsi(),
|
||
EndOfOverlapDateFa = x.EndOfOverlapDateTime.ToFarsi(),
|
||
EndOfOverlapTime = x.EndOfOverlapDateTime.ToString("HH:mm"),
|
||
StartOfOverlapTime = x.StartOfOverlapDateTime.ToString("HH:mm"),
|
||
EmployeeFullName = x.EmployeeFullName,
|
||
EmployeeId = x.EmployeeId
|
||
}).ToList();
|
||
}
|
||
|
||
|
||
public void UpdateRange(List<RollCall> rollCalls)
|
||
{
|
||
_context.RollCalls.UpdateRange(rollCalls);
|
||
}
|
||
|
||
//چون ویرایش دستی تمام حضور غیاب های یک روز را تعیین می کند
|
||
//قبل از ثبت باید حضور غیاب های شخص در آن روز پاک شود تا رکورد تکراری نداشته باشیم
|
||
//نیز پاک می شوند Undefined حضور و غیاب های
|
||
public void RemoveEmployeeRollCallsInDate(long workshopId, long employeeId, DateTime date)
|
||
{
|
||
var rollCalls = _context.RollCalls.IgnoreQueryFilters().Where(x =>
|
||
x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.ShiftDate == date.Date);
|
||
if (!rollCalls.Any())
|
||
return;
|
||
_context.RollCalls.RemoveRange(rollCalls);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// دریافت حضور و غیاب های شخص در یک روز
|
||
/// </summary>
|
||
public List<RollCallViewModel> GetWorkshopEmployeeRollCallsForDate(long workshopId, long employeeId, DateTime date)
|
||
{
|
||
var names = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId)
|
||
.Select(x => new
|
||
{
|
||
x.EmployeeId,
|
||
x.EmployeeFullName
|
||
}).ToList();
|
||
|
||
var rollcalls = _context.RollCalls
|
||
.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.ShiftDate.Date == date.Date)
|
||
.Select(x => new RollCallViewModel()
|
||
{
|
||
Id = x.id,
|
||
StartDate = x.StartDate.Value,
|
||
EndDate = x.EndDate.Value,
|
||
DateFa = x.ShiftDate.Date.ToFarsi(),
|
||
DateGr = x.ShiftDate.Date,
|
||
StartDateFa = x.StartDate.Value.ToFarsi(),
|
||
EndDateFa = x.EndDate != null ? x.EndDate.Value.ToFarsi() : null
|
||
}).ToList();
|
||
|
||
return rollcalls.Select(x => new RollCallViewModel()
|
||
{
|
||
Id = x.Id,
|
||
StartDate = x.StartDate,
|
||
EndDate = x.EndDate,
|
||
StartTimeString = x.StartDate!.Value.ToString("HH:mm"),
|
||
EndTimeString = x.EndDate?.ToString("HH:mm"),
|
||
DateFa = x.DateFa,
|
||
DateGr = x.DateGr,
|
||
StartDateFa = x.StartDateFa,
|
||
EndDateFa = x.EndDateFa,
|
||
EmployeeId = employeeId,
|
||
EmployeeFullName = names.FirstOrDefault(e => e.EmployeeId == employeeId)!.EmployeeFullName,
|
||
DayOfWeekFa = x.StartDate.Value.DayOfWeek.DayOfWeeKToPersian(),
|
||
StartDayOfWeekFa = x.StartDate.Value.DayOfWeek.DayOfWeeKToPersian(),
|
||
EndDayOfWeekFa = x.EndDate?.DayOfWeek.DayOfWeeKToPersian(),
|
||
TotalWorkingHoursSpan = x.EndDate == null ? new() : x.EndDate.Value - x.StartDate.Value
|
||
}).OrderBy(x => x.StartDate).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت حضور غیاب های غیر منقطع
|
||
/// </summary>
|
||
public IEnumerable<RollCallViewModel> GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart,
|
||
DateTime durationEnd)
|
||
{
|
||
if (durationEnd.Date >= DateTime.Now.Date)
|
||
durationEnd = DateTime.Now.AddDays(-1).Date;
|
||
|
||
var names = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId).ToList();
|
||
|
||
var rollCalls = _context.RollCalls.Where(x => x.WorkshopId == workshopId &&
|
||
x.ShiftDate.Date >= durationStart &&
|
||
x.ShiftDate.Date <= durationEnd && x.EndDate.HasValue).ToList();
|
||
if (rollCalls == null || !rollCalls.Any())
|
||
return new List<RollCallViewModel>();
|
||
return rollCalls.GroupBy(x => x.ShiftDate.Date).SelectMany(x =>
|
||
x.GroupBy(y => y.EmployeeId).Where(y => y.Count() == 1)
|
||
.SelectMany(y => y)).Select(x => new RollCallViewModel
|
||
{
|
||
Id = x.id,
|
||
StartDate = x.StartDate.Value,
|
||
EndDate = x.EndDate.Value,
|
||
EmployeeId = x.EmployeeId,
|
||
DateGr = x.ShiftDate.Date,
|
||
EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.EmployeeFullName ?? ""
|
||
});
|
||
}
|
||
|
||
|
||
public List<RollCallViewModel> GetRange(IEnumerable<long> rollCallIds)
|
||
{
|
||
var query = _context.RollCalls.Where(x => rollCallIds.Contains(x.id));
|
||
var names = _context.RollCallEmployees
|
||
.Where(x => query.Any(y => y.EmployeeId == x.EmployeeId && y.WorkshopId == x.WorkshopId)).ToList();
|
||
|
||
|
||
return query.Select(x => new RollCallViewModel
|
||
{
|
||
StartDate = x.StartDate.Value,
|
||
EndDate = x.EndDate.Value,
|
||
Id = x.id,
|
||
EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId && y.WorkshopId == x.WorkshopId)
|
||
.EmployeeFullName
|
||
}).ToList();
|
||
}
|
||
|
||
|
||
public List<RollCall> GetRangeByWorkshopIdEmployeeIdForDate(long workshopId, long employeeId,
|
||
DateTime date)
|
||
{
|
||
return _context.RollCalls.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId &&
|
||
x.ShiftDate.Date == date).ToList();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// undefined دریافت حضور و غیاب های
|
||
/// </summary>
|
||
public List<RollCallsByDateViewModel> GetUndefinedRollCallWorkFlowsInDates(long workshopId, DateTime start,
|
||
DateTime end)
|
||
{
|
||
{
|
||
var rollCalls = _context.RollCalls.IgnoreQueryFilters()
|
||
.Where(x => x.RollCallModifyType == RollCallModifyType.Undefined && x.WorkshopId == workshopId &&
|
||
x.ShiftDate.Date >= start.Date && x.ShiftDate.Date <= end.Date).ToList();
|
||
|
||
var names = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId)
|
||
.Select(x => new { x.EmployeeId, x.WorkshopId, x.EmployeeFullName }).ToList();
|
||
|
||
|
||
var result = rollCalls.GroupBy(x => x.ShiftDate.Date)
|
||
.Select(g => new RollCallsByDateViewModel()
|
||
{
|
||
DateGr = g.Key,
|
||
DateFa = g.Key.ToFarsi(),
|
||
DayOfWeekFa = g.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
ActiveEmployees = g.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeId = x.EmployeeId,
|
||
EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.EmployeeFullName ??
|
||
"",
|
||
WorkshopId = x.WorkshopId,
|
||
Id = x.id,
|
||
StartDate = x.StartDate,
|
||
EndDate = x.EndDate
|
||
})
|
||
})
|
||
.ToList();
|
||
return result;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
public long Flag(long employeeId, long workshopId)
|
||
{
|
||
var checkDate = DateTime.Now.AddDays(-5);
|
||
var query = _context.RollCalls
|
||
.Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.CreationDate >= checkDate);
|
||
if (query.Any())
|
||
{
|
||
var checkLastOne = query.OrderByDescending(x => x.StartDate).FirstOrDefault();
|
||
if (checkLastOne != null && checkLastOne.EndDate == null)
|
||
return checkLastOne.id;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
public string CheckRepeat(long employeeId, long workshopId)
|
||
{
|
||
var validSpan = new TimeSpan(0, 0, 2, 0);
|
||
var checkDate = DateTime.Now.AddDays(-3);
|
||
var query = _context.RollCalls
|
||
.Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.CreationDate >= checkDate);
|
||
|
||
if (query.Any())
|
||
{
|
||
var checkTime = DateTime.Now;
|
||
var checkLastOne = query.OrderByDescending(x => x.StartDate).FirstOrDefault();
|
||
if (checkLastOne != null && checkLastOne.EndDate == null &&
|
||
checkLastOne.RollCallModifyType == RollCallModifyType.None)
|
||
{
|
||
var checkSpan = (DateTime.Now - checkLastOne.StartDate);
|
||
if (checkSpan < validSpan)
|
||
{
|
||
return "IncomRegistred-InvalidOut";
|
||
}
|
||
}
|
||
|
||
if (checkLastOne != null && checkLastOne.EndDate != null &&
|
||
checkLastOne.RollCallModifyType == RollCallModifyType.None)
|
||
{
|
||
var checkSpan = (DateTime.Now - checkLastOne.EndDate);
|
||
if (checkSpan < validSpan)
|
||
{
|
||
return "outRegistred-InvalidIncom";
|
||
}
|
||
}
|
||
|
||
return "Valid";
|
||
}
|
||
else
|
||
{
|
||
return "Valid";
|
||
}
|
||
//test
|
||
}
|
||
|
||
|
||
public RollCallViewModel GetDetails(long rollCallId)
|
||
{
|
||
var entity = _context.RollCalls.FirstOrDefault(x => x.id == rollCallId);
|
||
if (entity == null)
|
||
return null;
|
||
var name = _context.RollCallEmployees
|
||
.FirstOrDefault(x => x.WorkshopId == entity.WorkshopId && x.EmployeeId == entity.EmployeeId)
|
||
.EmployeeFullName;
|
||
return new RollCallViewModel
|
||
{
|
||
WorkshopId = entity.WorkshopId,
|
||
EmployeeId = entity.EmployeeId,
|
||
StartDate = entity.StartDate.Value,
|
||
EndDate = entity.EndDate.Value,
|
||
EmployeeFullName = name,
|
||
Id = entity.id,
|
||
DateGr = entity.ShiftDate.Date
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// برای پرینت سوابق حضور و غیاب
|
||
/// </summary>
|
||
public EmployeeRollCallsByMonthViewModel GetEmployeeRollCallsHistoryForPrint(long employeeId, long workshopId,
|
||
DateTime firstRollCallToPrintStartDate, DateTime lastRollCallToPrintStartDate)
|
||
{
|
||
var selectedMonthPersian =
|
||
(new PersianCalendar()).GetMonth(firstRollCallToPrintStartDate).ToFarsiMonthByIntNumber();
|
||
var selectedYearPersian = (new PersianCalendar()).GetYear(firstRollCallToPrintStartDate);
|
||
var rollCallsList = _context.RollCalls.Where(x =>
|
||
x.EmployeeId == employeeId && x.WorkshopId == workshopId &&
|
||
x.ShiftDate.Date >= firstRollCallToPrintStartDate.Date &&
|
||
x.ShiftDate.Date <= lastRollCallToPrintStartDate.Date).ToList();
|
||
|
||
var employeeName = _context.Employees.FirstOrDefault(x => x.id == employeeId).FullName;
|
||
|
||
var personnelCode =
|
||
_context.PersonnelCodeSet.FirstOrDefault(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId);
|
||
|
||
var statuses = _context.RollCallEmployeesStatus.Include(x => x.RollCallEmployee)
|
||
.Where(x => x.RollCallEmployee.EmployeeId == employeeId && x.RollCallEmployee.WorkshopId == workshopId)
|
||
.ToList();
|
||
|
||
var leavesList = _context.LeaveList.Where(x =>
|
||
x.EmployeeId == employeeId && x.WorkshopId == workshopId &&
|
||
x.EndLeave.Date >= firstRollCallToPrintStartDate.Date &&
|
||
x.StartLeave.Date <= lastRollCallToPrintStartDate.AddDays(2)).ToList();
|
||
|
||
//if (rollCallsList.Count < 1)
|
||
// return new();
|
||
|
||
int dateRange = (int)(lastRollCallToPrintStartDate - firstRollCallToPrintStartDate).TotalDays + 1;
|
||
|
||
|
||
var completeDaysList = Enumerable.Range(0, dateRange)
|
||
.Select(offset => firstRollCallToPrintStartDate.AddDays(offset).Date);
|
||
|
||
var result = completeDaysList.Where(x =>
|
||
!rollCallsList.Any(y => y.ShiftDate.Date == x.Date && y.EndDate == null) &&
|
||
statuses.Any(y => x >= y.StartDate.Date && x <= y.EndDate.Date))
|
||
.Select(x =>
|
||
{
|
||
var leave = leavesList.FirstOrDefault(y => y.EndLeave >= x.Date && y.StartLeave <= x.Date);
|
||
return new RollCallViewModel()
|
||
{
|
||
DateGr = x.Date,
|
||
DateFa = x.Date.ToFarsi(),
|
||
RollCallTimesList = rollCallsList.Where(y => x.Date == y.StartDate!.Value.Date).Select(y =>
|
||
new RollCallTimeViewModel()
|
||
{
|
||
StartDate = y.StartDate.Value.ToString("HH:mm"),
|
||
EndDate = y.EndDate!.Value.ToString("HH:mm"),
|
||
StartDateGr = y.StartDate.Value,
|
||
EndDateGr = y.EndDate.Value,
|
||
EntryTimeDifferences =
|
||
CalculateEntryTimeDifferences(y.EarlyEntryDuration, y.LateEntryDuration),
|
||
ExitTimeDifferences = CalculateExitTimeDifferences(y.EarlyExitDuration, y.LateExitDuration)
|
||
}),
|
||
TotalWorkingHoursSpan = new TimeSpan(rollCallsList.Where(y => x.Date == y.ShiftDate.Date)
|
||
.Sum(y => (y.EndDate!.Value - y.StartDate.Value).Ticks)),
|
||
Reason = leave?.LeaveType ?? "",
|
||
HasLeave = (leave?.PaidLeaveType == "روزانه" || leave?.LeaveType == "استعلاجی") ? true : false
|
||
};
|
||
});
|
||
result = result.Select(x => new RollCallViewModel()
|
||
{
|
||
EmployeeFullName = employeeName,
|
||
EmployeeId = employeeId,
|
||
PersonnelCode = personnelCode.PersonnelCode.ToString(),
|
||
DateGr = x.DateGr,
|
||
DateFa = x.DateFa,
|
||
DayOfWeekFa = x.DateGr.DayOfWeek.DayOfWeeKToPersian(),
|
||
IsHoliday = _holidayItemApplication.IsHoliday(x.DateGr),
|
||
IsAbsent = !x.RollCallTimesList.Any(),
|
||
RollCallTimesList = x.RollCallTimesList,
|
||
HasLeave = x.HasLeave,
|
||
TotalWorkingHoursSpan = x.TotalWorkingHoursSpan,
|
||
TotalWorkingHours =
|
||
$"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}"
|
||
}).ToList();
|
||
var totalWorkingHours = new TimeSpan(result.Sum(x => x.TotalWorkingHoursSpan.Ticks));
|
||
|
||
return new EmployeeRollCallsByMonthViewModel()
|
||
{
|
||
PersianMonthName = selectedMonthPersian,
|
||
PersianYear = selectedYearPersian.ToString(),
|
||
DateGr = firstRollCallToPrintStartDate.AddMonthsFa(0, out _).ToGeorgianDateTime(),
|
||
RollCalls = result.OrderByDescending(x => x.DateGr),
|
||
TotalWorkingHours = totalWorkingHours.ToFarsiHoursAndMinutes(),
|
||
|
||
TotalWorkingHoursTimeSpan = $"{(int)totalWorkingHours.TotalHours}:{totalWorkingHours.Minutes:00}"
|
||
};
|
||
}
|
||
|
||
public List<RollCallViewModel> GetWorkshopEmployeeRollCallsWithUndefinedForDate(long workshopId, long employeeId,
|
||
DateTime date)
|
||
{
|
||
var names = _context.RollCallEmployees.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId)
|
||
.Select(x => new
|
||
{
|
||
x.EmployeeId,
|
||
x.EmployeeFullName
|
||
}).ToList();
|
||
|
||
var rollcalls = _context.RollCalls.IgnoreQueryFilters()
|
||
.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.ShiftDate.Date == date.Date)
|
||
.Select(x => new RollCallViewModel()
|
||
{
|
||
Id = x.id,
|
||
StartDate = x.StartDate.Value,
|
||
EndDate = x.EndDate.Value,
|
||
DateFa = x.ShiftDate.Date.ToFarsi(),
|
||
DateGr = x.ShiftDate.Date,
|
||
StartDateFa = x.StartDate.Value.ToFarsi(),
|
||
EndDateFa = x.EndDate != null ? x.EndDate.Value.ToFarsi() : null
|
||
}).ToList();
|
||
return rollcalls.Select(x => new RollCallViewModel()
|
||
{
|
||
Id = x.Id,
|
||
StartDate = x.StartDate,
|
||
EndDate = x.EndDate,
|
||
StartTimeString = x.StartDate!.Value.ToString("HH:mm"),
|
||
EndTimeString = x.EndDate?.ToString("HH:mm"),
|
||
DateFa = x.DateFa,
|
||
DateGr = x.DateGr,
|
||
StartDateFa = x.StartDateFa,
|
||
EndDateFa = x.EndDateFa,
|
||
EmployeeId = employeeId,
|
||
EmployeeFullName = names.FirstOrDefault(e => e.EmployeeId == employeeId)!.EmployeeFullName,
|
||
DayOfWeekFa = x.StartDate.Value.DayOfWeek.DayOfWeeKToPersian(),
|
||
StartDayOfWeekFa = x.StartDate.Value.DayOfWeek.DayOfWeeKToPersian(),
|
||
EndDayOfWeekFa = x.EndDate?.DayOfWeek.DayOfWeeKToPersian(),
|
||
TotalWorkingHoursSpan = x.EndDate == null ? new() : x.EndDate.Value - x.StartDate.Value
|
||
}).ToList();
|
||
}
|
||
|
||
public void RemoveEmployeeRollCallsWithUndefinedInDate(long workshopId, long employeeId, DateTime date)
|
||
{
|
||
var rollCalls = _context.RollCalls.IgnoreQueryFilters().Where(x =>
|
||
x.WorkshopId == workshopId && x.EmployeeId == employeeId && x.ShiftDate == date.Date);
|
||
if (!rollCalls.Any())
|
||
return;
|
||
_context.RollCalls.RemoveRange(rollCalls);
|
||
}
|
||
|
||
public List<PersonnelCheckoutDailyRollCallViewModel> GetEmployeeRollCallsForCustomizeCheckoutTemp(
|
||
IEnumerable<long> customizeCheckoutIds, long workshopId)
|
||
{
|
||
//if (workshopId == 170)
|
||
// return GetEmployeeRollCallsInDatesForKababMahdi(employeeIds, workshopId, start, end);
|
||
|
||
|
||
var checkoutJoinEmployee = _context.CustomizeCheckoutTemps.Where(x => customizeCheckoutIds.Contains(x.id))
|
||
.Join(_context.Employees,
|
||
(customizeCheckout) => customizeCheckout.EmployeeId,
|
||
(employee) => employee.id,
|
||
((customizeCheckout, employee) => new { customizeCheckout, employee })).Select(x => new
|
||
{
|
||
CustomizeCheckoutId = x.customizeCheckout.id,
|
||
CheckoutStart = x.customizeCheckout.ContractStart,
|
||
CheckoutEnd = x.customizeCheckout.ContractEnd,
|
||
EmployeeId = x.employee.id,
|
||
}).ToList();
|
||
|
||
List<PersonnelCheckoutDailyRollCallViewModel> result = new();
|
||
PersianCalendar pc = new();
|
||
foreach (var join in checkoutJoinEmployee)
|
||
{
|
||
var start = join.CheckoutStart;
|
||
var end = join.CheckoutEnd;
|
||
var employeeId = join.EmployeeId;
|
||
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
employeeId == x.EmployeeId && workshopId == x.WorkshopId && x.StartDate != null &&
|
||
x.EndDate != null && x.ShiftDate.Date >= start && x.ShiftDate.Date <= end).ToList();
|
||
|
||
var leaves = _context.LeaveList.Where(x =>
|
||
x.WorkshopId == workshopId && employeeId == x.EmployeeId && x.EndLeave.Date >= start.Date &&
|
||
x.StartLeave.Date <= end.Date && x.PaidLeaveType == "روزانه").ToList();
|
||
|
||
|
||
var employeeSettingsList =
|
||
_context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().Where(x => x.WorkshopId == workshopId)
|
||
.ToList();
|
||
|
||
var endOfMonth = start.AddMonthsFa(1, out _).ToGeorgianDateTime().Date.AddTicks(-1);
|
||
int dateRange = (int)(endOfMonth.Date - start).TotalDays + 1;
|
||
|
||
var completeDaysList = Enumerable.Range(0, dateRange).Select(offset => start.AddDays(offset).Date).ToList();
|
||
var holidays = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = start.ToFarsiYear()
|
||
});
|
||
|
||
var settings = employeeSettingsList.FirstOrDefault(x => x.EmployeeId == employeeId);
|
||
var birthDay = _context.Employees.Where(x => x.id == employeeId).Select(x => x.DateOfBirth).First();
|
||
var worksInFriday = settings.FridayWork != FridayWork.Default;
|
||
var worksInHolidays = settings.HolidayWork != HolidayWork.Default;
|
||
var absentRecords = completeDaysList.Where(x =>
|
||
!rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date))
|
||
.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y =>
|
||
y.EmployeeId == employeeId && y.EndLeave.Date >= x.Date && y.StartLeave.Date <= x.Date);
|
||
var isHoliday = holidays.Any(y => y.HolidaydateGr == x.Date);
|
||
var isFriday = x.Date.DayOfWeek == DayOfWeek.Friday;
|
||
var isNormalWorkingDay = isHoliday == false && isFriday == false;
|
||
var isInContractRange = x <= end && x >= start;
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = null,
|
||
EndDate1 = null,
|
||
DateTimeGr = x.Date.Date,
|
||
DayOfWeek = x.Date.DayOfWeek.ToString(),
|
||
RollCallDateFa = x.Date.ToFarsi(),
|
||
LeaveType = leave != null ? leave.LeaveType : "",
|
||
IsAbsent = leave == null && isInContractRange && (isNormalWorkingDay ||
|
||
(worksInFriday && x.Date.DayOfWeek ==
|
||
DayOfWeek.Friday) ||
|
||
(worksInHolidays && isHoliday)),
|
||
};
|
||
});
|
||
|
||
var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date)
|
||
.Select(x =>
|
||
{
|
||
var orderedRollcalls = x.OrderBy(y => y.ShiftDate).ToList();
|
||
var firstRollCall = orderedRollcalls.FirstOrDefault();
|
||
var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault();
|
||
//این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت
|
||
//منطق کباب مهدی!!!!
|
||
|
||
#region SecondTimeDiff
|
||
|
||
var hasSecondTimeDiff = false;
|
||
if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating)
|
||
{
|
||
if (firstRollCall != null && secondRollCall != null)
|
||
{
|
||
var firstShift = FindRotatingShift(firstRollCall.StartDate.Value,
|
||
firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
var secondShift = FindRotatingShift(secondRollCall.StartDate.Value,
|
||
secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
if (firstShift.start == secondShift.start && firstShift.end == secondShift.end)
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = firstRollCall?.StartDate?.ToString("HH:mm"),
|
||
EndDate1 = firstRollCall?.EndDate?.ToString("HH:mm"),
|
||
|
||
StartDate2 = secondRollCall?.StartDate?.ToString("HH:mm") ?? "",
|
||
EndDate2 = secondRollCall?.EndDate?.ToString("HH:mm") ?? "",
|
||
|
||
|
||
TotalhourseSpan =
|
||
new TimeSpan(x.Where(y => y.EndDate != null)
|
||
.Sum(y => (y.EndDate - y.StartDate)!.Value.Ticks)),
|
||
DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
RollCallDateFa = x.Key.Date.ToFarsi(),
|
||
DateTimeGr = x.Key.Date,
|
||
IsSliced = x.Count() > 2,
|
||
IsAbsent = false,
|
||
|
||
EnterDifferencesMinutes1 =
|
||
firstRollCall != null && firstRollCall.LateEntryDuration > TimeSpan.Zero
|
||
? CalculateEntryMinuteDifference(firstRollCall.EarlyEntryDuration,
|
||
firstRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes1 =
|
||
firstRollCall != null && firstRollCall.EarlyExitDuration > TimeSpan.Zero
|
||
? CalculateExitMinuteDifference(firstRollCall.EarlyExitDuration,
|
||
firstRollCall.LateExitDuration)
|
||
: "",
|
||
|
||
EnterDifferencesMinutes2 = secondRollCall != null &&
|
||
secondRollCall.LateEntryDuration > TimeSpan.Zero && hasSecondTimeDiff
|
||
? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration,
|
||
secondRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes2 = secondRollCall != null &&
|
||
secondRollCall.EarlyExitDuration > TimeSpan.Zero && hasSecondTimeDiff
|
||
? CalculateExitMinuteDifference(secondRollCall.EarlyExitDuration,
|
||
secondRollCall.LateExitDuration)
|
||
: ""
|
||
};
|
||
});
|
||
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
|
||
{
|
||
StartDate1 = x.StartDate1,
|
||
EndDate1 = x.EndDate1,
|
||
EndDate2 = x.EndDate2,
|
||
StartDate2 = x.StartDate2,
|
||
TotalWorkingHours = $"{(int)(x.TotalhourseSpan.TotalHours)}:{x.TotalhourseSpan.Minutes.ToString("00")}",
|
||
DayOfWeek = x.DayOfWeek,
|
||
RollCallDateFa = x.RollCallDateFa,
|
||
DateTimeGr = x.DateTimeGr,
|
||
IsSliced = x.IsSliced,
|
||
IsAbsent = false,
|
||
EnterDifferencesMinutes1 = x.EnterDifferencesMinutes1,
|
||
EnterDifferencesMinutes2 = x.EnterDifferencesMinutes2,
|
||
ExitDifferencesMinutes1 = x.ExitDifferencesMinutes1,
|
||
ExitDifferencesMinutes2 = x.ExitDifferencesMinutes2
|
||
});
|
||
|
||
List<CheckoutDailyRollCallViewModel> checkoutDailyRollCalls =
|
||
presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
|
||
|
||
checkoutDailyRollCalls.ForEach(x =>
|
||
{
|
||
x.IsFriday = x.DateTimeGr.DayOfWeek == DayOfWeek.Friday;
|
||
x.IsHoliday = holidays.Any(y => y.HolidaydateGr == x.DateTimeGr);
|
||
x.IsBirthDay = workshopId == 170 && pc.GetMonth(x.DateTimeGr) == pc.GetMonth(birthDay) &&
|
||
pc.GetDayOfMonth(x.DateTimeGr) == pc.GetDayOfMonth(birthDay);
|
||
});
|
||
|
||
var resultItem = new PersonnelCheckoutDailyRollCallViewModel()
|
||
{
|
||
EmployeeId = employeeId,
|
||
WorkshopId = workshopId,
|
||
DailyRollCalls = checkoutDailyRollCalls
|
||
};
|
||
result.Add(resultItem);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
public async Task<List<RollCall>> GetRollCallsInShiftDate(DateTime rollCallShiftDate, long employeeId,
|
||
long workshopId)
|
||
{
|
||
return await _context.RollCalls.Where(x =>
|
||
x.ShiftDate.Date == rollCallShiftDate.Date && x.WorkshopId == workshopId && x.EmployeeId == employeeId)
|
||
.ToListAsync();
|
||
}
|
||
|
||
//حضور غیاب گروهی از پرسنل برای پرینت گروهی فیش حقوقی غیر رسمی نهایی
|
||
public List<PersonnelCheckoutDailyRollCallViewModel> GetEmployeeRollCallsForMonthForKababMahdi(
|
||
IEnumerable<long> employeeIds, long workshopId, DateTime start, DateTime end)
|
||
{
|
||
var rollCalls = _context.RollCalls.Where(x =>
|
||
employeeIds.Contains(x.EmployeeId) && workshopId == x.WorkshopId && x.StartDate != null &&
|
||
x.EndDate != null && x.RollCallModifyType != RollCallModifyType.Undefined &&
|
||
x.ShiftDate.Date >= start && x.ShiftDate.Date <= end).ToList();
|
||
|
||
var leaves = _context.LeaveList.Where(x =>
|
||
x.WorkshopId == workshopId && employeeIds.Contains(x.EmployeeId) && x.EndLeave.Date >= start.Date &&
|
||
x.StartLeave.Date <= end.Date).ToList();
|
||
|
||
var employees = _context.Employees.Where(x => employeeIds.Contains(x.id))
|
||
.Select(x => new { Id = x.id, x.DateOfBirth }).ToList();
|
||
var year = Convert.ToInt32(start.ToFarsi().Substring(0, 4));
|
||
var month = Convert.ToInt32(start.ToFarsi().Substring(5, 2));
|
||
var firstDayOfCurrentMonth = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
|
||
if (month == 12)
|
||
{
|
||
year += 1;
|
||
month = 1;
|
||
}
|
||
else
|
||
month += 1;
|
||
|
||
var nextMonthDate = new DateTime(year, month, 1, new PersianCalendar());
|
||
|
||
var lastDayOfCurrentMonth = nextMonthDate.AddDays(-1);
|
||
|
||
int dateRange = (int)(lastDayOfCurrentMonth - firstDayOfCurrentMonth).TotalDays + 1;
|
||
var employeeSettingsList =
|
||
_context.CustomizeWorkshopEmployeeSettings.AsSplitQuery().Where(x => x.WorkshopId == workshopId).ToList();
|
||
var holidays = _holidayItemApplication.Search(new HolidayItemSearchModel()
|
||
{
|
||
HolidayYear = start.ToFarsiYear()
|
||
});
|
||
//all the dates from start to end, to be compared with present days to get absent dates
|
||
var completeDaysList = Enumerable.Range(0, dateRange).Select(offset => start.AddDays(offset).Date).ToList();
|
||
PersianCalendar pc = new();
|
||
|
||
List<PersonnelCheckoutDailyRollCallViewModel> result = new();
|
||
foreach (var employeeId in employeeIds)
|
||
{
|
||
var settings = employeeSettingsList.FirstOrDefault(x => x.EmployeeId == employeeId);
|
||
var worksInFriday = settings.FridayWork != FridayWork.Default;
|
||
var worksInHolidays = settings.HolidayWork != HolidayWork.Default;
|
||
var birthDay = employees.First(x => x.Id == employeeId).DateOfBirth;
|
||
var absentRecords = completeDaysList.Where(x =>
|
||
!rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date))
|
||
.Select(x =>
|
||
{
|
||
var leave = leaves.FirstOrDefault(y =>
|
||
y.EmployeeId == employeeId && y.EndLeave.Date >= x.Date && y.StartLeave.Date <= x.Date);
|
||
var isHoliday = holidays.Any(y => y.HolidaydateGr == x.Date);
|
||
var isFriday = x.Date.DayOfWeek == DayOfWeek.Friday;
|
||
var isBirthday = pc.GetMonth(x) == pc.GetMonth(birthDay) &&
|
||
pc.GetDayOfMonth(x) == pc.GetDayOfMonth(birthDay);
|
||
var isNormalWorkingDay = isHoliday == false && isFriday == false;
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = null,
|
||
EndDate1 = null,
|
||
DateTimeGr = x.Date,
|
||
DayOfWeek = x.Date.DayOfWeek.ToString(),
|
||
RollCallDateFa = x.Date.ToFarsi(),
|
||
LeaveType = leave != null ? leave.LeaveType : "",
|
||
IsAbsent = leave == null && (isNormalWorkingDay ||
|
||
(worksInFriday && x.Date.DayOfWeek == DayOfWeek.Friday) ||
|
||
(worksInHolidays && isHoliday)),
|
||
IsBirthDay = isBirthday
|
||
};
|
||
});
|
||
var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date)
|
||
.Select(x =>
|
||
{
|
||
var orderedRollcalls = x.OrderBy(y => y.StartDate!.Value).ToList();
|
||
var firstRollCall = orderedRollcalls.FirstOrDefault();
|
||
var secondRollCall = orderedRollcalls.Skip(1).FirstOrDefault();
|
||
|
||
//این برای این هست که ببینه اگر که این شخص گردشی بوده و دوبار وارد در دو شیفت مختلف وارد شده شیفت دوم تاثیر نخواهد گذاشت
|
||
//منطق کباب مهدی!!!!
|
||
|
||
#region SecondTimeDiff
|
||
|
||
var hasSecondTimeDiff = false;
|
||
if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating)
|
||
{
|
||
if (firstRollCall != null && secondRollCall != null)
|
||
{
|
||
var firstShift = FindRotatingShift(firstRollCall.StartDate.Value,
|
||
firstRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
var secondShift = FindRotatingShift(secondRollCall.StartDate.Value,
|
||
secondRollCall.EndDate.Value, settings.CustomizeRotatingShifts);
|
||
if (firstShift.start == secondShift.start && firstShift.end == secondShift.end)
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hasSecondTimeDiff = true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
return new CheckoutDailyRollCallViewModel()
|
||
{
|
||
StartDate1 = orderedRollcalls.FirstOrDefault()?.StartDate?.ToString("HH:mm"),
|
||
EndDate1 = orderedRollcalls.FirstOrDefault()?.EndDate?.ToString("HH:mm"),
|
||
|
||
StartDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.StartDate?.ToString("HH:mm") ?? "",
|
||
EndDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.EndDate?.ToString("HH:mm") ?? "",
|
||
|
||
TotalhourseSpan =
|
||
new TimeSpan(x.Where(y => y.EndDate != null)
|
||
.Sum(y => (y.EndDate - y.StartDate)!.Value.Ticks)),
|
||
DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(),
|
||
RollCallDateFa = x.Key.Date.ToFarsi(),
|
||
DateTimeGr = x.Key.Date,
|
||
IsSliced = x.Count() > 2,
|
||
IsAbsent = false,
|
||
IsBirthDay = pc.GetMonth(x.Key) == pc.GetMonth(birthDay) &&
|
||
pc.GetDayOfMonth(x.Key) == pc.GetDayOfMonth(birthDay),
|
||
|
||
EnterDifferencesMinutes1 = firstRollCall != null &&
|
||
firstRollCall.LateEntryDuration > TimeSpan.Zero && workshopId == 170
|
||
? CalculateEntryMinuteDifference(firstRollCall.EarlyEntryDuration,
|
||
firstRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes1 = "",
|
||
|
||
EnterDifferencesMinutes2 = secondRollCall != null &&
|
||
secondRollCall.LateEntryDuration > TimeSpan.Zero &&
|
||
workshopId == 170 && hasSecondTimeDiff
|
||
? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration,
|
||
secondRollCall.LateEntryDuration)
|
||
: "",
|
||
ExitDifferencesMinutes2 = ""
|
||
};
|
||
});
|
||
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
|
||
{
|
||
StartDate1 = x.StartDate1,
|
||
EndDate1 = x.EndDate1,
|
||
EndDate2 = x.EndDate2,
|
||
StartDate2 = x.StartDate2,
|
||
TotalWorkingHours = $"{(int)(x.TotalhourseSpan.TotalHours)}:{x.TotalhourseSpan.Minutes.ToString("00")}",
|
||
DayOfWeek = x.DayOfWeek,
|
||
RollCallDateFa = x.RollCallDateFa,
|
||
DateTimeGr = x.DateTimeGr,
|
||
IsSliced = x.IsSliced,
|
||
IsAbsent = false,
|
||
IsBirthDay = x.IsBirthDay,
|
||
EnterDifferencesMinutes1 = x.EnterDifferencesMinutes1,
|
||
ExitDifferencesMinutes1 = x.ExitDifferencesMinutes1,
|
||
EnterDifferencesMinutes2 = x.EnterDifferencesMinutes2,
|
||
ExitDifferencesMinutes2 = x.ExitDifferencesMinutes2,
|
||
});
|
||
|
||
|
||
List<CheckoutDailyRollCallViewModel> checkoutDailyRollCalls =
|
||
presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
|
||
|
||
checkoutDailyRollCalls.ForEach(x =>
|
||
{
|
||
x.IsFriday = x.DateTimeGr.DayOfWeek == DayOfWeek.Friday;
|
||
x.IsHoliday = holidays.Any(y => y.HolidaydateGr == x.DateTimeGr);
|
||
});
|
||
var resultItem = new PersonnelCheckoutDailyRollCallViewModel()
|
||
{
|
||
EmployeeId = employeeId,
|
||
WorkshopId = workshopId,
|
||
DailyRollCalls = checkoutDailyRollCalls
|
||
};
|
||
result.Add(resultItem);
|
||
}
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
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 oneHourBeforeStart = startEntryWithDate.AddHours(-1);
|
||
DateTime oneHourAfterStart = startEntryWithDate.AddHours(1);
|
||
DateTime oneHourBeforeEnd = endEntryWithDate.AddHours(-1);
|
||
DateTime oneHourAfterEnd = endEntryWithDate.AddHours(1);
|
||
|
||
|
||
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 =>
|
||
(oneHourBeforeStart <= shift.Start && oneHourAfterStart >= shift.Start) ||
|
||
(oneHourBeforeStart <= shift.End && oneHourAfterStart >= 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 =>
|
||
(oneHourBeforeEnd <= shift.Start && oneHourAfterEnd >= shift.Start) ||
|
||
(oneHourBeforeEnd <= shift.End && oneHourAfterEnd >= shift.End)).ToList();
|
||
if (endFilteredTimes.Count == 0)
|
||
{
|
||
endFilteredTimes = startFilteredTimes;
|
||
}
|
||
else if (endFilteredTimes.Count == 1)
|
||
{
|
||
var endChosenShift = endFilteredTimes.First();
|
||
return endChosenShift;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region اشتراک حضور غیاب و شیفت
|
||
|
||
var overlapShifts = endFilteredTimes.Select(shift => new
|
||
{
|
||
Shift = shift,
|
||
Overlap = new TimeSpan(Math.Max(0,
|
||
Math.Min(shift.End.Ticks, oneHourAfterEnd.Ticks) -
|
||
Math.Max(shift.Start.Ticks, oneHourBeforeStart.Ticks)))
|
||
});
|
||
|
||
var overlapChosenShift = overlapShifts.MaxBy(s => s.Overlap);
|
||
var end = overlapChosenShift.Shift.End;
|
||
if (overlapChosenShift.Shift.End < overlapChosenShift.Shift.Start)
|
||
end = overlapChosenShift.Shift.End.AddDays(1);
|
||
|
||
|
||
return (overlapChosenShift.Shift.Start, end);
|
||
|
||
#endregion
|
||
}
|
||
|
||
public async Task<List<RollCall>> GetRollCallsUntilNowWithWorkshopIdEmployeeIds(long workshopId,
|
||
List<long> employeeIds, DateTime fromDate)
|
||
{
|
||
return await _context.RollCalls.Where(x =>
|
||
x.ShiftDate >= fromDate && x.WorkshopId == workshopId && employeeIds.Contains(x.EmployeeId) &&
|
||
x.EndDate != null).ToListAsync();
|
||
}
|
||
|
||
public async Task<PagedResult<RollCallCaseHistoryTitleDto>> GetCaseHistoryTitles(long workshopId,
|
||
RollCallCaseHistorySearchModel searchModel)
|
||
{
|
||
var yesterday = DateTime.Now.AddDays(-1).Date;
|
||
|
||
var groupByMonth = false;
|
||
var rollCallStatusQuery = _context.RollCallEmployeesStatus
|
||
.Where(x => x.RollCallEmployee.WorkshopId == workshopId);
|
||
|
||
if (searchModel.EmployeeId is > 0)
|
||
{
|
||
rollCallStatusQuery =
|
||
rollCallStatusQuery.Where(x => x.RollCallEmployee.EmployeeId == searchModel.EmployeeId);
|
||
groupByMonth = true;
|
||
}
|
||
|
||
|
||
var startDateNullable = (await rollCallStatusQuery
|
||
.OrderBy(x => x.StartDate).FirstOrDefaultAsync())?.StartDate;
|
||
var endDateNullable = (await rollCallStatusQuery
|
||
.OrderByDescending(x => x.EndDate).FirstOrDefaultAsync())?.EndDate;
|
||
|
||
if (!startDateNullable.HasValue || !endDateNullable.HasValue)
|
||
{
|
||
return new PagedResult<RollCallCaseHistoryTitleDto>();
|
||
}
|
||
|
||
var startDate = startDateNullable.Value.Date;
|
||
var endDate = endDateNullable.Value.Date;
|
||
if (endDate.Date > yesterday)
|
||
{
|
||
endDate = yesterday;
|
||
}
|
||
|
||
var dateRange = (int)(endDate - startDate).TotalDays + 1;
|
||
|
||
var dates = Enumerable.Range(0, dateRange)
|
||
.Select(offset => startDate.AddDays(offset)).OrderByDescending(x => x).ToList();
|
||
|
||
if (!string.IsNullOrWhiteSpace(searchModel.OneDayDate))
|
||
{
|
||
var date = searchModel.OneDayDate.ToGeorgianDateTime();
|
||
|
||
dates = dates
|
||
.Where(x => x.Date == date.Date).ToList();
|
||
}
|
||
else if (!string.IsNullOrWhiteSpace(searchModel.StartDate)
|
||
&& !string.IsNullOrWhiteSpace(searchModel.EndDate))
|
||
{
|
||
var start = searchModel.StartDate.ToGeorgianDateTime();
|
||
var end = searchModel.EndDate.ToGeorgianDateTime();
|
||
|
||
dates = dates
|
||
.Where(x => x <= end && x >= start).ToList();
|
||
}
|
||
|
||
List<RollCallCaseHistoryTitleDto> rollCallCaseHistoryTitles;
|
||
if (groupByMonth)
|
||
{
|
||
var persianDates = dates
|
||
.Select(x => new PersianTools.Core.PersianDateTime(x)).ToList();
|
||
rollCallCaseHistoryTitles = persianDates.GroupBy(x => (x.Year, x.Month))
|
||
.Select(x => new RollCallCaseHistoryTitleDto()
|
||
{
|
||
Id = $"{x.Key.Year}_{x.Key.Month}",
|
||
Title = $"{x.Key.Year} {x.Key.Month.ToFarsiMonthByIntNumber()}"
|
||
}).ToList();
|
||
}
|
||
else
|
||
{
|
||
rollCallCaseHistoryTitles = dates
|
||
.Select(x => new RollCallCaseHistoryTitleDto()
|
||
{
|
||
Id = x.ToFarsi(),
|
||
Title = $"{x.ToFarsi()} {x.DayOfWeek.DayOfWeeKToPersian()}"
|
||
}).ToList();
|
||
}
|
||
|
||
|
||
var res = new PagedResult<RollCallCaseHistoryTitleDto>()
|
||
{
|
||
List = rollCallCaseHistoryTitles,
|
||
TotalCount = rollCallCaseHistoryTitles.Count
|
||
};
|
||
return res;
|
||
}
|
||
|
||
public async Task<List<RollCallCaseHistoryDetail>> GetCaseHistoryDetails(long workshopId, string titleId,
|
||
RollCallCaseHistorySearchModel searchModel)
|
||
{
|
||
var query = _context.RollCallEmployeesStatus
|
||
.Include(x => x.RollCallEmployee)
|
||
.Where(x => x.RollCallEmployee.WorkshopId == workshopId);
|
||
|
||
DateTime startDate;
|
||
DateTime endDate;
|
||
//این برای این هست که اگر بر اساس پرسنل جستجو شده بود و در titleId اگر به فرمت YYYY_MM اومد به این معنی هست که باید بر طبق ماه فیلتر بشه نه به صورت روزانه
|
||
if (searchModel.EmployeeId is > 0)
|
||
{
|
||
if (!Regex.IsMatch(titleId, @"^\d{4}_\d{2}$"))
|
||
throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است");
|
||
|
||
var splitDate = titleId.Split("_");
|
||
var year = Convert.ToInt32(splitDate.First());
|
||
var month = Convert.ToInt32(splitDate.Last());
|
||
|
||
var startDateFa = $"{year:D4}/{month:D2}/01";
|
||
if (!startDateFa.TryToGeorgianDateTime(out startDate))
|
||
{
|
||
throw new BadRequestException("تاریخ وارد شده نامعتبر است");
|
||
}
|
||
|
||
var endDateFa = startDateFa.FindeEndOfMonth();
|
||
|
||
if (!endDateFa.TryToGeorgianDateTime(out endDate))
|
||
{
|
||
throw new BadRequestException("تاریخ وارد شده نامعتبر است");
|
||
}
|
||
query = query
|
||
.Where(x => x.RollCallEmployee.EmployeeId == searchModel.EmployeeId);
|
||
}
|
||
else
|
||
{
|
||
if (!Regex.IsMatch(titleId, @"^\d{4}/\d{2}/\d{2}$"))
|
||
throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است");
|
||
|
||
|
||
startDate = titleId.ToGeorgianDateTime();
|
||
endDate = startDate;
|
||
}
|
||
query = query.Where(x => x.StartDate <= endDate && x.EndDate >= startDate);
|
||
|
||
var employeeIds = await query.Select(x => x.RollCallEmployee.EmployeeId).ToListAsync();
|
||
|
||
var rollCalls = await _context.RollCalls
|
||
.Where(x => x.WorkshopId == workshopId && employeeIds.Contains(x.EmployeeId)
|
||
&& startDate <= x.ShiftDate && endDate >= x.ShiftDate).ToListAsync();
|
||
|
||
var leaves = await _context.LeaveList.Where(x => x.WorkshopId == workshopId
|
||
&& employeeIds.Contains(x.EmployeeId) &&
|
||
x.StartLeave >= endDate && x.EndLeave <= startDate)
|
||
.ToListAsync();
|
||
var dateRange = (int)(endDate - startDate).TotalDays + 1;
|
||
|
||
var dates = Enumerable.Range(0, dateRange).Select(x => startDate.AddDays(x)).ToList();
|
||
|
||
var employees = await _context.Employees.Where(x => employeeIds
|
||
.Contains(x.id)).ToListAsync();
|
||
|
||
var personnelCodes = await _context.PersonnelCodeSet
|
||
.Where(x => x.WorkshopId == workshopId
|
||
&& employeeIds.Contains(x.EmployeeId)).ToListAsync();
|
||
|
||
var res = new List<RollCallCaseHistoryDetail>();
|
||
foreach (var date in dates)
|
||
{
|
||
var rollCallInDate = rollCalls
|
||
.Where(x => x.ShiftDate.Date == date.Date).ToList();
|
||
foreach (var employeeId in employeeIds)
|
||
{
|
||
var leave = leaves.FirstOrDefault(y => y.EmployeeId == employeeId);
|
||
var employeeRollCallsForDate = rollCallInDate
|
||
.Where(y => y.EmployeeId == employeeId).ToList();
|
||
var employee = employees.FirstOrDefault(x => x.id == employeeId);
|
||
|
||
var item = new RollCallCaseHistoryDetail()
|
||
{
|
||
EmployeeFullName = employee?.FullName ?? "",
|
||
EmployeeId = employee?.id ?? 0,
|
||
Records = employeeRollCallsForDate.OrderBy(r => r.StartDate).Select(y =>
|
||
new RollCallCaseHistoryDetailRecord()
|
||
{
|
||
EndTime = y.EndDate!.Value.ToString("HH:mm"),
|
||
StartTime = y.StartDate!.Value.ToString("HH:mm"),
|
||
EntryTimeDifference =
|
||
CalculateEntryTimeDifferencesTimeSpan(y.EarlyEntryDuration, y.LateEntryDuration),
|
||
ExitTimeDifference =
|
||
CalculateExitTimeDifferencesTimeSpan(y.EarlyExitDuration, y.LateExitDuration)
|
||
}).ToList(),
|
||
Status = employeeRollCallsForDate.Any() ? RollCallRecordStatus.Worked
|
||
: leave != null ? RollCallRecordStatus.Leaved
|
||
: RollCallRecordStatus.Absent,
|
||
TotalWorkingTime =
|
||
new TimeSpan(
|
||
employeeRollCallsForDate.Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks)),
|
||
PersonnelCode = personnelCodes.FirstOrDefault(y => y.EmployeeId == employeeId)?.PersonnelCode
|
||
.ToString(),
|
||
};
|
||
res.Add(item);
|
||
}
|
||
}
|
||
|
||
return res;
|
||
}
|
||
} |