Сохранение заказов клиентов в базе данных и обеспечение целостности этого заказа

В моем приложении Rails мне нужно хранить заказы клиентов, чтобы владелец магазина мог ссылаться на заказы позже.

Я обеспокоен тем, что после того, как заказ будет завершен, через некоторое время сотрудникам магазина может потребоваться изменить цену, детали или продукт в будущем.

Если предположить, что Продукт связан с Заказом только с помощью product_id, это поставит под угрозу целостность окончательного заказа.

Каковы общие подходы к управлению этим?

Вариант, который я могу придумать, - это негласно не разрешать обновления продуктов. Если персонал выполняет «обновление», за кулисами старая запись просто помечается как «старая», и на ее месте создается новый Продукт.

Другим вариантом может быть сохранение хэша в модели Order для продукта в том виде, в каком он появился на дату совершения транзакции.

Каковы плюсы и минусы этого? Существуют ли другие возможности, которые я должен рассмотреть в качестве признанного шаблона дизайна, чтобы справиться с этим?


person Turgs    schedule 09.07.2014    source источник
comment
Разве вы не думаете, что отношения между продуктом и заказами должны быть «многие ко многим», поскольку один продукт может быть в нескольких заказах, а заказы могут иметь несколько продуктов. Если вы используете подход «многие ко многим», вы можете сохранить цену каждого продукта по заказу в соединительной таблице.   -  person Abubakar    schedule 09.07.2014
comment
@Abk спасибо. Вы делаете хорошее замечание ... Я упустил эту деталь, когда составлял вопрос. Я обновил вопрос комментария, но я не думаю, что это меняет то, что я спрашиваю, за исключением того, что он открывает возможность сохранения данных в таблице ссылок. Тем не менее, я хочу обеспечить сохранение не только ценовых данных, но потенциально чего угодно. Им нужно увидеть, как продукт выглядел в момент совершения транзакции, независимо от того, что изменилось с тех пор.   -  person Turgs    schedule 09.07.2014


Ответы (1)


Два наиболее распространенных подхода заключаются в

  • сохранить все значения такими, какими они были на момент размещения заказа, и
  • хранить историю изменения значений, чтобы их можно было воссоздать на основе даты заказа.

Таким образом, таблица позиций для заказа могла бы выглядеть так, если бы вы сохраняли все значения. (Дата заказа не будет в этой таблице.) Вам также может понадобиться сохранить рассчитанные значения, такие как расширенная цена (количество * цена за единицу), налог с продаж и т. д.

order_num  quantity  units  product_code   product_name  unit_price
--
10132      5         each   13376-A        Widgets       $ 1.99
10132      2         dozen  BR549          Fimbels       $24.99
10132      3         boxes  THRUM          Thrums        $ 8.99

Если вы храните рассчитанные значения, используйте проверки, чтобы убедиться, что они синхронизированы с базовыми значениями.

Если бы вы хранили историю, таблица продуктов могла бы выглядеть так. (Цена менялась один раз, название менялось один раз.)

product_code  product_name  unit_price  units  from_date    to_date
--
13376-A       Widgets       $1.99       each   2014-01-01   (NULL or END_OF_TIME)
13376-A       Widgets       $1.95       each   2012-02-13   2014-12-31
13376-A       Wid-gets      $1.95       each   2009-06-17   2012-02-12
...

В таблице позиций будет храниться код продукта. Дата будет в таблице заказов. Соединение на основе line_items.product_code и orders.order_date извлечет правильные данные из этой таблицы истории. END_OF_TIME — это максимальное значение даты, которое поддерживает ваша СУБД.

В любом случае вам нужно хорошенько подумать о том, когда и как разрешать обновления таблиц. (Потому что, когда вы распечатываете заказ 10132 сегодня, он должен быть таким же, как и при размещении заказа.)

Во многих случаях системы разрешают никаких изменений в позициях. Вместо этого они используют компенсирующие позиции. Если кто-то заказал 5 дюжин фимбелов, а собирался заказать 6 дюжин, система не позволит вам изменить 5 на 6. Вместо этого она просто добавит еще одну позицию на 1 дюжину фимбелов. (Или казалось бы, что вы можете изменить 5 на 6, но вместо этого сохраните компенсирующую позицию.)

person Mike Sherrill 'Cat Recall'    schedule 09.07.2014