Files
Backend-Api/CompanyManagment.EFCore/Repository/RollCallRepository.cs
2025-01-08 20:16:58 +03:30

1386 lines
63 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.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.Globalization;
using System.Linq;
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)
{
//گرفتن ساعت استراحت پرسنل از تنظیمات
#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 year = Convert.ToInt32(startMonthDay.ToFarsi().Substring(0, 4));
var month = Convert.ToInt32(startMonthDay.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;
//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 => startMonthDay.AddDays(offset).Date);
var absentRecords = completeDaysList
.ExceptBy(rollCalls.Select(x => x.ShiftDate.Date), y => y.Date)
.Select(x => new CheckoutDailyRollCallViewModel()
{
StartDate1 = null,
EndDate1 = null,
DateTimeGr = x.Date,
DayOfWeek = x.Date.DayOfWeek.ToString(),
RollCallDateFa = x.Date.ToFarsi()
});
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));
var 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
};
});
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,
});
return presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
}
//محاسبه کارکرد پرسنل در هنگام جستجو
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)
{
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 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;
//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);
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,
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.StartDate!.Value);
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;
}
//خواسته کارفرما: هنگام جستجوی کارمند حضور غیاب های فرد در قالب های یک ماهه ظاهر شوند
//این قالب ها متناسب با جستجوی کاربر، یا حضور غیاب های موجود، ممکن است بازه ای کمتر از یک ماه را شامل باشد
//صورت گیرد 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
}),
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}"
};
}
//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
}).ToList();
}
//سوابق حضور غیاب کارگاه
public RollCallsByDateViewModel GetWorkshopRollCallHistory(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();
//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"),
}),
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 search year may be in another 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)
{
List<RollCallEmployee> activatedEmployeesListInDay = new();
//in working days everyone should be present
if (day.DayOfWeek != DayOfWeek.Friday && totalHolidays.All(x => x.HolidaydateGr != day))
{
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 worksers 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 = _holidayItemApplication.IsHoliday(day),
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.Select(y => new RollCallTimeViewModel()
{
StartDate = y.StartDate!.Value.ToString("HH:mm"),
EndDate = y.EndDate?.ToString("HH:mm")
}).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
}),
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();
}
}