Задачи и компании
Каждая фоновая задача выполняется в данных той компании, из которой она была поставлена — система запоминает компанию в момент постановки и восстанавливает её перед выполнением, без ручной настройки. Отдельно устроены кросс-компанийные задачи: они не привязаны к одной компании, а сами проходят по всем компаниям по очереди. Это начисление автоштрафов, автосписание, массовый пересчёт прибыли, а также обслуживание компаний и биллинг. Для них работа «вне компании» — штатный режим, и они объявлены такими явно.Расписание периодических задач
Расписание хранится в базе данных и редактируется в том числе из админки. Планировщик берёт задания из базы. Из статического конфига к CRM относятся две задачи (остальные — интеграции и ассистент):Помимо статического конфига, во время работы приложения в базе динамически создаются записи расписания:
одноразовые/периодические уведомления о ТО, одноразовые алерты «просрочка близко» и записи для начисления
автоштрафов (по ним итерирует задача начисления автоштрафов). Они не видны в статическом конфиге, но исполняются тем
же планировщиком.
Каталог фоновых процессов CRM
Легенда столбца «Тип»: периодическая — запускается по расписанию; задача — асинхронная задача из очереди; функция — обычный синхронный код (вызывается прямо в запросе, несмотря на расположение среди задач).Как это работает
Центральный пересчёт аренды
Это самая тяжёлая функция модуля: она заново считает всю финансовую картину аренды одним проходом по инвентарю и услугам и сохраняет аренду. Вызывается синхронно из десятка мест (изменение аренды, статуса, инвентаря, скидок, залога, доставки, бонусов, а также из начисления штрафа). Основные шаги:1
Ранний выход по удалённой аренде
Если аренда помечена как удалённая — снимаются запланированные списания, и функция завершается.
2
Расписание и режим подсчёта
Если у компании включена функция расписания транзакций, строится список дат аренды, оставшихся дат и оставшейся
длительности, и подсчёт ведётся по дням; иначе — по длительности.
3
Расчёт по каждой позиции: цена, штраф, скидка
Для каждой строки инвентаря считаются стоимость позиции, сумма автоматического штрафа и скидки. Формула штрафа
зависит от настройки округления периода просрочки (вверх/вниз), шага начисления штрафа, буфера просрочки и шага
округления суммы штрафа — см. ниже.
4
Агрегация и запись позиций
Суммы сворачиваются в «Сумму за инвентарь», «Инвентарь со скидкой», сумму штрафов и т.д., затем строки инвентаря и
услуг обновляются пакетно, если значения изменились.
5
Итоговые поля аренды и налог
Считаются «Сумма без скидок», «Итоговая сумма к оплате», «Сумма налога», «Сумма штрафов» (= автоматический штраф +
ручной штраф), «Размер скидки»; по периоду просрочки статус переводится между «В аренде» и «Просрочена», и аренда сохраняется.
6
Скидки, склад, расписание, прибыль
Пересчитываются применённые скидки и занятость склада; при включённой функции строится расписание платежей; и, если
плановый заработок разошёлся с фактической ценой, ставится асинхронная задача пересчёта прибыли по аренде.
Центральный пересчёт аренды поддерживает автопродление через ограниченный цикл повторов: если срок аренды истёк
(«сейчас» позже планового окончания) и аренда в статусе «В аренде» или «Просрочена», плановое окончание сдвигается на новый
период, а пересчёт запускается заново. Число повторов жёстко ограничено (до 15 проходов); если за это число проходов
расчёт не сошёлся (например, при некорректных данных, когда длительность автопродления равна нулю и окончание не
продвигается), в журнал пишется предупреждение и процедура завершается с последним результатом — бесконечный цикл
исключён.
Начисление автоштрафов по расписанию
Запускается каждую минуту. Работает партиями до 100 записей за раз, отсортированных по времени последнего запуска (сначала те, что ещё ни разу не запускались).1
Отбор просроченных
Выбираются записи штрафов, где подключена интеграция аренды, начисление включено, наступил срок, и с момента прошлого
запуска прошло не меньше заданного интервала.
2
Группировка по компаниям
Записи группируются по компаниям — задача обрабатывает каждую компанию по очереди.
3
Начисление или очистка
Для каждой аренды: если она удалена или не в статусе «В аренде» — удаляются все её записи для начисления штрафов;
иначе выполняется начисление штрафа, которое запускает центральный пересчёт аренды и, если аренда просрочена, ставит
уведомление о просрочке.
4
Отметка о запуске
У обработанных записей проставляется время последнего запуска.
Посев штрафов — это «посевная» функция: при создании аренды она создаёт/обновляет записи для начисления штрафов (по
одной на каждый уникальный срок окончания у инвентаря) и, отдельно, регистрирует одноразовые записи
расписания для алерта «скоро просрочка», если у компании настроены триггеры перехода из статуса «В аренде» в состояние
близкой просрочки с задержкой больше одной минуты.
Расписание платежей
Работает только при включённой функции расписания транзакций. Три уровня:- Построение расписания — строит список дат аренды и вычисляет выходные дни по правилам цикла рабочих и выходных дней и по кастомным пометкам расписания. Первый день по умолчанию считается выходным (не оплачивается), если не включена функция платы за первый день.
- Раскладка по дням — раскладывает цену инвентаря и скидки по дням пропорционально (цена дня = стоимость позиции ÷ число дней аренды), распределяет оплату, добавляет штрафы к дню их создания и синхронизирует записи расписания (создание/обновление/удаление).
- Разнос фактических оплат — «жадно» разносит фактические оплаты по дням расписания с переносом переплаты на предыдущие дни, ограничивая каждый день его плановой суммой.