> ## 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/rent/deposits-penalties-glossary).

## Обзор

Эта страница описывает, как **залоги** и **штрафы** прикрепляются к аренде и как они связаны с её жизненным циклом: кто их создаёт, что происходит при получении и возврате залога, как ручные и автоматические штрафы попадают в суммы аренды и позиций, и как устроено фоновое начисление штрафов за просрочку.

<Info>
  Здесь собрано всё, что относится к **аренде**: модель залога и штрафа, их связка с заявкой и её статусами, фоновое начисление и **формула авто-штрафа за просрочку**. Денежная сторона — как платёж-операция попадает в «Оплачено», как считается долг, возвраты и переводы между счетами — описана в финансовом модуле: [«Оплата: модель, знак и проверки»](/ru/logic/finances/payments) и [«Переводы между счетами и возвраты»](/ru/logic/finances/transfers-refunds).
</Info>

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

### Залог аренды

Залог всегда принадлежит одной аренде и хранит, что именно оставлено в залог и на какой стадии он находится.

| Поле            | Тип             | Назначение                                                   |
| --------------- | --------------- | ------------------------------------------------------------ |
| Аренда          | связь           | Заявка, к которой относится залог                            |
| Кем создан      | связь           | Сотрудник, оформивший залог                                  |
| Способ оплаты   | связь           | Тип оплаты залога (может быть пустым)                        |
| Тип залога      | перечисление    | Текстовый (описание) или денежный (сумма)                    |
| Статус залога   | перечисление    | Не получен → получен → возвращён                             |
| Сумма           | число (2 знака) | Сумма залога; для текстового залога принудительно обнуляется |
| Описание залога | текст           | Что оставлено в залог (например, «паспорт»)                  |
| Дата возврата   | дата/время      | Заполняется в момент возврата                                |

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

<Note>
  Тип залога и статус залога при создании и изменении **обязательны**. Если выбран денежный залог, но сумма не указана, запись не сохранится. Если выбран текстовый залог, сумма всегда сбрасывается в ноль — независимо от того, что прислал клиент.
</Note>

### Штраф аренды

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

| Поле                     | Тип             | Назначение                                       |
| ------------------------ | --------------- | ------------------------------------------------ |
| Тип штрафа               | перечисление    | Автоматический (за просрочку) или ручной         |
| Клиент                   | связь           | Клиент, к которому привязан штраф                |
| Аренда                   | связь           | Заявка, к которой относится штраф                |
| Позиция инвентаря        | связь           | Строка инвентаря, если штраф пер-позиционный     |
| Сумма штрафа             | число (2 знака) | Начисленная сумма                                |
| Оплачено                 | число (2 знака) | Оплаченная часть                                 |
| Кем создан               | связь           | Сотрудник (пусто для автоматических)             |
| Причина                  | текст           | Комментарий/причина                              |
| Штраф внешней интеграции | связь           | Связь со штрафом внешней интеграции (ПДД/камеры) |
| Пользовательский         | флаг            | Признак индивидуально заданного штрафа           |
| График штрафа            | список          | Разбивка суммы штрафа по датам                   |

<Warning>
  Ограничение базы данных требует, чтобы у штрафа был заполнен **хотя бы клиент, либо аренда**. Штраф не может «висеть в воздухе» без привязки ни к тому, ни к другому.
</Warning>

### Где хранятся суммарные штрафы

Итоговые суммы штрафов хранятся прямо в заявке аренды и в позициях инвентаря — чтобы не пересчитывать их при каждом чтении.

**Штрафные поля аренды:**

| Поле                  | Назначение                                                         |
| --------------------- | ------------------------------------------------------------------ |
| Общая сумма штрафов   | Авто-штрафы плюс ручные штрафы                                     |
| Авто-штрафы           | Штраф за просрочку, посчитанный по формуле по всем позициям аренды |
| Ручные штрафы         | Сумма ручных штрафов аренды                                        |
| Период просрочки      | Длительность просрочки для расчёта штрафа                          |
| Шаг начисления штрафа | Периодичность авто-начисления (по умолчанию 1 час)                 |
| Штрафы отключены      | Признак отключения начисления штрафов по аренде                    |

**Штрафные поля позиции инвентаря** — сумма штрафа позиции, её автоматическая и ручная части. Сумма штрафа позиции служит источником для пер-позиционного автоматического штрафа (см. ниже).

<Info>
  **У поля «Авто-штрафы» единственный владелец — пересчёт сумм аренды.** Он считает штраф по живой формуле просрочки, отдельно по каждой позиции, и уважает признак «штрафы отключены» (тогда поле обнуляется). Ни сохранение, ни удаление ручного штрафа это значение не меняют — они пересчитывают только «Ручные штрафы», а «Общая сумма штрафов» выводится как сумма двух частей. Поэтому добавление ручного штрафа больше не может «уронить» авто-штраф, а вместе с ним и итоговую сумму к оплате и долг.
</Info>

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

### Оформление и возврат залога

Залоги живут на своих адресах под аренды: список и создание, изменение и удаление, отдельное действие «возврат».

* **Создание.** Аренда берётся из адреса запроса, автор проставляется из текущего пользователя. Для текстового залога сумма обнуляется. После сохранения запускается **пересчёт сумм аренды**, чтобы залог учёлся в общей картине по заявке.
* **Изменение.** Работает симметрично: текстовый залог снова обнуляет сумму, затем идёт тот же пересчёт сумм аренды.
* **Удаление.** После удаления также выполняется пересчёт сумм аренды.
* **Возврат.** Отдельное действие возвращает залог клиенту: оно создаёт встречные расходные операции на внесённые по залогу деньги, переводит залог в статус «возвращён», проставляет дату возврата текущим моментом и пересчитывает суммы аренды. Залог ищется одновременно по своему идентификатору **и** по аренде из адреса запроса, поэтому вернуть через одну аренду залог другой нельзя.

### Что происходит с деньгами при возврате залога

Раньше возврат менял только статус и дату: касса и баланс счёта продолжали держать сумму залога, а «Оплачено» по аренде оставалось завышенным на приход, которого у компании уже нет. Теперь смена статуса и движение денег происходят **в одной операции**:

1. **Считается остаток по залогу.** Берутся все успешные операции, привязанные к этому залогу, и суммируются по каждой паре «вид оплаты + счёт». Возвращается именно **остаток** (приходы минус уже сделанные возвраты), а не номинал залога.
2. **Создаются встречные расходные операции.** На каждый положительный остаток создаётся расходная операция с отметкой возврата — той же формы, что и ручной возврат оплаты. Деньги уходят с того счёта, на который приходили (счёт определяется видом оплаты).
3. **Залог помечается возвращённым.** Проставляются статус «возвращён» и дата возврата, затем пересчитываются суммы аренды.

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

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

<Note>
  Уведомления по этим операциям **намеренно не отправляются**: операции по залогам и операции с отрицательной суммой не шумят в мессенджеры — возврат залога это правило сохраняет.
</Note>

### Ручные штрафы и пересчёт полей аренды

Ручные штрафы создаются и редактируются сотрудником через адреса под аренды. Список и создание, а также удаление работают **только с ручными штрафами** — автоматические через этот интерфейс не видны и не редактируются. Аренда, тип и автор при этом только для чтения: тип всегда «ручной», автор берётся из текущего пользователя, аренда — из адреса.

Каждое сохранение или удаление **ручного** штрафа автоматически пересчитывает штрафные поля аренды:

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

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

<Note>
  Ручной штраф можно оформить и на клиента, без привязки к аренде. Такой штраф в штрафные поля какой-либо аренды не попадает — обновлять просто нечего, и сохранение проходит штатно.
</Note>

### График разбивки штрафа

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

<Note>
  Если у штрафа задан непустой график, **сумма по всем датам обязана в точности совпадать с суммой штрафа**. Иначе сохранение отклоняется с ошибкой.
</Note>

### Автоматические штрафы по позициям инвентаря

Автоматические штрафы, начисленные на отдельные позиции, синхронизируются с суммами штрафов самих позиций отдельной фоновой задачей пересчёта. Задача берёт заявку и приводит пер-позиционные авто-штрафы в соответствие со штрафными полями позиций:

* Если у позиции сумма штрафа стала нулевой — соответствующий авто-штраф по этой позиции **удаляется**.
* Если сумма изменилась (и не ноль) — авто-штраф **обновляется**.
* Если у позиции появился штраф, а записи ещё нет — авто-штраф **создаётся**.

Так по каждой просроченной позиции возникает своя строка автоматического штрафа, привязанная и к аренде, и к позиции.

## Фоновое начисление штрафов за просрочку

### Формула авто-штрафа за просрочку

Основной расчёт выполняется в центральном пересчёте по аренде — отдельно для каждой строки инвентаря. Штраф начисляется, только если позиция уже была выдана (есть фактическая выдача), это аренда (не продажа), и фактическое время возврата превысило плановое окончание больше, чем на буфер (грейс-период):

```text theme={null}
Период просрочки = (фактический возврат или, если его нет, текущий момент)
                   − плановое окончание − время пауз

# штраф = 0, если:
#   позиция ещё не выдана, либо это продажа,
#   либо просрочка ещё в пределах грейс-периода

Штраф =
    шаг округления суммы ×
    ОКРУГЛ_ДО_ЦЕЛОГО(                             ← округление к ближайшему целому
        МАКСИМУМ(
            цена тарифа ×
            ОКРУГЛ_ШАГОВ( (Период просрочки − буфер) ÷ шаг начисления штрафа )
            ÷ округл_вверх( длительность тарифа ÷ шаг начисления штрафа )
            ÷ шаг округления суммы,
            0
        )
    )
```

где:

* **шаг начисления штрафа** — из настройки аренды «Шаг начисления штрафа», а если не задан — 1 час;
* **буфер (грейс-период)** — по умолчанию 1 час;
* **шаг округления суммы** — по умолчанию 1;
* **ОКРУГЛ\_ШАГОВ** — округление вверх, если включена настройка «штраф вперёд», иначе вниз. Округление вверх/вниз применяется **только к числу просроченных шагов**; внешнее приведение к целому округляет итог к ближайшему целому и от настройки «штраф вперёд» не зависит.

Сводная сумма авто-штрафа по аренде — это сумма штрафов по всем строкам инвентаря; она записывается в поле «Авто-штрафы» (обнуляется, если штрафы по аренде отключены).

<Tip>
  Числовой пример. Тариф — 3000 ₸ / сутки (цена тарифа 3000, длительность тарифа 24 ч), шаг начисления штрафа 1 ч, буфер 1 ч, «штраф вперёд» выключен (округление вниз), шаг округления суммы 1. Инвентарь вернули с просрочкой 5 ч 30 мин.

  ```text theme={null}
  шагов сверх буфера = округл_вниз((5,5 ч − 1 ч) ÷ 1 ч) = округл_вниз(4,5) = 4
  цена за шаг        = 3000 ÷ округл_вверх(24 ч ÷ 1 ч) = 3000 ÷ 24 = 125 ₸/час
  штраф              = 1 × округл_до_целого(3000 × 4 ÷ 24 ÷ 1) = округл_до_целого(500) = 500 ₸
  ```

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

### Расписание авто-штрафа

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

| Поле                   | Назначение                                               |
| ---------------------- | -------------------------------------------------------- |
| Компания               | Компания, которой принадлежит аренда                     |
| Индекс                 | Порядковый номер расписания внутри аренды                |
| ID аренды              | Идентификатор заявки (без прямой связи)                  |
| Дата старта начислений | Дата окончания позиции, с которой начинают капать штрафы |
| Последний запуск       | Когда штраф начислялся в последний раз                   |
| Шаг начисления         | Периодичность повторного начисления (по умолчанию 1 час) |
| Активно                | Включено ли расписание                                   |

Расписание уникально по сочетанию компании, индекса и идентификатора аренды.

### Как строится расписание

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

* **Дата старта начислений** = дата окончания позиции.
* **Шаг начисления** берётся из настройки шага начисления штрафа в аренде.
* **Активно** = аренда находится в статусе «в аренде» или «просрочка» **и** не удалена. В остальных статусах расписание помечается неактивным.

Лишние расписания (индексы больше числа найденных дат окончания) удаляются.

<Info>
  Генератор попутно планирует и уведомления о приближении просрочки: для настроенных триггеров сообщений он создаёт разовые задачи-оповещения, привязанные к моменту «конец аренды минус запас времени».
</Info>

### Как начисляются штрафы

Периодическая фоновая задача обходит расписания, которым пора сработать, и начисляет по ним штрафы. Ключевые правила связки с жизненным циклом:

1. Обрабатываются только компании с **активным подключением интеграции аренды**. Если у компании нет действующего подключения, её расписания в этом цикле не трогаются.
2. Расписание считается «пора», если оно активно и дата старта уже наступила, при этом выполнено хотя бы одно из условий: запусков ещё не было, с прошлого запуска прошёл хотя бы один шаг начисления, либо дата старта оказалась позже последнего запуска.
3. Для каждой аренды из расписания:
   * Если аренда **удалена** или её статус **не** «в аренде» и **не** «просрочка» — расписание по этой аренде **удаляется**, начисление не производится. Так завершённые, отменённые и забронированные аренды автоматически перестают штрафоваться.
   * Иначе выполняется начисление: пересчёт сумм аренды (который и обновляет штрафные поля), а для просроченных аренд дополнительно ставится уведомление «Аренда просрочена» — оно уходит сотрудникам, работавшим с этой арендой, и её создателю.
4. После обработки у обработанных за цикл расписаний обновляется отметка последнего запуска.

<Warning>
  За один цикл задача обрабатывает не более 100 расписаний. Если начислений накопилось больше, лишние переносятся на следующий цикл, а в лог пишется предупреждение. При большом числе одновременно просроченных аренд начисления могут идти с задержкой.
</Warning>

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

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

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

* Автоматический пересчёт штрафных полей аренды при сохранении/удалении штрафа срабатывает только для ручных штрафов; для автоматических он завершается сразу и ничего не пересчитывает.
* Поле авто-штрафов аренды пишет только пересчёт сумм аренды — по живой формуле просрочки и по всем позициям; сохранение или удаление ручного штрафа его не затрагивает.
* Ручной штраф, оформленный на клиента без привязки к аренде, сохраняется штатно и штрафные поля какой-либо аренды не меняет.
* Текстовый залог всегда принудительно обнуляет сумму при создании и изменении, даже если сумма была передана.
* Пропуск записи при пересчёте штрафных полей сравнивает только сумму ручных штрафов; общая сумма отдельно в условии не участвует, но пересчитывается вместе с ней.
* Возврат залога создаёт встречные расходные операции на остаток по залогу, поэтому повторный возврат ничего не создаёт, а по залогу без операций возврат просто меняет статус.
* Операции по возврату залога не порождают уведомлений — это то же правило, по которому не шумят операции по залогам и операции с отрицательной суммой.
* Условие срабатывания расписания включает три альтернативы: запусков ещё не было, с прошлого запуска прошёл шаг начисления, либо дата старта позже последнего запуска.
* Если у аренды нет позиций с датой окончания, удаление лишних расписаний внутри цикла не выполняется, так как оно вложено в перебор найденных дат.
* График штрафа валиден только если сумма по всем датам в точности равна сумме штрафа; проверка применяется только к непустому списку дат.

<Info>
  - Фоновое начисление за один цикл обрабатывает не более 100 расписаний; при превышении лишние переносятся на следующий цикл и пишется предупреждение в лог.
  - Штрафы начисляются только для компаний с активным подключением интеграции аренды; без действующего подключения расписания компании в цикле не обрабатываются.
  - При обработке аренды, которая удалена или вышла из статусов «в аренде»/«просрочка», расписание авто-штрафа по этой аренде удаляется, что автоматически прекращает начисления.
  - Ограничение базы данных требует заполненности хотя бы клиента либо аренды у штрафа.
  - Адреса ручных штрафов работают только со штрафами типа «ручной»; автоматические штрафы через них не отображаются и не редактируются.
</Info>

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

<CardGroup cols={2}>
  <Card title="Глоссарий: Депозиты и штрафы" icon="book" href="/ru/logic/rent/deposits-penalties-glossary">
    Полный перечень полей залогов, штрафов и расписаний авто-штрафа.
  </Card>

  <Card title="Аренда: заявки и жизненный цикл" icon="file-signature" href="/ru/logic/rent">
    Обзорный раздел обо всём модуле аренды и его страницах.
  </Card>

  <Card title="Аренда и статусы" icon="diagram-project" href="/ru/logic/rent/lifecycle">
    Ядро заявки, автомат статусов и статус оплаты, а также создание, редактирование и архивация заявок.
  </Card>

  <Card title="Выдача и приёмка" icon="right-left" href="/ru/logic/rent/actions">
    Действия по аренде — бронирование, сборка, выдача, приёмка, отмена — и отмена действия с восстановлением статуса.
  </Card>

  <Card title="Позиции инвентаря и обмен" icon="boxes-stacked" href="/ru/logic/rent/inventory-lines">
    Строки инвентаря аренды и продажи, их тарифы и периоды, массовые операции и обмен позиций внутри заявки.
  </Card>

  <Card title="Услуги и доставка" icon="truck" href="/ru/logic/rent/services-delivery">
    Услуги в составе аренды и доставки с привязкой к действиям выдачи и приёмки.
  </Card>

  <Card title="Пересчёт сумм и цен" icon="calculator" href="/ru/logic/rent/pricing">
    Движок пересчёта итогов: цены позиций и услуг, скидки, налоги, продление и суммарные поля заявки.
  </Card>

  <Card title="График оплат, паузы и рабочие дни" icon="calendar-days" href="/ru/logic/rent/schedule">
    График платежей, автосписание, паузы аренды и рабочие/выходные дни, влияющие на длительность и суммы.
  </Card>

  <Card title="Уведомления, бонусы и воронка" icon="bell" href="/ru/logic/rent/triggers">
    Реакции на смену статуса: уведомления, бонусы, реферальные выплаты и продвижение по воронке продаж.
  </Card>
</CardGroup>
