База данных: новая таблица или новое поле для атрибутов заказа - PullRequest
0 голосов
/ 29 января 2020

Текущая схема таблицы:

User
  - id
  - default_handling_fee(integer, null=True)

Order
  - id
  - buyer(user_id)
  - order_handling_fee(integer, null=True) 

Теперь мы хотим добавить второй тип комиссии, которая может применяться к заказам. Некоторые правила:

  1. Сборы распространяются на <10% заказов. </li>
  2. Заказ может иметь либо 0, либо обе комиссии.
  3. Каждый раз, когда информация о заказе отображается пользователям, нам нужно выделять сборы и указывать виды сборов.
  4. Сборы должны редактироваться в зависимости от заказа.
  5. Мы можем добавить дополнительные сборы в будущем.
  6. База данных в настоящее время довольно мала (несколько тысяч строк) и вряд ли вырастет за пределы 100 000 в следующие несколько лет.

Я вижу два варианта:

A: Добавить новое поле для заказа и одно для пользователя:

User
  - id
  - default_handling_fee(integer, null=True)
  - default_processing_fee(integer, null=True)

Order
  - id
  - buyer(user_id)
  - order_handling_fee(integer, null=True) 
  - order_processing_fee(integer, null=True)

или B, добавить новую «таблицу сборов»:

User
  - id

Order
  - id
  - buyer(user_id)
  - order_fees(many_to_many_field to OrderFees)

OrderFees
  - id
  - buyer(user_id)
  - price(integer)
  - fee_type(choices=['handling', 'processing'])
  - is_default_value(boolean)

Если пользователь создает заказ и применяет одну или обе комиссии, в варианте B (новая таблица) мы сначала будем искать существующие комиссии, которые соответствуют пользователю и цене. Если такая комбинация существует, мы добавим ее в поле order_fees. Если бы он не существовал (новая цена), мы создали бы новую строку и добавили бы эту строку в поле order_fees.

Я признаю, что вариант A намного проще: нет объединений при поиске сборов , нет создания новых строк, нет устаревших строк, которые создаются один раз и никогда не используются снова. Я вижу два недостатка А. Во-первых, он не расширяемый. Если мы добавим gift_wrapping_fee через несколько месяцев, это будет означать добавление третьего поля со значением NULL почти для каждого заказа и т. Д. Для дополнительных типов сборов за заказ. Вторым недостатком является то, что мы должны помнить, чтобы добавлять проверки в приложении в каждом месте, где отображается информация о заказе.

if order.order_processing_fee: 
  show fee
if order.order_handling_fee:
  show fee

С опцией B это всего лишь

for fee in order.order_fees:
  show fee

Вероятность ошибок в варианте B намного меньше при цене как минимум одного дополнительного запроса на заказ, показанный пользователям.

Еще один момент: поскольку все это делается с Django в качестве бэкэнда, мы можем определить методы для модели так, чтобы все поля цены были определены в одном месте.

Какие вариант лучше? Есть ли третий вариант, который я не рассматривал?

(отредактировано для ясности)

1 Ответ

0 голосов
/ 29 января 2020

Я думаю, что если в ближайшем будущем вам нужно будет добавить новые типы платежей, чем вариант B, лучше.

Рассматривали ли вы гибридный вариант A и B? Если я понимаю проблему, у вас есть не только плата за заказ, но и плата по умолчанию для пользователей.

Вы можете иметь таблицу вознаграждений:

Fees
-id
-type(choices=[your fee type list])
-price
...(other attributes)

И затем вы можете иметь отношение два ко многим, одно для Ордена

Order 
-id
-buyer(user)
-order_fees(many to many)

И второе для пользователь

User
-id
-default_fees(many to many)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...