Files
Academic-Affairs-System/tests/Jiaowu.Api.Tests/ScheduleSettingsControllerTests.cs
T
biss e4a12931ea 自动排课完成后逐条显示“需人工处理”的任务和原因,并提供“检查排课约束”入口;刷新页面后仍可读取最近一次结果。
批量排课约束新增校区、教学楼、多教室统一指定,也支持清除原有限定。
课表新增“总视图”,同一时段、不同周次课程会并列显示。
周视图按教学周过滤,支持上一周、下一周、周次下拉和回到本周。
日视图按周次过滤;连续两节课程会跨两行完整占格。
2026-07-25 10:55:09 +08:00

122 lines
3.8 KiB
C#

using Jiaowu.Api.Controllers;
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
namespace Jiaowu.Api.Tests;
public sealed class ScheduleSettingsControllerTests
{
[Fact]
public async Task Batch_constraints_assign_same_classroom_scope_to_all_tasks()
{
await using var connection = new SqliteConnection("Data Source=:memory:");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlite(connection)
.Options;
await using var db = new AppDbContext(options);
await db.Database.EnsureCreatedAsync();
var campus = new Campus { Code = "MAIN", Name = "主校区" };
var building = new Building
{
Code = "J1",
Name = "第一教学楼",
Campus = campus
};
var classroom = new Classroom
{
Code = "J1-201",
Name = "J1-201",
Building = building,
Capacity = 80
};
var college = new College { Code = "CS", Name = "计算机学院" };
var course = new Course
{
Code = "CS101",
Name = "程序设计基础",
College = college,
Credits = 4,
TotalHours = 64,
LectureHours = 48,
PracticeHours = 16
};
var term = new AcademicTerm
{
Code = "2026-F",
Name = "2026 秋季",
AcademicYear = "2026-2027",
Season = TermSeason.Autumn,
StartDate = new DateOnly(2026, 9, 7),
EndDate = new DateOnly(2027, 1, 17)
};
var firstTask = NewTask("TASK-01", course, term);
var secondTask = NewTask("TASK-02", course, term);
db.AddRange(
campus,
building,
classroom,
college,
course,
term,
firstTask,
secondTask);
await db.SaveChangesAsync();
var controller = new ScheduleSettingsController(db);
var result = await controller.SaveConstraintsBatch(
new TeachingTaskScheduleConstraintBatchRequest(
term.Id,
[firstTask.Id, secondTask.Id],
null,
null,
null,
true,
campus.Id,
building.Id,
[classroom.Id],
false,
null,
null),
CancellationToken.None);
Assert.IsType<OkObjectResult>(result);
db.ChangeTracker.Clear();
var constraints = await db.TeachingTaskScheduleConstraints
.Include(item => item.AllowedClassrooms)
.OrderBy(item => item.TeachingTaskId)
.ToListAsync();
Assert.Equal(2, constraints.Count);
Assert.All(constraints, constraint =>
{
Assert.True(constraint.RequiresClassroom);
Assert.Equal(campus.Id, constraint.RequiredCampusId);
Assert.Equal(building.Id, constraint.RequiredBuildingId);
Assert.Equal(
classroom.Id,
Assert.Single(constraint.AllowedClassrooms).ClassroomId);
});
}
private static TeachingTask NewTask(
string taskNumber,
Course course,
AcademicTerm term) =>
new()
{
TaskNumber = taskNumber,
Name = $"{course.Name}教学班",
Course = course,
AcademicTerm = term,
Capacity = 60,
WeeklyHours = 4,
StartWeek = 1,
EndWeek = 16,
Status = TeachingTaskStatus.Published
};
}