diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs index 99ba614ac..00c9abaeb 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddEpisodeToCollectionHandler.cs @@ -1,16 +1,13 @@ -using System.Linq; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; -using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; namespace ErsatzTV.Application.MediaCollections.Commands { public class - AddEpisodeToCollectionHandler : MediatR.IRequestHandler> + AddEpisodeToCollectionHandler : MediatR.IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly ITelevisionRepository _televisionRepository; @@ -27,41 +24,27 @@ namespace ErsatzTV.Application.MediaCollections.Commands AddEpisodeToCollection request, CancellationToken cancellationToken) => Validate(request) - .MapT(ApplyAddTelevisionEpisodeRequest) + .MapT(_ => ApplyAddTelevisionEpisodeRequest(request)) .Bind(v => v.ToEitherAsync()); - private async Task ApplyAddTelevisionEpisodeRequest(RequestParameters parameters) - { - if (parameters.Collection.MediaItems.All(s => s.Id != parameters.EpisodeToAdd.Id)) - { - parameters.Collection.MediaItems.Add(parameters.EpisodeToAdd); - await _mediaCollectionRepository.Update(parameters.Collection); - } - - return Unit.Default; - } + private Task ApplyAddTelevisionEpisodeRequest(AddEpisodeToCollection request) => + _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.EpisodeId); - private async Task> - Validate(AddEpisodeToCollection request) => - (await SimpleMediaCollectionMustExist(request), await ValidateEpisode(request)) - .Apply( - (collectionToUpdate, episode) => - new RequestParameters(collectionToUpdate, episode)); + private async Task> Validate(AddEpisodeToCollection request) => + (await CollectionMustExist(request), await ValidateEpisode(request)) + .Apply((_, _) => Unit.Default); - private Task> SimpleMediaCollectionMustExist( - AddEpisodeToCollection updateCollection) => - _mediaCollectionRepository.GetCollectionWithItems(updateCollection.CollectionId) + private Task> CollectionMustExist(AddEpisodeToCollection request) => + _mediaCollectionRepository.Get(request.CollectionId) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Collection does not exist.")); - private Task> ValidateEpisode( - AddEpisodeToCollection request) => + private Task> ValidateEpisode(AddEpisodeToCollection request) => LoadTelevisionEpisode(request) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Episode does not exist")); - private Task> LoadTelevisionEpisode( - AddEpisodeToCollection request) => - _televisionRepository.GetEpisode(request.EpisodeId); - - private record RequestParameters(Collection Collection, Episode EpisodeToAdd); + private Task> LoadTelevisionEpisode(AddEpisodeToCollection request) => + _televisionRepository.GetEpisode(request.EpisodeId).MapT(e => e.Id); } } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs index 0b81eab03..d0f3d521b 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddMovieToCollectionHandler.cs @@ -7,9 +7,7 @@ using LanguageExt; namespace ErsatzTV.Application.MediaCollections.Commands { - public class - AddMovieToCollectionHandler : MediatR.IRequestHandler> + public class AddMovieToCollectionHandler : MediatR.IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly IMovieRepository _movieRepository; @@ -26,37 +24,27 @@ namespace ErsatzTV.Application.MediaCollections.Commands AddMovieToCollection request, CancellationToken cancellationToken) => Validate(request) - .MapT(ApplyAddMoviesRequest) + .MapT(_ => ApplyAddMoviesRequest(request)) .Bind(v => v.ToEitherAsync()); - private async Task ApplyAddMoviesRequest(RequestParameters parameters) - { - parameters.Collection.MediaItems.Add(parameters.MovieToAdd); - await _mediaCollectionRepository.Update(parameters.Collection); - - return Unit.Default; - } + private Task ApplyAddMoviesRequest(AddMovieToCollection request) => + _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.MovieId); - private async Task> - Validate(AddMovieToCollection request) => - (await SimpleMediaCollectionMustExist(request), await ValidateMovies(request)) - .Apply( - (collectionToUpdate, movieToAdd) => - new RequestParameters(collectionToUpdate, movieToAdd)); + private async Task> Validate(AddMovieToCollection request) => + (await CollectionMustExist(request), await ValidateMovies(request)) + .Apply((_, _) => Unit.Default); - private Task> SimpleMediaCollectionMustExist( - AddMovieToCollection updateCollection) => - _mediaCollectionRepository.GetCollectionWithItems(updateCollection.CollectionId) + private Task> CollectionMustExist(AddMovieToCollection request) => + _mediaCollectionRepository.GetCollectionWithItems(request.CollectionId) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Collection does not exist.")); - private Task> ValidateMovies( - AddMovieToCollection request) => + private Task> ValidateMovies(AddMovieToCollection request) => LoadMovie(request) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Movie does not exist")); private Task> LoadMovie(AddMovieToCollection request) => _movieRepository.GetMovie(request.MovieId); - - private record RequestParameters(Collection Collection, Movie MovieToAdd); } } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs index ee1c1038f..4812be04b 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddSeasonToCollectionHandler.cs @@ -1,5 +1,4 @@ -using System.Linq; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Domain; @@ -8,9 +7,7 @@ using LanguageExt; namespace ErsatzTV.Application.MediaCollections.Commands { - public class - AddSeasonToCollectionHandler : MediatR.IRequestHandler> + public class AddSeasonToCollectionHandler : MediatR.IRequestHandler> { private readonly IMediaCollectionRepository _mediaCollectionRepository; private readonly ITelevisionRepository _televisionRepository; @@ -27,41 +24,28 @@ namespace ErsatzTV.Application.MediaCollections.Commands AddSeasonToCollection request, CancellationToken cancellationToken) => Validate(request) - .MapT(ApplyAddTelevisionSeasonRequest) + .MapT(_ => ApplyAddTelevisionSeasonRequest(request)) .Bind(v => v.ToEitherAsync()); - private async Task ApplyAddTelevisionSeasonRequest(RequestParameters parameters) - { - if (parameters.Collection.MediaItems.All(s => s.Id != parameters.SeasonToAdd.Id)) - { - parameters.Collection.MediaItems.Add(parameters.SeasonToAdd); - await _mediaCollectionRepository.Update(parameters.Collection); - } - - return Unit.Default; - } + private async Task ApplyAddTelevisionSeasonRequest(AddSeasonToCollection request) => + await _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.SeasonId); - private async Task> - Validate(AddSeasonToCollection request) => - (await SimpleMediaCollectionMustExist(request), await ValidateSeason(request)) - .Apply( - (collectionToUpdate, season) => - new RequestParameters(collectionToUpdate, season)); + private async Task> Validate(AddSeasonToCollection request) => + (await CollectionMustExist(request), await ValidateSeason(request)) + .Apply((_, _) => Unit.Default); - private Task> SimpleMediaCollectionMustExist( - AddSeasonToCollection updateCollection) => - _mediaCollectionRepository.GetCollectionWithItems(updateCollection.CollectionId) + private Task> CollectionMustExist(AddSeasonToCollection request) => + _mediaCollectionRepository.GetCollectionWithItems(request.CollectionId) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Collection does not exist.")); - private Task> ValidateSeason( - AddSeasonToCollection request) => + private Task> ValidateSeason(AddSeasonToCollection request) => LoadTelevisionSeason(request) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Season does not exist")); private Task> LoadTelevisionSeason( AddSeasonToCollection request) => _televisionRepository.GetSeason(request.SeasonId); - - private record RequestParameters(Collection Collection, Season SeasonToAdd); } } diff --git a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs index d6b1aa5ba..9c7e780a9 100644 --- a/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs +++ b/ErsatzTV.Application/MediaCollections/Commands/AddShowToCollectionHandler.cs @@ -1,5 +1,4 @@ -using System.Linq; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Domain; @@ -25,40 +24,27 @@ namespace ErsatzTV.Application.MediaCollections.Commands AddShowToCollection request, CancellationToken cancellationToken) => Validate(request) - .MapT(ApplyAddTelevisionShowRequest) + .MapT(_ => ApplyAddTelevisionShowRequest(request)) .Bind(v => v.ToEitherAsync()); - private async Task ApplyAddTelevisionShowRequest(RequestParameters parameters) - { - if (parameters.Collection.MediaItems.All(s => s.Id != parameters.ShowToAdd.Id)) - { - parameters.Collection.MediaItems.Add(parameters.ShowToAdd); - await _mediaCollectionRepository.Update(parameters.Collection); - } - - return Unit.Default; - } + private Task ApplyAddTelevisionShowRequest(AddShowToCollection request) + => _mediaCollectionRepository.AddMediaItem(request.CollectionId, request.ShowId); - private async Task> - Validate(AddShowToCollection request) => - (await SimpleMediaCollectionMustExist(request), await ValidateShow(request)) - .Apply( - (collectionToUpdate, show) => - new RequestParameters(collectionToUpdate, show)); + private async Task> Validate(AddShowToCollection request) => + (await CollectionMustExist(request), await ValidateShow(request)) + .Apply((_, _) => Unit.Default); - private Task> SimpleMediaCollectionMustExist( - AddShowToCollection updateCollection) => - _mediaCollectionRepository.GetCollectionWithItems(updateCollection.CollectionId) + private Task> CollectionMustExist(AddShowToCollection request) => + _mediaCollectionRepository.GetCollectionWithItems(request.CollectionId) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Collection does not exist.")); - private Task> ValidateShow( - AddShowToCollection request) => + private Task> ValidateShow(AddShowToCollection request) => LoadTelevisionShow(request) + .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Show does not exist")); private Task> LoadTelevisionShow(AddShowToCollection request) => _televisionRepository.GetShow(request.ShowId); - - private record RequestParameters(Collection Collection, Show ShowToAdd); } } diff --git a/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs b/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs index ecc211446..8a94581a2 100644 --- a/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs +++ b/ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs @@ -16,6 +16,7 @@ namespace ErsatzTV.Core.Tests.Fakes public FakeMediaCollectionRepository(Map> data) => _data = data; public Task Add(Collection collection) => throw new NotSupportedException(); + public Task AddMediaItem(int collectionId, int mediaItemId) => throw new NotSupportedException(); public Task> Get(int id) => throw new NotSupportedException(); diff --git a/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs index 7fe621efc..248fa0764 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs @@ -8,6 +8,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories public interface IMediaCollectionRepository { Task Add(Collection collection); + Task AddMediaItem(int collectionId, int mediaItemId); Task> Get(int id); Task> GetCollectionWithItems(int id); Task> GetCollectionWithItemsUntracked(int id); diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs index 658469fd5..cc26f3dcc 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs @@ -29,6 +29,37 @@ namespace ErsatzTV.Infrastructure.Data.Repositories return collection; } + + public async Task AddMediaItem(int collectionId, int mediaItemId) + { + Option maybeCollection = await _dbContext.Collections + .Include(c => c.MediaItems) + .OrderBy(c => c.Id) + .SingleOrDefaultAsync(c => c.Id == collectionId) + .Map(Optional); + + await maybeCollection.IfSomeAsync( + async collection => + { + if (collection.MediaItems.All(i => i.Id != mediaItemId)) + { + Option maybeMediaItem = await _dbContext.MediaItems + .OrderBy(i => i.Id) + .SingleOrDefaultAsync(i => i.Id == mediaItemId) + .Map(Optional); + + await maybeMediaItem.IfSomeAsync( + async mediaItem => + { + collection.MediaItems.Add(mediaItem); + await _dbContext.SaveChangesAsync(); + }); + } + }); + + return Unit.Default; + } + public Task> Get(int id) => _dbContext.Collections .OrderBy(c => c.Id)