Files
show-dont-tell/csharp/src/OrderDomain/Order.cs
T
mostalive 4e0aea732a Add payment state to Order with guarded Pay transition
- Order records payments: Payments, AmountPaid, Outstanding,
  IsFullyPaid (parameterless, replaces IsFullyPaid(expectedTotal))
- Pay rejects open orders, non-positive amounts, and overpayments
- 4 new OrderCompletion tests assert observable state:
  PaymentOnOpenOrder_Throws_OrderStillUnpaid,
  CompletedOrder_PartialPayment_IsNotFullyPaid,
  CompletedOrder_PaymentsSummingToTotal_IsFullyPaid,
  Overpayment_Throws_AmountPaidUnchanged
- 11 tests green (6 OrderTotal + 5 OrderCompletion)
2026-10-01 13:46:10 +01:00

40 lines
1.2 KiB
C#

namespace OrderDomain;
public class Order
{
private readonly List<decimal> payments = new();
public List<OrderLine> Lines { get; } = new();
public decimal Total => Lines.Sum(l => l.Value);
public bool IsCompleted { get; private set; }
public IReadOnlyList<decimal> Payments => payments;
public decimal AmountPaid => payments.Sum();
public decimal Outstanding => Total - AmountPaid;
public bool IsFullyPaid => IsCompleted && Outstanding == 0m;
public void AddLine(decimal unitPrice, int quantity)
=> Lines.Add(new OrderLine(unitPrice, quantity));
public void ApplyDiscount(int lineIndex)
=> Lines[lineIndex].ApplyDiscount();
public void Complete() => IsCompleted = true;
public void Pay(decimal amount)
{
if (!IsCompleted)
throw new InvalidOperationException("Cannot pay an open order.");
if (amount <= 0m)
throw new ArgumentOutOfRangeException(nameof(amount), amount, "Payment must be positive.");
if (amount > Outstanding)
throw new InvalidOperationException("Payment exceeds outstanding amount.");
payments.Add(amount);
}
}