Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions test/ClinicalScheduler/EvaluationPolicyServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,18 @@ public void RequiresPrimaryEvaluator_RotationClosed_ReturnsFalse()
};

// Act - Pass rotationClosed = true
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 2, rotationClosed: true);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 2, rotationClosed: true);

// Assert
Assert.False(result);
}

#endregion

#region WeekSize = 1 Tests
#region MinConsecutiveWeeks = 1 Tests

[Fact]
public void RequiresPrimaryEvaluator_WeekSize1_NonExtendedWeek_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks1_NonExtendedWeek_ReturnsTrue()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -111,14 +111,14 @@ public void RequiresPrimaryEvaluator_WeekSize1_NonExtendedWeek_ReturnsTrue()
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 1);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 1);

// Assert
Assert.True(result);
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize1_ExtendedWeek_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks1_ExtendedWeek_ReturnsFalse()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -127,18 +127,18 @@ public void RequiresPrimaryEvaluator_WeekSize1_ExtendedWeek_ReturnsFalse()
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 1);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 1);

// Assert
Assert.False(result);
}

#endregion

#region WeekSize = 2 Tests
#region MinConsecutiveWeeks = 2 Tests

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_StartWeek_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_StartWeek_ReturnsFalse()
{
// Arrange - First week of a 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -148,14 +148,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_StartWeek_ReturnsFalse()
};

// Act
var result = _service.RequiresPrimaryEvaluator(28, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(28, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.False(result); // First week doesn't need evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_SecondWeek_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_SecondWeek_ReturnsTrue()
{
// Arrange - Second week of a 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -165,14 +165,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_SecondWeek_ReturnsTrue()
};

// Act
var result = _service.RequiresPrimaryEvaluator(29, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(29, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Second week needs evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_ThreeWeekRotationWithExtended_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_ThreeWeekRotationWithExtended_ReturnsFalse()
{
// Arrange - 3-week rotation where week 3 is extended
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -183,14 +183,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_ThreeWeekRotationWithExtended_Ret
};

// Act - Check week 32 (would normally be evaluation week, but week 33 is extended)
var result = _service.RequiresPrimaryEvaluator(32, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(32, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.False(result); // No evaluation needed because week 3 is extended
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_RegularTwoWeekBlock_SecondWeekTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_RegularTwoWeekBlock_SecondWeekTrue()
{
// Arrange - Regular 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -201,14 +201,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_RegularTwoWeekBlock_SecondWeekTru
};

// Act - Check week 36 (second week of block)
var result = _service.RequiresPrimaryEvaluator(36, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(36, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Second week needs evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_LastWeekOfYear_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_LastWeekOfYear_ReturnsTrue()
{
// Arrange - Last week with no next week
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -218,7 +218,7 @@ public void RequiresPrimaryEvaluator_WeekSize2_LastWeekOfYear_ReturnsTrue()
};

// Act - Check week 43 (last week, no next week)
var result = _service.RequiresPrimaryEvaluator(43, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(43, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Last week needs evaluator
Expand Down Expand Up @@ -289,36 +289,36 @@ public void RequiresPrimaryEvaluator_Rotation603Year2026_CorrectEvaluation(int w
var relevantWeeks = weeks.Where(w => w.WeekNum >= weekNum - 1 && w.WeekNum <= weekNum + 1).ToList();

// Act
var result = _service.RequiresPrimaryEvaluator(weekNum, relevantWeeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(weekNum, relevantWeeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.Equal(shouldRequireEvaluator, result);
}

#endregion

#region No WeekSize Configuration Tests
#region No MinConsecutiveWeeks Configuration Tests

[Fact]
public void RequiresPrimaryEvaluator_NoWeekSize_ReturnsFalse()
public void RequiresPrimaryEvaluator_NoMinConsecutiveWeeks_ReturnsFalse()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
{
new() { WeekNum = 5, ExtendedRotation = false }
};

// Act - No serviceWeekSize provided
// Act - No serviceMinConsecutiveWeeks provided
var result = _service.RequiresPrimaryEvaluator(5, weeks);

// Assert
Assert.False(result); // Default behavior when no weekSize
Assert.False(result); // Default behavior when no MinConsecutiveWeeks
}

[Theory]
[InlineData(0)]
[InlineData(-1)]
public void RequiresPrimaryEvaluator_InvalidWeekSize_ReturnsFalse(int weekSize)
public void RequiresPrimaryEvaluator_InvalidMinConsecutiveWeeks_ReturnsFalse(int MinConsecutiveWeeks)
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -327,15 +327,15 @@ public void RequiresPrimaryEvaluator_InvalidWeekSize_ReturnsFalse(int weekSize)
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: weekSize);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: MinConsecutiveWeeks);

// Assert
Assert.False(result); // Invalid weekSize (0, negative) defaults to false
Assert.False(result); // Invalid MinConsecutiveWeeks (0, negative) defaults to false
}


[Fact]
public void RequiresPrimaryEvaluator_WeekSize4_OnlyLastWeekRequiresEvaluation()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks4_OnlyLastWeekRequiresEvaluation()
{
// Arrange - 4-week rotation blocks
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -348,10 +348,10 @@ public void RequiresPrimaryEvaluator_WeekSize4_OnlyLastWeekRequiresEvaluation()
};

// Act & Assert - For 4-week blocks, only the last week (4th) should require evaluation
Assert.False(_service.RequiresPrimaryEvaluator(10, weeks, serviceWeekSize: 4)); // First week
Assert.False(_service.RequiresPrimaryEvaluator(11, weeks, serviceWeekSize: 4)); // Second week
Assert.False(_service.RequiresPrimaryEvaluator(12, weeks, serviceWeekSize: 4)); // Third week
Assert.True(_service.RequiresPrimaryEvaluator(13, weeks, serviceWeekSize: 4)); // Fourth week (last)
Assert.False(_service.RequiresPrimaryEvaluator(10, weeks, serviceMinConsecutiveWeeks: 4)); // First week
Assert.False(_service.RequiresPrimaryEvaluator(11, weeks, serviceMinConsecutiveWeeks: 4)); // Second week
Assert.False(_service.RequiresPrimaryEvaluator(12, weeks, serviceMinConsecutiveWeeks: 4)); // Third week
Assert.True(_service.RequiresPrimaryEvaluator(13, weeks, serviceMinConsecutiveWeeks: 4)); // Fourth week (last)
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion test/ClinicalScheduler/RotationMappingExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void ToDto_MapsRotationPropertiesCorrectly()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = "SVMSecure.ClnSched.EditSurgery"
}
};
Expand Down
12 changes: 6 additions & 6 deletions test/ClinicalScheduler/ServiceMappingExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public void ToDto_MapsServicePropertiesCorrectly()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = "SVMSecure.ClnSched.EditSurgery"
};

Expand All @@ -24,7 +24,7 @@ public void ToDto_MapsServicePropertiesCorrectly()
// Assert
Assert.Equal(service.ServiceId, dto.ServiceId);
Assert.Equal(service.ServiceName, dto.ServiceName);
Assert.Equal(service.WeekSize, dto.WeekSize);
Assert.Equal(service.MinConsecutiveWeeks, dto.MinConsecutiveWeeks);
Assert.Equal(service.ScheduleEditPermission, dto.ScheduleEditPermission);
}

Expand Down Expand Up @@ -73,7 +73,7 @@ public void ToDto_HandlesNullScheduleEditPermission()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = null
};

Expand All @@ -86,22 +86,22 @@ public void ToDto_HandlesNullScheduleEditPermission()
}

[Fact]
public void ToDto_HandlesZeroWeekSize()
public void ToDto_HandlesZeroMinConsecutiveWeeks()
{
// Arrange
var service = new Service
{
ServiceId = 10,
ServiceName = "Special Service",
ShortName = "SPEC",
WeekSize = 0
MinConsecutiveWeeks = 0
};

// Act
var dto = service.ToDto();

// Assert
Assert.Equal(0, dto.WeekSize);
Assert.Equal(0, dto.MinConsecutiveWeeks);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ private object BuildWeekScheduleItem(WeekDto week, IEnumerable<InstructorSchedul
var requiresPrimary = _evaluationPolicyService.RequiresPrimaryEvaluator(
week.WeekNum,
rotationWeeks,
rotation?.Service?.WeekSize,
rotation?.Service?.MinConsecutiveWeeks,
rotationClosed);

return new
Expand Down Expand Up @@ -621,7 +621,7 @@ private object BuildSimpleRotationResponse(RotationDto rotation)
{
rotation.Service.ServiceId,
rotation.Service.ServiceName,
rotation.Service.WeekSize
rotation.Service.MinConsecutiveWeeks
} : null
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static ServiceDto ToDto(this Service service)
{
ServiceId = service.ServiceId,
ServiceName = service.ServiceName,
WeekSize = service.WeekSize,
MinConsecutiveWeeks = service.MinConsecutiveWeeks,
ScheduleEditPermission = service.ScheduleEditPermission
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class ServiceDto
{
public int ServiceId { get; set; }
public string ServiceName { get; set; } = string.Empty;
public int? WeekSize { get; set; }
public int? MinConsecutiveWeeks { get; set; }
public string? ScheduleEditPermission { get; set; }
}
}
24 changes: 12 additions & 12 deletions web/Areas/ClinicalScheduler/Services/EvaluationPolicyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,25 @@ public EvaluationPolicyService()
/// Determines if a week requires a primary evaluator based on simple business rules:
///
/// 1. If RotationWeeklyPref.Closed = 1 for the rotation and week, no primary needed
/// 2. If weekSize = 1, every week needs a primary
/// 3. If weekSize > 1 (2, 3, 4, etc.), the last week of each block needs a primary:
/// - For weekSize=2: usually the second week
/// - For weekSize=3: usually the third week
/// - For weekSize=4: usually the fourth week
/// 2. If MinConsecutiveWeeks = 1, every week needs a primary
/// 3. If MinConsecutiveWeeks > 1 (2, 3, 4, etc.), the last week of each block needs a primary:
/// - For MinConsecutiveWeeks=2: usually the second week
/// - For MinConsecutiveWeeks=3: usually the third week
/// - For MinConsecutiveWeeks=4: usually the fourth week
/// - For blocks with ExtendedRotation=true weeks, no evaluation needed
/// - Logic: For StartWeek=false, check next week:
/// * If next week has ExtendedRotation=true, no primary needed
/// * Otherwise, primary is needed
/// </summary>
/// <param name="weekNumber">The week number to check</param>
/// <param name="rotationWeeks">All weeks for the rotation in the year</param>
/// <param name="serviceWeekSize">The WeekSize from the Service table (1, 2, 3, 4, etc.)</param>
/// <param name="serviceMinConsecutiveWeeks">The MinConsecutiveWeeks from the Service table (1, 2, 3, 4, etc.)</param>
/// <param name="rotationClosed">Whether the rotation is closed this week (from RotationWeeklyPref)</param>
/// <returns>True if the week requires a primary evaluator</returns>
public bool RequiresPrimaryEvaluator(
int weekNumber,
IEnumerable<IRotationWeekInfo> rotationWeeks,
int? serviceWeekSize = null,
int? serviceMinConsecutiveWeeks = null,
bool rotationClosed = false)
{
// Rule 1: If rotation is closed for this week, no primary needed
Expand Down Expand Up @@ -61,16 +61,16 @@ public bool RequiresPrimaryEvaluator(
return false;
}

// Handle null or invalid WeekSize values
if (!serviceWeekSize.HasValue || serviceWeekSize.Value <= 0)
// Handle null or invalid MinConsecutiveWeeks values
if (!serviceMinConsecutiveWeeks.HasValue || serviceMinConsecutiveWeeks.Value <= 0)
{
// NULL or 0 WeekSize indicates undefined rotation structure
// NULL or 0 MinConsecutiveWeeks indicates undefined rotation structure
// Default to no evaluation requirement for safety
return false;
}

// Handle different WeekSize values
if (serviceWeekSize == 1)
// Handle different MinConsecutiveWeeks values
if (serviceMinConsecutiveWeeks == 1)
{
// Single-week rotations: every week is a complete block requiring evaluation
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ public interface IEvaluationPolicyService
/// </summary>
/// <param name="weekNumber">Week number to check</param>
/// <param name="rotationWeeks">Collection of rotation week info</param>
/// <param name="serviceWeekSize">Week size configuration for the service (1 or 2)</param>
/// <param name="serviceMinConsecutiveWeeks">Minimum number of consecutive weeks that require evaluation</param>
/// <param name="rotationClosed">Whether the rotation is closed for this week</param>
/// <returns>True if a primary evaluator is required for this week</returns>
bool RequiresPrimaryEvaluator(
int weekNumber,
IEnumerable<IRotationWeekInfo> rotationWeeks,
int? serviceWeekSize = null,
int? serviceMinConsecutiveWeeks = null,
bool rotationClosed = false);
}
}
2 changes: 1 addition & 1 deletion web/Classes/SQLContext/ClinicalSchedulerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.ServiceName).HasColumnName("ServiceName");
entity.Property(e => e.ShortName).HasColumnName("ShortName");
entity.Property(e => e.ScheduleEditPermission).HasColumnName("ScheduleEditPermission").IsRequired(false);
entity.Property(e => e.WeekSize).HasColumnName("WeekSize").IsRequired(false);
entity.Property(e => e.MinConsecutiveWeeks).HasColumnName("MinConsecutiveWeeks").IsRequired(false);
});

modelBuilder.Entity<InstructorSchedule>(entity =>
Expand Down
Loading
Loading