I want to save an order with order items with prices in my write database. But firstly I need to fetch products with their prices because I don't trust a user - he could pass a lower price, that's why I don't want to add a Price property to CreateOrderDTO.
Where should I fetch product prices? In a command handler - if yes then from which database: read database or write database? Or maybe in a controller before sending a command?
The flow in my application is the following:
API - the controller:
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderDTO orderDto)
{
var orderCmd = new CreateOrderCommand(orderDto.CustomerId, orderDto.OrderItems);
await _mediator.Send(orderCmd);
}
The CreateOrderDTO model:
public class CreateOrderDTO
{
public Guid CustomerId { get; set; }
public List<CreateOrderItemDTO> OrderItems { get; set; }
}
public class CreateOrderItemDTO
{
public Guid ProductId { get; set; }
public int Quantity { get; set; }
}
The command and command handler:
public class CreateOrderCommand : IRequest
{
public Guid CustomerId { get; }
public List<CreateOrderItemDTO> OrderItems { get; }
public CreateOrderCommand(Guid customerId, List<CreateOrderItemDTO> orderItems)
{
CustomerId = customerId;
OrderItems = orderItems;
}
}
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand>
{
private readonly IEventStoreRepository _eventStoreRepository;
public CreateCustomerCommandHandler(
IEventStoreRepository eventStoreRepository)
{
_eventStoreRepository = eventStoreRepository;
}
public async Task<Unit> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
var order = new Order(Guid.NewGuid(), request.CustomerId);
foreach (var item in request.OrderItems)
{
order.AddOrderItem(item.ProductId, item.Quantity, /* I need a price here */);
}
await _eventStoreRepository.Save(order);
return Unit.Value;
}
}
And my aggregate root:
public class Order : AggregateRoot
{
public Guid Id { get; private set; }
public Guid CustomerId { get; private set; }
public List<OrderItem> OrderItems { get; private set; }
public Order(Guid id, Guid customerId)
{
OrderItems = new List<OrderItem>();
}
public void AddOrderItem(Guid productId, int quantity, decimal price)
{
//...
}
}