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

2396 lines
110 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using _0_Framework.Application;
using _0_Framework.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;
}
}