From 05d860795e424034e9ad9a707d3504e1d99a0284 Mon Sep 17 00:00:00 2001 From: mahan Date: Sun, 11 Jan 2026 15:12:08 +0330 Subject: [PATCH 01/17] add rollcall title case history query --- .../RollCallAgg/IRollCallRepository.cs | 5 + .../RollCall/IRollCallApplication.cs | 46 + .../RollCallApplication.cs | 11 + .../Repository/EmployeeDocumentsRepository.cs | 11 +- .../Repository/RollCallRepository.cs | 1165 ++++++++++------- .../RollCall/CaseHistoryController.cs | 31 + ServiceHost/Properties/launchSettings.json | 2 +- 7 files changed, 764 insertions(+), 507 deletions(-) create mode 100644 ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs diff --git a/Company.Domain/RollCallAgg/IRollCallRepository.cs b/Company.Domain/RollCallAgg/IRollCallRepository.cs index 47f851c6..4afc1f6a 100644 --- a/Company.Domain/RollCallAgg/IRollCallRepository.cs +++ b/Company.Domain/RollCallAgg/IRollCallRepository.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using _0_Framework.Application; using _0_Framework.Domain; using CompanyManagment.App.Contracts.RollCall; using CompanyManagment.App.Contracts.WorkingHoursTemp; @@ -91,5 +92,9 @@ namespace Company.Domain.RollCallAgg Task> GetRollCallsUntilNowWithWorkshopIdEmployeeIds(long workshopId, List employeeIds, DateTime fromDate); #endregion + + Task> GetCaseHistoryTitles(long workshopId,RollCallCaseHistorySearchModel searchModel); + Task> GetCaseHistoryDetails(long workshopId, + string titleId, RollCallCaseHistorySearchModel searchModel); } } diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index 6ce7bbfd..78132004 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using _0_Framework.Application; +using CompanyManagment.App.Contracts.Workshop; +using Microsoft.AspNetCore.Mvc; namespace CompanyManagment.App.Contracts.RollCall { @@ -125,7 +127,51 @@ namespace CompanyManagment.App.Contracts.RollCall /// /// Task RecalculateValues(long workshopId, List command); + + Task> GetCaseHistoryTitles(long workshopId,RollCallCaseHistorySearchModel searchModel); + Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel); } + + public class RollCallCaseHistoryDetail + { + public string EmployeeFullName { get; set; } + public string PersonnelCode { get; set; } + public TimeSpan TotalWorkingTime { get; set; } + public List Records { get; set; } + public RollCallRecordStatus Status { get; set; } + + } + + public enum RollCallRecordStatus + { + Worked = 0, + Absent = 1, + Leaved = 2 + } + + public class RollCallCaseHistoryDetailRecord + { + public TimeSpan EntryTimeDifference { get; set; } + public string StartTime { get; set; } + public string EndTime { get; set; } + public TimeSpan ExitTimeDifference { get; set; } + + } + + public class RollCallCaseHistorySearchModel:PaginationRequest + { + public string StartDate { get; set; } + public string EndDate { get; set; } + public string OneDayDate { get; set; } + public long? EmployeeId { get; set; } + } + + public class RollCallCaseHistoryTitleDto + { + public string Id { get; set; } + public string Title { get; set; } + } + public class ReCalculateRollCallValues { public long EmployeeId { get; set; } diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index e73e4c3e..96594dc8 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -858,4 +858,15 @@ public class RollCallApplication : IRollCallApplication } } + public async Task> GetCaseHistoryTitles(long workshopId, + RollCallCaseHistorySearchModel searchModel) + { + return await _rollCallRepository.GetCaseHistoryTitles(workshopId,searchModel); + } + + public async Task> GetCaseHistoryDetails(long workshopId, + string titleId, RollCallCaseHistorySearchModel searchModel) + { + return await _rollCallRepository.GetCaseHistoryDetails(workshopId, titleId, searchModel); + } } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs b/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs index 1cffdc1d..b1728546 100644 --- a/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs +++ b/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs @@ -713,10 +713,15 @@ public class EmployeeDocumentsRepository : RepositoryBase x.DocumentStatus != DocumentStatus.Unsubmitted) .Include(x => x.EmployeeDocuments) - .ThenInclude(x => x.Workshop).ThenInclude(x => x.WorkshopEmployers).ThenInclude(x => x.Employer) - .GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel() + .ThenInclude(x => x.Workshop) + .ThenInclude(x => x.WorkshopEmployers) + .ThenInclude(x => x.Employer) + .GroupBy(x => x.WorkshopId) + .Select(x => new WorkshopWithEmployeeDocumentsViewModel() { - SubmittedItemsCount = x.Count(y => y.DocumentStatus == DocumentStatus.SubmittedByAdmin || y.DocumentStatus == DocumentStatus.SubmittedByClient), + SubmittedItemsCount = x + .Count(y => y.DocumentStatus == DocumentStatus.SubmittedByAdmin + || y.DocumentStatus == DocumentStatus.SubmittedByClient), WorkshopId = x.Key, WorkshopFullName = x.First().EmployeeDocuments.Workshop.WorkshopName, EmployerName = x.First().EmployeeDocuments.Workshop.WorkshopEmployers.First().Employer.FullName diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index b76e01b8..5923d1de 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -14,6 +14,7 @@ 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.Threading.Tasks; @@ -27,7 +28,10 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) + + public RollCallRepository(CompanyContext context, IHolidayItemApplication holidayItemApplication, + IAuthHelper authHelper, IWorkshopRepository workshopRepository, + IRollCallMandatoryRepository rollCallMandatoryRepository) : base(context) { _context = context; _holidayItemApplication = holidayItemApplication; @@ -36,13 +40,12 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } - #region Pooya + //حضور غیاب گروهی از پرسنل برای پرینت گروهی فیش حقوقی غیر رسمی موقت public List GetEmployeeRollCallsInDates(IEnumerable employeeIds, - long workshopId, DateTime start, DateTime end) + 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 && @@ -55,8 +58,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos List result = new(); foreach (var employeeId in employeeIds) { - - var absentRecords = completeDaysList.Where(x => !rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date)) + var absentRecords = completeDaysList.Where(x => + !rollCalls.Any(y => y.EmployeeId == employeeId && x.Date.Date == y.ShiftDate.Date)) .Select(x => new CheckoutDailyRollCallViewModel() { StartDate1 = null, @@ -65,25 +68,27 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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() + var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date) + .Select(x => { - StartDate1 = orderedRollcalls.FirstOrDefault().StartDate.Value.ToString("HH:mm"), - EndDate1 = orderedRollcalls.FirstOrDefault().EndDate.Value.ToString("HH:mm"), + 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") ?? "", + 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 - }; - }); + 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, @@ -95,10 +100,10 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos RollCallDateFa = x.RollCallDateFa, DateTimeGr = x.DateTimeGr, IsSliced = x.IsSliced - }); - List checkoutDailyRollCalls = presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); + List checkoutDailyRollCalls = + presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); var resultItem = new PersonnelCheckoutDailyRollCallViewModel() @@ -112,17 +117,17 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return result; - - } - //قطع شده توسط سیستم - public List GetRollCallWorkFlowsCutByBgService(long workshopId, DateTime start, DateTime end) + //قطع شده توسط سیستم + public List 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 && + .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) @@ -145,25 +150,29 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos }) }) .ToList(); - } - //حضور غیاب در پرینت فیش حقوقی رسمی - public List GetEmployeeRollCallsForMonth(long employeeId, long workshopId, DateTime startMonthDay, DateTime endMonthDay) + //حضور غیاب در پرینت فیش حقوقی رسمی + public List GetEmployeeRollCallsForMonth(long employeeId, long workshopId, + DateTime startMonthDay, DateTime endMonthDay) { - var firstDayOfMonth = $"{startMonthDay.ToFarsi().Substring(0,8)}01".ToGeorgianDateTime(); + 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(); + 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 => @@ -194,10 +203,11 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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 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) + .ExceptBy(rollCalls.Select(x => x.ShiftDate.Date), y => y.Date) .Select(x => { var leave = leaves.FirstOrDefault(y => @@ -219,35 +229,35 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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); + 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"), + { + 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") ?? "", + StartDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.StartDate?.ToString("HH:mm") ?? "", + EndDate2 = orderedRollcalls.Skip(1).FirstOrDefault()?.EndDate?.ToString("HH:mm") ?? "", - TotalhourseSpan = rollCallTimeSpanPerDay - breakTimePerDay, + TotalhourseSpan = rollCallTimeSpanPerDay - breakTimePerDay, - BreakTimeTimeSpan = breakTimePerDay, + BreakTimeTimeSpan = breakTimePerDay, - DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(), - RollCallDateFa = x.Key.Date.ToFarsi(), - DateTimeGr = x.Key.Date, - IsSliced = x.Count() > 2, - IsAbsent = false - }; + DayOfWeek = x.Key.DayOfWeek.DayOfWeeKToPersian(), + RollCallDateFa = x.Key.Date.ToFarsi(), + DateTimeGr = x.Key.Date, + IsSliced = x.Count() > 2, + IsAbsent = false + }; }); @@ -276,34 +286,32 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos }); return result; - } - //محاسبه کارکرد پرسنل در هنگام جستجو - public TimeSpan GetEmployeeRollCallTimeSpanForDuration(long employeeId, long workshopId, DateTime start, DateTime end) + //محاسبه کارکرد پرسنل در هنگام جستجو + 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(); + 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 GetEmployeeRollCallsForMonth(IEnumerable employeeIds, long workshopId, DateTime start, DateTime end) + public List GetEmployeeRollCallsForMonth(IEnumerable 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(); + 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 && @@ -365,72 +373,78 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos (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) + var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date) + .Select(x => { - if (firstRollCall != null && secondRollCall != null) + 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) { - 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) + if (firstRollCall != null && secondRollCall != null) { - hasSecondTimeDiff = true; + 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; + } - } - 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") ?? "", - #endregion + 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) + : "", - 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) - : "" - }; - }); + 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, @@ -447,10 +461,10 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos ExitDifferencesMinutes1 = x.ExitDifferencesMinutes1, EnterDifferencesMinutes2 = x.EnterDifferencesMinutes2, ExitDifferencesMinutes2 = x.ExitDifferencesMinutes2 - }); - List checkoutDailyRollCalls = presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); + List checkoutDailyRollCalls = + presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); checkoutDailyRollCalls.ForEach(x => { @@ -468,8 +482,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return result; - - } private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late) @@ -536,7 +548,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos .FirstOrDefault(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId); //if no status was found return empty - if (employeeRollCallStatuses == null || employeeRollCallStatuses.EmployeesStatus == null || !employeeRollCallStatuses.EmployeesStatus.Any()) + 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, @@ -551,7 +564,9 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos var persianStartFirstDayOfMonth = new PersianDateTime(persianStartDate.Year, persianStartDate.Month, 1); - for (PersianDateTime start = persianStartFirstDayOfMonth; start <= persianEndDate && start < PersianDateTime.Today.Date; start = start.AddMonths(1)) + for (PersianDateTime start = persianStartFirstDayOfMonth; + start <= persianEndDate && start < PersianDateTime.Today.Date; + start = start.AddMonths(1)) { activeMonths.Add(start); } @@ -571,14 +586,19 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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(); + 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(); + 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 @@ -607,23 +627,27 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //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); + _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); + 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; + _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 }) + 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(); @@ -635,7 +659,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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); + 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 @@ -644,36 +669,38 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //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() + 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 => { - DateGr = x.Date, - DateFa = x.Date.ToFarsi(), + //iterating day by day - //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 - }; - }); + //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() @@ -690,7 +717,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos RollCallTimesList = x.RollCallTimesList.OrderBy(r => r.StartDateGr), HasLeave = x.HasLeave, TotalWorkingHoursSpan = x.TotalWorkingHoursSpan, - TotalWorkingHours = $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}" + TotalWorkingHours = + $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}" }).ToList(); //total working hours in the whole month or duration @@ -706,7 +734,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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}" - }; } @@ -728,7 +755,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos { return $""; } - } private string CalculateEntryTimeDifferences(TimeSpan early, TimeSpan late) @@ -749,17 +775,18 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos { return $""; } - } //Without Paginate, With EndDate==null, without undefined, Ordered Descending By StartDate - public List GetEmployeeRollCallsHistoryAllInDates(long workshopId, long employeeId, DateTime start, DateTime end) + public List 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) + (x.EndDate == null || x.EndDate.Value.Date >= start.Date) && + x.ShiftDate.Date <= end.Date) .OrderByDescending(x => x.StartDate.Value) .Select(x => new RollCallViewModel { @@ -776,13 +803,11 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //سوابق حضور غیاب کارگاه 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)) { @@ -791,9 +816,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } - - else - if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa)) + else if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa)) { searchDurationEnd = searchModel.ExactDateFa.ToGeorgianDateTime().Date; searchDurationStart = searchModel.ExactDateFa.ToGeorgianDateTime().AddDays(-1).Date; @@ -804,7 +827,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return new(); - DateTime dateIndex = searchDurationEnd.AddDays(-1 * (searchModel.DateIndex)).Date; if (dateIndex <= searchDurationStart) @@ -813,12 +835,15 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //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.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 && + .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); @@ -826,9 +851,10 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //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) && + .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)); + && !rollCallsQuery.Any(rc => rc.EmployeeId == x.EmployeeId && !rc.EndDate.HasValue)); if (searchModel.EmployeeId > 0) { @@ -861,17 +887,21 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) - }), + 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(), + TotalWorkingHoursSpan = + new TimeSpan(employeeRollCallsForDate.Sum(y => (y.EndDate!.Value - y.StartDate!.Value).Ticks)), + PersonnelCode = personnelCodeList.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.PersonnelCode + .ToString(), }; }) }; @@ -884,7 +914,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos HasLeave = x.HasLeave, IsAbsent = x.IsAbsent, PersonnelCode = x.PersonnelCode, - TotalWorkingHours = $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{(x.TotalWorkingHoursSpan.Minutes).ToString("00")}" + TotalWorkingHours = + $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{(x.TotalWorkingHoursSpan.Minutes).ToString("00")}" }); return result; } @@ -892,14 +923,12 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //برای دریافت سوابق به صورت 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)) { @@ -908,9 +937,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } - - else - if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa)) + else if (!string.IsNullOrWhiteSpace(searchModel.ExactDateFa)) { searchDurationEnd = searchModel.ExactDateFa.ToGeorgianDateTime().Date; searchDurationStart = searchModel.ExactDateFa.ToGeorgianDateTime().AddDays(-1).Date; @@ -921,7 +948,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return new(); - DateTime dateIndex = searchDurationEnd.AddDays(-1 * (searchModel.DateIndex)).Date; if (dateIndex <= searchDurationStart) @@ -930,7 +956,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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(); + x.EmployeesStatus.Any(y => y.EndDate.Date >= dateIndex && y.StartDate.Date <= dateIndex)) + .ToList(); var result = new RollCallsByDateViewModel() { @@ -944,14 +971,19 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } //سوابق غیبت - public List GetWorkshopAbsentHistory(long workshopId, DateTime startSearch, DateTime endSearch) + public List 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); + 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() @@ -966,7 +998,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) && + x.EmployeesStatus.Any(y => + y.EndDate.Date >= startSearch && y.StartDate.Date <= endSearch) && withPersonnelCode.Any(y => y.EmployeeId == x.EmployeeId)); var employeeSettingsList = @@ -995,14 +1028,16 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos List 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(); + .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) + .Join(employeeSettingsList.Where(x => + x.WeeklyOffDays == null || x.HolidayWork != HolidayWork.Default) , x => x.EmployeeId, y => y.EmployeeId, (x, _) => x).ToList(); } @@ -1037,15 +1072,16 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) && + !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 - }), + .Select(x => new RollCallViewModel() + { + EmployeeId = x.EmployeeId, + EmployeeFullName = x.EmployeeFullName, + Id = x.id, + WorkshopId = x.WorkshopId + }), IsHoliday = isHoliday, IsFriday = day.DayOfWeek == DayOfWeek.Friday }; @@ -1056,7 +1092,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } - //گزارش آنلاین حضور غیاب کارگاه public CurrentDayRollCall GetWorkshopCurrentDayRollCalls(long workshopId) { @@ -1067,7 +1102,9 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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)) + ((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); @@ -1077,7 +1114,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos // _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) @@ -1087,17 +1123,15 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //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); - - + 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(); + .Any(y => x.EmployeeId == y.EmployeeId)).ToList(); var nameReferences = activeEmployees.ToList(); @@ -1110,17 +1144,15 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos .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)), + 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() @@ -1138,10 +1170,9 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos .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)) + .Where(x => absentsQuery.Any(y => y.EmployeeId == x.EmployeeId)) .Select(x => new { x.EmployeeId, x.LeaveType }).ToList(); var personnelCodesList = personnelCodes.ToList(); @@ -1161,7 +1192,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return new CurrentDayRollCall() { AbsentEmployees = absentsViewModel.ToList(), - PresentEmployees = presentEmployees.OrderByDescending(x => x.RollCallTimesList.Any(y => string.IsNullOrWhiteSpace(y.EndDate))) + PresentEmployees = presentEmployees + .OrderByDescending(x => x.RollCallTimesList.Any(y => string.IsNullOrWhiteSpace(y.EndDate))) .ThenByDescending(x => x.RollCallTimesList.Max(y => y.StartDate)).ToList() }; } @@ -1176,38 +1208,40 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //تداخل مرخصی در کارپوشه public EditRollCall GetByEmployeeIdAndWorkshopId(long employeeId, long workshopId) { - throw new NotImplementedException(); + throw new NotImplementedException(); } public EditRollCall GetById(long id) { - throw new NotImplementedException(); + throw new NotImplementedException(); } public List GetOverlappedRollCallsWithLeaveInDates(long workshopId, DateTime start, DateTime end) { - - var rollCalls = _context.RollCalls.Where(x => x.WorkshopId == workshopId && x.ShiftDate.Date >= start.Date && x.EndDate.HasValue && + 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(); + _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 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)); + 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)); + dailyLeaves.Any(y => x.EmployeeId == y.EmployeeId && x.ShiftDate.Date == y.StartLeave.Date)); - var hourlyOverlappedRollCallsResult = hourlyOverlappedRollCalls.Select(x => + var hourlyOverlappedRollCallsResult = hourlyOverlappedRollCalls.Select(x => { var leave = leaves.FirstOrDefault(y => x.EmployeeId == y.EmployeeId && - x.EndDate.Value >= y.StartLeave && - x.StartDate.Value <= y.EndLeave); + x.EndDate.Value >= y.StartLeave && + x.StartDate.Value <= y.EndLeave); return new OverlappedRollCallWithLeave() { RollCallId = x.id, @@ -1221,22 +1255,22 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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 - }; + 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() + return result.Select(x => new OverlappedRollCallWithLeave() { RollCallId = x.RollCallId, LeaveId = x.LeaveId, @@ -1248,7 +1282,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos StartOfOverlapTime = x.StartOfOverlapDateTime.ToString("HH:mm"), EmployeeFullName = x.EmployeeFullName, EmployeeId = x.EmployeeId - }).ToList(); } @@ -1263,7 +1296,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //نیز پاک می شوند 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); + 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); @@ -1275,11 +1309,12 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos /// public List 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 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) @@ -1311,13 +1346,14 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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(); + }).OrderBy(x => x.StartDate).ToList(); } /// /// دریافت حضور غیاب های غیر منقطع /// - public IEnumerable GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, DateTime durationEnd) + public IEnumerable GetNotSlicedRollCallsByWorkshopId(long workshopId, DateTime durationStart, + DateTime durationEnd) { if (durationEnd.Date >= DateTime.Now.Date) durationEnd = DateTime.Now.AddDays(-1).Date; @@ -1325,12 +1361,13 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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(); + x.ShiftDate.Date >= durationStart && + x.ShiftDate.Date <= durationEnd && x.EndDate.HasValue).ToList(); if (rollCalls == null || !rollCalls.Any()) return new List(); 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 + x.GroupBy(y => y.EmployeeId).Where(y => y.Count() == 1) + .SelectMany(y => y)).Select(x => new RollCallViewModel { Id = x.id, StartDate = x.StartDate.Value, @@ -1339,14 +1376,14 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos DateGr = x.ShiftDate.Date, EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.EmployeeFullName ?? "" }); - } - + public List GetRange(IEnumerable 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(); + var names = _context.RollCallEmployees + .Where(x => query.Any(y => y.EmployeeId == x.EmployeeId && y.WorkshopId == x.WorkshopId)).ToList(); return query.Select(x => new RollCallViewModel @@ -1354,53 +1391,57 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos StartDate = x.StartDate.Value, EndDate = x.EndDate.Value, Id = x.id, - EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId && y.WorkshopId == x.WorkshopId).EmployeeFullName + EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId && y.WorkshopId == x.WorkshopId) + .EmployeeFullName }).ToList(); } public List GetRangeByWorkshopIdEmployeeIdForDate(long workshopId, long employeeId, - DateTime date) + DateTime date) { - return _context.RollCalls.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId && - x.ShiftDate.Date == date).ToList(); + return _context.RollCalls.Where(x => x.WorkshopId == workshopId && x.EmployeeId == employeeId && + x.ShiftDate.Date == date).ToList(); } - /// - /// undefined دریافت حضور و غیاب های - /// - public List GetUndefinedRollCallWorkFlowsInDates(long workshopId, DateTime start, DateTime end) + /// + /// undefined دریافت حضور و غیاب های + /// + public List 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(); + 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() + .Select(g => new RollCallsByDateViewModel() { - EmployeeId = x.EmployeeId, - EmployeeFullName = names.FirstOrDefault(y => y.EmployeeId == x.EmployeeId)?.EmployeeFullName ?? "", - WorkshopId = x.WorkshopId, - Id = x.id, - StartDate = x.StartDate, - EndDate = x.EndDate + 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(); + .ToList(); return result; } } + #endregion @@ -1434,7 +1475,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos { var checkTime = DateTime.Now; var checkLastOne = query.OrderByDescending(x => x.StartDate).FirstOrDefault(); - if (checkLastOne != null && checkLastOne.EndDate == null && checkLastOne.RollCallModifyType == RollCallModifyType.None) + if (checkLastOne != null && checkLastOne.EndDate == null && + checkLastOne.RollCallModifyType == RollCallModifyType.None) { var checkSpan = (DateTime.Now - checkLastOne.StartDate); if (checkSpan < validSpan) @@ -1443,7 +1485,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } } - if (checkLastOne != null && checkLastOne.EndDate != null && checkLastOne.RollCallModifyType == RollCallModifyType.None) + if (checkLastOne != null && checkLastOne.EndDate != null && + checkLastOne.RollCallModifyType == RollCallModifyType.None) { var checkSpan = (DateTime.Now - checkLastOne.EndDate); if (checkSpan < validSpan) @@ -1451,6 +1494,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return "outRegistred-InvalidIncom"; } } + return "Valid"; } else @@ -1466,7 +1510,9 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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; + var name = _context.RollCallEmployees + .FirstOrDefault(x => x.WorkshopId == entity.WorkshopId && x.EmployeeId == entity.EmployeeId) + .EmployeeFullName; return new RollCallViewModel { WorkshopId = entity.WorkshopId, @@ -1482,23 +1528,30 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos /// /// برای پرینت سوابق حضور و غیاب /// - public EmployeeRollCallsByMonthViewModel GetEmployeeRollCallsHistoryForPrint(long employeeId, long workshopId, DateTime firstRollCallToPrintStartDate, DateTime lastRollCallToPrintStartDate) + public EmployeeRollCallsByMonthViewModel GetEmployeeRollCallsHistoryForPrint(long employeeId, long workshopId, + DateTime firstRollCallToPrintStartDate, DateTime lastRollCallToPrintStartDate) { - - var selectedMonthPersian = (new PersianCalendar()).GetMonth(firstRollCallToPrintStartDate).ToFarsiMonthByIntNumber(); + 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 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 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(); + .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(); + 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(); @@ -1506,33 +1559,36 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos int dateRange = (int)(lastRollCallToPrintStartDate - firstRollCallToPrintStartDate).TotalDays + 1; - var completeDaysList = Enumerable.Range(0, dateRange).Select(offset => firstRollCallToPrintStartDate.AddDays(offset).Date); + 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 - }; - }); + 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, @@ -1546,73 +1602,76 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos RollCallTimesList = x.RollCallTimesList, HasLeave = x.HasLeave, TotalWorkingHoursSpan = x.TotalWorkingHoursSpan, - TotalWorkingHours = $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}" + TotalWorkingHours = + $"{(int)x.TotalWorkingHoursSpan.TotalHours}:{x.TotalWorkingHoursSpan.Minutes.ToString("00")}" }).ToList(); var totalWorkingHours = new TimeSpan(result.Sum(x => x.TotalWorkingHoursSpan.Ticks)); - return new EmployeeRollCallsByMonthViewModel() + 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 GetWorkshopEmployeeRollCallsWithUndefinedForDate(long workshopId, long employeeId, DateTime date) + public List 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 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(), + 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, + 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(); - } + 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); + } - 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 GetEmployeeRollCallsForCustomizeCheckoutTemp(IEnumerable customizeCheckoutIds, long workshopId) + public List GetEmployeeRollCallsForCustomizeCheckoutTemp( + IEnumerable customizeCheckoutIds, long workshopId) { //if (workshopId == 170) // return GetEmployeeRollCallsInDatesForKababMahdi(employeeIds, workshopId, start, end); @@ -1623,13 +1682,12 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos (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(); + { + CustomizeCheckoutId = x.customizeCheckout.id, + CheckoutStart = x.customizeCheckout.ContractStart, + CheckoutEnd = x.customizeCheckout.ContractEnd, + EmployeeId = x.employee.id, + }).ToList(); List result = new(); PersianCalendar pc = new(); @@ -1687,13 +1745,11 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos (worksInFriday && x.Date.DayOfWeek == DayOfWeek.Friday) || (worksInHolidays && isHoliday)), - - }; }); - var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date).Select( - x => + 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(); @@ -1702,28 +1758,29 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //منطق کباب مهدی!!!! #region SecondTimeDiff + var hasSecondTimeDiff = false; if (settings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating) { - if (firstRollCall !=null && secondRollCall != null) + 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); + 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"), @@ -1742,20 +1799,24 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) - : "", + 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 + EnterDifferencesMinutes2 = secondRollCall != null && + secondRollCall.LateEntryDuration > TimeSpan.Zero && hasSecondTimeDiff ? CalculateEntryMinuteDifference(secondRollCall.EarlyEntryDuration, secondRollCall.LateEntryDuration) : "", - ExitDifferencesMinutes2 = secondRollCall != null && secondRollCall.EarlyExitDuration > TimeSpan.Zero && hasSecondTimeDiff + ExitDifferencesMinutes2 = secondRollCall != null && + secondRollCall.EarlyExitDuration > TimeSpan.Zero && hasSecondTimeDiff ? CalculateExitMinuteDifference(secondRollCall.EarlyExitDuration, secondRollCall.LateExitDuration) : "" @@ -1777,8 +1838,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos EnterDifferencesMinutes2 = x.EnterDifferencesMinutes2, ExitDifferencesMinutes1 = x.ExitDifferencesMinutes1, ExitDifferencesMinutes2 = x.ExitDifferencesMinutes2 - - }); List checkoutDailyRollCalls = @@ -1788,7 +1847,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos { 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); + x.IsBirthDay = workshopId == 170 && pc.GetMonth(x.DateTimeGr) == pc.GetMonth(birthDay) && + pc.GetDayOfMonth(x.DateTimeGr) == pc.GetDayOfMonth(birthDay); }); var resultItem = new PersonnelCheckoutDailyRollCallViewModel() @@ -1798,31 +1858,34 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos DailyRollCalls = checkoutDailyRollCalls }; result.Add(resultItem); - } return result; - } - public async Task> GetRollCallsInShiftDate(DateTime rollCallShiftDate, long employeeId, long workshopId) + public async Task> 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(); + return await _context.RollCalls.Where(x => + x.ShiftDate.Date == rollCallShiftDate.Date && x.WorkshopId == workshopId && x.EmployeeId == employeeId) + .ToListAsync(); } //حضور غیاب گروهی از پرسنل برای پرینت گروهی فیش حقوقی غیر رسمی نهایی - public List GetEmployeeRollCallsForMonthForKababMahdi(IEnumerable employeeIds, long workshopId, DateTime start, DateTime end) + public List GetEmployeeRollCallsForMonthForKababMahdi( + IEnumerable 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(); + 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 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()); @@ -1866,7 +1929,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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 isBirthday = pc.GetMonth(x) == pc.GetMonth(birthDay) && + pc.GetDayOfMonth(x) == pc.GetDayOfMonth(birthDay); var isNormalWorkingDay = isHoliday == false && isFriday == false; return new CheckoutDailyRollCallViewModel() { @@ -1882,89 +1946,97 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos 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) + var presentDays = rollCalls.Where(x => x.EmployeeId == employeeId).GroupBy(x => x.ShiftDate.Date) + .Select(x => { - if (firstRollCall != null && secondRollCall != null) + 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) { - 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) + if (firstRollCall != null && secondRollCall != null) { - hasSecondTimeDiff = true; + 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; + } - } - 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, + }); - - #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 checkoutDailyRollCalls = presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); + List checkoutDailyRollCalls = + presentDays.Concat(absentRecords).OrderBy(x => x.DateTimeGr).ToList(); checkoutDailyRollCalls.ForEach(x => { @@ -1982,18 +2054,15 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return result; - - - } + public static (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, - ICollection rotatingShifts) + ICollection rotatingShifts) { DateTime startDate = startRollCall.Date; DateTime endDate = endRollCall.Date; - DateTime startEntryWithDate = startDate.Add(startRollCall.TimeOfDay); DateTime endEntryWithDate = endDate.Add(endRollCall.TimeOfDay); @@ -2039,7 +2108,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return startChosenShift; } - #endregion #region مقایسه پایان حضورغیاب با شیفت @@ -2057,7 +2125,6 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return endChosenShift; } - #endregion #region اشتراک حضور غیاب و شیفت @@ -2081,11 +2148,103 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos #endregion } - public async Task> GetRollCallsUntilNowWithWorkshopIdEmployeeIds(long workshopId, List employeeIds, DateTime fromDate) + public async Task> GetRollCallsUntilNowWithWorkshopIdEmployeeIds(long workshopId, + List 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> 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(); + } + + 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 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() + { + List = rollCallCaseHistoryTitles, + TotalCount = rollCallCaseHistoryTitles.Count + }; + return res; + } + + public Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs new file mode 100644 index 00000000..b6cbeccc --- /dev/null +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -0,0 +1,31 @@ +using _0_Framework.Application; +using CompanyManagment.App.Contracts.RollCall; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Client.Controllers.RollCall; + +public class CaseHistoryController:ClientBaseController +{ + private readonly IRollCallApplication _rollCallApplication; + private long _workshopId; + + public CaseHistoryController(IRollCallApplication rollCallApplication, + IAuthHelper authHelper) + { + _rollCallApplication = rollCallApplication; + _workshopId = authHelper.GetWorkshopId(); + } + + [HttpGet] + public async Task>> GetTitles(RollCallCaseHistorySearchModel searchModel) + { + return await _rollCallApplication.GetCaseHistoryTitles(_workshopId, searchModel); + } + + [HttpGet("{titleId}")] + public async Task GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) + { + return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); + } +} \ No newline at end of file diff --git a/ServiceHost/Properties/launchSettings.json b/ServiceHost/Properties/launchSettings.json index 788962e4..d7381591 100644 --- a/ServiceHost/Properties/launchSettings.json +++ b/ServiceHost/Properties/launchSettings.json @@ -19,7 +19,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;", + "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5006", "jsWebView2Debugging": false, "hotReloadEnabled": true }, From 8f6007835c55929fda5fcdbd3acc3f0a4816f840 Mon Sep 17 00:00:00 2001 From: mahan Date: Sun, 11 Jan 2026 17:25:56 +0330 Subject: [PATCH 02/17] complete rollcallCase history details by employee --- 0_Framework/Application/PagedResult.cs | 2 +- .../RollCall/IRollCallApplication.cs | 2 +- .../Repository/RollCallRepository.cs | 135 +++++++++++++++++- .../RollCall/CaseHistoryController.cs | 2 +- ServiceHost/Properties/launchSettings.json | 2 +- 5 files changed, 136 insertions(+), 7 deletions(-) diff --git a/0_Framework/Application/PagedResult.cs b/0_Framework/Application/PagedResult.cs index ecfa9ea1..c076e18d 100644 --- a/0_Framework/Application/PagedResult.cs +++ b/0_Framework/Application/PagedResult.cs @@ -7,7 +7,7 @@ namespace _0_Framework.Application; public class PagedResult where T : class { public int TotalCount { get; set; } - public List List { get; set; } + public List List { get; set; } = []; } public class PagedResult:PagedResult where T : class { diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index 78132004..0a717f0d 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -139,7 +139,7 @@ namespace CompanyManagment.App.Contracts.RollCall public TimeSpan TotalWorkingTime { get; set; } public List Records { get; set; } public RollCallRecordStatus Status { get; set; } - + public long EmployeeId { get; set; } } public enum RollCallRecordStatus diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index 5923d1de..f055dc1c 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -17,7 +17,9 @@ 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; namespace CompanyManagment.EFCore.Repository; @@ -777,6 +779,46 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos } } + 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 GetEmployeeRollCallsHistoryAllInDates(long workshopId, long employeeId, DateTime start, DateTime end) @@ -2202,7 +2244,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos dates = dates .Where(x => x.Date == date.Date).ToList(); } - else if (!string.IsNullOrWhiteSpace(searchModel.StartDate) + else if (!string.IsNullOrWhiteSpace(searchModel.StartDate) && !string.IsNullOrWhiteSpace(searchModel.EndDate)) { var start = searchModel.StartDate.ToGeorgianDateTime(); @@ -2243,8 +2285,95 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return res; } - public Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel) + public async Task> GetCaseHistoryDetails(long workshopId, string titleId, + RollCallCaseHistorySearchModel searchModel) { - throw new NotImplementedException(); + var query = _context.RollCallEmployeesStatus + .Include(x => x.RollCallEmployee) + .Where(x => x.RollCallEmployee.WorkshopId == workshopId); + + //این برای این هست که اگر بر اساس پرسنل جستجو شده بود و در titleId اگر به فرمت YYYY_MM اومد به این معنی هست که باید بر طبق ماه فیلتر بشه نه به صورت روزانه + if (searchModel.EmployeeId is > 0) + { + //TODO: set correct regex. + // if (!Regex.IsMatch(titleId, "")) + // 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"; + var endDateFa = startDateFa.FindeEndOfMonth(); + + var startDate = startDateFa.ToGeorgianDateTime(); + var endDate = endDateFa.ToGeorgianDateTime(); + + query = query.Where(x => x.StartDate <= endDate && x.EndDate >= startDate + && x.RollCallEmployee.EmployeeId == searchModel.EmployeeId); + + 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 PagedResult(); + 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.List.Add(item); + } + } + + return res; + + + } + return new PagedResult(); } } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index b6cbeccc..b5d18351 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -24,7 +24,7 @@ public class CaseHistoryController:ClientBaseController } [HttpGet("{titleId}")] - public async Task GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) + public async Task>> GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); } diff --git a/ServiceHost/Properties/launchSettings.json b/ServiceHost/Properties/launchSettings.json index d7381591..788962e4 100644 --- a/ServiceHost/Properties/launchSettings.json +++ b/ServiceHost/Properties/launchSettings.json @@ -19,7 +19,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5006", + "applicationUrl": "https://localhost:5004;http://localhost:5003;", "jsWebView2Debugging": false, "hotReloadEnabled": true }, From 0d72392701b1d8f1a7c3784d898572fbed030124 Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 12 Jan 2026 10:48:19 +0330 Subject: [PATCH 03/17] complete rollcall history details --- .../Repository/RollCallRepository.cs | 149 ++++++++++-------- .../RollCall/CaseHistoryController.cs | 2 +- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index f055dc1c..eb09e73a 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -813,7 +813,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos if (early != TimeSpan.Zero) { - return early*1; + return early * 1; } return TimeSpan.Zero; @@ -2292,6 +2292,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos .Include(x => x.RollCallEmployee) .Where(x => x.RollCallEmployee.WorkshopId == workshopId); + DateTime startDate; + DateTime endDate; //این برای این هست که اگر بر اساس پرسنل جستجو شده بود و در titleId اگر به فرمت YYYY_MM اومد به این معنی هست که باید بر طبق ماه فیلتر بشه نه به صورت روزانه if (searchModel.EmployeeId is > 0) { @@ -2305,75 +2307,84 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos var startDateFa = $"{year:D4}/{month:D2}/01"; var endDateFa = startDateFa.FindeEndOfMonth(); - var startDate = startDateFa.ToGeorgianDateTime(); - var endDate = endDateFa.ToGeorgianDateTime(); - - query = query.Where(x => x.StartDate <= endDate && x.EndDate >= startDate - && x.RollCallEmployee.EmployeeId == searchModel.EmployeeId); - - 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 PagedResult(); - 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.List.Add(item); - } - } - - return res; - - + startDate = startDateFa.ToGeorgianDateTime(); + endDate = endDateFa.ToGeorgianDateTime(); + query = query + .Where(x => x.RollCallEmployee.EmployeeId == searchModel.EmployeeId); } + else + { + //TODO: set correct regex. + // if (!Regex.IsMatch(titleId, "")) + // 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 PagedResult(); + 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.List.Add(item); + } + } + + return res; + return new PagedResult(); } } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index b5d18351..df1f1b9d 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -23,7 +23,7 @@ public class CaseHistoryController:ClientBaseController return await _rollCallApplication.GetCaseHistoryTitles(_workshopId, searchModel); } - [HttpGet("{titleId}")] + [HttpGet("details")] public async Task>> GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); From 915f16c7c0037b3051bf8b9ab74ab3c9b7b13227 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 13 Jan 2026 14:03:10 +0330 Subject: [PATCH 04/17] add rollcall case history upsert --- .../RollCall/CaseHistoryController.cs | 23 +++++++++++++++---- .../BaseControllers/AdminBaseController.cs | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index df1f1b9d..6ecead24 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -5,10 +5,10 @@ using ServiceHost.BaseControllers; namespace ServiceHost.Areas.Client.Controllers.RollCall; -public class CaseHistoryController:ClientBaseController +public class CaseHistoryController : ClientBaseController { private readonly IRollCallApplication _rollCallApplication; - private long _workshopId; + private readonly long _workshopId; public CaseHistoryController(IRollCallApplication rollCallApplication, IAuthHelper authHelper) @@ -18,14 +18,29 @@ public class CaseHistoryController:ClientBaseController } [HttpGet] - public async Task>> GetTitles(RollCallCaseHistorySearchModel searchModel) + public async Task>> GetTitles( + RollCallCaseHistorySearchModel searchModel) { return await _rollCallApplication.GetCaseHistoryTitles(_workshopId, searchModel); } [HttpGet("details")] - public async Task>> GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) + public async Task>> GetDetails(string titleId, + RollCallCaseHistorySearchModel searchModel) { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); } + + /// + /// ایجاد و ویرایش + /// + /// + /// + [HttpPost] + public ActionResult Upsert(CreateOrEditEmployeeRollCall command) + { + command.WorkshopId = _workshopId; + return _rollCallApplication.ManualEdit(command); + } + } \ No newline at end of file diff --git a/ServiceHost/BaseControllers/AdminBaseController.cs b/ServiceHost/BaseControllers/AdminBaseController.cs index 2ba56a71..059774bf 100644 --- a/ServiceHost/BaseControllers/AdminBaseController.cs +++ b/ServiceHost/BaseControllers/AdminBaseController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; + namespace ServiceHost.BaseControllers; [Authorize(Policy = "AdminArea")] From 8850328fd4b7f5ba64b7a39585d969ae4d462ae3 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 13 Jan 2026 16:08:13 +0330 Subject: [PATCH 05/17] add GetEditDetails controller method --- .../RollCall/CaseHistoryController.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index 6ecead24..5dea4b3f 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -43,4 +43,25 @@ public class CaseHistoryController : ClientBaseController return _rollCallApplication.ManualEdit(command); } + // [HttpGet("edit")] + // public ActionResult<> GetEditDetails(string date,long employeeId) + // { + // var result = _rollCallApplication.GetWorkshopEmployeeRollCallsForDate(_workshopId, employeeId, date); + // //var dates = _rollCallApplication.GetEditableDatesForManualEdit(date.ToGeorgianDateTime()); + // var name = _rollCallEmployeeApplication.GetByEmployeeIdAndWorkshopId(employeeId, _workshopId); + // + // var total = new TimeSpan(result.Sum(x => + // (x.EndDate!.Value.Ticks - x.StartDate!.Value.Ticks))); + // + // var command = new EmployeeRollCallsViewModel() + // { + // EmployeeFullName = name.EmployeeFullName, + // EmployeeId = employeeId, + // DateFa = date, + // //EditableDates = dates, + // RollCalls = result, + // TotalRollCallsDuration = total.ToFarsiHoursAndMinutes("-") + // }; + // } + } \ No newline at end of file From d179c90c487c681135da4765e2f1752274b4ed26 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 13 Jan 2026 18:31:10 +0330 Subject: [PATCH 06/17] change paginated to list --- Company.Domain/RollCallAgg/IRollCallRepository.cs | 2 +- .../RollCall/IRollCallApplication.cs | 3 ++- CompanyManagment.Application/RollCallApplication.cs | 2 +- CompanyManagment.EFCore/Repository/RollCallRepository.cs | 8 +++----- .../Client/Controllers/RollCall/CaseHistoryController.cs | 6 +++++- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Company.Domain/RollCallAgg/IRollCallRepository.cs b/Company.Domain/RollCallAgg/IRollCallRepository.cs index 4afc1f6a..9d05d620 100644 --- a/Company.Domain/RollCallAgg/IRollCallRepository.cs +++ b/Company.Domain/RollCallAgg/IRollCallRepository.cs @@ -94,7 +94,7 @@ namespace Company.Domain.RollCallAgg #endregion Task> GetCaseHistoryTitles(long workshopId,RollCallCaseHistorySearchModel searchModel); - Task> GetCaseHistoryDetails(long workshopId, + Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel); } } diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index 0a717f0d..bdff1e85 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -129,7 +129,8 @@ namespace CompanyManagment.App.Contracts.RollCall Task RecalculateValues(long workshopId, List command); Task> GetCaseHistoryTitles(long workshopId,RollCallCaseHistorySearchModel searchModel); - Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel); + Task> GetCaseHistoryDetails(long workshopId, string titleId, + RollCallCaseHistorySearchModel searchModel); } public class RollCallCaseHistoryDetail diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 96594dc8..7f145407 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -864,7 +864,7 @@ public class RollCallApplication : IRollCallApplication return await _rollCallRepository.GetCaseHistoryTitles(workshopId,searchModel); } - public async Task> GetCaseHistoryDetails(long workshopId, + public async Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel) { return await _rollCallRepository.GetCaseHistoryDetails(workshopId, titleId, searchModel); diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index eb09e73a..eb5e40f7 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -2285,7 +2285,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos return res; } - public async Task> GetCaseHistoryDetails(long workshopId, string titleId, + public async Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel) { var query = _context.RollCallEmployeesStatus @@ -2344,7 +2344,7 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos .Where(x => x.WorkshopId == workshopId && employeeIds.Contains(x.EmployeeId)).ToListAsync(); - var res = new PagedResult(); + var res = new List(); foreach (var date in dates) { var rollCallInDate = rollCalls @@ -2379,12 +2379,10 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos PersonnelCode = personnelCodes.FirstOrDefault(y => y.EmployeeId == employeeId)?.PersonnelCode .ToString(), }; - res.List.Add(item); + res.Add(item); } } return res; - - return new PagedResult(); } } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index 5dea4b3f..9ad0ee58 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -25,7 +25,7 @@ public class CaseHistoryController : ClientBaseController } [HttpGet("details")] - public async Task>> GetDetails(string titleId, + public async Task>> GetDetails(string titleId, RollCallCaseHistorySearchModel searchModel) { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); @@ -42,6 +42,10 @@ public class CaseHistoryController : ClientBaseController command.WorkshopId = _workshopId; return _rollCallApplication.ManualEdit(command); } + + // [HttpGet("print")] + // public ActionResult<> + // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) From 4c7599b568af6c4bfb4d5492bfdfc089785ab174 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 13 Jan 2026 18:50:18 +0330 Subject: [PATCH 07/17] add print to rollcall case history --- .../Client/Controllers/RollCall/CaseHistoryController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index 9ad0ee58..cb2e3ff5 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -43,9 +43,12 @@ public class CaseHistoryController : ClientBaseController return _rollCallApplication.ManualEdit(command); } - // [HttpGet("print")] - // public ActionResult<> - + [HttpGet("print")] + public async Task>> GetPrintDetails(string titleId, + RollCallCaseHistorySearchModel searchModel) + { + return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); + } // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) From eb8352e8fcfe51de8ada41776100ac5a62e14a60 Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 14 Jan 2026 09:37:55 +0330 Subject: [PATCH 08/17] add rollcall download excel controller. --- .../Controllers/RollCall/CaseHistoryController.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index cb2e3ff5..1e709fa0 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -1,4 +1,5 @@ using _0_Framework.Application; +using CompanyManagement.Infrastructure.Excel.RollCall; using CompanyManagment.App.Contracts.RollCall; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; @@ -49,6 +50,16 @@ public class CaseHistoryController : ClientBaseController { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); } + + [HttpGet("excel")] + public async Task GetDownload() + { + byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(caseHistoryRollCallExcelForOneDay); + return File(excelBytes, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); + + } // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) From 90fa0ac8f8eed3cdc273c6f95faba1e27877cedd Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 14 Jan 2026 10:20:58 +0330 Subject: [PATCH 09/17] change excel download api controller --- .../Client/Controllers/RollCall/CaseHistoryController.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index 1e709fa0..40a8a9d4 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -52,9 +52,10 @@ public class CaseHistoryController : ClientBaseController } [HttpGet("excel")] - public async Task GetDownload() + public async Task GetDownload(string titleId,RollCallCaseHistorySearchModel searchModel) { - byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(caseHistoryRollCallExcelForOneDay); + var data = await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); + byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); return File(excelBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); From 355ec72140a1c7a1466a6a29c2d8328cc1e5a0c5 Mon Sep 17 00:00:00 2001 From: mahan Date: Sun, 18 Jan 2026 14:17:23 +0330 Subject: [PATCH 10/17] comment excel data --- .../RollCall/CaseHistoryController.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs index 40a8a9d4..5f8b8b77 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs @@ -51,16 +51,16 @@ public class CaseHistoryController : ClientBaseController return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); } - [HttpGet("excel")] - public async Task GetDownload(string titleId,RollCallCaseHistorySearchModel searchModel) - { - var data = await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); - byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); - return File(excelBytes, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); - - } + // [HttpGet("excel")] + // public async Task GetDownload(string titleId,RollCallCaseHistorySearchModel searchModel) + // { + // var data = await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); + // byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); + // return File(excelBytes, + // "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + // $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); + // + // } // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) From 5c3c9739d17c88a3ad4977e6aabfd68d19ce22a7 Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 19 Jan 2026 15:30:28 +0330 Subject: [PATCH 11/17] fix regex and validation for rollcall history case details --- .../Repository/RollCallRepository.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index eb5e40f7..f0758afb 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -20,6 +20,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using _0_Framework.Exceptions; +using OfficeOpenXml.Packaging.Ionic.Zip; namespace CompanyManagment.EFCore.Repository; @@ -2297,26 +2298,33 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos //این برای این هست که اگر بر اساس پرسنل جستجو شده بود و در titleId اگر به فرمت YYYY_MM اومد به این معنی هست که باید بر طبق ماه فیلتر بشه نه به صورت روزانه if (searchModel.EmployeeId is > 0) { - //TODO: set correct regex. - // if (!Regex.IsMatch(titleId, "")) - // throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است"); + 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(); - - startDate = startDateFa.ToGeorgianDateTime(); - endDate = endDateFa.ToGeorgianDateTime(); + + if (!endDateFa.TryToGeorgianDateTime(out endDate)) + { + throw new BadRequestException("تاریخ وارد شده نامعتبر است"); + } query = query .Where(x => x.RollCallEmployee.EmployeeId == searchModel.EmployeeId); } else { - //TODO: set correct regex. - // if (!Regex.IsMatch(titleId, "")) - // throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است"); + if (!Regex.IsMatch(titleId, @"^\d{4}/\d{2}/\d{2}$")) + throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است"); + startDate = titleId.ToGeorgianDateTime(); endDate = startDate; From 5942075dd625c35955fd3bbf4681025968201a57 Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 2 Feb 2026 17:31:37 +0330 Subject: [PATCH 12/17] refactor roll call case history controller and add total working hours endpoint --- ...er.cs => RollCallCaseHistoryController.cs} | 49 +++++++++++++++-- .../Company/RollCall/CaseHistory.cshtml.cs | 4 +- ServiceHost/Controllers/GeneralController.cs | 55 ++++--------------- 3 files changed, 57 insertions(+), 51 deletions(-) rename ServiceHost/Areas/Client/Controllers/RollCall/{CaseHistoryController.cs => RollCallCaseHistoryController.cs} (71%) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs similarity index 71% rename from ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs rename to ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs index 5f8b8b77..5bbf6c70 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/CaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs @@ -6,12 +6,12 @@ using ServiceHost.BaseControllers; namespace ServiceHost.Areas.Client.Controllers.RollCall; -public class CaseHistoryController : ClientBaseController +public class RollCallCaseHistoryController : ClientBaseController { private readonly IRollCallApplication _rollCallApplication; private readonly long _workshopId; - public CaseHistoryController(IRollCallApplication rollCallApplication, + public RollCallCaseHistoryController(IRollCallApplication rollCallApplication, IAuthHelper authHelper) { _rollCallApplication = rollCallApplication; @@ -50,6 +50,48 @@ public class CaseHistoryController : ClientBaseController { return await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); } + + [HttpGet("total-working")] + public ActionResult> OnGetTotalWorking( + string startDate, + string startTime, + string endDate, + string endTime) + { + var op = new OperationResult(); + const string emptyValue = "-"; + + if (!TryParseDateTime(startDate, startTime, out var start) || + !TryParseDateTime(endDate, endTime, out var end)) + { + return op.Succcedded(emptyValue); + } + + if (start >= end) + { + return op.Succcedded(emptyValue); + } + + var duration = (end - start).ToFarsiHoursAndMinutes(emptyValue); + return op.Succcedded(duration); + } + + private static bool TryParseDateTime(string date, string time, out DateTime result) + { + result = default; + + try + { + var dateTime = date.ToGeorgianDateTime(); + var timeOnly = TimeOnly.Parse(time); + result = dateTime.AddTicks(timeOnly.Ticks); + return true; + } + catch + { + return false; + } + } // [HttpGet("excel")] // public async Task GetDownload(string titleId,RollCallCaseHistorySearchModel searchModel) @@ -61,7 +103,7 @@ public class CaseHistoryController : ClientBaseController // $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); // // } - + // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) // { @@ -82,5 +124,4 @@ public class CaseHistoryController : ClientBaseController // TotalRollCallsDuration = total.ToFarsiHoursAndMinutes("-") // }; // } - } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Pages/Company/RollCall/CaseHistory.cshtml.cs b/ServiceHost/Areas/Client/Pages/Company/RollCall/CaseHistory.cshtml.cs index 04e0d1b0..7b4f8966 100644 --- a/ServiceHost/Areas/Client/Pages/Company/RollCall/CaseHistory.cshtml.cs +++ b/ServiceHost/Areas/Client/Pages/Company/RollCall/CaseHistory.cshtml.cs @@ -250,9 +250,7 @@ namespace ServiceHost.Areas.Client.Pages.Company.RollCall var span = end - start; var hours = (int)span.TotalHours; var minutes = span.Minutes; - - - + if (hours > 0 && minutes > 0) { return new JsonResult(new diff --git a/ServiceHost/Controllers/GeneralController.cs b/ServiceHost/Controllers/GeneralController.cs index 7871eef9..01ed3d64 100644 --- a/ServiceHost/Controllers/GeneralController.cs +++ b/ServiceHost/Controllers/GeneralController.cs @@ -42,6 +42,15 @@ public class GeneralController : GeneralBaseController currentDate }); } + [HttpGet("persian-day-of-week")] + public ActionResult> OnGetDayOfWeek(string dateFa) + { + var op = new OperationResult(); + if (!dateFa.TryToGeorgianDateTime(out DateTime date)) + return op.Failed("تاریخ وارد شده نامعتبر است"); + + return op.Succcedded(date.DayOfWeek.DayOfWeeKToPersian()); + } // [HttpGet("pm-permissions")] // public IActionResult GetPMPermissions() @@ -96,44 +105,8 @@ public class GeneralController : GeneralBaseController var statusCode = isSuccess ? "1" : "0"; return $"{baseUrl}/callback?Status={statusCode}&transactionId={transactionId}"; } -} - -public class TokenReq -{ - public long Amount { get; set; } - - public string CallbackUrl { get; set; } - - [Display(Name = "شماره فاکتور")] - [MaxLength(100)] - [Required] - [Key] - // be ezaye har pazirande bayad yekta bashad - public string invoiceID { get; set; } - - [Required] public long terminalID { get; set; } - - /* - * JSON Bashad - * etelaate takmili site harchi - * nabayad char khas dashte bashe (*'"xp_%!+- ...) - */ - public string Payload { get; set; } = ""; - public string email { get; set; } -} - -public class TokenResp -{ - // if 0 = success - public int Status { get; set; } - public string AccessToken { get; set; } -} - -public class PayRequest -{ - [Required] [MaxLength(3000)] public string token { get; set; } - [Required] public long terminalID { get; set; } - public string nationalCode { get; set; } + + } public class SepehrGatewayPayResponse @@ -169,10 +142,4 @@ public class SepehrGatewayPayResponse public string issuerbank { get; set; } [Display(Name = " شماره کارت ")] public string cardnumber { get; set; } -} - -public class AdviceReq -{ - [Display(Name = " رسید دیجیتال ")] public string digitalreceipt { get; set; } - public long Tid { get; set; } } \ No newline at end of file From 88744bd4cf2e7d5bd65507b99092d3182de2dfb9 Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 2 Feb 2026 17:54:33 +0330 Subject: [PATCH 13/17] add endpoint to download case history as Excel file --- .../RollCall/IRollCallApplication.cs | 10 +++++++ .../RollCallApplication.cs | 16 +++++++++-- .../RollCall/RollCallCaseHistoryController.cs | 27 ++++++++++--------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index bdff1e85..31960578 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -131,6 +131,16 @@ namespace CompanyManagment.App.Contracts.RollCall Task> GetCaseHistoryTitles(long workshopId,RollCallCaseHistorySearchModel searchModel); Task> GetCaseHistoryDetails(long workshopId, string titleId, RollCallCaseHistorySearchModel searchModel); + + Task DownloadCaseHistoryExcel(long workshopId, string titleId, + RollCallCaseHistorySearchModel searchModel); + } + + public class RollCallCaseHistoryExcelDto + { + public byte[] Bytes { get; set; } + public string FileName { get; set; } + public string MimeType { get; set; } } public class RollCallCaseHistoryDetail diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 7f145407..1397b15b 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -16,6 +16,7 @@ using Company.Domain.LeaveAgg; using Company.Domain.RollCallAgg; using Company.Domain.RollCallAgg.DomainService; using Company.Domain.RollCallEmployeeAgg; +using Company.Domain.WorkshopAgg; using CompanyManagment.App.Contracts.Checkout; using CompanyManagment.App.Contracts.Employee; using CompanyManagment.App.Contracts.RollCall; @@ -34,8 +35,9 @@ public class RollCallApplication : IRollCallApplication private readonly ICustomizeWorkshopSettingsRepository _customizeWorkshopSettingsRepository; private readonly ICustomizeWorkshopEmployeeSettingsRepository _customizeWorkshopEmployeeSettingsRepository; private readonly ICustomizeCheckoutTempRepository _customizeCheckoutTempRepository; + private readonly IWorkshopRepository _workshopRepository; - public RollCallApplication(IRollCallRepository rollCallRepository, IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, ILeaveRepository leaveRepository, ICustomizeCheckoutRepository customizeCheckoutRepository, ICheckoutRepository checkoutRepository, IRollCallDomainService rollCallDomainService, ICustomizeWorkshopSettingsRepository customizeWorkshopSettingsRepository, ICustomizeWorkshopEmployeeSettingsRepository customizeWorkshopEmployeeSettingsRepository, ICustomizeCheckoutTempRepository customizeCheckoutTempRepository) + public RollCallApplication(IRollCallRepository rollCallRepository, IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, ILeaveRepository leaveRepository, ICustomizeCheckoutRepository customizeCheckoutRepository, ICheckoutRepository checkoutRepository, IRollCallDomainService rollCallDomainService, ICustomizeWorkshopSettingsRepository customizeWorkshopSettingsRepository, ICustomizeWorkshopEmployeeSettingsRepository customizeWorkshopEmployeeSettingsRepository, ICustomizeCheckoutTempRepository customizeCheckoutTempRepository, IWorkshopRepository workshopRepository) { _rollCallRepository = rollCallRepository; _rollCallEmployeeRepository = rollCallEmployeeRepository; @@ -47,7 +49,8 @@ public class RollCallApplication : IRollCallApplication _customizeWorkshopSettingsRepository = customizeWorkshopSettingsRepository; _customizeWorkshopEmployeeSettingsRepository = customizeWorkshopEmployeeSettingsRepository; _customizeCheckoutTempRepository = customizeCheckoutTempRepository; - } + _workshopRepository = workshopRepository; + } public OperationResult Create(CreateRollCall command) { @@ -869,4 +872,13 @@ public class RollCallApplication : IRollCallApplication { return await _rollCallRepository.GetCaseHistoryDetails(workshopId, titleId, searchModel); } + + public async Task DownloadCaseHistoryExcel(long workshopId, string titleId, + RollCallCaseHistorySearchModel searchModel) + { + var data = await _rollCallRepository + .GetCaseHistoryDetails(workshopId, titleId, searchModel); + var workshopFullName = _workshopRepository.(workshopId); + byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); + } } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs index 5bbf6c70..fc22ec04 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs @@ -1,6 +1,7 @@ using _0_Framework.Application; using CompanyManagement.Infrastructure.Excel.RollCall; using CompanyManagment.App.Contracts.RollCall; +using CompanyManagment.App.Contracts.Workshop; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; @@ -10,11 +11,12 @@ public class RollCallCaseHistoryController : ClientBaseController { private readonly IRollCallApplication _rollCallApplication; private readonly long _workshopId; - + private readonly IWorkshopApplication _workshopApplication; public RollCallCaseHistoryController(IRollCallApplication rollCallApplication, - IAuthHelper authHelper) + IAuthHelper authHelper, IWorkshopApplication workshopApplication) { _rollCallApplication = rollCallApplication; + _workshopApplication = workshopApplication; _workshopId = authHelper.GetWorkshopId(); } @@ -93,16 +95,17 @@ public class RollCallCaseHistoryController : ClientBaseController } } - // [HttpGet("excel")] - // public async Task GetDownload(string titleId,RollCallCaseHistorySearchModel searchModel) - // { - // var data = await _rollCallApplication.GetCaseHistoryDetails(_workshopId, titleId, searchModel); - // byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); - // return File(excelBytes, - // "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - // $"{workshopFullName} - {caseHistoryRollCallExcelForOneDay.DayOfWeekFa}،{caseHistoryRollCallExcelForOneDay.DateFa}.xlsx"); - // - // } + [HttpGet("excel")] + public async Task GetDownload(string titleId, RollCallCaseHistorySearchModel searchModel) + { + var res =await _rollCallApplication.DownloadCaseHistoryExcel(_workshopId, titleId, searchModel); + + + return File(res.Bytes, + res.MimeType, + res.FileName); + + } // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) From bf2a102a55592079b2096f5f48b333a5bf11d036 Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 2 Feb 2026 19:07:11 +0330 Subject: [PATCH 14/17] add Excel export functionality for roll call case history --- .../RollCall/RollCallExcelGenerator.cs | 111 ++++++++++++++++++ .../CompanyManagment.Application.csproj | 1 + .../RollCallApplication.cs | 47 +++++++- ServiceHost/Properties/launchSettings.json | 2 +- 4 files changed, 155 insertions(+), 6 deletions(-) diff --git a/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs index 8c749dd4..8f0247a3 100644 --- a/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs @@ -1,6 +1,12 @@ using _0_Framework.Excel; +using _0_Framework.Application; +using CompanyManagment.App.Contracts.RollCall; using OfficeOpenXml; using OfficeOpenXml.Drawing; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; namespace CompanyManagement.Infrastructure.Excel.RollCall; @@ -308,6 +314,111 @@ public class RollCallExcelGenerator : ExcelGenerator return package.GetAsByteArray(); } + public static byte[] CaseHistoryExcelForEmployee(List data, string titleId) + { + if (!Regex.IsMatch(titleId, @"^\d{4}_\d{2}$")) + throw new ArgumentException("Invalid titleId format.", nameof(titleId)); + + var splitDate = titleId.Split("_"); + var year = Convert.ToInt32(splitDate.First()); + var month = Convert.ToInt32(splitDate.Last()); + + var startDateFa = $"{year:D4}/{month:D2}/01"; + var startDate = startDateFa.ToGeorgianDateTime(); + var endDateFa = startDateFa.FindeEndOfMonth(); + var endDate = endDateFa.ToGeorgianDateTime(); + + var dateRange = (int)(endDate.Date - startDate.Date).TotalDays + 1; + var dates = Enumerable.Range(0, dateRange).Select(x => startDate.AddDays(x)).ToList(); + + var safeData = data ?? new List(); + var first = safeData.FirstOrDefault(); + var totalWorkingTime = new TimeSpan(safeData.Sum(x => x.TotalWorkingTime.Ticks)); + + var viewModel = new CaseHistoryRollCallExcelForEmployeeViewModel + { + EmployeeId = first?.EmployeeId ?? 0, + DateGr = startDate, + PersonnelCode = first?.PersonnelCode, + EmployeeFullName = first?.EmployeeFullName, + PersianMonthName = month.ToFarsiMonthByIntNumber(), + PersianYear = year.ToString(), + TotalWorkingHoursFa = totalWorkingTime.ToFarsiHoursAndMinutes("-"), + TotalWorkingTimeSpan = $"{(int)totalWorkingTime.TotalHours}:{totalWorkingTime.Minutes:00}", + RollCalls = dates.Select((date, index) => + { + var item = index < safeData.Count ? safeData[index] : null; + var records = item?.Records ?? new List(); + + return new RollCallItemForEmployeeExcelViewModel + { + DateGr = date, + DateFa = date.ToFarsi(), + DayOfWeekFa = date.DayOfWeek.DayOfWeeKToPersian(), + PersonnelCode = item?.PersonnelCode, + EmployeeFullName = item?.EmployeeFullName, + IsAbsent = item?.Status == RollCallRecordStatus.Absent, + HasLeave = item?.Status == RollCallRecordStatus.Leaved, + IsHoliday = false, + TotalWorkingHours = (item?.TotalWorkingTime ?? TimeSpan.Zero).ToFarsiHoursAndMinutes("-"), + StartsItems = JoinRecords(records, r => r.StartTime), + EndsItems = JoinRecords(records, r => r.EndTime), + EnterTimeDifferences = JoinRecords(records, r => FormatSignedTimeSpan(r.EntryTimeDifference)), + ExitTimeDifferences = JoinRecords(records, r => FormatSignedTimeSpan(r.ExitTimeDifference)) + }; + }).ToList() + }; + + return CaseHistoryExcelForEmployee(viewModel); + } + + public static byte[] CaseHistoryExcelForOneDay(List data, string titleId) + { + if (!Regex.IsMatch(titleId, @"^\d{4}/\d{2}/\d{2}$")) + throw new ArgumentException("Invalid titleId format.", nameof(titleId)); + + var dateGr = titleId.ToGeorgianDateTime(); + var safeData = data ?? new List(); + + var viewModel = new CaseHistoryRollCallForOneDayViewModel + { + DateFa = titleId, + DateGr = dateGr, + DayOfWeekFa = dateGr.DayOfWeek.DayOfWeeKToPersian(), + RollCalls = safeData.Select(item => + { + var records = item.Records ?? new List(); + return new RollCallItemForOneDayExcelViewModel + { + EmployeeFullName = item.EmployeeFullName, + PersonnelCode = item.PersonnelCode, + StartsItems = JoinRecords(records, r => r.StartTime), + EndsItems = JoinRecords(records, r => r.EndTime), + TotalWorkingHours = item.TotalWorkingTime.ToFarsiHoursAndMinutes("-") + }; + }).ToList() + }; + + return CaseHistoryExcelForOneDay(viewModel); + } + + private static string JoinRecords(IEnumerable records, Func selector) + { + var safeRecords = records ?? Enumerable.Empty(); + var values = safeRecords.Select(selector).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + return values.Count == 0 ? string.Empty : string.Join(Environment.NewLine, values); + } + + private static string FormatSignedTimeSpan(TimeSpan value) + { + if (value == TimeSpan.Zero) + return "-"; + + var abs = value.Duration(); + var sign = value.Ticks < 0 ? "-" : "+"; + return $"{(int)abs.TotalHours}:{abs.Minutes:00}{sign}"; + } + private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late) { if (early == TimeSpan.Zero && late == TimeSpan.Zero) diff --git a/CompanyManagment.Application/CompanyManagment.Application.csproj b/CompanyManagment.Application/CompanyManagment.Application.csproj index f6e0f038..d33e4227 100644 --- a/CompanyManagment.Application/CompanyManagment.Application.csproj +++ b/CompanyManagment.Application/CompanyManagment.Application.csproj @@ -13,6 +13,7 @@ + diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 1397b15b..e987d47e 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using _0_Framework.Application; using _0_Framework.Domain.CustomizeCheckoutShared.Enums; +using _0_Framework.Exceptions; using Company.Domain.CheckoutAgg; using Company.Domain.CustomizeCheckoutAgg; using Company.Domain.CustomizeCheckoutTempAgg; @@ -17,6 +19,7 @@ using Company.Domain.RollCallAgg; using Company.Domain.RollCallAgg.DomainService; using Company.Domain.RollCallEmployeeAgg; using Company.Domain.WorkshopAgg; +using CompanyManagement.Infrastructure.Excel.RollCall; using CompanyManagment.App.Contracts.Checkout; using CompanyManagment.App.Contracts.Employee; using CompanyManagment.App.Contracts.RollCall; @@ -874,11 +877,45 @@ public class RollCallApplication : IRollCallApplication } public async Task DownloadCaseHistoryExcel(long workshopId, string titleId, - RollCallCaseHistorySearchModel searchModel) + RollCallCaseHistorySearchModel searchModel) { - var data = await _rollCallRepository - .GetCaseHistoryDetails(workshopId, titleId, searchModel); - var workshopFullName = _workshopRepository.(workshopId); - byte[] excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data); + var data = await _rollCallRepository + .GetCaseHistoryDetails(workshopId, titleId, searchModel); + string nameSecondPart = ""; + byte[] excelBytes; + + if (Regex.IsMatch(titleId, @"^\d{4}_\d{2}$")) + { + var splitDate = titleId.Split("_"); + var year = Convert.ToInt32(splitDate.First()); + var month = Convert.ToInt32(splitDate.Last()); + + var monthName = Convert.ToInt32(month).ToFarsiMonthByIntNumber(); + nameSecondPart = $"{year}/{monthName}"; + excelBytes = RollCallExcelGenerator.CaseHistoryExcelForEmployee(data, titleId); + } + else if (Regex.IsMatch(titleId, @"^\d{4}/\d{2}/\d{2}$")) + { + var oneDayDate = titleId.ToGeorgianDateTime(); + nameSecondPart = $" {oneDayDate.DayOfWeek.DayOfWeeKToPersian()}،{titleId}"; + excelBytes = RollCallExcelGenerator.CaseHistoryExcelForOneDay(data, titleId); + } + else + { + throw new BadRequestException("شناسه سر تیتر وارد شده نامعتبر است"); + } + + var workshopFullName = _workshopRepository.Get(workshopId)?.WorkshopFullName ?? "بدون کارگاه"; + + var fileName = $"{workshopFullName} - {nameSecondPart}.xlsx"; + + var res = new RollCallCaseHistoryExcelDto() + { + Bytes = excelBytes, + MimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + FileName = fileName + }; + + return res; } } \ No newline at end of file diff --git a/ServiceHost/Properties/launchSettings.json b/ServiceHost/Properties/launchSettings.json index 788962e4..3c6abef3 100644 --- a/ServiceHost/Properties/launchSettings.json +++ b/ServiceHost/Properties/launchSettings.json @@ -19,7 +19,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;", + "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5005", "jsWebView2Debugging": false, "hotReloadEnabled": true }, From 3dace574ffaca65caa555b995bc6d1fde0d6597e Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 2 Feb 2026 19:08:25 +0330 Subject: [PATCH 15/17] refactor date parsing method in RollCallCaseHistoryController --- .../RollCall/RollCallCaseHistoryController.cs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs index fc22ec04..ec8d347d 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs @@ -78,28 +78,12 @@ public class RollCallCaseHistoryController : ClientBaseController return op.Succcedded(duration); } - private static bool TryParseDateTime(string date, string time, out DateTime result) - { - result = default; - - try - { - var dateTime = date.ToGeorgianDateTime(); - var timeOnly = TimeOnly.Parse(time); - result = dateTime.AddTicks(timeOnly.Ticks); - return true; - } - catch - { - return false; - } - } + [HttpGet("excel")] public async Task GetDownload(string titleId, RollCallCaseHistorySearchModel searchModel) { var res =await _rollCallApplication.DownloadCaseHistoryExcel(_workshopId, titleId, searchModel); - return File(res.Bytes, res.MimeType, @@ -127,4 +111,22 @@ public class RollCallCaseHistoryController : ClientBaseController // TotalRollCallsDuration = total.ToFarsiHoursAndMinutes("-") // }; // } + + + private static bool TryParseDateTime(string date, string time, out DateTime result) + { + result = default; + + try + { + var dateTime = date.ToGeorgianDateTime(); + var timeOnly = TimeOnly.Parse(time); + result = dateTime.AddTicks(timeOnly.Ticks); + return true; + } + catch + { + return false; + } + } } \ No newline at end of file From dddc4b143a248c3ff0534137381b0b518a7cf156 Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 5 Feb 2026 11:29:41 +0330 Subject: [PATCH 16/17] add edit functionality for employee roll call details --- .../RollCall/RollCallCaseHistoryController.cs | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs index ec8d347d..d9928860 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs @@ -1,6 +1,7 @@ using _0_Framework.Application; using CompanyManagement.Infrastructure.Excel.RollCall; using CompanyManagment.App.Contracts.RollCall; +using CompanyManagment.App.Contracts.RollCallEmployee; using CompanyManagment.App.Contracts.Workshop; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; @@ -12,11 +13,14 @@ public class RollCallCaseHistoryController : ClientBaseController private readonly IRollCallApplication _rollCallApplication; private readonly long _workshopId; private readonly IWorkshopApplication _workshopApplication; + private readonly IRollCallEmployeeApplication _rollCallEmployeeApplication; public RollCallCaseHistoryController(IRollCallApplication rollCallApplication, - IAuthHelper authHelper, IWorkshopApplication workshopApplication) + IAuthHelper authHelper, IWorkshopApplication workshopApplication, + IRollCallEmployeeApplication rollCallEmployeeApplication) { _rollCallApplication = rollCallApplication; _workshopApplication = workshopApplication; + _rollCallEmployeeApplication = rollCallEmployeeApplication; _workshopId = authHelper.GetWorkshopId(); } @@ -91,6 +95,45 @@ public class RollCallCaseHistoryController : ClientBaseController } + [HttpGet("edit")] + public ActionResult GetEditDetails(string date, long employeeId) + { + var result = _rollCallApplication.GetWorkshopEmployeeRollCallsForDate(_workshopId, employeeId, date); + //var dates = _rollCallApplication.GetEditableDatesForManualEdit(date.ToGeorgianDateTime()); + var name = _rollCallEmployeeApplication.GetByEmployeeIdAndWorkshopId(employeeId, _workshopId); + + var total = new TimeSpan(result.Sum(x => + (x.EndDate!.Value.Ticks - x.StartDate!.Value.Ticks))); + + var res = new EditRollCallDetailsResult() + { + EmployeeFullName = name.EmployeeFullName, + EmployeeId = employeeId, + DateFa = date, + //EditableDates = dates, + Records = result.Select(x=>new EmployeeRollCallRecord() + { + Date = x.DateGr, + EndDate = x.EndDateFa, + EndTime = x.EndTimeString, + RollCallId = x.Id, + StartDate = x.StartDateFa, + StartTime = x.StartTimeString + }).ToList(), + TotalRollCallsDuration = total.ToFarsiHoursAndMinutes("-") + }; + + return res; + } + [HttpPost("edit")] + public ActionResult Edit(CreateOrEditEmployeeRollCall command) + { + command.WorkshopId = _workshopId; + var result = _rollCallApplication.ManualEdit(command); + return result; + } + + // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) // { @@ -129,4 +172,13 @@ public class RollCallCaseHistoryController : ClientBaseController return false; } } +} + +public class EditRollCallDetailsResult +{ + public string EmployeeFullName { get; set; } + public long EmployeeId { get; set; } + public string DateFa { get; set; } + public string TotalRollCallsDuration { get; set; } + public List Records { get; set; } } \ No newline at end of file From 9475c786d3ec6220c4b8d901ffce8d50d39845e5 Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 5 Feb 2026 11:58:52 +0330 Subject: [PATCH 17/17] add endpoint to remove employee roll calls by date --- .../RollCall/RollCallCaseHistoryController.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs index d9928860..e82b436e 100644 --- a/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs +++ b/ServiceHost/Areas/Client/Controllers/RollCall/RollCallCaseHistoryController.cs @@ -132,7 +132,17 @@ public class RollCallCaseHistoryController : ClientBaseController var result = _rollCallApplication.ManualEdit(command); return result; } - + [HttpDelete("delete")] + public IActionResult OnPostRemoveEmployeeRollCallsInDate(RemoveEmployeeRollCallRequest request) + { + var result = _rollCallApplication.RemoveEmployeeRollCallsInDate(_workshopId, request.EmployeeId, request.Date); + + return new JsonResult(new + { + success = result.IsSuccedded, + message = result.Message, + }); + } // [HttpGet("edit")] // public ActionResult<> GetEditDetails(string date,long employeeId) @@ -181,4 +191,10 @@ public class EditRollCallDetailsResult public string DateFa { get; set; } public string TotalRollCallsDuration { get; set; } public List Records { get; set; } -} \ No newline at end of file +} + +public class RemoveEmployeeRollCallRequest +{ + public long EmployeeId { get; set; } + public string Date { get; set; } +}