using ErsatzTV.Core; using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.Scheduling; public class CreateDecoTemplateGroupHandler(IDbContextFactory dbContextFactory) : IRequestHandler> { public async Task> Handle( CreateDecoTemplateGroup request, CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); return await validation.Apply(profile => PersistDecoTemplateGroup(dbContext, profile)); } private static async Task PersistDecoTemplateGroup( TvContext dbContext, DecoTemplateGroup decoDecoTemplateGroup) { await dbContext.DecoTemplateGroups.AddAsync(decoDecoTemplateGroup); await dbContext.SaveChangesAsync(); return Mapper.ProjectToViewModel(decoDecoTemplateGroup); } private static Task> Validate( TvContext dbContext, CreateDecoTemplateGroup request) => ValidateName(dbContext, request).MapT(name => new DecoTemplateGroup { Name = name, DecoTemplates = [] }); private static async Task> ValidateName( TvContext dbContext, CreateDecoTemplateGroup createDecoTemplateGroup) { Validation result1 = createDecoTemplateGroup.NotEmpty(c => c.Name) .Bind(_ => createDecoTemplateGroup.NotLongerThan(50)(c => c.Name)); bool duplicateName = await dbContext.DecoTemplateGroups .AnyAsync(ps => ps.Name == createDecoTemplateGroup.Name); Validation result2 = duplicateName ? Fail("Deco template group name must be unique") : Success(Unit.Default); return (result1, result2).Apply((_, _) => createDecoTemplateGroup.Name); } }