64 lines
2.5 KiB
C#
64 lines
2.5 KiB
C#
using Jiaowu.Api.Domain.Academic;
|
|
using Jiaowu.Api.Infrastructure.Persistence;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Jiaowu.Api.Infrastructure.Timetables;
|
|
|
|
public sealed class PublishedTimetableProjectionService(AppDbContext db)
|
|
{
|
|
private const int WriteBatchSize = 2_000;
|
|
public async Task RebuildPublishedPlansForTaskAsync(Guid teachingTaskId, CancellationToken cancellationToken)
|
|
{
|
|
var plans = await db.SchedulePlans
|
|
.Where(plan => plan.Status == SchedulePlanStatus.Published &&
|
|
plan.Entries.Any(entry => entry.TeachingTaskId == teachingTaskId))
|
|
.Include(plan => plan.Entries)
|
|
.ToListAsync(cancellationToken);
|
|
foreach (var plan in plans)
|
|
await RebuildAsync(plan, cancellationToken);
|
|
}
|
|
|
|
public async Task RebuildAsync(SchedulePlan plan, CancellationToken cancellationToken)
|
|
{
|
|
await db.PublishedScheduleOccurrences
|
|
.Where(x => x.SchedulePlanId == plan.Id)
|
|
.ExecuteDeleteAsync(cancellationToken);
|
|
|
|
var rows = new List<PublishedScheduleOccurrence>(WriteBatchSize);
|
|
foreach (var entry in plan.Entries)
|
|
for (var week = entry.StartWeek; week <= entry.EndWeek; week++)
|
|
{
|
|
if (entry.WeekPattern == WeekPattern.Odd && week % 2 == 0 ||
|
|
entry.WeekPattern == WeekPattern.Even && week % 2 != 0) continue;
|
|
rows.Add(new PublishedScheduleOccurrence
|
|
{
|
|
SchedulePlanId = plan.Id,
|
|
AcademicTermId = plan.AcademicTermId,
|
|
ScheduleEntryId = entry.Id,
|
|
TeachingTaskId = entry.TeachingTaskId,
|
|
ClassroomId = entry.ClassroomId,
|
|
Week = week,
|
|
DayOfWeek = entry.DayOfWeek,
|
|
StartPeriod = entry.StartPeriod,
|
|
PeriodCount = entry.PeriodCount,
|
|
Kind = entry.Kind
|
|
});
|
|
if (rows.Count == WriteBatchSize)
|
|
await WriteBatchAsync(rows, cancellationToken);
|
|
}
|
|
if (rows.Count > 0)
|
|
await WriteBatchAsync(rows, cancellationToken);
|
|
}
|
|
|
|
private async Task WriteBatchAsync(
|
|
List<PublishedScheduleOccurrence> rows,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
db.PublishedScheduleOccurrences.AddRange(rows);
|
|
await db.SaveChangesAsync(cancellationToken);
|
|
foreach (var row in rows)
|
|
db.Entry(row).State = EntityState.Detached;
|
|
rows.Clear();
|
|
}
|
|
}
|