Ok.
Рассчет цены - это кросс-граничная операция (пересекает несколько контекстов — лояльность, пользователь, история заказаов). Поэтому, если использовать Заказ как Агрегат, то модификаторам цены в нем не место (ему ведь в сущности только конечная цена интересна и совершенно не важно, как она расчитывалась).
Для такой логики можем использовать Domain Service, логика его работы примерно такая:
OrderService //stateless-сервис
void placeOrder(orderId, itemId, qty) {
//определение стоимости элемента в заказе с учетом модификаторов
//
order.place(item, price); //это может быть удаленный вызов другого сервиса на уровне реализации
}
Но то, что заказ не может быть изменен, наводит на мысль, что Заказ - это Value Object. Если у него совершенно нет никакого жиненного цикла, он не может быть изменен, то это упростит реалзиацию. Советую подумать об этом 🙂
Для чего я задавал вопросы:
>> Стоимость расчитывется всегда в контексте отдельного элемента заказа или элементы могут оказывать взаимное влияние на конечную цену (например - три товара в заказе - скидка 10%, четыре - 15%, общая сумма заказа больше 10.000, значит скидка на заказ 5% и так далее)?
Чтобы определить, является ли расчет цены частью инварианта Заказа, ответ - нет, так как состав заказ в контексте заказа на цену не влияет.
>>
Если заказ уже создан и не изменяется, может ли динамически измениться цена? (например, скидка для города изменилась с 5% до 10%)>> В какой момент цена фиксируется? В момент оплаты?Чтобы определить, возможно ли изменение цены после создания заказа, если возможно, то цена должна расчитываться динамически при каждом обращении к сущности Заказ.
———————
Если нужна история примененный акций, это может быть решено обычным логированием последовательности примененных акций в момент рассчета цены, вроде Discount (orderId, discountId, discountType, discount, dateApplied, ….)