Обзор
Каждая аренда живёт не только через свой статус, но и через журнал событий — упорядоченную ленту записей, где каждая строка фиксирует один этап жизненного цикла: создание, бронь, инкассацию, выдачу, приёмку, отмену, архивирование, а также забор и выдачу по доставке. Такая запись называется Действие по аренде. Смысл журнала в том, что статус аренды — величина производная: он не задаётся «вручную», а пересобирается из накопленных действий и из состояния позиций инвентаря. Поэтому продвижение аренды вперёд (например, «выдать» или «принять») — это всегда добавление нового действия, а откат назад — удаление действия с последующим пересчётом статуса и фактических дат.Действие всегда привязано к конкретной аренде и к исполнителю (пользователю, который его выполнил). Оно может ссылаться на набор затронутых позиций инвентаря, а для событий по доставке — ещё и на конкретную доставку. При удалении аренды все её действия удаляются каскадно.
Модель данных
Порядок этапов
Пять «продвигающих» этапов выстроены в строгую последовательность:- Создание
- Бронирование
- Инкассация
- Выдача
- Приёмка
Неудаляемые действия
Часть событий защищена от удаления:- создание,
- отмена,
- архивирование,
- забор при доставке,
- выдача при доставке.
Каждый этап создаётся отдельной записью через специализированные методы создания — по одному на тип события. Это значит, что в журнале одной аренды может накапливаться несколько записей одного типа (например, несколько частичных выдач или приёмок).
Логика и побочные эффекты
Создание действия
Создание действия — это продвижение аренды по жизненному циклу. Запрос принимает целевой статус (обязателен), опционально явный тип действия, список идентификаторов участвующих позиций и момент действия. Момент действия по умолчанию — текущее время; при этом он не может быть в будущем — иначе запрос отклоняется с ошибкой валидации. Внутри одного запроса, в рамках единой транзакции, последовательно проверяется несколько условий, и в зависимости от них создаются соответствующие записи и меняется статус аренды.Какие позиции попадают в действие
От целевого статуса и настроек компании зависит, берутся ли все позиции аренды или только явно перечисленные:- при переходе в бронь — всегда все позиции;
- при переходе в аренду и включённой настройке «единая выдача» — все позиции;
- при переходе в завершена и включённой настройке «единая приёмка» — все позиции;
- во всех остальных случаях — только позиции из переданного списка идентификаторов.
Бронирование
Если явно указан тип «бронирование», целевой статус — «Бронь», аренда сейчас в «Заявке» и в компании включена возможность брони, создаётся событие бронирования (со всеми позициями) и аренда переводится в «Бронь».Инкассация
Если явно указан тип «инкассация» и аренда находится в одном из рабочих статусов (заявка, бронь, в аренде, просрочка, должник), создаётся событие инкассации с переданными позициями. Статус при этом само́й инкассацией не меняется.Выдача (переход «в аренде»)
Это центральная операция. Она срабатывает при запросе статуса «В аренде», а также — если в компании отключена бронь — при запросе брони (тогда бронь фактически сразу превращается в выдачу). Что происходит:- Продажные позиции. Для позиций типа «Продажа», у которых ещё не проставлена дата продажи, у соответствующих единиц инвентаря фиксируются цена продажи (равная цене позиции со скидкой) и дата продажи (момент действия).
- Фактическое начало. Если у аренды ещё не заполнено фактическое начало, оно ставится равным моменту действия.
- Событие выдачи. Создаётся событие выдачи, куда попадают только позиции без проставленного факт-начала.
- Статус аренды становится «В аренде».
- Тем же позициям (без факт-начала) проставляется фактическое начало — момент действия.
Приёмка (переход «завершена»)
Срабатывает при запросе статуса «Завершена», когда аренда сейчас в аренде, просрочке или в статусе должника. Что происходит:- Событие приёмки создаётся с арендными позициями, у которых ещё не проставлено факт-окончание.
- Этим арендным позициям проставляется фактическое окончание — момент действия.
- Итог приёмки определяется тем же единым правилом, что применяется при обычном сохранении аренды и при откате действия:
- если осталась хотя бы одна нетронутая позиция (не выдавалась и не принималась — любого типа, включая продажную) или хотя бы одна выданная, но несданная арендная позиция — этот шаг статус не меняет и фактическое окончание аренды не проставляет;
- иначе аренде проставляется фактическое окончание и выбирается статус: Завершена, если оплаченная сумма покрывает итоговую сумму со скидкой, иначе — Должник.
Единое правило строже, чем прежняя логика этого шага, в двух местах: заказ, у которого есть только продажные позиции и хотя бы одна из них не выдавалась, приёмкой больше не завершается; и фактическое окончание аренды больше не проставляется, если какая-то позиция вообще не выдавалась. В таких случаях итоговый статус досчитывает общий пересчёт — ровно тот же, что и раньше приводил вердикт этого шага к своему.
Возврат инвентаря на рент-поинт при приёмке
Именно приёмка перемещает единицы инвентаря между точками выдачи. При создании события приёмки, если есть принимаемые позиции:- если в компании включён возврат на отдельную точку возврата, у аренды указана точка возврата и она отличается от точки выдачи — единицы инвентаря принимаемых позиций (кроме позиций, оформленных как обмен) перемещаются на точку возврата;
- иначе, если у аренды задана точка выдачи — те же единицы возвращаются на точку выдачи.
Отмена
При запросе статуса «Отменена» создаётся событие отмены, аренда переводится в «Отменена», а у всех продажных позиций аренды сбрасываются дата и цена продажи у единиц инвентаря (продажа откатывается).Завершение запроса создания
После всех веток аренда пересчитывается общей процедурой пересчёта позиций и сумм, а затем для неё перегенерируется расписание авто-штрафов. Это гарантирует, что суммы, скидки и производные состояния приведены в соответствие с новым набором действий.Удаление действия и откат
Удаление действия из журнала — это откат этапа. Он проходит через несколько защит и завершается пересчётом.Защиты при удалении
- Неудаляемые типы. Создание, отмена, архивирование и оба события доставки удалить нельзя — попытка возвращает ошибку «Это действие нельзя удалить».
- Пройденный более поздний этап. Нельзя удалить действие, если у аренды уже есть событие более позднего этапа (по порядку этапов). Например, нельзя откатить выдачу, если уже была приёмка — сначала нужно откатить приёмку. Попытка возвращает ошибку «аренда уже прошла более поздний этап».
- Права. Удаление доступно автору действия или администратору, при наличии прав на аренду и на рент-поинты.
Как реконструируется состояние
Откат работает так, чтобы после него аренда выглядела ровно так, будто удаляемого действия никогда не было:- Сброс фактических дат у позиций. Если удаляется выдача — у её позиций сбрасывается фактическое начало. Если удаляется приёмка — сбрасывается фактическое окончание.
- Удаление самой записи действия.
- Пересбор дат по оставшимся действиям. По журналу вычисляются: последняя бронь, самая ранняя выдача, последняя приёмка и последняя отмена.
- Подсчёт по позициям (без позиций-обменов): сколько позиций вообще не тронуты (без факт-начала и без факт-окончания) и сколько арендных позиций выдано, но не принято.
- Определение статуса по приоритету:
- есть отмена → Отменена;
- есть приёмка, нет нетронутых позиций и нет невозвращённых → Завершена (если оплата покрывает сумму со скидкой) либо Должник;
- есть выдача или есть невозвращённые арендные позиции → В аренде;
- есть бронь → Бронь;
- иначе → Заявка.
- Фактическое начало аренды выставляется по самой ранней выдаче (или очищается, если выдач не осталось), фактическое окончание — по последней приёмке, но только если итоговый статус «Завершена» или «Должник»; иначе очищается.
- Аренда прогоняется через общий пересчёт позиций и сумм.
Чтение журнала
Для интерфейсов предусмотрены два представления записи действия:- краткое — идентификатор, исполнитель, момент создания, тип действия и идентификаторы затронутых позиций; используется в списках;
- детальное — дополнительно подтягивает из связанной аренды клиента, её статус и статус оплаты, а также разворачивает список конкретных единиц инвентаря по затронутым позициям.
Как это используется
- Продвижение аренды вперёд (бронь → выдача → приёмка, отмена, инкассация) идёт через один адрес создания действия: он принимает целевой статус и сам выбирает, какие записи создать и какие побочные эффекты применить.
- Откат этапа идёт через адрес удаления действия: он проверяет допустимость удаления и запускает реконструкцию статуса и дат.
- Журнал одновременно служит и лентой истории (кто, когда и что сделал с какими позициями), и источником истины для вычисления статуса и фактических сроков аренды.
Особенности поведения
- Создание, отмена, архивирование и оба события доставки защищены от удаления и не откатываются через журнал ни при каких условиях.
- При откате фактическое начало аренды берётся по самой ранней выдаче, а фактическое окончание — по последней приёмке, причём окончание сохраняется только если итоговый статус «Завершена» или «Должник», иначе очищается.
- Отмена аренды сбрасывает дату и цену продажи у единиц инвентаря продажных позиций, то есть откатывает ранее зафиксированную продажу.
- Момент действия не может быть в будущем: при передаче будущей даты запрос отклоняется валидацией, по умолчанию используется текущее время.
- Старт аренды напрямую из «Заявки» в «В аренде» с уже прошедшим плановым окончанием отклоняется ошибкой позднего старта — сначала нужно поправить сроки.
- Позиции-обмены исключаются из перемещения инвентаря при приёмке и из подсчётов состояния как при приёмке, так и при откате.
- Приёмка, обычное сохранение аренды и откат действия пользуются одним и тем же правилом перехода в «Завершена»/«Должник»: сначала состояние позиций (нет нетронутых и несданных), затем сравнение оплаты с итоговой суммой со скидкой. Штраф в этот порог не входит.
- Заказ, в котором есть только продажные позиции и хотя бы одна из них не выдавалась, приёмкой не завершается; фактическое окончание аренды не проставляется, пока есть позиция, которая вообще не выдавалась.
- Удаление действия доступно только автору действия или администратору и требует прав на аренду и рент-поинты.
Связанные страницы
Глоссарий: Выдача и приёмка
Полный перечень полей и терминов журнала действий по аренде.
Аренда: заявки и жизненный цикл
Обзорный раздел модуля аренды со всеми его страницами.
Аренда и статусы
Ядро сущности аренды и автомат статусов от заявки до завершения или отмены.
Позиции инвентаря и обмен
Строки инвентаря аренды, их тарифы и периоды, массовые операции и обмен позиций.
Услуги и доставка
Услуги в составе аренды и доставки с выдачей, приёмкой, подтверждением и отменой.
Пересчёт сумм и цен
Движок пересчёта итогов аренды: цены, скидки, налоги, продление и суммарные поля.
Депозиты и штрафы
Привязка депозитов и штрафов к аренде и позициям и генерация штрафных задач.
График оплат, паузы и рабочие дни
График платежей, автосписание, паузы аренды и рабочие условия для длительности и сумм.
Уведомления, бонусы и воронка
Реакции на смену статуса аренды: уведомления, бонусы, рефералы и продвижение по воронке.