Skip to main content
Полный перечень полей — в глоссарии.

Обзор

Эта страница описывает, как залоги и штрафы прикрепляются к аренде и как они связаны с её жизненным циклом: кто их создаёт, что происходит при получении и возврате залога, как ручные и автоматические штрафы попадают в суммы аренды и позиций, и как устроено фоновое начисление штрафов за просрочку.
Здесь собрано всё, что относится к аренде: модель залога и штрафа, их связка с заявкой и её статусами, фоновое начисление и формула авто-штрафа за просрочку. Денежная сторона — как платёж-операция попадает в «Оплачено», как считается долг, возвраты и переводы между счетами — описана в финансовом модуле: «Оплата: модель, знак и проверки» и «Переводы между счетами и возвраты».

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

Залог аренды

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

Штраф аренды

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Основной расчёт выполняется в центральном пересчёте по аренде — отдельно для каждой строки инвентаря. Штраф начисляется, только если позиция уже была выдана (есть фактическая выдача), это аренда (не продажа), и фактическое время возврата превысило плановое окончание больше, чем на буфер (грейс-период):
где:
  • шаг начисления штрафа — из настройки аренды «Шаг начисления штрафа», а если не задан — 1 час;
  • буфер (грейс-период) — по умолчанию 1 час;
  • шаг округления суммы — по умолчанию 1;
  • ОКРУГЛ_ШАГОВ — округление вверх, если включена настройка «штраф вперёд», иначе вниз. Округление вверх/вниз применяется только к числу просроченных шагов; внешнее приведение к целому округляет итог к ближайшему целому и от настройки «штраф вперёд» не зависит.
Сводная сумма авто-штрафа по аренде — это сумма штрафов по всем строкам инвентаря; она записывается в поле «Авто-штрафы» (обнуляется, если штрафы по аренде отключены).
Числовой пример. Тариф — 3000 ₸ / сутки (цена тарифа 3000, длительность тарифа 24 ч), шаг начисления штрафа 1 ч, буфер 1 ч, «штраф вперёд» выключен (округление вниз), шаг округления суммы 1. Инвентарь вернули с просрочкой 5 ч 30 мин.
Внешнее округление — к ближайшему целому: здесь результат уже целый (500), но на дробных суммах итог округляется к ближайшему целому независимо от настройки «штраф вперёд».

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

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

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

Расписания создаёт генератор расписаний штрафов, который вызывается при изменениях аренды. Он смотрит на позиции инвентаря аренды (кроме обменянных) и группирует их по дате окончания. Для каждой уникальной даты окончания создаётся своё расписание со своим индексом:
  • Дата старта начислений = дата окончания позиции.
  • Шаг начисления берётся из настройки шага начисления штрафа в аренде.
  • Активно = аренда находится в статусе «в аренде» или «просрочка» и не удалена. В остальных статусах расписание помечается неактивным.
Лишние расписания (индексы больше числа найденных дат окончания) удаляются.
Генератор попутно планирует и уведомления о приближении просрочки: для настроенных триггеров сообщений он создаёт разовые задачи-оповещения, привязанные к моменту «конец аренды минус запас времени».

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

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

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

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

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

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

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

Глоссарий: Депозиты и штрафы

Полный перечень полей залогов, штрафов и расписаний авто-штрафа.

Аренда: заявки и жизненный цикл

Обзорный раздел обо всём модуле аренды и его страницах.

Аренда и статусы

Ядро заявки, автомат статусов и статус оплаты, а также создание, редактирование и архивация заявок.

Выдача и приёмка

Действия по аренде — бронирование, сборка, выдача, приёмка, отмена — и отмена действия с восстановлением статуса.

Позиции инвентаря и обмен

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

Услуги и доставка

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

Пересчёт сумм и цен

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

График оплат, паузы и рабочие дни

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

Уведомления, бонусы и воронка

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