From c168843afc713554eb99177d463b22d71ebe6cbd Mon Sep 17 00:00:00 2001 From: MahanCh Date: Sun, 11 May 2025 17:02:48 +0330 Subject: [PATCH] add new find rotating shifts --- .../DomainService/IRollCallDomainService.cs | 93 +++++++++++++++---- .../RollCallApplication.cs | 4 +- .../Repository/RollCallRepository.cs | 3 +- .../Pages/Company/AndroidApk/Index.cshtml.cs | 6 +- 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/Company.Domain/RollCallAgg/DomainService/IRollCallDomainService.cs b/Company.Domain/RollCallAgg/DomainService/IRollCallDomainService.cs index 9c13b981..90b53377 100644 --- a/Company.Domain/RollCallAgg/DomainService/IRollCallDomainService.cs +++ b/Company.Domain/RollCallAgg/DomainService/IRollCallDomainService.cs @@ -31,6 +31,7 @@ public interface IRollCallDomainService void CalculateTimeDifferences(RollCall rollCall); (DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, ICollection rotatingShifts); + (DateTime start, DateTime end) FindRotatingShift(List<(DateTime StartDate, DateTime EndDate)> rollcalls, ICollection rotatingShifts); } public class RollCallDomainService : IRollCallDomainService @@ -257,7 +258,7 @@ public class RollCallDomainService : IRollCallDomainService var earlyEntryRollCall = rollCallsInShift.OrderBy(x => x.StartDate).FirstOrDefault(x => x.StartDate < employeeShift.start); var lateEntryRollCall = rollCallsInShift.OrderBy(x => x.StartDate).FirstOrDefault(x => x.StartDate > employeeShift.start); - + @@ -354,7 +355,9 @@ public class RollCallDomainService : IRollCallDomainService var rotatingShifts = shiftDetails.rotatingShifts; - var shift = FindRotatingShift(starDateTime, endDateTime, rotatingShifts); + var rollCallStartEnds = rollCalls.Select(x => (x.StartDate.Value, x.EndDate.Value)).ToList(); + + var shift = FindRotatingShift(rollCallStartEnds, rotatingShifts); var rotatingShiftStart = shift.start; var rotatingShiftEnd = shift.end; @@ -374,8 +377,7 @@ public class RollCallDomainService : IRollCallDomainService var earlyEntryRollCallRotating = rollCallsInRotatingShift.OrderBy(x => x.StartDate).FirstOrDefault(x => x.StartDate < shift.start); var lateEntryRollCallRotating = rollCallsInRotatingShift.OrderBy(x => x.StartDate).FirstOrDefault(x => x.StartDate > shift.start); - earlyEntryRollCallRotating?.ClearTimeDiff(); - lateEntryRollCallRotating?.ClearTimeDiff(); + earlyEntryRollCallRotating?.SetEarlyEnter(TimeSpan.Zero); if (earlyEntryRollCallRotating != null) { @@ -404,8 +406,7 @@ public class RollCallDomainService : IRollCallDomainService var earlyExitRollCallRotating = rollCallsInRotatingShift.OrderByDescending(x => x.EndDate).FirstOrDefault(x => x.EndDate < shift.end); var lateExitRollCallRotating = rollCallsInRotatingShift.OrderBy(x => x.EndDate).FirstOrDefault(x => x.EndDate > shift.end); - earlyExitRollCallRotating?.ClearTimeDiff(); - lateExitRollCallRotating?.ClearTimeDiff(); + earlyExitRollCallRotating?.SetEarlyExit(TimeSpan.Zero); @@ -450,17 +451,6 @@ public class RollCallDomainService : IRollCallDomainService DateTime startDate = startRollCall.Date; DateTime endDate = endRollCall.Date; - - - DateTime startEntryWithDate = startDate.Add(startRollCall.TimeOfDay); - DateTime endEntryWithDate = endDate.Add(endRollCall.TimeOfDay); - - DateTime twoHourBeforeStart = startEntryWithDate.AddHours(-2); - DateTime twoHourAfterStart = startEntryWithDate.AddHours(2); - DateTime twoHourBeforeEnd = endEntryWithDate.AddHours(-2); - DateTime twoHourAfterEnd = endEntryWithDate.AddHours(2); - - var shiftDateTimes = rotatingShifts.SelectMany(shift => { var shifts = new List<(DateTime Start, DateTime End)>(); @@ -538,7 +528,8 @@ public class RollCallDomainService : IRollCallDomainService .ThenByDescending(s => s.Overlap) // 2. بیشترین Overlap .ThenBy(s => s.TotalDistance) .ThenBy(s => s.StartDistance) - .ThenBy(x => x.EndDistance); // 3. اگر برابر بود، Start نزدیک‌تر + .ThenBy(x => x.EndDistance); // 3. اگر برابر بود، + var overlapChosenShift = overlapShifts.First(); var end = overlapChosenShift.Shift.End; @@ -551,6 +542,72 @@ public class RollCallDomainService : IRollCallDomainService #endregion } + public (DateTime start, DateTime end) FindRotatingShift(List<(DateTime StartDate, DateTime EndDate)> rollCalls, ICollection rotatingShifts) + { + + DateTime startDate = rollCalls.MinBy(x => x.StartDate).StartDate.Date; + DateTime endDate = rollCalls.MaxBy(x => x.EndDate).EndDate.Date; + + var shiftDateTimes = rotatingShifts.SelectMany(shift => + { + var shifts = new List<(DateTime Start, DateTime End)>(); + for (int i = -1; i <= 1; i++) + { + var shiftStart = startDate.AddDays(i).Date; + shiftStart = shiftStart.Add(shift.StartTime.ToTimeSpan()); + var shiftEnd = shift.StartTime < shift.EndTime + ? startDate.AddDays(i).Date.Add(shift.EndTime.ToTimeSpan()) + : startDate.AddDays(i + 1).Date.Add(shift.EndTime.ToTimeSpan()); + shifts.Add((shiftStart, shiftEnd)); + } + + return shifts; + }).ToList(); + + var shiftScores = shiftDateTimes + .Select(shift => + { + var totalOverlap = TimeSpan.Zero; + long totalStartDistance = 0; + long totalEndDistance = 0; + + foreach (var rollCall in rollCalls) + { + var start = rollCall.StartDate; + var end = rollCall.EndDate; + + var overlapTicks = Math.Max(0, + Math.Min(shift.End.Ticks, end.Ticks) - + Math.Max(shift.Start.Ticks, start.Ticks)); + + totalOverlap += new TimeSpan(overlapTicks); + totalStartDistance += Math.Abs((shift.Start - start).Ticks); + totalEndDistance += Math.Abs((shift.End - end).Ticks); + } + + return new + { + Shift = shift, + TotalOverlap = totalOverlap, + TotalDistance = totalStartDistance + totalEndDistance, + StartDistance = totalStartDistance, + EndDistance = totalEndDistance + }; + }) + .OrderByDescending(s => s.TotalOverlap) + .ThenBy(s => s.TotalDistance) + .ThenBy(s => s.StartDistance) + .ThenBy(s => s.EndDistance); + + var overlapChosenShift = shiftScores.First(); + var end = overlapChosenShift.Shift.End; + if (overlapChosenShift.Shift.End < overlapChosenShift.Shift.Start) + end = overlapChosenShift.Shift.End.AddDays(1); + + + return (overlapChosenShift.Shift.Start, end); + } + private DateTime CalculateRegularShiftDate(DateTime startDate, TimeOnly offset) { DateTime nextOffSetDateTime; diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index e97a8282..c470f86f 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -470,7 +470,7 @@ public class RollCallApplication : IRollCallApplication if (newRollCallDates.Any(x => employeeRollCalls.Any(y => - y.StartDate.Value.Date != command.DateFa.ToGeorgianDateTime().Date && + y.ShiftDate.Date != command.DateFa.ToGeorgianDateTime().Date && x.EndDate >= y.StartDate.Value && x.StartDate <= y.EndDate.Value))) return operation.Failed("بازه های وارد شده با حضور غیاب های مربوط به روز های قبل و بعد تداخل زمانی دارد"); @@ -650,7 +650,7 @@ public class RollCallApplication : IRollCallApplication } if (newRollCallDates.Any(x => employeeRollCalls.Any(y => - y.StartDate.Value.Date != command.DateFa.ToGeorgianDateTime().Date && + y.ShiftDate.Date != command.DateFa.ToGeorgianDateTime().Date && x.EndDate >= y.StartDate.Value && x.StartDate <= y.EndDate.Value))) return operation.Failed("بازه های وارد شده با حضور غیاب های مربوط به روز های قبل و بعد تداخل زمانی دارد"); diff --git a/CompanyManagment.EFCore/Repository/RollCallRepository.cs b/CompanyManagment.EFCore/Repository/RollCallRepository.cs index baf7fb5c..71e58423 100644 --- a/CompanyManagment.EFCore/Repository/RollCallRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallRepository.cs @@ -756,7 +756,8 @@ public class RollCallRepository : RepositoryBase, IRollCallRepos WorkshopId = workshopId, StartDate = x.StartDate, EndDate = x.EndDate, - DateGr = x.ShiftDate + DateGr = x.ShiftDate, + ShiftDate = x.ShiftDate }).ToList(); } diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs index fc3fa0fa..3e2a8b3b 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs +++ b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs @@ -1,4 +1,5 @@ using _0_Framework.Application; +using _0_Framework.Domain.CustomizeCheckoutShared.Enums; using AccountManagement.Domain.AccountLeftWorkAgg; using AccountMangement.Infrastructure.EFCore; using Company.Domain.CustomizeCheckoutAgg.ValueObjects; @@ -64,7 +65,10 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk public IActionResult OnPostShiftDateNew() { var startRollCall = new DateTime(2025, 4, 21); - var rollCalls = _context.RollCalls.Where(x => x.ShiftDate >= startRollCall && x.EndDate != null ).ToList(); + var employees = _context.CustomizeWorkshopEmployeeSettings + .Where(x => x.WorkshopShiftStatus == WorkshopShiftStatus.Rotating).Select(x => x.EmployeeId).ToList(); + + var rollCalls = _context.RollCalls.Where(x => x.ShiftDate >= startRollCall && x.EndDate != null &&employees.Contains(x.EmployeeId)).ToList(); var r1 = rollCalls.ToList(); Console.ForegroundColor = ConsoleColor.DarkRed;