diff --git a/ErsatzTV.Application/Playouts/Commands/CreatePlayoutHandler.cs b/ErsatzTV.Application/Playouts/Commands/CreatePlayoutHandler.cs index ef4065b44..ceb6fd60d 100644 --- a/ErsatzTV.Application/Playouts/Commands/CreatePlayoutHandler.cs +++ b/ErsatzTV.Application/Playouts/Commands/CreatePlayoutHandler.cs @@ -48,7 +48,7 @@ namespace ErsatzTV.Application.Playouts.Commands } private async Task> Validate(CreatePlayout request) => - (await ChannelMustExist(request), await ProgramScheduleMustExist(request), ValidatePlayoutType(request)) + (await ValidateChannel(request), await ProgramScheduleMustExist(request), ValidatePlayoutType(request)) .Apply( (channel, programSchedule, playoutType) => new Playout { @@ -57,10 +57,19 @@ namespace ErsatzTV.Application.Playouts.Commands ProgramSchedulePlayoutType = playoutType }); + private Task> ValidateChannel(CreatePlayout createPlayout) => + ChannelMustExist(createPlayout).BindT(ChannelMustNotHavePlayouts); + private async Task> ChannelMustExist(CreatePlayout createPlayout) => (await _channelRepository.Get(createPlayout.ChannelId)) .ToValidation("Channel does not exist."); + private async Task> ChannelMustNotHavePlayouts(Channel channel) => + Optional(await _channelRepository.CountPlayouts(channel.Id)) + .Filter(count => count == 0) + .Map(_ => channel) + .ToValidation("Channel already has one playout."); + private async Task> ProgramScheduleMustExist( CreatePlayout createPlayout) => (await _programScheduleRepository.GetWithPlayouts(createPlayout.ProgramScheduleId)) diff --git a/ErsatzTV.Core/Interfaces/Repositories/IChannelRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/IChannelRepository.cs index 47cf8a227..d5a39c73f 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/IChannelRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/IChannelRepository.cs @@ -14,5 +14,6 @@ namespace ErsatzTV.Core.Interfaces.Repositories Task> GetAllForGuide(); Task Update(Channel channel); Task Delete(int channelId); + Task CountPlayouts(int channelId); } } diff --git a/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs index 14db39080..3f5d3cfaa 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; +using System.Data; using System.Linq; using System.Threading.Tasks; +using Dapper; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; @@ -12,8 +14,13 @@ namespace ErsatzTV.Infrastructure.Data.Repositories public class ChannelRepository : IChannelRepository { private readonly TvContext _dbContext; + private readonly IDbConnection _dbConnection; - public ChannelRepository(TvContext dbContext) => _dbContext = dbContext; + public ChannelRepository(TvContext dbContext, IDbConnection dbConnection) + { + _dbContext = dbContext; + _dbConnection = dbConnection; + } public async Task Add(Channel channel) { @@ -81,5 +88,10 @@ namespace ErsatzTV.Infrastructure.Data.Repositories _dbContext.Channels.Remove(channel); await _dbContext.SaveChangesAsync(); } + + public Task CountPlayouts(int channelId) => + _dbConnection.QuerySingleAsync( + @"SELECT COUNT(*) FROM Playout WHERE ChannelId = @ChannelId", + new { ChannelId = channelId }); } } diff --git a/docs/user-guide/search.md b/docs/user-guide/search.md index 3c8f27934..06640c950 100644 --- a/docs/user-guide/search.md +++ b/docs/user-guide/search.md @@ -24,11 +24,11 @@ Note that the `title` field is searched by default if no other field is specifie ## Sample Searches -### Christmas Movies +### Christmas `plot:christmas` -### Christmas Movies without Horror +### Christmas without Horror `plot:christmas NOT genre:horror`