From 599faa992fbf65b4bcfa4cd436eadd10166b8b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Sun, 26 May 2024 22:24:35 +1000 Subject: [PATCH] Order barista orders by place order timestamp (#4) --- src/Barista/NCafe.Barista.Api/Program.cs | 5 ++++- .../Projections/BaristaOrderProjectionService.cs | 9 +++++++-- .../NCafe.Barista.Domain/Entities/BaristaOrder.cs | 7 ++++++- src/Barista/NCafe.Barista.Domain/Events/OrderPlaced.cs | 1 + .../NCafe.Barista.Domain/Events/OrderPrepared.cs | 3 +++ src/Barista/NCafe.Barista.Domain/Queries/GetOrders.cs | 6 ++++-- .../NCafe.Barista.Domain/ReadModels/BaristaOrder.cs | 2 ++ src/Common/NCafe.Shared/Hubs/Order.cs | 2 +- src/UI/NCafe.Web/Models/BaristaOrder.cs | 2 +- src/UI/NCafe.Web/Pages/Barista/Index.razor | 10 +++++----- 10 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Barista/NCafe.Barista.Api/Program.cs b/src/Barista/NCafe.Barista.Api/Program.cs index 0010aed..6d19509 100644 --- a/src/Barista/NCafe.Barista.Api/Program.cs +++ b/src/Barista/NCafe.Barista.Api/Program.cs @@ -68,7 +68,10 @@ await mediator.Send(new PlaceOrder( // Notify clients await hubContext.Clients.All.SendAsync( "ReceiveOrder", - new Order(message.Id, message.OrderItems.Select(i => new NCafe.Shared.Hubs.OrderItem(i.Name, i.Quantity)).ToArray(), message.CustomerName)); + new Order(message.Id, + message.OrderItems.Select(i => new NCafe.Shared.Hubs.OrderItem(i.Name, i.Quantity)).ToArray(), + message.CustomerName, + DateTimeOffset.Now)); }); app.MapDefaultEndpoints(); diff --git a/src/Barista/NCafe.Barista.Api/Projections/BaristaOrderProjectionService.cs b/src/Barista/NCafe.Barista.Api/Projections/BaristaOrderProjectionService.cs index 2b8b3ab..3368d9b 100644 --- a/src/Barista/NCafe.Barista.Api/Projections/BaristaOrderProjectionService.cs +++ b/src/Barista/NCafe.Barista.Api/Projections/BaristaOrderProjectionService.cs @@ -16,16 +16,21 @@ public BaristaOrderProjectionService(IProjectionService projection { Id = @event.Id, CustomerName = @event.Customer, + OrderPlacedAt = @event.OrderPlacedAt, Items = @event.OrderItems.Select(item => new BaristaOrderItem { Name = item.Name, - Quantity = item.Quantity + Quantity = item.Quantity, }).ToArray() }); projectionService.OnUpdate( order => order.Id, - (@event, order) => order.IsCompleted = true); + (@event, order) => + { + order.IsCompleted = true; + order.OrderPreparedAt = @event.OrderPreparedAt; + }); } protected async override Task ExecuteAsync(CancellationToken stoppingToken) diff --git a/src/Barista/NCafe.Barista.Domain/Entities/BaristaOrder.cs b/src/Barista/NCafe.Barista.Domain/Entities/BaristaOrder.cs index 60c614d..c9533fb 100644 --- a/src/Barista/NCafe.Barista.Domain/Entities/BaristaOrder.cs +++ b/src/Barista/NCafe.Barista.Domain/Entities/BaristaOrder.cs @@ -19,13 +19,16 @@ public BaristaOrder(Guid id, ValueObjects.OrderItem[] orderItems, string custome RaiseEvent(new OrderPlaced(id) { OrderItems = orderItems, - Customer = customer + Customer = customer, + OrderPlacedAt = DateTimeOffset.UtcNow, }); } public IReadOnlyCollection Items { get; private set; } public string Customer { get; private set; } public bool IsCompleted { get; private set; } + public DateTimeOffset? OrderPlacedAt { get; private set; } + public DateTimeOffset? OrderPreparedAt { get; private set; } public void CompletePreparation() { @@ -42,11 +45,13 @@ private void Apply(OrderPlaced @event) Id = @event.Id; Items = @event.OrderItems; Customer = @event.Customer; + OrderPlacedAt = @event.OrderPlacedAt; IsCompleted = false; } private void Apply(OrderPrepared @event) { IsCompleted = true; + OrderPreparedAt = @event.OrderPreparedAt; } } diff --git a/src/Barista/NCafe.Barista.Domain/Events/OrderPlaced.cs b/src/Barista/NCafe.Barista.Domain/Events/OrderPlaced.cs index 742fb65..ccc3d43 100644 --- a/src/Barista/NCafe.Barista.Domain/Events/OrderPlaced.cs +++ b/src/Barista/NCafe.Barista.Domain/Events/OrderPlaced.cs @@ -10,6 +10,7 @@ public OrderPlaced(Guid id) Id = id; } + public DateTimeOffset OrderPlacedAt { get; init; } public OrderItem[] OrderItems { get; init; } public string Customer { get; init; } } diff --git a/src/Barista/NCafe.Barista.Domain/Events/OrderPrepared.cs b/src/Barista/NCafe.Barista.Domain/Events/OrderPrepared.cs index 9a26a42..397cee8 100644 --- a/src/Barista/NCafe.Barista.Domain/Events/OrderPrepared.cs +++ b/src/Barista/NCafe.Barista.Domain/Events/OrderPrepared.cs @@ -7,5 +7,8 @@ public sealed record OrderPrepared : Event public OrderPrepared(Guid id) { Id = id; + OrderPreparedAt = DateTimeOffset.UtcNow; } + + public DateTimeOffset OrderPreparedAt { get; init; } } diff --git a/src/Barista/NCafe.Barista.Domain/Queries/GetOrders.cs b/src/Barista/NCafe.Barista.Domain/Queries/GetOrders.cs index 3c98485..8bac691 100644 --- a/src/Barista/NCafe.Barista.Domain/Queries/GetOrders.cs +++ b/src/Barista/NCafe.Barista.Domain/Queries/GetOrders.cs @@ -13,8 +13,10 @@ internal sealed class GetOrdersHandler(IReadModelRepository orderR public Task Handle(GetOrders query, CancellationToken cancellationToken) { - var products = _orderRepository.GetAll() + var orders = _orderRepository.GetAll() + .Where(order => !order.IsCompleted) + .OrderBy(order => order.OrderPlacedAt) .ToArray(); - return Task.FromResult(products); + return Task.FromResult(orders); } } diff --git a/src/Barista/NCafe.Barista.Domain/ReadModels/BaristaOrder.cs b/src/Barista/NCafe.Barista.Domain/ReadModels/BaristaOrder.cs index 7c4a999..99b50f5 100644 --- a/src/Barista/NCafe.Barista.Domain/ReadModels/BaristaOrder.cs +++ b/src/Barista/NCafe.Barista.Domain/ReadModels/BaristaOrder.cs @@ -6,6 +6,8 @@ public sealed class BaristaOrder : ReadModel { public string CustomerName { get; set; } public BaristaOrderItem[] Items { get; set; } + public DateTimeOffset OrderPlacedAt { get; set; } + public DateTimeOffset? OrderPreparedAt { get; set; } public bool IsCompleted { get; set; } } diff --git a/src/Common/NCafe.Shared/Hubs/Order.cs b/src/Common/NCafe.Shared/Hubs/Order.cs index 6c1f81f..f542972 100644 --- a/src/Common/NCafe.Shared/Hubs/Order.cs +++ b/src/Common/NCafe.Shared/Hubs/Order.cs @@ -1,5 +1,5 @@ namespace NCafe.Shared.Hubs; -public sealed record Order(Guid Id, OrderItem[] OrderItems, string Customer); +public sealed record Order(Guid Id, OrderItem[] OrderItems, string Customer, DateTimeOffset OrderPlacedAt); public sealed record OrderItem(string Name, int Quantity); diff --git a/src/UI/NCafe.Web/Models/BaristaOrder.cs b/src/UI/NCafe.Web/Models/BaristaOrder.cs index 9815993..f18dcaf 100644 --- a/src/UI/NCafe.Web/Models/BaristaOrder.cs +++ b/src/UI/NCafe.Web/Models/BaristaOrder.cs @@ -1,5 +1,5 @@ namespace NCafe.Web.Models; -public record BaristaOrder(Guid Id, string CustomerName, BaristaOrderItem[] Items, bool IsCompleted); +public record BaristaOrder(Guid Id, string CustomerName, BaristaOrderItem[] Items, DateTimeOffset OrderPlacedAt); public record BaristaOrderItem(string Name, int Quantity); diff --git a/src/UI/NCafe.Web/Pages/Barista/Index.razor b/src/UI/NCafe.Web/Pages/Barista/Index.razor index 3d759ff..05fd4c6 100644 --- a/src/UI/NCafe.Web/Pages/Barista/Index.razor +++ b/src/UI/NCafe.Web/Pages/Barista/Index.razor @@ -15,14 +15,14 @@ { } -else if (!orders.Any(o => !o.IsCompleted)) +else if (!orders.Any()) { } else { - @foreach (var order in orders.Where(o => !o.IsCompleted)) + @foreach (var order in orders.OrderBy(o => o.OrderPlacedAt)) {
@order.CustomerName
@@ -58,17 +58,17 @@ else var url = $"{Configuration["BaristaBaseAddress"]}/orders/prepared"; try { + var order = orders.Single(o => o.Id == orderId); var response = await Http.PostAsJsonAsync(url, new { OrderId = orderId }); response.EnsureSuccessStatusCode(); _ = NotificationService.Open(new NotificationConfig { - Message = "Order Completed", + Message = $"{order.CustomerName}'s order Completed", Description = $"Order completed successfully.", NotificationType = NotificationType.Success }); - var order = orders.FirstOrDefault(o => o.Id == orderId); orders.Remove(order); StateHasChanged(); @@ -97,7 +97,7 @@ else order.Id, order.Customer, order.OrderItems.Select(i => new BaristaOrderItem(i.Name, i.Quantity)).ToArray(), - false)); + order.OrderPlacedAt)); StateHasChanged(); });