feat: add locked new-year rollover wizard for season transitions
Promote returning students, assign officers, and clear last season's data after an automatic SQLite backup, with Docker volume path docs fixed for /app/Data. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
using System.Text.Json;
|
||||
using WebApp.Models;
|
||||
|
||||
namespace WebApp.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Persists chapter settings to <c>Data/appsettings.json</c>.
|
||||
/// </summary>
|
||||
public class ChapterSettingsWriter : IChapterSettingsWriter
|
||||
{
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<ChapterSettingsWriter> _logger;
|
||||
|
||||
public ChapterSettingsWriter(
|
||||
IWebHostEnvironment environment,
|
||||
IConfiguration configuration,
|
||||
ILogger<ChapterSettingsWriter> logger)
|
||||
{
|
||||
_environment = environment;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task WriteAsync(ChapterSettings settings, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
var appSettingsPath = GetAppSettingsPath();
|
||||
var dataDir = Path.GetDirectoryName(appSettingsPath);
|
||||
if (dataDir != null && !Directory.Exists(dataDir))
|
||||
{
|
||||
Directory.CreateDirectory(dataDir);
|
||||
}
|
||||
|
||||
Dictionary<string, object?> root;
|
||||
if (File.Exists(appSettingsPath))
|
||||
{
|
||||
var existingJson = await File.ReadAllTextAsync(appSettingsPath, cancellationToken);
|
||||
root = JsonSerializer.Deserialize<Dictionary<string, object?>>(existingJson)
|
||||
?? [];
|
||||
}
|
||||
else
|
||||
{
|
||||
root = [];
|
||||
}
|
||||
|
||||
root["ChapterSettings"] = settings;
|
||||
|
||||
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||
var json = JsonSerializer.Serialize(root, options);
|
||||
await File.WriteAllTextAsync(appSettingsPath, json, cancellationToken);
|
||||
|
||||
_logger.LogInformation("Chapter settings written to {Path}", appSettingsPath);
|
||||
}
|
||||
|
||||
public async Task UpdateCompetitionYearAsync(string competitionYear, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var settings = _configuration.GetSection("ChapterSettings").Get<ChapterSettings>()
|
||||
?? new ChapterSettings();
|
||||
settings.CompetitionYear = competitionYear;
|
||||
await WriteAsync(settings, cancellationToken);
|
||||
}
|
||||
|
||||
private string GetAppSettingsPath() =>
|
||||
Path.Combine(_environment.ContentRootPath, "Data", "appsettings.json");
|
||||
}
|
||||
Reference in New Issue
Block a user