> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yume.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Продукт

> Учёт взаимозаменяемого инвентаря по количеству, а не по отдельным единицам: управление карточкой продукта, состоянием и тарифами продукта.

Полный перечень полей — в [глоссарии](/ru/logic/inventory/inventory-groups-glossary).

## Что такое продукт

**Продукт** — это учётная карточка взаимозаменяемого инвентаря. В отличие от отдельной единицы оборудования, у которой есть собственная жизнь (состояние, пробег, страховка, история выдач), продукт описывает позицию целиком и ведёт учёт **по количеству**, а не по каждому экземпляру отдельно. Во внутренней базе данных этот раздел называется «Продукты».

Продукт используется в двух режимах:

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

<Info>
  Свободный остаток и доступность **не хранятся** в карточке продукта — они вычисляются в момент запроса на основании выбранного интервала времени и расписания занятости единиц. Поэтому один и тот же продукт может показывать разное «свободно» в зависимости от запрошенных дат.
</Info>

## Модель данных

### Основные поля

| Поле         | Тип          | Назначение                                                                                          |
| ------------ | ------------ | --------------------------------------------------------------------------------------------------- |
| Название     | текст        | Название продукта; при выдаче единиц копируется в них                                               |
| Артикул      | текст        | Пользовательский идентификатор продукта; при включённой проверке уникальности не должен повторяться |
| Штрихкод     | текст        | Штрихкод продукта                                                                                   |
| Комментарий  | текст        | Свободное описание; копируется в создаваемые единицы                                                |
| Тип продукта | перечисление | Аренда или продажа                                                                                  |
| Изображение  | файл         | Фото продукта; при сохранении автоматически генерируется миниатюра                                  |

### Классификация и витрина

| Поле                | Тип           | Назначение                                                              |
| ------------------- | ------------- | ----------------------------------------------------------------------- |
| Категория           | связь         | Категория каталога; проставляется единицам продукта при смене категории |
| Скидка              | связь         | Привязанная скидка                                                      |
| Точка проката       | связь         | Точка/филиал, к которому относится продукт                              |
| Фильтры             | список текста | Значения характеристик для витрины                                      |
| Точки (доступность) | список чисел  | Идентификаторы точек проката, где доступен продукт                      |
| Срок службы         | число         | Ресурс/срок эксплуатации продукта                                       |

### Учёт по количеству

| Поле              | Тип             | Назначение                                                |
| ----------------- | --------------- | --------------------------------------------------------- |
| Единица измерения | перечисление    | Штука, литр, миллилитр, килограмм, грамм, кубический метр |
| Цена за единицу   | число (2 знака) | Стоимость одной единицы измерения                         |
| Количество единиц | число (2 знака) | Учитываемый остаток по количеству                         |
| Сумма по единицам | число (2 знака) | Вычисляется автоматически как цена × количество           |

<Note>
  **Сумма по единицам** — расчётное поле. Даже если во входящих данных передать своё значение, при сохранении оно всегда перезаписывается произведением цены за единицу на количество единиц. Задавать её вручную бессмысленно.
</Note>

### Служебные поля

| Поле                       | Тип              | Назначение                                            |
| -------------------------- | ---------------- | ----------------------------------------------------- |
| Доп. поля                  | структура (JSON) | Произвольные атрибуты продукта                        |
| Слаг (URL)                 | текст            | Формируется из названия; уникален в пределах компании |
| Компания                   | связь            | Владелец записи (арендатор)                           |
| История изменений          | журнал           | Аудит-лог изменений записи                            |
| Дата создания / обновления | дата/время       | Заполняются автоматически                             |

<Warning>
  В модели остаются несколько устаревших полей (в том числе флаг публикации, отдельная цена, бонус и количество), помеченных в коде как подлежащие удалению. Логика продукта на них уже не опирается — при работе с продуктом ориентируйтесь на поля учёта по количеству и на тарифы, а не на эти остатки прежней схемы.
</Warning>

## Логика и побочные эффекты

### Что происходит при сохранении

При каждом сохранении карточки продукта автоматически выполняется несколько действий:

1. **Миниатюра изображения.** Если фото изменилось и оно задано, для него генерируется миниатюра.
2. **Слаг (URL).** Если изменилось название или слаг ещё не заполнен, он формируется из названия. Слаг обязан быть уникальным в пределах компании.
3. **Пересчёт суммы.** Сумма по единицам пересчитывается как цена за единицу × количество единиц.
4. **Защита от конфликта слага.** Если при записи возникает конфликт уникальности (компания + слаг), слаг сбрасывается и запись сохраняется повторно уже без него.

<Note>
  Слаг уникален именно в паре «компания + слаг», а не глобально. Разные компании могут иметь продукты с одинаковым слагом, внутри одной компании — нет.
</Note>

### Синхронизация с единицами и витриной

Сохранение и удаление продукта запускают фоновые эффекты:

* **Обновление категории у единиц.** Если у существующего продукта **действительно сменили категорию**, новая категория проставляется всем его единицам. Так категория продукта наследуется входящими в него единицами. Прочие правки продукта (переименование, смена фото, цены и т. п.) категории единиц не трогают, поэтому вручную выставленная у отдельной единицы категория сохраняется.
* **Обновление витрины.** При сохранении и при удалении продукта запускается фоновая задача обновления публичного каталога продуктов, чтобы витрина отражала актуальное состояние.

### Массовое создание единиц из продукта

При создании или обновлении продукта можно сразу сгенерировать привязанные к нему отдельные единицы инвентаря через форму создания единиц. Логика такая:

* Указывается **количество** (до 1000 за раз), а также необязательные точка проката, цена и дата покупки, субарендодатель и его процент, доп. поля.
* Артикулы создаваемых единиц нумеруются автоматически по сквозному счётчику компании, привязанному к конкретному продукту. Формат артикула — «артикул продукта (или его идентификатор) + порядковый номер из трёх цифр». Счётчик берётся с блокировкой и увеличивается на запрошенное количество, поэтому номера не пересекаются даже при параллельных запросах.
* В каждую единицу копируются название, комментарий и изображение продукта; категория берётся у продукта либо, если она не задана, из первой доступной категории каталога.

<Tip>
  Форма создания единиц работает и при создании продукта, и при его обновлении. Это позволяет «добрать» ещё несколько единиц к уже существующему продукту: счётчик продолжит нумерацию с того места, где остановился в прошлый раз.
</Tip>

### Проверка уникальности артикула

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

### Удаление — это вывод из оборота

Удаление продукта не стирает запись физически. Вместо этого создаётся запись о выводе из оборота со способом «удаление» и указанием, кто его выполнил. Благодаря этому в списках продукт помечается как удалённый, но его история и связанные данные сохраняются.

<Warning>
  «Удалённый» продукт — это продукт с записью о выводе из оборота, а не отсутствующая запись. В выборках такие продукты отфильтровываются по признаку наличия записи о выводе из оборота, поэтому реального удаления данных не происходит.
</Warning>

## Расчёт остатков и доступности

Список продуктов возвращается вместе с вычисляемыми на лету показателями. Для каждого показателя учитываются только «живые» единицы: не проданные, не находящиеся на складе как отдельная сущность и не выведенные из оборота.

| Показатель          | Что означает                                                                          |
| ------------------- | ------------------------------------------------------------------------------------- |
| Всего единиц        | Количество действующих единиц в продукте                                              |
| Свободно единиц     | Сколько единиц свободно в запрошенном интервале времени с учётом расписания занятости |
| Есть субаренда      | Признак того, что среди единиц продукта есть хотя бы одна субарендная                 |
| Выведена из оборота | Способ вывода из оборота, если продукт отключён                                       |
| Удалена             | Признак наличия записи об удалении                                                    |

### Интервал доступности

Свободный остаток считается для интервала «начало–конец», который берётся из запроса. Если даты не переданы, обе границы приравниваются к текущему моменту. Дополнительно можно передать список идентификаторов единиц, которые нужно исключить из подсчёта свободных (например, уже отложенные в текущий черновик заказа) — список либо передаётся напрямую, либо подтягивается из заранее сохранённого во временном хранилище набора по ключу.

<Info>
  Список свободных единиц исключает переданные идентификаторы, а список «всего» — нет. Это позволяет показывать, сколько единиц физически в продукте, и отдельно — сколько из них реально можно взять на запрошенные даты.
</Info>

### Ограничение по точке проката и правам

Видимость продуктов и подсчёт остатков зависят от роли пользователя:

* **Администратор компании** без выбранной точки видит все продукты; с выбранной точкой — только продукты этой точки.
* **Остальные сотрудники** видят только продукты тех точек проката, к которым они привязаны.

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

<Note>
  При включённой настройке «доступность продукта» список скрывает продукты, в которых нет ни одной действующей единицы. Это удобно для витрины, но означает, что пустой продукт просто не покажется в списке, пока в него не добавят единицы.
</Note>

## Тарифы продукта

Ценообразование продукта задаётся его **тарифами**. Тариф — это правило: цена за определённый период времени с возможным ограничением по дням недели и времени суток.

| Поле тарифа             | Тип             | Назначение                                  |
| ----------------------- | --------------- | ------------------------------------------- |
| Название тарифа         | текст           | Отображаемое имя правила                    |
| Цена                    | число (2 знака) | Стоимость за период                         |
| Период времени          | связь           | Тарифицируемый период (час, сутки и т. п.)  |
| Дни недели              | список чисел    | Дни, в которые действует тариф              |
| Начало / конец действия | время           | Диапазон времени суток, когда тариф активен |
| Порядок                 | число           | Порядок сортировки тарифов                  |

Одна и та же модель тарифа обслуживает тарифы продукта, отдельной единицы и комплекта — для тарифа продукта заполняется связь именно с продуктом.

### Управление тарифами

Тарифы можно вести двумя способами:

* **Вместе с карточкой продукта.** При создании или обновлении продукта можно передать форму тарифов. Новые тарифы (без идентификатора) создаются пакетно; существующие (с идентификатором) пакетно обновляются по полям дней недели, времени начала и конца, названия, цены и порядка. Если порядок не указан, новым тарифам он присваивается по позиции в списке.
* **Отдельными операциями.** Есть отдельный список тарифов конкретного продукта (создание и просмотр) и отдельная работа с одним тарифом (просмотр, изменение, удаление).

<Warning>
  Обновление тарифов через карточку продукта затрагивает только те тарифы, которые пришли в форме. Тарифы, отсутствующие в переданном списке, **не удаляются** автоматически — чтобы убрать тариф, его нужно удалить отдельной операцией.
</Warning>

<Tip>
  В общем списке продуктов подгружаются только «ненулевые» тарифы (с ценой больше нуля). Тарифы с нулевой ценой в этой сводке не показываются, хотя сами по себе существуют.
</Tip>

## Состояния и статусы единиц продукта

Для продукта доступны две сводки по его единицам, обе без постраничной разбивки:

* **Разбивка по состояниям.** Показывает, сколько действующих единиц продукта находится в каждом состоянии инвентаря. Учитываются только не выведенные из оборота единицы, с фильтрацией по доступным пользователю точкам проката.
* **Разбивка по вычисляемым статусам.** Показывает количество единиц по их вычисляемому статусу (свободна, в аренде и т. п.), также с учётом прав на точки и без выведенных из оборота единиц.

Обе сводки уважают ту же логику доступа по точкам проката, что и основной список: администратор компании видит всё или одну выбранную точку, остальные сотрудники — только свои точки.

## Как это используется

* **В каталоге и списках CRM** продукт — это карточка, которую менеджер видит в каталоге: название, категория, фото, остатки и тарифы. Отсюда же запускается массовое создание единиц.
* **При оформлении заказа** по продукту считается свободный остаток на нужные даты, а исключаемые идентификаторы позволяют не учитывать уже отложенные единицы.
* **На витрине/сайте** продукт синхронизируется фоновой задачей при каждом изменении, чтобы публичный каталог оставался актуальным.
* **Для расходуемого инвентаря** продукт работает как простой количественный учёт: цена за единицу, остаток и автоматически считаемая сумма.

## Особенности поведения

* Сумма по единицам всегда пересчитывается при сохранении как цена за единицу, умноженная на количество единиц, поэтому переданное вручную значение этого поля игнорируется.
* Слаг уникален только в паре «компания + слаг»; при конфликте уникальности слаг сбрасывается в пустое значение и запись сохраняется повторно.
* Свободный остаток и «всего единиц» не хранятся, а вычисляются на лету по интервалу времени из запроса; при отсутствии дат обе границы равны текущему моменту.
* Список свободных единиц исключает переданные идентификаторы исключаемых единиц, тогда как счётчик «всего единиц» их не исключает.
* Проверка уникальности артикула выполняется только при включённой настройке компании и учитывает лишь не выведенные из оборота продукты, исключая текущую запись при редактировании.
* Обновление тарифов через форму карточки продукта не удаляет тарифы, отсутствующие в переданном списке; удаление возможно только отдельной операцией.
* Артикулы массово создаваемых единиц нумеруются через сквозной счётчик компании, привязанный к продукту и взятый с блокировкой; формат — артикул или идентификатор продукта плюс трёхзначный порядковый номер.
* При включённой настройке «доступность продукта» список продуктов скрывает те из них, где нет ни одной действующей единицы (когда «всего единиц» равно нулю).
* Обновление категории у единиц продукта происходит только при обновлении уже существующего продукта и только когда его категория действительно изменилась; при создании продукта и при любых других правках категории единиц не переписываются.
* В общий список продуктов подгружаются только тарифы с ценой больше нуля, поэтому тарифы с нулевой ценой в этой сводке не видны.
* В модели остаются устаревшие поля (флаг публикации, отдельная цена, бонус, количество), помеченные как подлежащие удалению; актуальная логика на них не опирается.

## Связанные страницы

<CardGroup cols={2}>
  <Card title="Глоссарий: Продукт" icon="book" href="/ru/logic/inventory/inventory-groups-glossary">
    Полный перечень полей и терминов модели продукта.
  </Card>

  <Card title="Инвентарь и услуги (CRM)" icon="boxes-stacked" href="/ru/logic/inventory">
    Обзорная страница модуля учёта инвентаря и услуг.
  </Card>

  <Card title="Инвентарь (единицы)" icon="box" href="/ru/logic/inventory/inventory-items">
    Отдельные единицы оборудования: статусы и состояние, пробег, страховка, авто-поля, импорт, массовое обновление, перемещение и продажа.
  </Card>

  <Card title="Комплекты (наборы)" icon="boxes-stacked" href="/ru/logic/inventory/inventory-sets">
    Наборы инвентаря, сдаваемые как единое целое: состав, позиции и цены комплекта.
  </Card>

  <Card title="Тарифы и цены" icon="tags" href="/ru/logic/inventory/tariffs">
    Тарифы аренды по временным периодам для единиц, продуктов и комплектов инвентаря.
  </Card>

  <Card title="Доступность и расписание" icon="calendar-check" href="/ru/logic/inventory/availability">
    Расписание занятости инвентаря и расчёт доступности с учётом заказов, склада и задач мастерской.
  </Card>

  <Card title="Субаренда" icon="handshake" href="/ru/logic/inventory/sublease">
    Периоды субаренды единиц инвентаря с процентом владельца — источник истории для распределения выручки.
  </Card>

  <Card title="Услуги (сервисы)" icon="concierge-bell" href="/ru/logic/inventory/services">
    Дополнительные платные услуги и их тарифы, публикуемые в каталоге и добавляемые к заказам.
  </Card>

  <Card title="Обслуживание и ремонт" icon="screwdriver-wrench" href="/ru/logic/inventory/maintenance">
    Плановое и разовое техобслуживание инвентаря по интервалу или пробегу, с ресурсами и уведомлениями.
  </Card>

  <Card title="Инвентаризация" icon="clipboard-check" href="/ru/logic/inventory/inventorization">
    Проверки состояния инвентаря при выдаче и приёмке заказов, автоматически обновляющие статус единицы.
  </Card>
</CardGroup>
