Skip to content

Commit

Permalink
Merge pull request #72 from Livl-Corporation/jvm/feat/26-notification…
Browse files Browse the repository at this point in the history
…-review-received

refactor(review/request): notification review received and tell don't ask
  • Loading branch information
Kayn017 authored Jun 4, 2024
2 parents 66d3134 + 52f6ace commit 74cc64f
Show file tree
Hide file tree
Showing 19 changed files with 106 additions and 98 deletions.
11 changes: 6 additions & 5 deletions LivlReviews.Api/Controllers/ReviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ public async Task<ActionResult> CreateReview([FromBody] PostReviewRequest review
{
return BadRequest(ModelState);
}

var request = requestRepository.GetById(reviewRequest.RequestId);

var request = requestRepository
.GetAndInclude(r => r.Id == reviewRequest.RequestId, ["Product", "User", "Admin"]).FirstOrDefault();

if (request == null)
{
Expand All @@ -36,15 +37,15 @@ public async Task<ActionResult> CreateReview([FromBody] PostReviewRequest review

var review = new Review
{
RequestId = reviewRequest.RequestId,
RequestId = request.Id,
Rating = reviewRequest.Rating,
Content = reviewRequest.Content,
Title = reviewRequest.Title,
Title = reviewRequest.Title
};

try
{
review = reviewManager.CreateReview(review);
review = reviewManager.CreateReview(review, request);
}
catch (Exception e)
{
Expand Down
2 changes: 1 addition & 1 deletion LivlReviews.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
"AdminPassword": "administrator"
},
"Frontend": {
"BaseUrl": "https://localhost:3000"
"BaseUrl": "http://localhost:3000"
}
}
21 changes: 13 additions & 8 deletions LivlReviews.Domain.Test/Entities/RequestTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using LivlReviews.Domain.Entities;
using LivlReviews.Domain.Enums;
using LivlReviews.Domain.Models;
using LivlReviews.Domain.Test.Fakes;
using LivlReviews.Domain.Test.Spies;
using LivlReviews.Domain.Test.Stubs;
Expand Down Expand Up @@ -101,22 +102,24 @@ public void Approve_a_request_reject_other_request_on_same_product()
ProductId = 1
};

Request firstRequest = new Request
Request firstRequest = new Request()
{
Id = 1,
ProductId = 1,
AdminId = "1",
UserId = "2",
State = RequestState.Pending
State = RequestState.Pending,
Clock = new FakeClock(new DateTime(2024, 5, 28))
};

Request secondRequest = new Request
Request secondRequest = new Request()
{
Id = 2,
ProductId = 1,
AdminId = "1",
UserId = "3",
State = RequestState.Pending
State = RequestState.Pending,
Clock = new FakeClock(new DateTime(2024, 5, 28))
};

FakeRequestInventory requestInventory = new FakeRequestInventory([stock], [firstRequest, secondRequest], new NotificationManagerSpy());
Expand Down Expand Up @@ -150,13 +153,14 @@ public void Approve_a_request_remove_stock()
ProductId = 1
};

Request firstRequest = new Request
Request firstRequest = new Request()
{
Id = 1,
ProductId = 1,
AdminId = "1",
UserId = "2",
State = RequestState.Pending
State = RequestState.Pending,
Clock = new FakeClock(new DateTime(2024, 5, 28))
};

FakeRequestInventory requestInventory = new FakeRequestInventory([stock], [firstRequest], new NotificationManagerSpy());
Expand Down Expand Up @@ -218,13 +222,14 @@ public async Task Send_notification_to_user_when_request_state_updated()
ProductId = 1
};

Request firstRequest = new Request
Request firstRequest = new Request()
{
Id = 1,
ProductId = 1,
AdminId = UsersStub.Admin.Id,
UserId = "2",
State = RequestState.Pending
State = RequestState.Pending,
Clock = new FakeClock(new DateTime(2024, 5, 28))
};

FakeRequestInventory requestInventory = new FakeRequestInventory([stock], [firstRequest], new NotificationManagerSpy());
Expand Down
44 changes: 20 additions & 24 deletions LivlReviews.Domain.Test/Entities/Review.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using LivlReviews.Domain.Entities;
using LivlReviews.Domain.Enums;
using LivlReviews.Domain.Test.Clock;
using LivlReviews.Domain.Models;
using LivlReviews.Domain.Test.Fakes;
using LivlReviews.Domain.Test.Spies;
using LivlReviews.Domain.Test.Stubs;
using Xunit;

namespace LivlReviews.Domain.Test.Entities;
Expand All @@ -14,19 +13,18 @@ public class ReviewTest
public void Is_Request_Reviewable_When_Reviewable_Date_Reached()
{
// Arrange
var request = new Request
var currentTime = new DateTime(2024, 5, 28);
var fakeClock = new FakeClock(currentTime);
var request = new Request()
{
Id = 1,
State = RequestState.Received,
ReviewableAt = new DateTime(2024, 5, 20)
ReviewableAt = new DateTime(2024, 5, 20),
Clock = fakeClock
};

var fakeClock = new FakeClock(new DateTime(2024, 5, 28));

var reviewInventory = new FakeReviewInventory(request, fakeClock);

// Act
var result = reviewInventory.IsReviewableDateReached(request.Id);
var result = request.IsReviewable;

// Assert
Assert.True(result);
Expand All @@ -36,19 +34,18 @@ public void Is_Request_Reviewable_When_Reviewable_Date_Reached()
public void Is_Request_Not_Reviewable_When_Reviewable_Date_Not_Reached()
{
// Arrange
var request = new Request
var currentTime = new DateTime(2024, 5, 20);
var fakeClock = new FakeClock(currentTime);
var request = new Request()
{
Id = 1,
State = RequestState.Received,
ReviewableAt = new DateTime(2024, 5, 23)
ReviewableAt = new DateTime(2024, 5, 23),
Clock = fakeClock
};

var fakeClock = new FakeClock(new DateTime(2024, 5, 20)); // 3 days before the reviewable date

var reviewInventory = new FakeReviewInventory(request, fakeClock);

// Act
var result = reviewInventory.IsReviewableDateReached(request.Id);
var result = request.IsReviewable;

// Assert
Assert.False(result);
Expand All @@ -58,22 +55,21 @@ public void Is_Request_Not_Reviewable_When_Reviewable_Date_Not_Reached()
public void Set_Request_State_To_Completed_When_Review_Created()
{
// Arrange
var request = new Request
var request = new Request()
{
Id = 1,
State = RequestState.Received,
ReviewableAt = new DateTime(2024, 5, 20)
ReviewableAt = new DateTime(2024, 5, 20),
Clock = new FakeClock(new DateTime(2024, 5, 28))
};

var fakeClock = new FakeClock(new DateTime(2024, 5, 28));

var reviewInventory = new FakeReviewInventory(request, fakeClock);

var reviewInventory = new FakeReviewInventory();
var requestInventory = new FakeRequestInventory(new List<ProductStock>(), new List<Request> { request }, new NotificationManagerSpy());

NotificationManagerSpy notificationManager = new NotificationManagerSpy();
StockManager stockManager = new StockManager(requestInventory, notificationManager);

var reviewManager = new ReviewManager(reviewInventory, stockManager);
var reviewManager = new ReviewManager(reviewInventory, stockManager, new NotificationManagerSpy());

var review = new Review
{
Expand All @@ -86,7 +82,7 @@ public void Set_Request_State_To_Completed_When_Review_Created()
};

// Act
reviewManager.CreateReview(review);
reviewManager.CreateReview(review, request);

// Assert
var requestState = requestInventory.requests.Find(r => r.Id == request.Id)?.State;
Expand Down
16 changes: 2 additions & 14 deletions LivlReviews.Domain.Test/Fakes/FakeReviewInventory.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
using LivlReviews.Domain.Domain_interfaces_output;
using LivlReviews.Domain.Entities;
using LivlReviews.Domain.Enums;
using LivlReviews.Domain.Test.Clock;

namespace LivlReviews.Domain.Test.Stubs;
namespace LivlReviews.Domain.Test.Fakes;

public class FakeReviewInventory(Request request, IClock clock) : IReviewInventory
public class FakeReviewInventory() : IReviewInventory
{
public bool IsReviewableDateReached(int requestId)
{
return request.Id == requestId && clock.Now >= request.ReviewableAt;
}

public Review CreateReview(Review review)
{
return review;
}

public bool HasStatusReceived(int requestId)
{
return request.Id == requestId && request.State == RequestState.Received;
}
}
7 changes: 7 additions & 0 deletions LivlReviews.Domain.Test/Spies/NotificationManagerSpy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class NotificationManagerSpy : INotificationManager
public bool IsSendAccountInvitationNotificationCalled { get; private set; }
public bool IsSendRequestFromUserToAdminNotificationCalled { get; private set; }
public bool IsSendNotificationToUserAboutRequestStateChangeCalled { get; private set; }
public bool IsSendReceivedReviewNotificationCalled { get; private set; }

public Task SendAccountInvitationNotification(List<RecipientNotificationInvitation> recipientEmailInvitations)
{
Expand All @@ -27,4 +28,10 @@ public Task SendNotificationToUserAboutRequestStateChange(Request request)
IsSendNotificationToUserAboutRequestStateChangeCalled = true;
return Task.CompletedTask;
}

public Task SendNotificationToAdminWhenReviewSubmitted(Review review)
{
IsSendReceivedReviewNotificationCalled = true;
return Task.CompletedTask;
}
}
4 changes: 1 addition & 3 deletions LivlReviews.Domain/Domain_interfaces_input/IReviewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ namespace LivlReviews.Domain.Domain_interfaces_input;

public interface IReviewManager
{
public bool IsReviewableDateReached(int requestId);
public bool HasStatusReceived(int requestId);
public Review CreateReview(Review review);
public Review CreateReview(Review review, Request request);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LivlReviews.Domain.Test.Clock;
namespace LivlReviews.Domain.Domain_interfaces_output;

public interface IClock
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public interface INotificationContent
public string GenerateAccountInvitationTokenContent(string activationLink);
public string GenerateRequestFromUserToAdminContent(Request request);
public string GenerateRequestStateChangeContent(Request request);
public string GenerateReceivedReviewContent(Review review);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ public interface INotificationManager
public Task SendAccountInvitationNotification(List<RecipientNotificationInvitation> recipientEmailInvitations);
public Task SendRequestFromUserToAdminNotification(Request request);
public Task SendNotificationToUserAboutRequestStateChange(Request request);
public Task SendNotificationToAdminWhenReviewSubmitted(Review review);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ namespace LivlReviews.Domain.Domain_interfaces_output;

public interface IReviewInventory
{
bool IsReviewableDateReached(int requestId);
Review CreateReview(Review review);
bool HasStatusReceived(int requestId);
}
8 changes: 7 additions & 1 deletion LivlReviews.Domain/Entities/Request.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using LivlReviews.Domain.Domain_interfaces_output;
using LivlReviews.Domain.Entities.Interfaces;
using LivlReviews.Domain.Enums;
using LivlReviews.Domain.Models;

namespace LivlReviews.Domain.Entities;

public class Request : ICreatedDate, IUpdatedDate
public class Request() : ICreatedDate, IUpdatedDate
{
public int Id { get; set; }

Expand All @@ -25,6 +27,10 @@ public class Request : ICreatedDate, IUpdatedDate
public DateTime UpdatedAt { get; set; }

public DateTime? ReviewableAt { get; set; }

public IClock Clock { private get; set; } = new Clock();

public bool IsReviewable => State == RequestState.Received && ReviewableAt <= Clock.Now;

public static bool Can(Role role, Operation operation)
{
Expand Down
8 changes: 8 additions & 0 deletions LivlReviews.Domain/Models/Clock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using LivlReviews.Domain.Domain_interfaces_output;

namespace LivlReviews.Domain.Models;

public class Clock : IClock
{
public DateTime Now => DateTime.Now;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace LivlReviews.Domain.Test.Clock;
using LivlReviews.Domain.Domain_interfaces_output;

namespace LivlReviews.Domain.Models;

public class FakeClock(DateTime fakeDateTime) : IClock
{
Expand Down
31 changes: 10 additions & 21 deletions LivlReviews.Domain/ReviewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,22 @@

namespace LivlReviews.Domain;

public class ReviewManager(IReviewInventory reviewInventory, IStockManager stockManager) : IReviewManager
public class ReviewManager(IReviewInventory reviewInventory, IStockManager stockManager, INotificationManager notificationManager) : IReviewManager
{
public bool IsReviewableDateReached(int requestId)
public Review CreateReview(Review review, Request request)
{
return reviewInventory.IsReviewableDateReached(requestId);
}

public bool HasStatusReceived(int requestId)
{
return reviewInventory.HasStatusReceived(requestId);
}

public Review CreateReview(Review review)
{
if(!IsReviewableDateReached(review.RequestId))
if(!request.IsReviewable)
{
throw new Exception("The request is not reviewable yet, please wait until the reviewable date.");
}

if(!HasStatusReceived(review.RequestId))
{
throw new Exception("The request should be in the received state to create a review.");
throw new Exception("The request is not reviewable.");
}

var createdReview = reviewInventory.CreateReview(review);
stockManager.UpdateRequestState(review.Request, RequestState.Completed);


stockManager.UpdateRequestState(request, RequestState.Completed);

createdReview.Request = request;
notificationManager.SendNotificationToAdminWhenReviewSubmitted(createdReview);

return createdReview;
}
}
Loading

0 comments on commit 74cc64f

Please sign in to comment.