Fix parsing shift times
This commit is contained in:
parent
803c390c81
commit
85a4ecb2aa
5 changed files with 99 additions and 49 deletions
|
|
@ -15,7 +15,7 @@ namespace ShiftScheduler.Client.Pages
|
||||||
private Dictionary<DateTime, string> SelectedSchedule { get; set; } = new();
|
private Dictionary<DateTime, string> SelectedSchedule { get; set; } = new();
|
||||||
private Dictionary<DateTime, ShiftWithTransport> SelectedShiftsWithTransport { get; set; } = new();
|
private Dictionary<DateTime, ShiftWithTransport> SelectedShiftsWithTransport { get; set; } = new();
|
||||||
|
|
||||||
private bool _isCurrentMonth = false;
|
private bool _isCurrentMonth = true;
|
||||||
private bool _isLoadingTransport = false;
|
private bool _isLoadingTransport = false;
|
||||||
private bool _isLoadingInitial = false;
|
private bool _isLoadingInitial = false;
|
||||||
private bool _showConfigDialog = false;
|
private bool _showConfigDialog = false;
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,15 @@ namespace ShiftScheduler.Server.Controllers
|
||||||
var transportConfig = _configurationService.GetTransportConfiguration();
|
var transportConfig = _configurationService.GetTransportConfiguration();
|
||||||
TransportConnection? morningTransport = null;
|
TransportConnection? morningTransport = null;
|
||||||
TransportConnection? afternoonTransport = null;
|
TransportConnection? afternoonTransport = null;
|
||||||
|
|
||||||
|
var shifTimes = _configurationService.ParseShiftTimes(request.Date, shift);
|
||||||
|
|
||||||
// Get transport for morning shift if it has morning time
|
// Get transport for morning shift if it has morning time
|
||||||
if (!string.IsNullOrEmpty(shift.MorningTime))
|
if (!string.IsNullOrEmpty(shift.MorningTime))
|
||||||
{
|
{
|
||||||
var morningStartTime = ParseShiftTime(request.Date, shift.MorningTime);
|
if (shifTimes.MorningStart.HasValue)
|
||||||
if (morningStartTime.HasValue)
|
|
||||||
{
|
{
|
||||||
morningTransport = await _transportService.GetConnectionAsync(morningStartTime.Value);
|
morningTransport = await _transportService.GetConnectionAsync(shifTimes.MorningStart.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,22 +66,18 @@ namespace ShiftScheduler.Server.Controllers
|
||||||
// If both morning and afternoon shifts exist, check break duration
|
// If both morning and afternoon shifts exist, check break duration
|
||||||
if (!string.IsNullOrEmpty(shift.MorningTime) && !string.IsNullOrEmpty(shift.AfternoonTime))
|
if (!string.IsNullOrEmpty(shift.MorningTime) && !string.IsNullOrEmpty(shift.AfternoonTime))
|
||||||
{
|
{
|
||||||
var morningEndTime = ParseShiftEndTime(request.Date, shift.MorningTime);
|
if (shifTimes.MorningEnd.HasValue && shifTimes.AfternoonStart.HasValue)
|
||||||
var afternoonStartTime = ParseShiftTime(request.Date, shift.AfternoonTime);
|
|
||||||
|
|
||||||
if (morningEndTime.HasValue && afternoonStartTime.HasValue)
|
|
||||||
{
|
{
|
||||||
var breakDurationMinutes = (afternoonStartTime.Value - morningEndTime.Value).TotalMinutes;
|
var breakDurationMinutes = (shifTimes.AfternoonStart.Value - shifTimes.MorningEnd.Value).TotalMinutes;
|
||||||
shouldLoadAfternoonTransport = breakDurationMinutes >= transportConfig.MinBreakMinutes;
|
shouldLoadAfternoonTransport = breakDurationMinutes >= transportConfig.MinBreakMinutes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldLoadAfternoonTransport)
|
if (shouldLoadAfternoonTransport)
|
||||||
{
|
{
|
||||||
var afternoonStartTime = ParseShiftTime(request.Date, shift.AfternoonTime);
|
if (shifTimes.AfternoonStart.HasValue)
|
||||||
if (afternoonStartTime.HasValue)
|
|
||||||
{
|
{
|
||||||
afternoonTransport = await _transportService.GetConnectionAsync(afternoonStartTime.Value);
|
afternoonTransport = await _transportService.GetConnectionAsync(shifTimes.AfternoonStart.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,40 +93,6 @@ namespace ShiftScheduler.Server.Controllers
|
||||||
return Ok(shiftWithTransport);
|
return Ok(shiftWithTransport);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DateTime? ParseShiftTime(DateTime date, string timeRange)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var times = timeRange.Split('-');
|
|
||||||
if (times.Length > 0 && TimeSpan.TryParse(times[0], out var startTime))
|
|
||||||
{
|
|
||||||
return date.Add(startTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore parsing errors
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DateTime? ParseShiftEndTime(DateTime date, string timeRange)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var times = timeRange.Split('-');
|
|
||||||
if (times.Length > 1 && TimeSpan.TryParse(times[1], out var endTime))
|
|
||||||
{
|
|
||||||
return date.Add(endTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore parsing errors
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("export_ics")]
|
[HttpPost("export_ics")]
|
||||||
public IActionResult ExportIcsWithTransport([FromBody] List<ShiftWithTransport> shiftsWithTransport)
|
public IActionResult ExportIcsWithTransport([FromBody] List<ShiftWithTransport> shiftsWithTransport)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,15 @@ namespace ShiftScheduler.Services
|
||||||
List<Shift> GetShifts();
|
List<Shift> GetShifts();
|
||||||
TransportConfiguration GetTransportConfiguration();
|
TransportConfiguration GetTransportConfiguration();
|
||||||
|
|
||||||
// Schedule persistence methods
|
|
||||||
Task SaveScheduleAsync(int year, int month, Dictionary<DateTime, string> schedule);
|
Task SaveScheduleAsync(int year, int month, Dictionary<DateTime, string> schedule);
|
||||||
Task<Dictionary<DateTime, string>> LoadScheduleAsync(int year, int month);
|
Task<Dictionary<DateTime, string>> LoadScheduleAsync(int year, int month);
|
||||||
Task DeleteScheduleAsync(int year, int month);
|
Task DeleteScheduleAsync(int year, int month);
|
||||||
|
|
||||||
|
ShiftTimes ParseShiftTimes(DateTime date, Shift shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record ShiftTimes(DateTimeOffset? MorningStart, DateTimeOffset? MorningEnd, DateTimeOffset? AfternoonStart, DateTimeOffset? AfternoonEnd);
|
||||||
|
|
||||||
public class ConfigurationService : IConfigurationService
|
public class ConfigurationService : IConfigurationService
|
||||||
{
|
{
|
||||||
private ApplicationConfiguration _configuration;
|
private ApplicationConfiguration _configuration;
|
||||||
|
|
@ -201,7 +204,45 @@ namespace ShiftScheduler.Services
|
||||||
// Log error if needed, but don't throw
|
// Log error if needed, but don't throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ShiftTimes ParseShiftTimes(DateTime date, Shift shift)
|
||||||
|
{
|
||||||
|
DateTimeOffset? morningStart = null;
|
||||||
|
DateTimeOffset? morningEnd = null;
|
||||||
|
DateTimeOffset? afternoonStart = null;
|
||||||
|
DateTimeOffset? afternoonEnd = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(shift.MorningTime))
|
||||||
|
{
|
||||||
|
var times = shift.MorningTime.Split('-');
|
||||||
|
if (times.Length == 2)
|
||||||
|
{
|
||||||
|
var start = $"{date:yyyy-MM-dd}T{times[0]}:00";
|
||||||
|
var end = $"{date:yyyy-MM-dd}T{times[1]}:00";
|
||||||
|
morningStart = DateTimeOffset.Parse(start);
|
||||||
|
morningEnd = DateTimeOffset.Parse(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(shift.AfternoonTime))
|
||||||
|
{
|
||||||
|
var times = shift.AfternoonTime.Split('-');
|
||||||
|
if (times.Length == 2)
|
||||||
|
{
|
||||||
|
var start = $"{date:yyyy-MM-dd}T{times[0]}:00";
|
||||||
|
var end = $"{date:yyyy-MM-dd}T{times[1]}:00";
|
||||||
|
afternoonStart = DateTimeOffset.Parse(start);
|
||||||
|
afternoonEnd = DateTimeOffset.Parse(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ShiftTimes(
|
||||||
|
MorningStart: morningStart,
|
||||||
|
MorningEnd: morningEnd,
|
||||||
|
AfternoonStart: afternoonStart,
|
||||||
|
AfternoonEnd: afternoonEnd);
|
||||||
|
}
|
||||||
|
|
||||||
private ApplicationConfiguration LoadConfigurationFromFiles(ApplicationConfiguration fallbackConfiguration)
|
private ApplicationConfiguration LoadConfigurationFromFiles(ApplicationConfiguration fallbackConfiguration)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
47
ShiftScheduler.Services.Tests/ConfigurationServiceTests.cs
Normal file
47
ShiftScheduler.Services.Tests/ConfigurationServiceTests.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
using ShiftScheduler.Shared;
|
||||||
|
using Shouldly;
|
||||||
|
|
||||||
|
namespace ShiftScheduler.Services.Tests;
|
||||||
|
|
||||||
|
public class ConfigurationServiceTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ParseShiftTimes_WithMorningAndAfternoon_ShouldReturnValid()
|
||||||
|
{
|
||||||
|
var applicationConfig = new ApplicationConfiguration();
|
||||||
|
var configurationService = new ConfigurationService(applicationConfig);
|
||||||
|
var shift = new Shift
|
||||||
|
{
|
||||||
|
MorningTime = "06:00-12:30",
|
||||||
|
AfternoonTime = "13:00-17:30"
|
||||||
|
};
|
||||||
|
|
||||||
|
var shiftTimes = configurationService.ParseShiftTimes(DateTime.Parse("2025-07-13T13:00:00"), shift);
|
||||||
|
shiftTimes.MorningStart.ShouldBe(T("2025-07-13T06:00:00+02:00"));
|
||||||
|
shiftTimes.MorningEnd.ShouldBe(T("2025-07-13T12:30:00+02:00"));
|
||||||
|
shiftTimes.AfternoonStart.ShouldBe(T("2025-07-13T13:00:00+02:00"));
|
||||||
|
shiftTimes.AfternoonEnd.ShouldBe(T("2025-07-13T17:30:00+02:00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParseShiftTimes_WithMorning_ShouldReturnValid()
|
||||||
|
{
|
||||||
|
var applicationConfig = new ApplicationConfiguration();
|
||||||
|
var configurationService = new ConfigurationService(applicationConfig);
|
||||||
|
var shift = new Shift
|
||||||
|
{
|
||||||
|
MorningTime = "06:00-12:30"
|
||||||
|
};
|
||||||
|
|
||||||
|
var shiftTimes = configurationService.ParseShiftTimes(DateTime.Parse("2025-07-13T13:00:00"), shift);
|
||||||
|
shiftTimes.MorningStart.ShouldBe(T("2025-07-13T06:00:00+02:00"));
|
||||||
|
shiftTimes.MorningEnd.ShouldBe(T("2025-07-13T12:30:00+02:00"));
|
||||||
|
shiftTimes.AfternoonStart.ShouldBeNull();
|
||||||
|
shiftTimes.AfternoonEnd.ShouldBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTimeOffset T(string dateTimeString)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.Parse(dateTimeString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,6 @@ public class TransportConnectionCalculatorTests
|
||||||
{
|
{
|
||||||
private readonly Mock<ILogger> loggerMock = new();
|
private readonly Mock<ILogger> loggerMock = new();
|
||||||
|
|
||||||
// Tests for new enhanced logic
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void FindBestConnectionEnhanced_WithGoodTimingConnection_ShouldReturnLatestValidConnection()
|
public void FindBestConnectionEnhanced_WithGoodTimingConnection_ShouldReturnLatestValidConnection()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue