-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Remove item Let the cashier remove/cancel an item from the order - Add a trash button to the order summary - Add a new endpoint to cashier API - Add RemoveItem and Apply (OrderItemRemoved) methods to Order entity - Add Total property to OrderItem ValueObject and use it to calculate the Order Total instead of Price - Update AntDesign package to latest version - Change the Place order modal to use Ant component - Removed custom Modal component * Add test case --------- Co-authored-by: Andre Foresti <[email protected]>
- Loading branch information
Showing
13 changed files
with
321 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/Cashier/NCafe.Cashier.Domain.Tests/Commands/RemoveItemTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
using NCafe.Cashier.Domain.Commands; | ||
using NCafe.Cashier.Domain.Entities; | ||
using NCafe.Cashier.Domain.Exceptions; | ||
using NCafe.Cashier.Domain.ValueObjects; | ||
using NCafe.Core.Repositories; | ||
using System.Threading; | ||
|
||
namespace NCafe.Cashier.Domain.Tests.Commands; | ||
|
||
public class RemoveItemTests | ||
{ | ||
private readonly RemoveItemFromOrderHandler _sut; | ||
private readonly IRepository _repository; | ||
|
||
public RemoveItemTests() | ||
{ | ||
_repository = A.Fake<IRepository>(); | ||
_sut = new RemoveItemFromOrderHandler(_repository); | ||
} | ||
|
||
[Fact] | ||
public async Task ShouldSaveOrder() | ||
{ | ||
// Arrange | ||
var orderId = Guid.NewGuid(); | ||
var productId = Guid.NewGuid(); | ||
var command = new RemoveItemFromOrder(orderId, productId, Quantity: 1); | ||
var order = new Order(orderId, "cashier-1", DateTimeOffset.UtcNow); | ||
order.AddItem(new OrderItem(productId, "product1", 1, 5)); | ||
|
||
A.CallTo(() => _repository.GetById<Order>(orderId)) | ||
.Returns(Task.FromResult(order)); | ||
|
||
// Act | ||
await _sut.Handle(command, CancellationToken.None); | ||
|
||
// Assert | ||
A.CallTo(() => _repository.Save( | ||
A<Order>.That.Matches(o => o.Id == orderId && | ||
o.Items.All(i => i.ProductId != productId)))) | ||
.MustHaveHappenedOnceExactly(); | ||
} | ||
|
||
[Fact] | ||
public async Task GivenOrderNotFound_ShouldThrow() | ||
{ | ||
// Arrange | ||
var orderId = Guid.NewGuid(); | ||
var productId = Guid.NewGuid(); | ||
var command = new RemoveItemFromOrder(orderId, productId, Quantity: 1); | ||
|
||
// Act | ||
var exception = await Record.ExceptionAsync(() => _sut.Handle(command, CancellationToken.None)); | ||
|
||
// Assert | ||
exception.ShouldBeOfType<OrderNotFoundException>(); | ||
} | ||
|
||
[Fact] | ||
public async Task GivenNotNewOrder_ShouldThrow() | ||
{ | ||
// Arrange | ||
var orderId = Guid.NewGuid(); | ||
var productId = Guid.NewGuid(); | ||
var command = new RemoveItemFromOrder(orderId, productId, Quantity: 1); | ||
var order = new Order(orderId, "cashier-1", DateTimeOffset.UtcNow); | ||
order.AddItem(new OrderItem(productId, "product1", quantity: 1, 5)); | ||
order.PlaceOrder(new Customer("John Doe"), DateTimeOffset.UtcNow); | ||
|
||
A.CallTo(() => _repository.GetById<Order>(orderId)) | ||
.Returns(Task.FromResult(order)); | ||
|
||
// Act | ||
var exception = await Record.ExceptionAsync(() => _sut.Handle(command, CancellationToken.None)); | ||
|
||
// Assert | ||
exception.ShouldBeOfType<CannotRemoveItemFromOrderException>(); | ||
} | ||
|
||
[Fact] | ||
public async Task GivenRemovingMoreItemsThanOrdered_ShouldThrow() | ||
{ | ||
// Arrange | ||
var orderId = Guid.NewGuid(); | ||
var productId = Guid.NewGuid(); | ||
var command = new RemoveItemFromOrder(orderId, productId, Quantity: 2); | ||
var order = new Order(orderId, "cashier-1", DateTimeOffset.UtcNow); | ||
order.AddItem(new OrderItem(productId, "product1", 1, 5)); | ||
|
||
A.CallTo(() => _repository.GetById<Order>(orderId)) | ||
.Returns(Task.FromResult(order)); | ||
|
||
// Act | ||
var exception = await Record.ExceptionAsync(() => _sut.Handle(command, CancellationToken.None)); | ||
|
||
// Assert | ||
exception.ShouldBeOfType<CannotRemoveMoreItemsThanOrderedException>(); | ||
} | ||
|
||
[Fact] | ||
public async Task GivenRemovingLessItemsThanOrdered_ShouldSaveOrder() | ||
{ | ||
// Arrange | ||
var orderId = Guid.NewGuid(); | ||
var productId = Guid.NewGuid(); | ||
var command = new RemoveItemFromOrder(orderId, productId, Quantity: 1); | ||
var order = new Order(orderId, "cashier-1", DateTimeOffset.UtcNow); | ||
order.AddItem(new OrderItem(productId, "product1", 2, 5)); | ||
|
||
A.CallTo(() => _repository.GetById<Order>(orderId)) | ||
.Returns(Task.FromResult(order)); | ||
|
||
// Act | ||
await _sut.Handle(command, CancellationToken.None); | ||
|
||
// Assert | ||
A.CallTo(() => _repository.Save( | ||
A<Order>.That.Matches(o => o.Id == orderId && | ||
o.Items.Any(i => i.ProductId == productId && i.Quantity == 1)))) | ||
.MustHaveHappenedOnceExactly(); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
src/Cashier/NCafe.Cashier.Domain/Commands/RemoveItemFromOrder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using MediatR; | ||
using NCafe.Cashier.Domain.Entities; | ||
using NCafe.Cashier.Domain.Exceptions; | ||
using NCafe.Cashier.Domain.ReadModels; | ||
using NCafe.Cashier.Domain.ValueObjects; | ||
using NCafe.Core.ReadModels; | ||
using NCafe.Core.Repositories; | ||
|
||
namespace NCafe.Cashier.Domain.Commands; | ||
|
||
public record RemoveItemFromOrder(Guid OrderId, Guid ProductId, int Quantity) : IRequest; | ||
|
||
internal sealed class RemoveItemFromOrderHandler(IRepository repository) : IRequestHandler<RemoveItemFromOrder> | ||
{ | ||
private readonly IRepository _repository = repository; | ||
|
||
public async Task Handle(RemoveItemFromOrder command, CancellationToken cancellationToken) | ||
{ | ||
var order = await _repository.GetById<Order>(command.OrderId) ?? throw new OrderNotFoundException(command.OrderId); | ||
|
||
order.RemoveItem(command.ProductId, command.Quantity); | ||
|
||
await _repository.Save(order); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/Cashier/NCafe.Cashier.Domain/Events/OrderItemRemoved.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using NCafe.Core.Domain; | ||
|
||
namespace NCafe.Cashier.Domain.Events; | ||
|
||
public sealed record OrderItemRemoved : Event | ||
{ | ||
public OrderItemRemoved(Guid id, Guid productId, int quantity) | ||
{ | ||
Id = id; | ||
ProductId = productId; | ||
Quantity = quantity; | ||
} | ||
|
||
public Guid ProductId { get; } | ||
public int Quantity { get; } | ||
} |
10 changes: 10 additions & 0 deletions
10
src/Cashier/NCafe.Cashier.Domain/Exceptions/CannotRemoveItemFromOrderException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using NCafe.Core.Exceptions; | ||
|
||
namespace NCafe.Cashier.Domain.Exceptions; | ||
|
||
public class CannotRemoveItemFromOrderException(Guid orderId, Guid productId) | ||
: DomainException($"Cannot remove item '{productId}' from order '{orderId}' when status is not New.") | ||
{ | ||
public Guid OrderId { get; } = orderId; | ||
public Guid ProductId { get; } = productId; | ||
} |
11 changes: 11 additions & 0 deletions
11
src/Cashier/NCafe.Cashier.Domain/Exceptions/CannotRemoveMoreItemsThanOrderedException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using NCafe.Core.Exceptions; | ||
|
||
namespace NCafe.Cashier.Domain.Exceptions; | ||
|
||
public class CannotRemoveMoreItemsThanOrderedException(Guid orderId, Guid productId, int quantity) | ||
: DomainException($"Cannot remove more items ({quantity}) than existing in the order '{orderId}'.") | ||
{ | ||
public Guid OrderId { get; } = orderId; | ||
public Guid ProductId { get; } = productId; | ||
public int Quantity { get; } = quantity; | ||
} |
10 changes: 10 additions & 0 deletions
10
src/Cashier/NCafe.Cashier.Domain/Exceptions/OrderItemNotFoundException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using NCafe.Core.Exceptions; | ||
|
||
namespace NCafe.Cashier.Domain.Exceptions; | ||
|
||
public class OrderItemNotFoundException(Guid orderId, Guid productId) | ||
: DomainException($"Order item {productId} was not found in order '{orderId}'.") | ||
{ | ||
public Guid OrderId { get; } = orderId; | ||
public Guid ProductId { get; } = productId; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.