add new find rotating shifts

This commit is contained in:
MahanCh
2025-05-11 17:02:48 +03:30
parent 51291d6de7
commit c168843afc
4 changed files with 84 additions and 22 deletions

View File

@@ -31,6 +31,7 @@ public interface IRollCallDomainService
void CalculateTimeDifferences(RollCall rollCall);
(DateTime start, DateTime end) FindRotatingShift(DateTime startRollCall, DateTime endRollCall, ICollection<CustomizeRotatingShift> rotatingShifts);
(DateTime start, DateTime end) FindRotatingShift(List<(DateTime StartDate, DateTime EndDate)> rollcalls, ICollection<CustomizeRotatingShift> 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<CustomizeRotatingShift> 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;

View File

@@ -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("بازه های وارد شده با حضور غیاب های مربوط به روز های قبل و بعد تداخل زمانی دارد");

View File

@@ -756,7 +756,8 @@ public class RollCallRepository : RepositoryBase<long, RollCall>, IRollCallRepos
WorkshopId = workshopId,
StartDate = x.StartDate,
EndDate = x.EndDate,
DateGr = x.ShiftDate
DateGr = x.ShiftDate,
ShiftDate = x.ShiftDate
}).ToList();
}

View File

@@ -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;