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);
+ }
+}