7.6 KiB
7.6 KiB
E-Commerce Example: Domain Requirements
Define the requirements for a complete e-commerce order management system.
Business Requirements
Order Management
As a customer, I want to:
- ✅ Place orders with multiple items
- ✅ View my order history
- ✅ Track order status (Placed, Paid, Shipped, Delivered, Cancelled)
- ✅ Cancel orders before shipment
- ✅ Receive email notifications for order events
As an admin, I want to:
- ✅ View all orders
- ✅ Filter orders by status, customer, date range
- ✅ Process payments
- ✅ Mark orders as shipped
- ✅ View order analytics (total revenue, order count)
Inventory Management
As a system, I need to:
- ✅ Reserve inventory when orders are placed
- ✅ Release inventory when orders are cancelled
- ✅ Prevent overselling (no negative inventory)
- ✅ Track inventory levels per product
Payment Processing
As a system, I need to:
- ✅ Charge customers when orders are placed
- ✅ Refund customers when orders are cancelled
- ✅ Handle payment failures gracefully
- ✅ Prevent double-charging
Analytics
As an admin, I want to:
- ✅ View total revenue
- ✅ View order count by status
- ✅ View top-selling products
- ✅ View customer purchase history
Domain Model
Entities
Order (Aggregate Root)
public class Order
{
public string OrderId { get; set; }
public string CustomerId { get; set; }
public List<OrderLine> Lines { get; set; }
public decimal TotalAmount { get; set; }
public OrderStatus Status { get; set; }
public DateTimeOffset PlacedAt { get; set; }
public DateTimeOffset? PaidAt { get; set; }
public DateTimeOffset? ShippedAt { get; set; }
public DateTimeOffset? DeliveredAt { get; set; }
public DateTimeOffset? CancelledAt { get; set; }
}
public enum OrderStatus
{
Placed,
Paid,
Shipped,
Delivered,
Cancelled
}
public class OrderLine
{
public string ProductId { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal LineTotal => Quantity * UnitPrice;
}
Customer
public class Customer
{
public string CustomerId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public decimal TotalSpent { get; set; }
public int OrderCount { get; set; }
}
Product
public class Product
{
public string ProductId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int AvailableStock { get; set; }
}
Domain Events
Order Events
public record OrderPlacedEvent
{
public string OrderId { get; init; }
public string CustomerId { get; init; }
public List<OrderLineDto> Lines { get; init; }
public decimal TotalAmount { get; init; }
public DateTimeOffset PlacedAt { get; init; }
}
public record OrderPaidEvent
{
public string OrderId { get; init; }
public string PaymentId { get; init; }
public decimal Amount { get; init; }
public DateTimeOffset PaidAt { get; init; }
}
public record OrderShippedEvent
{
public string OrderId { get; init; }
public string ShipmentId { get; init; }
public string TrackingNumber { get; init; }
public DateTimeOffset ShippedAt { get; init; }
}
public record OrderDeliveredEvent
{
public string OrderId { get; init; }
public DateTimeOffset DeliveredAt { get; init; }
}
public record OrderCancelledEvent
{
public string OrderId { get; init; }
public string Reason { get; init; }
public DateTimeOffset CancelledAt { get; init; }
}
Inventory Events
public record InventoryReservedEvent
{
public string OrderId { get; init; }
public string ReservationId { get; init; }
public List<InventoryItemDto> Items { get; init; }
public DateTimeOffset ReservedAt { get; init; }
}
public record InventoryReleasedEvent
{
public string ReservationId { get; init; }
public List<InventoryItemDto> Items { get; init; }
public DateTimeOffset ReleasedAt { get; init; }
}
public record InventoryDepletedEvent
{
public string ProductId { get; init; }
public DateTimeOffset DepletedAt { get; init; }
}
Payment Events
public record PaymentProcessedEvent
{
public string PaymentId { get; init; }
public string OrderId { get; init; }
public decimal Amount { get; init; }
public DateTimeOffset ProcessedAt { get; init; }
}
public record PaymentRefundedEvent
{
public string PaymentId { get; init; }
public string OrderId { get; init; }
public decimal Amount { get; init; }
public DateTimeOffset RefundedAt { get; init; }
}
public record PaymentFailedEvent
{
public string OrderId { get; init; }
public string Reason { get; init; }
public DateTimeOffset FailedAt { get; init; }
}
User Stories
Story 1: Place Order
Given I am a customer When I place an order with 2 items Then The system should:
- Create an order in "Placed" status
- Reserve inventory for the items
- Publish OrderPlacedEvent
- Send order confirmation email
Story 2: Process Payment
Given An order has been placed When The payment is processed successfully Then The system should:
- Update order status to "Paid"
- Publish PaymentProcessedEvent and OrderPaidEvent
- Send payment confirmation email
Story 3: Ship Order
Given An order has been paid When The order is shipped Then The system should:
- Update order status to "Shipped"
- Create shipment record with tracking number
- Publish OrderShippedEvent
- Send shipment notification email
Story 4: Cancel Order
Given An order has been placed but not shipped When The customer cancels the order Then The system should:
- Update order status to "Cancelled"
- Release reserved inventory
- Refund payment if already paid
- Publish OrderCancelledEvent
- Send cancellation confirmation email
Story 5: View Order History
Given I am a customer When I view my order history Then I should see:
- All my orders sorted by date
- Order status for each order
- Items in each order
- Order totals
Success Criteria
✅ Functional:
- Orders can be placed, paid, shipped, and cancelled
- Inventory is accurately tracked and reserved
- Payments are processed and refunded correctly
- Order history is queryable
✅ Non-Functional:
- System handles 100 orders/second
- Order history queries return in < 100ms
- Events are processed in < 1 second
- System is resilient to failures (retry logic)
Architecture Decisions
CQRS Pattern
- Commands: PlaceOrder, ProcessPayment, ShipOrder, CancelOrder
- Queries: GetOrder, ListOrders, GetOrderHistory, GetAnalytics
- Events: All state changes emit domain events
- Projections: Order summary, customer analytics, product analytics
Event Sourcing
- Order aggregate state is rebuilt from events
- Enables full audit trail
- Allows rebuilding projections
- Supports temporal queries
Saga Pattern
- OrderFulfillmentSaga coordinates order processing:
- Reserve inventory
- Process payment
- Ship order
- Compensation logic for failures
Next Steps
- 02-domain-events.md - Define domain events in detail
- 03-commands.md - Implement commands and handlers
- 04-queries.md - Build queries and projections