Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ await audit.WriteAsync(
{
salesOrderItemId = result.Value.Id,
productId = product.Id,
// #747 — snapshotted, never resolved by a reader later: a
// renamed product would otherwise re-render this row under
// a name the seller never saw (#720's rule, applied to the
// name). The unit is here because quantity alone is
// ambiguous — 8 trays and 8 eggs are both "8".
productName = product.Name,
unit = unit.ToString(),
quantity = command.Quantity,
unitPriceMinorUnits = unitPrice.MinorUnits,
listUnitPriceMinorUnits,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
namespace Cluckwork.Application.Features.Sales.UpdateOrderItem;

using Cluckwork.Application.Common;
using Cluckwork.Application.Features.Catalog;
using Cluckwork.Application.Features.Sales;
using Cluckwork.Domain.Common;
using Cluckwork.Domain.Sales;

public sealed class UpdateOrderItemHandler(
ISalesOrderRepository orders,
IProductRepository products,
IAuditWriter audit,
IUnitOfWork unitOfWork)
{
Expand Down Expand Up @@ -40,6 +42,15 @@ public async Task<Result> HandleAsync(UpdateOrderItemCommand command, Cancellati
var beforeProductId = existing?.ProductId;
var beforeListUnitPriceMinorUnits = existing?.ListUnitPriceMinorUnits;
var beforeListPriceBasis = existing?.ListPriceBasis.ToString();
// #747 — the unit comes off the line's own snapshot; the name needs a
// product read, because SalesOrderItem carries ProductId and no name.
// Read HERE, at the moment of the edit: that is what this row is a
// record of. Null only if the product row is gone, which leaves the id
// in the payload as the stable join key.
var beforeUnit = existing?.Unit.ToString();
var beforeProductName = existing is null
? null
: (await products.GetByIdAsync(existing.ProductId, ct))?.Name;

var result = order.UpdateItem(command.ItemId, command.Quantity, unitPrice);
if (result.IsFailure)
Expand All @@ -56,6 +67,8 @@ await audit.WriteAsync(
{
salesOrderItemId = command.ItemId,
productId = beforeProductId!.Value,
productName = beforeProductName,
unit = beforeUnit,
before = new
{
quantity = beforeQuantity!.Value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public async Task UpdateItem_RecordsThePriceItChangedFromAndTo()
// later removal, which cascades the row away.
Assert.Equal(itemId, root.GetProperty("salesOrderItemId").GetGuid());
Assert.Equal(productId, root.GetProperty("productId").GetGuid());
// #747 — same snapshot on the edit path. Read at the moment of the
// edit, which is the right question for an UpdateItem row.
Assert.Equal("Large Eggs", root.GetProperty("productName").GetString());
Assert.Equal("Egg", root.GetProperty("unit").GetString());

// The price it changed FROM and the price it changed TO. Reading these
// through a reference held across order.UpdateItem would make them
Expand Down Expand Up @@ -187,6 +191,12 @@ public async Task AddItem_RecordsListPriceBasisByName()
Assert.Equal(ListPrice, root.GetProperty("listUnitPriceMinorUnits").GetInt64());
Assert.Equal(DiscountedPrice, root.GetProperty("unitPriceMinorUnits").GetInt64());
Assert.Equal(productId, root.GetProperty("productId").GetGuid());
// #747 — the NAME and the UNIT, snapshotted. A reader resolving the id
// live would get today's name, so a renamed product would re-render
// history under a name the seller never saw. "Large Eggs" and "Egg" are
// distinct strings, so transposing the two fields reddens here.
Assert.Equal("Large Eggs", root.GetProperty("productName").GetString());
Assert.Equal("Egg", root.GetProperty("unit").GetString());
Assert.Equal(10, root.GetProperty("quantity").GetInt32());
Assert.Equal("USD", root.GetProperty("currencyCode").GetString());
Assert.Equal(2, root.GetProperty("currencyMinorUnit").GetInt32());
Expand Down
Loading