Skip to content

Commit 793e242

Browse files
committed
Allow auto-schedule for different times on different days
1 parent c622904 commit 793e242

20 files changed

+1472
-222
lines changed

backend/api.test/Database/DatabaseUtilities.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,7 @@ public async Task<MissionDefinition> NewMissionDefinition(
167167
LastSuccessfulRun = lastSuccessfulRun,
168168
AutoScheduleFrequency = new AutoScheduleFrequency
169169
{
170-
TimesOfDayCET = [timeOfDay],
171-
DaysOfWeek = [dateNow.DayOfWeek],
170+
SchedulingTimesCETperWeek = [new TimeAndDay(dateNow.DayOfWeek, timeOfDay)],
172171
},
173172
};
174173

backend/api/Controllers/MissionDefinitionController.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,20 @@ [FromBody] UpdateMissionDefinitionQuery missionDefinitionQuery
162162
return BadRequest("Name cannot be null.");
163163
}
164164

165-
try
166-
{
167-
missionDefinitionQuery.AutoScheduleFrequency?.ValidateAutoScheduleFrequency();
168-
}
169-
catch (ArgumentException e)
170-
{
171-
return BadRequest(e.Message);
172-
}
173-
174165
missionDefinition.Name = missionDefinitionQuery.Name;
175166
missionDefinition.Comment = missionDefinitionQuery.Comment;
176167
missionDefinition.InspectionFrequency = missionDefinitionQuery.InspectionFrequency;
177-
missionDefinition.AutoScheduleFrequency =
178-
await autoScheduleService.UpdateAutoScheduleFrequency(
179-
missionDefinition,
180-
missionDefinitionQuery.AutoScheduleFrequency
181-
);
168+
if (missionDefinitionQuery.SchedulingTimesCETperWeek != null)
169+
{
170+
var schedulingTimesCETperWeek = missionDefinitionQuery
171+
.SchedulingTimesCETperWeek.Select(s => new TimeAndDay(s.DayOfWeek, s.TimeOfDay))
172+
.ToList();
173+
missionDefinition.AutoScheduleFrequency =
174+
await autoScheduleService.UpdateAutoScheduleFrequency(
175+
missionDefinition,
176+
schedulingTimesCETperWeek
177+
);
178+
}
182179

183180
var newMissionDefinition = await missionDefinitionService.Update(missionDefinition);
184181
return new MissionDefinitionResponse(newMissionDefinition);

backend/api/Controllers/Models/UpdateMissionDefinitionQuery.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,22 @@ public struct UpdateMissionDefinitionQuery
2121

2222
/// <summary>
2323
/// Change the time and day in the automated scheduling frequency
24+
/// Will be unchanged if null. Use an empty list to remove all scheduled times.
2425
/// </summary>
25-
public AutoScheduleFrequency? AutoScheduleFrequency { get; set; }
26+
public IList<TimeAndDayQuery>? SchedulingTimesCETperWeek { get; set; }
27+
}
28+
29+
public struct TimeAndDayQuery
30+
{
31+
/// <summary>
32+
/// The day of the week to schedule the mission
33+
/// </summary>
34+
public DayOfWeek DayOfWeek { get; set; }
35+
36+
/// <summary>
37+
/// The time of day to schedule the mission
38+
/// </summary>
39+
public TimeOnly TimeOfDay { get; set; }
2640
}
2741

2842
public struct SkipAutoMissionQuery

backend/api/Database/Context/FlotillaDbContext.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
6969
.Entity<MissionDefinition>()
7070
.Property(m => m.InspectionFrequency)
7171
.HasConversion(new TimeSpanToTicksConverter());
72-
73-
modelBuilder.Entity<MissionDefinition>().OwnsOne(m => m.AutoScheduleFrequency);
7472
modelBuilder
7573
.Entity<MissionDefinition>()
7674
.HasOne(m => m.InspectionArea)

backend/api/Database/Models/AutoScheduleFrequency.cs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,48 @@
66
#pragma warning disable CS8618
77
namespace Api.Database.Models
88
{
9-
[Owned]
109
public class AutoScheduleFrequency
1110
{
12-
[Required]
13-
// In Central European Time
14-
public IList<TimeOnly> TimesOfDayCET { get; set; } = new List<TimeOnly>();
11+
[Key]
12+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
13+
public string Id { get; set; }
1514

1615
[Required]
17-
public IList<DayOfWeek> DaysOfWeek { get; set; } = new List<DayOfWeek>();
16+
public IList<TimeAndDay> SchedulingTimesCETperWeek { get; set; } = new List<TimeAndDay>();
1817

1918
public string? AutoScheduledJobs { get; set; }
2019

2120
public bool HasValidValue()
2221
{
23-
return TimesOfDayCET.Count != 0 && DaysOfWeek.Count != 0;
22+
return SchedulingTimesCETperWeek.Count != 0;
2423
}
2524

26-
public void ValidateAutoScheduleFrequency()
25+
public bool IsUnchanged(IList<TimeAndDay>? newSchedulingTimesCETperWeek)
2726
{
28-
if (TimesOfDayCET.Count == 0)
27+
if (newSchedulingTimesCETperWeek == null || SchedulingTimesCETperWeek == null)
28+
{
29+
return newSchedulingTimesCETperWeek == SchedulingTimesCETperWeek;
30+
}
31+
32+
if (newSchedulingTimesCETperWeek.Count != SchedulingTimesCETperWeek.Count)
2933
{
30-
throw new ArgumentException(
31-
"AutoScheduleFrequency must have at least one time of day"
32-
);
34+
return false;
3335
}
3436

35-
if (DaysOfWeek.Count == 0)
37+
foreach (var schedulingTime in newSchedulingTimesCETperWeek)
3638
{
37-
throw new ArgumentException(
38-
"AutoScheduleFrequency must have at least one day of week"
39-
);
39+
if (
40+
!SchedulingTimesCETperWeek.Any(existingTime =>
41+
existingTime.DayOfWeek == schedulingTime.DayOfWeek
42+
&& existingTime.TimeOfDay == schedulingTime.TimeOfDay
43+
)
44+
)
45+
{
46+
return false;
47+
}
4048
}
49+
50+
return true;
4151
}
4252

4353
public IList<(TimeSpan, TimeOnly)>? GetSchedulingTimesUntilMidnight()
@@ -51,15 +61,31 @@ public void ValidateAutoScheduleFrequency()
5161

5262
var autoScheduleNext = new List<(TimeSpan, TimeOnly)>();
5363

54-
if (DaysOfWeek.Contains(nowLocal.DayOfWeek))
55-
{
56-
autoScheduleNext.AddRange(
57-
TimesOfDayCET
58-
.Where(time => time >= nowLocalTimeOnly)
59-
.Select(time => (time - nowLocalTimeOnly, time))
60-
);
61-
}
64+
autoScheduleNext.AddRange(
65+
SchedulingTimesCETperWeek
66+
.Where(schedulingTime => schedulingTime.DayOfWeek == nowLocal.DayOfWeek)
67+
.Where(schedulingTime => schedulingTime.TimeOfDay > nowLocalTimeOnly)
68+
.Select(schedulingTime =>
69+
(schedulingTime.TimeOfDay - nowLocalTimeOnly, schedulingTime.TimeOfDay)
70+
)
71+
);
6272
return autoScheduleNext.Count > 0 ? autoScheduleNext : null;
6373
}
6474
}
75+
76+
[Owned]
77+
public class TimeAndDay
78+
{
79+
[Key]
80+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
81+
public string Id { get; set; }
82+
public DayOfWeek DayOfWeek { get; set; }
83+
public TimeOnly TimeOfDay { get; set; }
84+
85+
public TimeAndDay(DayOfWeek dayOfWeek, TimeOnly timeOfDay)
86+
{
87+
DayOfWeek = dayOfWeek;
88+
TimeOfDay = timeOfDay;
89+
}
90+
}
6591
}

0 commit comments

Comments
 (0)