配置保存在独立数据库表 CourseGradeStatisticsRefreshSettings,不是修改 appsettings.json。 后台每 10 秒读取配置,仅到期扫描;成绩录入、导入、审批时不再立即创建统计任务。 扫描发现过期数据后,仍通过持久任务、Outbox 和 RabbitMQ 执行;Redis统计缓存由处理任务统一刷新。
79 lines
2.7 KiB
C#
79 lines
2.7 KiB
C#
using System.Collections;
|
|
using Jiaowu.Api.Controllers;
|
|
using Jiaowu.Api.Domain.Academic;
|
|
using Jiaowu.Api.Domain.Identity;
|
|
using Jiaowu.Api.Infrastructure.Auth;
|
|
using Jiaowu.Api.Infrastructure.Persistence;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Data.Sqlite;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Jiaowu.Api.Tests;
|
|
|
|
public sealed class WarningRulePersistenceTests
|
|
{
|
|
[Fact]
|
|
public async Task SaveRules_PersistsAutoCheck_AndReturnsNumericType()
|
|
{
|
|
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 term = new AcademicTerm
|
|
{
|
|
Code = "WARN-TERM",
|
|
Name = "预警测试学期",
|
|
AcademicYear = "2026-2027",
|
|
Season = TermSeason.Autumn,
|
|
StartDate = new DateOnly(2026, 9, 1),
|
|
EndDate = new DateOnly(2027, 1, 15)
|
|
};
|
|
db.AcademicTerms.Add(term);
|
|
await db.SaveChangesAsync();
|
|
var controller = new WarningsController(db, new AllDataScope());
|
|
|
|
var saveResult = await controller.SaveRules(term.Id,
|
|
[
|
|
new WarningRuleDto(
|
|
WarningType.FailedCredits,
|
|
"不及格学分",
|
|
2m,
|
|
true,
|
|
true,
|
|
true,
|
|
null,
|
|
true,
|
|
1,
|
|
9,
|
|
30)
|
|
], CancellationToken.None);
|
|
|
|
Assert.IsType<NoContentResult>(saveResult);
|
|
db.ChangeTracker.Clear();
|
|
var persisted = Assert.Single(await db.WarningRules.AsNoTracking().ToListAsync());
|
|
Assert.True(persisted.AutoCheckEnabled);
|
|
Assert.Equal(1, persisted.CheckDayOfWeek);
|
|
Assert.Equal(9, persisted.CheckHour);
|
|
Assert.Equal(30, persisted.CheckMinute);
|
|
|
|
var getResult = await controller.GetRules(term.Id, CancellationToken.None);
|
|
var ok = Assert.IsType<OkObjectResult>(getResult);
|
|
var row = Assert.Single(Assert.IsAssignableFrom<IEnumerable>(ok.Value).Cast<object>());
|
|
var type = row.GetType().GetProperty("Type")?.GetValue(row);
|
|
Assert.Equal(1, Assert.IsType<int>(type));
|
|
}
|
|
|
|
private sealed class AllDataScope : ICurrentUserDataScope
|
|
{
|
|
public CurrentUserScope Current { get; } = new(
|
|
Guid.NewGuid(),
|
|
"测试管理员",
|
|
null,
|
|
DataScope.All,
|
|
new HashSet<string>([SystemRoles.SuperAdmin]));
|
|
}
|
|
}
|