diff --git a/src/After/Order.cs b/src/After/Order.cs index 9892c2e..95777a9 100644 --- a/src/After/Order.cs +++ b/src/After/Order.cs @@ -24,6 +24,15 @@ public class Order /// public int TotalInCents { get; set; } + /// + /// The discounted total in cents, copied onto the order by the caller of + /// the discount flow (see ). Derived + /// data: it lives in the domain only — neither + /// nor carries it — and the applied percentage + /// is not stored either, being derivable from the two totals. + /// + public int DiscountedTotalInCents { get; set; } + /// /// The client that owns this order. Set automatically by /// when the order is added to diff --git a/tests/BeforeAfter.Tests/DiscountedOrderMappingTests.cs b/tests/BeforeAfter.Tests/DiscountedOrderMappingTests.cs new file mode 100644 index 0000000..0c1cb6a --- /dev/null +++ b/tests/BeforeAfter.Tests/DiscountedOrderMappingTests.cs @@ -0,0 +1,59 @@ +using After; +using static BeforeAfter.Tests.TestData.ClientBuilder; +using static BeforeAfter.Tests.TestData.OrderBuilder; + +namespace BeforeAfter.Tests; + +/// +/// EXERCISE — the mapping from a onto an +/// is NOT one-on-one. (This is the solution participants +/// arrive at from the stub in EXERCISE.md.) +/// +public class DiscountedOrderMappingTests +{ + [Fact] // EXERCISE STEP 2 + public void A_discounted_order_can_be_correlated_onto_its_order() + { + var db = new DbContext(); + var order = ValidOrder().WithDescription("big order").WithTotal(150_00).Build(); + var client = ValidClient().WithName("Acme").WithOrder(order).Build(); + db.Save(client); + db.Save(order); + + // 10 % for orders above €100: + var discounted = DiscountCalculator.CalculateDiscount( + order, discountBarrierCents: 100_00, discountPercentage: 10); + + // Correlate: the discounted result belongs to the order carrying this id. + Assert.Equal(order.Id, discounted.OrderId); + + // Copy the discounted total onto the order. The discount percentage is + // deliberately NOT copied — it is derivable from the two totals. + order.DiscountedTotalInCents = discounted.DiscountedTotalInCents; + + Assert.Equal(135_00, order.DiscountedTotalInCents); + } + + [Fact] // EXERCISE STEP 3 + public void Saving_a_discounted_order_keeps_the_stored_total_untouched() + { + var db = new DbContext(); + var order = ValidOrder().WithDescription("big order").WithTotal(150_00).Build(); + var client = ValidClient().WithName("Acme").WithOrder(order).Build(); + db.Save(client); + db.Save(order); + + var discounted = DiscountCalculator.CalculateDiscount( + order, discountBarrierCents: 100_00, discountPercentage: 10); + Assert.Equal(order.Id, discounted.OrderId); + order.DiscountedTotalInCents = discounted.DiscountedTotalInCents; + + // Save the updated order: the context refreshes the stored row in place. + db.Save(order); + + // The persisted record keeps the ORIGINAL total: the database knows + // nothing about discounts — derived data lives in the domain only. + var row = db.Find(candidate => candidate.Id == discounted.OrderId)!; + Assert.Equal(150_00, row.TotalInCents); + } +}