Skip to content

Commit

Permalink
Merge pull request #21 from CamiloBernal/develop
Browse files Browse the repository at this point in the history
Refactor repository
  • Loading branch information
CamiloBernal committed Oct 4, 2022
2 parents 79c9a02 + 6a90650 commit 74d98bb
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 36 deletions.
8 changes: 8 additions & 0 deletions src/Application/Exceptions/BookNotFoundInListException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace BooksWishlist.Application.Exceptions;

public class BookNotFoundInListException : Exception
{
public BookNotFoundInListException() : base("The book was not found in the collection.")
{
}
}
7 changes: 7 additions & 0 deletions src/Infrastructure/Store/IUserWishlistsRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,12 @@ Task<UserWishlists> UpdateAsync(UserWishlists list, string listName, string owne
Task<bool?> AddBooksAsync(string listName, IEnumerable<Book?>? books, string owner,
CancellationToken cancellationToken = default);

Task<bool?> RemoveBooksAsync(string listName, string bookId, string owner,
CancellationToken cancellationToken = default);


Task<IEnumerable<Book?>?> GetListBooks(string listName, string owner,
CancellationToken cancellationToken = default);

Task<UserWishlists?> FindByNameAsync(string listName, string owner, CancellationToken cancellationToken = default);
}
79 changes: 44 additions & 35 deletions src/Infrastructure/Store/UserWishlistsRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,68 +31,66 @@ public async Task<UserWishlists> CreateAsync(UserWishlists list, CancellationTok
public async Task<UserWishlists> UpdateAsync(UserWishlists list, string listName, string owner,
CancellationToken cancellationToken = default)
{
var filterDefinition = GetFilterByNameAndOwner(listName, owner);
var foundList = await _unitOfWork.GetOneAsync(filterDefinition, cancellationToken);
if (foundList is null)
{
throw new WishListNotFoundException();
}

foundList.Merge(list);
await _unitOfWork.UpdateAsync(filterDefinition, list, cancellationToken);
return foundList;
var foundList = await GetUserWishlist(listName, owner, cancellationToken: cancellationToken);
foundList.list.Merge(list);
await _unitOfWork.UpdateAsync(foundList.filterDefinition, list, cancellationToken);
return foundList.list;
}

public async Task<bool> DeleteAsync(string listName, string owner, CancellationToken cancellationToken = default)
{
var filterDefinition = GetFilterByNameAndOwner(listName, owner);
var foundList = await _unitOfWork.GetOneAsync(filterDefinition, cancellationToken);
if (foundList is null)
{
throw new WishListNotFoundException();
}

await _unitOfWork.RemoveAsync(filterDefinition, cancellationToken);
var filterDefinition =
await GetUserWishlist(listName, owner,
cancellationToken: cancellationToken); //For handle not found exception
await _unitOfWork.RemoveAsync(filterDefinition.filterDefinition, cancellationToken);
_log.LogWarning($"The Wishlist with name {listName} associated with the user {owner} and was deleted.");
return true;
}

public async Task<bool?> AddBooksAsync(string listName, IEnumerable<Book?>? books, string owner,
CancellationToken cancellationToken = default)
{
if (books is null)
{
return null;
}

var filterDefinition = GetFilterByNameAndOwner(listName, owner);
var foundList = await _unitOfWork.GetOneAsync(filterDefinition, cancellationToken);
if (foundList is null)
{
throw new WishListNotFoundException();
}

if (foundList.Books is not null && foundList.Books.Any())
if (books is null) return null;
var foundList = await GetUserWishlist(listName, owner, cancellationToken: cancellationToken);
if (foundList.list.Books is not null && foundList.list.Books.Any())
{
var conflictedBooks = (from registeredBooks in foundList.Books
var conflictedBooks = (from registeredBooks in foundList.list.Books
join newBooks in books on registeredBooks.BookId equals newBooks.BookId
select newBooks).ToList();
if (conflictedBooks.Any())
{
throw new DuplicatedBookInListException($"The book had already been added to the WishList {listName}");
}

foundList.Books = foundList.Books.Concat(books);
foundList.list.Books = foundList.list.Books.Concat(books);
}
else
{
foundList.Books = books;
foundList.list.Books = books;
}

await _unitOfWork.UpdateAsync(filterDefinition, foundList, cancellationToken);
await _unitOfWork.UpdateAsync(foundList.filterDefinition, foundList.list, cancellationToken);
return true;
}

public async Task<bool?> RemoveBooksAsync(string listName, string bookId, string owner,
CancellationToken cancellationToken = default)
{
var foundList = await GetUserWishlist(listName, owner, cancellationToken: cancellationToken);
var foundBook = foundList.list.Books?.FirstOrDefault(b => b?.BookId == bookId);
if (foundBook is null) throw new BookNotFoundInListException();
foundList.list.Books = foundList.list.Books?.Where(b => b?.BookId != bookId);
await _unitOfWork.UpdateAsync(foundList.filterDefinition, foundList.list, cancellationToken);
return true;
}

public async Task<IEnumerable<Book?>?> GetListBooks(string listName, string owner,
CancellationToken cancellationToken = default)
{
var foundList = await GetUserWishlist(listName, owner, cancellationToken: cancellationToken);
return foundList.list?.Books;
}

public Task<UserWishlists?> FindByNameAsync(string listName, string owner,
CancellationToken cancellationToken = default) =>
throw new NotImplementedException();
Expand All @@ -117,6 +115,17 @@ private static FilterDefinition<UserWishlists> GetFilterByNameAndOwner(string li
}


private async Task<(UserWishlists list, FilterDefinition<UserWishlists> filterDefinition)> GetUserWishlist(
string listName, string owner, bool handleNotFoundException = true,
CancellationToken cancellationToken = default)
{
var filterDefinition = GetFilterByNameAndOwner(listName, owner);
var foundList = await _unitOfWork.GetOneAsync(filterDefinition, cancellationToken);
if (foundList == null && handleNotFoundException) throw new WishListNotFoundException();
return (foundList, filterDefinition);
}


private async Task<bool> WishListExists(string listName, string owner,
CancellationToken cancellationToken = default)
{
Expand Down
116 changes: 115 additions & 1 deletion src/Presentation/Modules/UserWishlistsModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,124 @@ public static IEndpointRouteBuilder MapUserWishlistsEndpoints(this IEndpointRout
MapDeleteWishlistsEndpoint(routes);
MapAddBookToWishListEndpoint(routes);
MapEditWishListEndpoint(routes);
MapRemoveBookToWishListEndpoint(routes);
MapListWishlistsBooksEndpoint(routes);
return routes;
}


private static void MapListWishlistsBooksEndpoint(IEndpointRouteBuilder routes) =>
routes.MapGet("/wishlists/{listName?}/books", [Authorize] async (HttpContext ctx,
IUserWishlistsRepository wishlistsRepository,
ILoggerService log,
[FromRoute] string? listName,
CancellationToken cancellationToken) =>
{
if (listName == null)
{
return Utils.BuildBadRequestResult("Wishlist name not provided",
"You must specify the name of the list that you want to list.");
}
var currentUser = ctx.User.Identity?.Name;
if (currentUser is null)
{
return Results.Unauthorized();
}
try
{
var booksInList = await wishlistsRepository.GetListBooks(listName, currentUser, cancellationToken);
return Results.Ok(booksInList);
}
catch (Exception e)
{
log.LogError(e.Message, e);
return Results.Problem(e.Message, title: "Error creating the wishlist");
}
})
.WithName("wishlists/books/get")
.WithTags("Business Endpoints")
.Produces<IEnumerable<Book>>()
.ProducesProblem(400)
.ProducesProblem(401)
.ProducesProblem(500)
.RequireAuthorization();


private static void MapRemoveBookToWishListEndpoint(IEndpointRouteBuilder routes) =>
routes.MapDelete("/wishlists/{listName?}/books/{bookId?}", [Authorize] async (
IUserWishlistsRepository wishlistsRepository,
IGoogleBooksService booksService,
ILoggerService log, HttpContext ctx, [FromRoute] string? listName,
[FromRoute] string? bookId,
CancellationToken cancellationToken) =>
{
if (bookId is null)
{
return Utils.BuildBadRequestResult("Book Id for remove not provided",
"You must send the id of the book to remove from the list");
}
if (listName == null)
{
return Utils.BuildBadRequestResult("Wishlist name not provided",
"You must specify the name of the list that you want to delete.");
}
try
{
var currentUser = ctx.User.Identity?.Name;
if (currentUser is null)
{
return Results.Unauthorized();
}
_ = await wishlistsRepository.RemoveBooksAsync(listName, bookId, currentUser, cancellationToken);
return Results.NoContent();
}
catch (InvalidBookReferenceException invalidBookReferenceException)
{
log.LogError(invalidBookReferenceException.Message, invalidBookReferenceException);
return Utils.BuildBadRequestResult("Invalid Book Reference", invalidBookReferenceException.Message);
}
catch (WishListNotFoundException notFoundException)
{
log.LogError(notFoundException, notFoundException.Message);
return Results.NotFound(new ProblemDetails
{
Title = "Wishlist not found",
Detail =
"The specified Wishlist was not found in the database or is not associated with the current user",
Status = 404
});
}
catch (DuplicatedBookInListException duplicatedBookException)
{
log.LogError(duplicatedBookException.Message, duplicatedBookException);
return Results.Conflict(new ProblemDetails
{
Status = 409,
Detail = duplicatedBookException.Message,
Title = "Book duplicated in wishlist",
Type = Constants.ConflictResponseType
});
}
catch (Exception e)
{
log.LogError(e.Message, e);
return Results.Problem(e.Message, title: "Error creating the wishlist");
}
})
.WithName("/wishlists/books/delete")
.WithTags("Business Endpoints")
.Produces(204)
.ProducesProblem(400)
.ProducesProblem(401)
.ProducesProblem(500)
.RequireAuthorization();


private static void MapAddBookToWishListEndpoint(IEndpointRouteBuilder routes) =>
routes.MapPut("/wishlists/{listName?}/books/", [Authorize] async (IUserWishlistsRepository wishlistsRepository,
IGoogleBooksService booksService,
Expand Down Expand Up @@ -318,7 +432,7 @@ await wishlistsDtoValidator.HandleModelValidationAsync(wishlist, log,
})
.WithName("/wishlists/put")
.WithTags("Business Endpoints")
.Produces(201)
.Produces<UserWishlists>(202)
.ProducesProblem(400)
.ProducesProblem(409)
.ProducesProblem(401)
Expand Down

0 comments on commit 74d98bb

Please sign in to comment.