Files
vtuber-awards/Backend/Endpoints/AdminSeasonCreateEndpoints.cs
T
AzuTear 441ef2b850
CI - Build & Verify / Build, Typecheck & Hygiene (push) Successful in 59s
CI - Build & Verify / Deploy to award.noveria.net (push) Failing after 53s
Update release notes and deploy workspace
2026-06-29 17:49:54 +02:00

139 lines
5.2 KiB
C#

using Backend.Contracts;
using Backend.Common;
using Backend.Data;
using Backend.Domain;
using Backend.Services;
using Microsoft.EntityFrameworkCore;
namespace Backend.Endpoints;
public static partial class AdminSeasonManagementEndpoints
{
private static async Task<IResult> CreateSeason(
HttpContext context,
CreateSeasonRequest request,
AwardsDbContext db,
IAdminAuditService adminAuditService)
{
var session = AdminEndpointConventions.CurrentSession(context);
var validationError = ValidateSeasonRequest(request);
if (validationError is not null)
{
return validationError;
}
if (await db.Seasons.AnyAsync(item => item.Year == request.Year))
{
return Results.BadRequest(new { message = $"A season for {request.Year} already exists." });
}
var settings = await db.SiteSettings
.AsNoTracking()
.FirstOrDefaultAsync(item => item.Id == 1, context.RequestAborted);
var initialWorkflowRulesJson = WorkflowRuleSettings.Serialize(WorkflowRuleSettings.Read(settings));
var season = new Season
{
Year = request.Year,
Name = request.Name.Trim(),
IsDemo = false,
CurrentPhase = request.CurrentPhase.Trim(),
IsCurrent = request.IsCurrent,
IsCommunityOnly = request.IsCommunityOnly,
NominationStartsAt = request.NominationStartsAt,
NominationEndsAt = request.NominationEndsAt,
VotingStartsAt = request.VotingStartsAt,
VotingEndsAt = request.VotingEndsAt,
ReviewStartsAt = request.ReviewStartsAt,
ReviewEndsAt = request.ReviewEndsAt,
ShowDate = request.ShowDate,
ShowStartsAt = request.ShowStartsAt,
SubcategoryTemplatesJson = "[]",
WorkflowRulesJson = initialWorkflowRulesJson,
};
db.Seasons.Add(season);
var copiedCategoryCount = 0;
if (request.CopyStructureFromSeasonId is { } sourceSeasonId)
{
if (sourceSeasonId <= 0)
{
return Results.BadRequest(new { message = "A valid source season is required for copying structure." });
}
var sourceSeasonExists = await db.Seasons
.AsNoTracking()
.AnyAsync(item => item.Id == sourceSeasonId, context.RequestAborted);
if (!sourceSeasonExists)
{
return Results.BadRequest(new { message = "Source season for structure copy was not found." });
}
var sourceCategories = await db.Categories
.AsNoTracking()
.Where(item => item.SeasonId == sourceSeasonId)
.OrderBy(item => item.SortOrder)
.ThenBy(item => item.Name)
.ToArrayAsync(context.RequestAborted);
copiedCategoryCount = sourceCategories.Length;
var sourceSeason = await db.Seasons
.AsNoTracking()
.FirstAsync(item => item.Id == sourceSeasonId, context.RequestAborted);
season.SubcategoryTemplatesJson = sourceSeason.SubcategoryTemplatesJson;
season.WorkflowRulesJson = string.IsNullOrWhiteSpace(sourceSeason.WorkflowRulesJson)
? initialWorkflowRulesJson
: sourceSeason.WorkflowRulesJson;
foreach (var category in sourceCategories)
{
db.Categories.Add(new Category
{
Season = season,
GroupName = category.GroupName,
Name = category.Name,
Slug = category.Slug,
Description = category.Description,
SortOrder = category.SortOrder,
MaxNomineesPerUser = category.MaxNomineesPerUser,
ViewerRangeMin = category.ViewerRangeMin,
ViewerRangeMax = category.ViewerRangeMax,
});
}
}
var readinessIssues = BuildNewSeasonReadinessIssues(
request.CurrentPhase,
request.IsCurrent,
copiedCategoryCount);
if (readinessIssues.Length > 0)
{
return CreateReadinessError(readinessIssues);
}
await UnsetOtherCurrentSeasonsAsync(db, request.IsCurrent, null, context.RequestAborted);
adminAuditService.AddEntry(
session.TwitchUserId,
"season.create",
"season",
request.Year.ToString(),
copiedCategoryCount > 0
? $"Season {request.Year} wurde angelegt und {copiedCategoryCount} Kategorien wurden kopiert."
: $"Season {request.Year} wurde angelegt.",
new
{
request.IsCurrent,
request.IsCommunityOnly,
request.CurrentPhase,
request.ShowDate,
request.ShowStartsAt,
request.CopyStructureFromSeasonId,
copiedCategoryCount,
},
RequestMetadataReader.Read(context));
await db.SaveChangesAsync(context.RequestAborted);
return Results.Ok(new { saved = true, seasonId = season.Id, copiedCategoryCount });
}
}