Size: a a a

Software Design/Architecture/Zen

2021 January 10

ПГ

Павел Г. in Software Design/Architecture/Zen
Приветствую. Подскажите плиз с задачей.
Есть товар, есть различные модификаторы цены которые действуют на конечную цену в заказе (как в плюс так и в минус). Ну например: временные акции, статус пользователя, история заказов пользователя, тираж заказа, какие либо еще модификаторы.  Как видно они могут быть из совсем разных источников, лежать в разных таблицах и прочее. Как лучше всего их хранить для заказа? Мне видится какая то единая сущность  "модификаторы цены заказа" которая будет many to one к каждому заказу, но не уверен что пихать разные модификаторы в одну кучу - хорошая идея.
источник

D

Dim in Software Design/Architecture/Zen
помогите расшифровать датаграмму
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Павел Г.
Приветствую. Подскажите плиз с задачей.
Есть товар, есть различные модификаторы цены которые действуют на конечную цену в заказе (как в плюс так и в минус). Ну например: временные акции, статус пользователя, история заказов пользователя, тираж заказа, какие либо еще модификаторы.  Как видно они могут быть из совсем разных источников, лежать в разных таблицах и прочее. Как лучше всего их хранить для заказа? Мне видится какая то единая сущность  "модификаторы цены заказа" которая будет many to one к каждому заказу, но не уверен что пихать разные модификаторы в одну кучу - хорошая идея.
Стоимость расчитывется всегда в контексте отдельного элемента заказа или элементы могут оказывать взаимное влияние на конечную цену (например - три товара в заказе - скидка 10%, четыре - 15%, общая сумма заказа больше 10.000, значит скидка на заказ 5% и так далее)?
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
Стоимость расчитывется всегда в контексте отдельного элемента заказа или элементы могут оказывать взаимное влияние на конечную цену (например - три товара в заказе - скидка 10%, четыре - 15%, общая сумма заказа больше 10.000, значит скидка на заказ 5% и так далее)?
У нас 1 товар =  1 заказ. А модификаторы - могут быть несколько на 1 заказ. Количество больше 1000 для определенного товара -5% , определнный город еще -5% и т.д.
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Павел Г.
У нас 1 товар =  1 заказ. А модификаторы - могут быть несколько на 1 заказ. Количество больше 1000 для определенного товара -5% , определнный город еще -5% и т.д.
Если заказ уже создан и не изменяется, может ли динамически измениться цена? (например, скидка для города изменилась с 5% до 10%)
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
Если заказ уже создан и не изменяется, может ли динамически измениться цена? (например, скидка для города изменилась с 5% до 10%)
Может, поэтому я думаю что надо дублировать данные для заказа. Не просто ссылаться на акцию, скидку.  Т.е. я имел ввиду что сущность "модификатор цены заказа" - это конкретно к заказу. А отдельно сущности "акции" и прочее.
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Павел Г.
Может, поэтому я думаю что надо дублировать данные для заказа. Не просто ссылаться на акцию, скидку.  Т.е. я имел ввиду что сущность "модификатор цены заказа" - это конкретно к заказу. А отдельно сущности "акции" и прочее.
В какой момент цена фиксируется? В момент оплаты?
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
В какой момент цена фиксируется? В момент оплаты?
В момент создания заказа. Оплата у нас может быть после заказа.
П.С. Возможно не совсем правильно понял про динамику изменения цены. Цена у заказа не меняется, а вот у акций может и это не должно влиять на уже созданные заказы
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Павел Г.
В момент создания заказа. Оплата у нас может быть после заказа.
П.С. Возможно не совсем правильно понял про динамику изменения цены. Цена у заказа не меняется, а вот у акций может и это не должно влиять на уже созданные заказы
Отлично. А сам заказ, какие-либо его параметры, изменить после создания можно?
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
Отлично. А сам заказ, какие-либо его параметры, изменить после создания можно?
Нет
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Вы знакомы с DDD? Я могу использовать терминологию DDD, чтобы предложить вариант решения?)
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
Вы знакомы с DDD? Я могу использовать терминологию DDD, чтобы предложить вариант решения?)
Да :)
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
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, ….)
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
подходит или что-то не учтено?
источник

DT

Dmitriy Tkachenko in Software Design/Architecture/Zen
Зачем заказ value object? В целом если он не изменяется, разница в реализации будет только в том, что заказ не как VO будет иметь id
источник

Е

Евгений in Software Design/Architecture/Zen
А у вас не бывает ситуаций когда клиент отказывается от части товаров после формирования заказа, или просит поменять часть?
источник

SB

Sergey Baranov in Software Design/Architecture/Zen
Dmitriy Tkachenko
Зачем заказ value object? В целом если он не изменяется, разница в реализации будет только в том, что заказ не как VO будет иметь id
И в том, что по условиям модели его нельзя изменить после создания. Это важное решение :)
Если это будет Value Object, то нужно будет подумать, какому агрегату он будет принадлежать.

Согласен, что здесь не очевидно с первого взгляда что лучше использоватьч
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Евгений
А у вас не бывает ситуаций когда клиент отказывается от части товаров после формирования заказа, или просит поменять часть?
Нет. В менеджерке есть некие возможности, но думаю пока не стоит усложнять в вопросе.
источник

ПГ

Павел Г. in Software Design/Architecture/Zen
Sergey Baranov
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, ….)
Спасибо за развернутость. Основная часть вопроса была в том, что я хочу не просто рассчитать стоимость, а сохранить эти данные в заказе.
источник

Е

Евгений in Software Design/Architecture/Zen
Если не усложнять, то в комментарий к заказу записать все модификаторы или в json
источник