diff --git a/.idea/.idea.BookHive/.idea/workspace.xml b/.idea/.idea.BookHive/.idea/workspace.xml
index fb89e6d..0c39774 100644
--- a/.idea/.idea.BookHive/.idea/workspace.xml
+++ b/.idea/.idea.BookHive/.idea/workspace.xml
@@ -6,11 +6,14 @@
-
-
-
-
+
+
+
+
+
+
+
@@ -33,6 +36,8 @@
+
+
{
@@ -98,7 +103,7 @@
1773087844958
-
+
@@ -116,7 +121,15 @@
1773090621044
-
+
+
+ 1773091913623
+
+
+
+ 1773091913623
+
+
@@ -127,7 +140,8 @@
-
+
+
diff --git a/BookHive/Endpoints/Authors/DeleteAuthorEndpoint.cs b/BookHive/Endpoints/Authors/DeleteAuthorEndpoint.cs
index 2617798..3015caf 100644
--- a/BookHive/Endpoints/Authors/DeleteAuthorEndpoint.cs
+++ b/BookHive/Endpoints/Authors/DeleteAuthorEndpoint.cs
@@ -27,6 +27,12 @@ public class DeleteAuthorEndpoint(AuthorRepository authorRepository) : Endpoint<
await Send.NotFoundAsync(ct);
return;
}
+
+ if (author.Books?.Count > 0)
+ {
+ await Send.StringAsync("L'auteur possède encore des livres",409, cancellation: ct);
+ return;
+ }
await authorRepository.DeleteAsync(author, ct);
await Send.OkAsync(cancellation: ct);
diff --git a/BookHive/Endpoints/Books/CreateBookEndpoint.cs b/BookHive/Endpoints/Books/CreateBookEndpoint.cs
index f0603d0..0c916dd 100644
--- a/BookHive/Endpoints/Books/CreateBookEndpoint.cs
+++ b/BookHive/Endpoints/Books/CreateBookEndpoint.cs
@@ -1,11 +1,12 @@
using BookHive.DTO.Book;
using BookHive.Models;
using BookHive.Repositories;
+using BookHive.Specifications.Authors;
using FastEndpoints;
namespace BookHive.Endpoints.Books;
-public class CreateBookEndpoint(BookRepository bookRepository, AutoMapper.IMapper mapper) : Endpoint
+public class CreateBookEndpoint(BookRepository bookRepository, AuthorRepository authorRepository, AutoMapper.IMapper mapper) : Endpoint
{
public override void Configure()
{
@@ -15,6 +16,13 @@ public class CreateBookEndpoint(BookRepository bookRepository, AutoMapper.IMappe
public override async Task HandleAsync(CreateBookDto req, CancellationToken ct)
{
+ Author? author = await authorRepository.SingleOrDefaultAsync(new GetAuthorByIdSpec(req.AuthorId), ct);
+ if (author is null)
+ {
+ await Send.NotFoundAsync(ct);
+ return;
+ }
+
await bookRepository.AddAsync(mapper.Map(req), ct);
await Send.OkAsync(cancellation: ct);
}
diff --git a/BookHive/Endpoints/Books/DeleteBookEndpoint.cs b/BookHive/Endpoints/Books/DeleteBookEndpoint.cs
index 53e9252..45d91ff 100644
--- a/BookHive/Endpoints/Books/DeleteBookEndpoint.cs
+++ b/BookHive/Endpoints/Books/DeleteBookEndpoint.cs
@@ -1,6 +1,7 @@
using BookHive.Models;
using BookHive.Repositories;
using BookHive.Specifications.Books;
+using BookHive.Specifications.Loans;
using FastEndpoints;
namespace BookHive.Endpoints.Books;
@@ -10,14 +11,14 @@ public class DeleteBookRequest
public int Id { get; set; }
}
-public class DeleteBookEndpoint(BookRepository bookRepository) : Endpoint
+public class DeleteBookEndpoint(BookRepository bookRepository, LoanRepository loanRepository) : Endpoint
{
public override void Configure()
{
Delete("/books/{@Id}", x => new { x.Id });
AllowAnonymous();
}
-
+
public override async Task HandleAsync(DeleteBookRequest req, CancellationToken ct)
{
Book? book = await bookRepository.SingleOrDefaultAsync(new GetBookByIdSpec(req.Id), ct);
@@ -27,7 +28,14 @@ public class DeleteBookEndpoint(BookRepository bookRepository) : Endpoint
+public class CreateLoanEndpoint(LoanRepository loanRepository, BookRepository bookRepository, MemberRepository memberRepository, AutoMapper.IMapper mapper) : Endpoint
{
public override void Configure()
{
@@ -15,6 +18,39 @@ public class CreateLoanEndpoint(LoanRepository loanRepository, AutoMapper.IMappe
public override async Task HandleAsync(CreateLoanDto req, CancellationToken ct)
{
+ Book? book = await bookRepository.SingleOrDefaultAsync(new GetBookByIdSpec(req.BookId), ct);
+ if (book is null)
+ {
+ await Send.NotFoundAsync(ct);
+ return;
+ }
+
+ Member? member = await memberRepository.SingleOrDefaultAsync(new GetMemberByIdSpec(req.MemberId), ct);
+ if (member is null)
+ {
+ await Send.NotFoundAsync(ct);
+ return;
+ }
+
+ if (!member.IsActive)
+ {
+ await Send.StringAsync("Le membre est désactivé", 400, cancellation: ct);
+ return;
+ }
+
+ Loan? loan = await loanRepository.FirstOrDefaultAsync(new GetAvailableBookByIdSpec(req.BookId), ct);
+ if (loan is not null)
+ {
+ await Send.StringAsync("Ce livre est déjà emprunté", 400, cancellation: ct);
+ return;
+ }
+
+ if (req.DueDate < req.LoanDate || req.DueDate.DayNumber - req.LoanDate.DayNumber < 1 || req.DueDate.DayNumber - req.LoanDate.DayNumber > 30)
+ {
+ await Send.StringAsync("La date de retour estimée est incorrecte", 400, cancellation: ct);
+ return;
+ }
+
await loanRepository.AddAsync(mapper.Map(req), ct);
await Send.OkAsync(cancellation: ct);
}
diff --git a/BookHive/Endpoints/Reviews/CreateReviewEndpoint.cs b/BookHive/Endpoints/Reviews/CreateReviewEndpoint.cs
index 8e6f29c..ce15647 100644
--- a/BookHive/Endpoints/Reviews/CreateReviewEndpoint.cs
+++ b/BookHive/Endpoints/Reviews/CreateReviewEndpoint.cs
@@ -3,6 +3,7 @@ using BookHive.Models;
using BookHive.Repositories;
using BookHive.Specifications.Books;
using BookHive.Specifications.Members;
+using BookHive.Specifications.Reviews;
using FastEndpoints;
namespace BookHive.Endpoints.Reviews;
@@ -36,6 +37,19 @@ public class CreateReviewEndpoint(
return;
}
+ if (!member.IsActive)
+ {
+ await Send.StringAsync("Le membre est désactivé", 400, cancellation: ct);
+ return;
+ }
+
+ Review? review = await reviewRepository.SingleOrDefaultAsync(new GetReviewByCriteriaSpec(req.BookId, req.MemberId), ct);
+ if (review is not null)
+ {
+ await Send.StringAsync("Le membre a déjà posté un commentaire", 400, cancellation: ct);
+ return;
+ }
+
await reviewRepository.AddAsync(mapper.Map(req), ct);
await Send.OkAsync(cancellation: ct);
}
diff --git a/BookHive/Specifications/Loans/GetAvailableBookByIdSpec.cs b/BookHive/Specifications/Loans/GetAvailableBookByIdSpec.cs
new file mode 100644
index 0000000..fe7224b
--- /dev/null
+++ b/BookHive/Specifications/Loans/GetAvailableBookByIdSpec.cs
@@ -0,0 +1,13 @@
+using Ardalis.Specification;
+using BookHive.Models;
+
+namespace BookHive.Specifications.Loans;
+
+public class GetAvailableBookByIdSpec : Specification
+{
+ public GetAvailableBookByIdSpec(int bookId)
+ {
+ Query
+ .Where(x => x.BookId == bookId && x.ReturnDate == null);
+ }
+}
\ No newline at end of file
diff --git a/BookHive/Specifications/Reviews/GetReviewByCriteriaSpec.cs b/BookHive/Specifications/Reviews/GetReviewByCriteriaSpec.cs
new file mode 100644
index 0000000..23753a0
--- /dev/null
+++ b/BookHive/Specifications/Reviews/GetReviewByCriteriaSpec.cs
@@ -0,0 +1,13 @@
+using Ardalis.Specification;
+using BookHive.Models;
+
+namespace BookHive.Specifications.Reviews;
+
+public class GetReviewByCriteriaSpec : SingleResultSpecification
+{
+ public GetReviewByCriteriaSpec(int bookId, int memberId)
+ {
+ Query
+ .Where(x => x.BookId == bookId && x.MemberId == memberId);
+ }
+}
\ No newline at end of file