Files
Backend-Api/CompanyManagment.EFCore/Repository/RollCallRepository.cs
2024-10-28 19:01:02 +03:30

495 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using _0_Framework.Application;
using _0_Framework.InfraStructure;
using Company.Domain.RollCallAgg;
using CompanyManagment.App.Contracts.HolidayItem;
using CompanyManagment.App.Contracts.RollCall;
using MD.PersianDateTime.Standard;
using Microsoft.EntityFrameworkCore;
namespace CompanyManagment.EFCore.Repository;
public class RollCallRepository : RepositoryBase<long, RollCall>, IRollCallRepository
{
private readonly CompanyContext _context;
private readonly IHolidayItemApplication _holidayItemApplication;
public RollCallRepository(CompanyContext context, IHolidayItemApplication holidayItemApplication) : base(context)
{
_context = context;
_holidayItemApplication = holidayItemApplication;
}
public EditRollCall GetByEmployeeIdAndWorkshopId(long employeeId, long workshopId)
{
throw new NotImplementedException();
}
public EditRollCall GetById(long id)
{
throw new NotImplementedException();
}
public List<RollCallViewModel> Search(RollCallSearchModel searchModel)
{
throw new NotImplementedException();
}
#region Pooya
//حضور غیاب فیش حقوقی
public List<CheckoutDailyRollCallViewModel> GetEmployeeRollCallsForMonth(long employeeId, long workshopId, DateTime startMonthDay, DateTime endMonthDay)
{
var rollCalls = _context.RollCalls.Where(x =>
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate != null && x.EndDate != null &&
x.StartDate.Value.Date >= startMonthDay && x.StartDate.Value.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.StartDate!.Value.Date), y => y.Date.Date)
.Select(x => new CheckoutDailyRollCallViewModel()
{
StartDate = null,
EndDate = null,
DateTimeGr = x.Date.Date,
DayOfWeek = x.Date.DayOfWeek.ToString(),
RollCallDateFa = x.Date.ToFarsi()
});
var presentDays = rollCalls.GroupBy(x => x.StartDate!.Value.Date).Select(x => new CheckoutDailyRollCallViewModel()
{
StartDate = x.Min(y => y.StartDate)!.Value.ToString("HH:mm"),
EndDate = x.Max(y => y.EndDate)!.Value.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() > 1
});
presentDays = presentDays.Select(x => new CheckoutDailyRollCallViewModel
{
StartDate = x.StartDate,
EndDate = x.EndDate,
TotalWorkingHours = $"{(int)x.TotalhourseSpan.TotalHours}:{(x.TotalhourseSpan.Minutes):00}",
DayOfWeek = x.DayOfWeek,
RollCallDateFa = x.RollCallDateFa,
DateTimeGr = x.DateTimeGr,
IsSliced = x.IsSliced,
});
return presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList();
}
//جستجوی سوابق حضور غیاب بر اساس کارمند
public EmployeeRollCallsByMonthViewModel GetEmployeeRollCallsHistory(long employeeId, long workshopId,
DateTime? startDateTime, DateTime? endDateTime, DateTime? exactDateTime, DateTime? dateIndex)
{
//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 none was found return empty
if (employeeRollCallStatuses == null)
return new();
//this list will have all the months which employee was active 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 save 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
if (exactDateTime.HasValue)
{
//start and end will be the same date
startSearch = new PersianDateTime(exactDateTime.Value);
endSearch = startSearch;
//get the
activeMonthsList = activeMonthsList.Where(x => x.Year >= startSearch.Year && x.Month >= startSearch.Month && x.Year <= endSearch.Year && x.Month <= endSearch.Month).ToList();
}
if (dateIndex != null)
{
var persianDateIndex = new PersianDateTime(dateIndex.Value);
var dateIndexFirstOfMonth = persianDateIndex.AddDays(-(persianDateIndex.Day - 1));
activeMonthsList = activeMonthsList.Where(x => dateIndexFirstOfMonth >= x).ToList();
}
if (!activeMonthsList.Any()) return new();
//get the last month which user was active in
PersianDateTime selectedMonthPersian = activeMonthsList.First();
DateTime selectedMonthFirstDay = selectedMonthPersian;
DateTime nextMonthFirstDay = selectedMonthPersian.AddMonths(1);
var statusesOfMonth = employeeRollCallStatuses.EmployeesStatus.Where(x => x.EndDate >= selectedMonthFirstDay &&
x.StartDate < nextMonthFirstDay);
var leavesQuery =
_context.LeaveList.Where(x => (x.LeaveType == "استعلاجی" || (x.LeaveType == "استحقاقی" && x.PaidLeaveType == "روزانه")) &&
x.IsAccepted &&
x.EndLeave >= selectedMonthFirstDay && x.StartLeave < nextMonthFirstDay && x.WorkshopId == workshopId);
var rollCalls = _context.RollCalls.Where(x =>
!leavesQuery.Any(y =>
y.StartLeave.Date <= x.StartDate.Value.Date && y.EndLeave.Date >= x.StartDate.Value.Date) &&
x.EmployeeId == employeeId && x.WorkshopId == workshopId && x.StartDate != null && x.EndDate != null &&
x.StartDate >= selectedMonthFirstDay && x.StartDate < nextMonthFirstDay);
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();
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);
var result = completeDaysList.Where(x => statusesOfMonth.Any(y => x >= y.StartDate.Date && x <= y.EndDate.Date))
.Select(x => new RollCallViewModel()
{
DateGr = x.Date.Date,
DateFa = x.Date.Date.ToFarsi(),
RollCallTimesList = rollCallsList.Where(y => x.Date.Date == y.StartDate!.Value.Date).Select(y =>
new RollCallTimeViewModel()
{
StartDate = y.StartDate.Value.ToString("HH:mm"),
EndDate = y.EndDate!.Value.ToString("HH:mm")
}),
TotalWorkingHoursSpan = new TimeSpan(rollCallsList.Where(y => x.Date.Date == y.StartDate!.Value.Date)
.Sum(y => (y.EndDate!.Value - y.StartDate.Value).Ticks)),
Reason = leavesList.FirstOrDefault(y => y.EndLeave >= x.Date.Date && y.StartLeave <= x.Date.Date)?.LeaveType ?? ""
});
result = result.Select(x => new RollCallViewModel()
{
EmployeeFullName = employeeName.EmployeeFullName,
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,
TotalWorkingHours = $"{x.TotalWorkingHoursSpan.TotalHours.ToString("0")}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}",
}).ToList();
return new EmployeeRollCallsByMonthViewModel()
{
PersianMonthName = selectedMonthPersian.ToString("MMMM"),
PersianYear = selectedMonthPersian.ToString("yyyy"),
DateGr = selectedMonthFirstDay,
RollCalls = result,
DateIndex = activeMonthsList.Count > 1 ? activeMonthsList.Skip(1).First().ToString("yyyy/MM/dd") : null
};
}
//سوابق حضور غیاب کارگاه
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.EndDate.HasValue && x.StartDate < DateTime.Now.Date &&
x.StartDate.Value.Date == dateIndex.Date);
//get active employees of workshop in dateIndex date
var activeEmployeesQuery =
_context.RollCallEmployees.Include(x => x.EmployeesStatus)
.Where(x => x.WorkshopId == searchModel.WorkshopId && x.EmployeesStatus.Any(y => y.EndDate.Date >= dateIndex && y.StartDate.Date <= dateIndex));
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 =
_context.PersonnelCodeSet.Where(x => activeEmployeesQuery.Any(y => y.EmployeeId == x.EmployeeId));
var rollCallsList = rollCallsQuery.ToList();
var activatedEmployeesList = activeEmployeesQuery.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.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 = $"{x.TotalWorkingHoursSpan.TotalHours.ToString("0")}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}"
});
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).ToList();
//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 && x.IsActiveString == "true" && 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.StartDate.Value.Date == date);
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();
//join leave and absents
var absentsViewModel = absentsQuery.Select(x => new AbsentEmployeeViewModel()
{
PersonnelCode = personnelCodes
.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.ToList()
};
}
#endregion
public long Flag(long employeeId, long workshopId)
{
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 checkLastOne = query.OrderByDescending(x => x.StartDate).FirstOrDefault();
if (checkLastOne != null && checkLastOne.EndDate == null)
return checkLastOne.id;
return 0;
}
else
{
return 0;
}
}
}