Как правильно разработать базу данных для услуги, цена которой изменяется в зависимости от выбранных опций?

Здравствуйте! <br/> <br/> Можете подсказать, как правильно спроектировать базу данных для следующей задачи? <br/> <br/> У нас есть цифровая услуга, связанная с работой с аудио, стоимость которой варьируется в зависимости от выбранных пользователем характеристик. <br/> Если продолжительность аудио составляет менее 60 секунд, то цена фиксирована на уровне 0, независимо от выбранных опций. <br/> Если продолжительность превышает 60 секунд, стоимость рассчитывается за каждые 60 секунд по установленной цене. Кроме того, стоимость увеличивается за каждую выбранную опцию и также рассчитывается поминутно. <br/> <br/> Как лучше всего реализовать эту структуру? Подходит ли в данном случае использование SKU, или стоит рассмотреть другие варианты?
  • 25 октября 2024 г. 13:42
Ответы на вопрос 3
Для проектирования базы данных для вашей услуги, цена которой зависит от различных опций, нужно учесть несколько аспектов:

1. **Модели данных**: необходимо создать таблицы, которые смогут правильно отражать все характеристики услуги и динамику формирования цены.

2. **Структура таблиц**: вы можете использовать следующие таблицы:

- **Users** (Пользователи)
  - `user_id` (PK)
  - `username`
  - `email`
  - `...` (другие поля, если нужно)

- **Services** (Услуги)
  - `service_id` (PK)
  - `name` (Название услуги)
  - `base_price` (Базовая цена за 60 секунд, если необходимо)

- **Options** (Опции)
  - `option_id` (PK)
  - `name` (Название опции)
  - `additional_price` (Дополнительная цена за опцию)

- **AudioRequests** (Запросы на услуги)
  - `request_id` (PK)
  - `user_id` (FK, ссылается на Users)
  - `service_id` (FK, ссылается на Services)
  - `duration` (Длительность аудио в секундах)
  - `selected_options` (JSON или отдельная таблица с отсылками на `option_id`)
  - `total_price` (Итоговая цена)

3. **Ценообразование**:
   - Если длительность аудио менее 60 секунд, `total_price` будет равен 0, независимо от выбранных опций.
   - Если длительность превышает 60 секунд, нужно рассчитать стоимость по формуле:
     - Базовая цена за каждую минуту, взятую из `base_price`.
     - Плюс цена всех выбранных опций, которая может быть получена через `JOIN` с таблицей `Options` или с помощью анализа `selected_options`.
  
4. **Пример расчета**:
   - Если пользователь выбрал опции и длительность аудио составляет, например, 120 секунд, можно рассчитать так:
     - Базовая цена = `base_price` за 2 (120 сек / 60 сек).
     - Дополнительные опции = сумма `additional_price` всех выбранных опций.
     - Итоговая цена = базовая цена + дополнительные опции.

5. **Использование SKU**: Система SKU (Stock Keeping Unit) может быть избыточной для этого случая, поскольку она используется в основном для управления физическими товарами. Вместо этого лучше использовать систему, основанную на комбинации таблиц и расчетов, как описано выше.

6. **Оптимизация и расширяемость**: Если в будущем планируете вводить новые опции или услуги, структурирование таблиц позволит легко добавлять новые записи без необходимости изменения основной логики расчетов.

Следуя данному подходу, вы сможете построить гибкую и масштабируемую систему для учета услуг, которая будет легко адаптироваться под будущие изменения.
Причём тут это к проектированию БД? Если ваша цена зависит от чего-то там сверхъестественного, то это слой бизнес-логики , который будет высчитывать цену в зависимости от каких-то параметров. В БД вы эту информацию только храните и всё 

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

Всё что дальше, это уже бизнес-логика

UPD:
Для этой задачи SKU (артикулы) могут быть не совсем подходящим решением, поскольку у вас динамическое ценообразование. По таблицам будет примерно следующая ситуация (Накидал на коленках):

services:
 - id:uuid
 - name:varchar
 - description:varchar

options:
 - id:uuid
 - name:varchar
 - price:float

orders:
 - id:uuid
 - duration:integer
 - total_price:float
 - service_fk:uuid

order_options:
 - order_fk:uuid
 - option:fk:uuid
Выглядит как просто набор разных «товаров»: базовая услуга и к ней опции. А нулевую цену можно по-разному сделать (в виде скидки, например), смотря что у вас на бэкенде будет заказы обрабатывать. 

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