Перейти к содержанию

Предодобренный овердрафт (T22)

preapproval.py раз в сутки считает для каждого клиента банка «Вам доступно до X»: овердрафт на 12 месяцев без залога (SPEC §4, §6 этап 0). Это «быстрая полоса» для микробизнеса. Сумму показывает баннер на главной кабинета (T29).

Предодобрение — мягкое предложение. Клиент всё равно подаёт заявку, и она рассчитывается заново на данных того дня (WORKFLOW.md). Если данные не изменились, заявка на овердрафт на предодобренную сумму получает автоматическое предложение с той же суммой и ставкой. Это проверяет тест.

Как считается

Для каждого клиента проходят те же этапы, что у заявки, но без заявки:

  1. Обогащение — тот же enrich и те же адаптеры (T07). Запрос к БКИ идёт по согласию, которое клиент дал при открытии счёта (см. «Упрощения»).
  2. Качество данных — data_quality(...) без заявленной выручки. Подходит только FULL (SPEC §5.1). Если у компании нет выручки в ФНС, покрытие выручки посчитать не с чем, уровень будет THIN, и предодобрения она не получит.
  3. Стоп-факторы и флаги (T14) — их не должно быть ни одного. Быстрая полоса только для чистого автоматического маршрута.
  4. Скоринг — только основная модель (T15), модель-претендент не считается.
  5. Лимит и ставка — quote(cf, score, OVERDRAFT, 12, Route.AUTO, requested=None) (T16, LIMITS.md). Запрошенной суммы нет, поэтому лимит — минимум из потока, оборотов (50% средних поступлений), долговой нагрузки и максимума продукта, округлённый вниз до 10 000 ₽.
  6. Маршрут этой суммы по матрице полномочий (T18) должен быть auto. Например, грейд D уходит к андеррайтеру, предодобрения нет.

preapprove(...) — чистая функция: одинаковые входы дают одинаковый результат.

Результат: PreApproval

Это не контракт (contracts.py не менялся), его производит только этот модуль.

Поле Что
approved Есть ли предодобрение
amount, rate, binding Сумма, ставка и ограничение, которое задало сумму. Без предодобрения — null
grade, data_quality_tier, model_version, policy_version На чём построено
reasons Одна причина: почему нет, или определяющее ограничение лимита
as_of, computed_at, valid_until Дата данных, время расчёта, срок действия (30 дней)

Коды причин отказа: preapproval_company_not_found, preapproval_source_unavailable, preapproval_data_partial, preapproval_data_thin, preapproval_stop_factor, preapproval_flag, preapproval_not_scored, preapproval_below_product_minimum, preapproval_rate_above_cap, preapproval_not_auto, preapproval_expired. Для предодобрения — preapproval_limit_<ограничение>.

Хранение и запуск

  • Таблица preapprovals (миграция 0006_preapprovals): одна строка на ИНН с последним результатом. Каждый запуск заменяет строку.
  • Worker (worker.py) раз в 0,5 с вызывает preapproval.tick(). Если последнему расчёту больше суток, расчёт запускается в отдельном потоке, и очередь заявок его не ждёт. Упавший расчёт повторяется не чаще раза в час.
  • Вручную: python -m apps.api.preapproval или POST /api/v2/staff/preapproval/run.
  • На синтетическом мире (зерно 7, 1500 компаний) расчёт идёт около 2 с. Предодобрение получают 16% клиентов (238), медианная сумма — 350 тыс. ₽. Чаще всего предодобрения нет из-за лимита ниже минимума продукта: в мире тонкая маржа (LIMITS.md, «Что видно на синтетическом мире»). Следом идут уровни PARTIAL / THIN и флаги.

API

Метод Кто Что
GET /api/v2/preapproval?inn=… клиент Для баннера: {"product", "term_months", "amount", "rate", "valid_until", "client_text"} или null, если предодобрения нет или срок прошёл
GET /api/v2/preapproval?inn=… сотрудник Весь PreApproval, в том числе причина отказа
POST /api/v2/staff/preapproval/run сотрудник Запустить расчёт сейчас (202): {"started", "last_run"}. started: false — расчёт уже идёт

Упрощения

  • # MOCK: согласие на запрос в БКИ (218-ФЗ) считается данным при открытии счёта: за компанию и за основного собственника по ЕГРЮЛ. В банке есть реестр согласий со своими датами и объёмом. Заявка всё равно собирает согласия сама (T25).
  • # MOCK: клиентская база — весь синтетический мир: у каждой компании есть счёт в банке.
  • # MOCK: расчёт опрашивает источники по каждому клиенту, как заявка, только без имитации задержки. Настоящий пакетный расчёт читает хранилище данных банка и пакетный файл из БКИ. Так у заявок и предодобрения один путь в коде.
  • # SIMPLIFICATION: собственник для согласия берётся из повторного запроса в ЕГРЮЛ. В банке он есть в реестре согласий.
  • # SIMPLIFICATION: «ночной» расчёт — это «последний расчёт старше суток», его проверяет worker внутри процесса API. В банке расчёт ставит планировщик заданий на ночь.
  • # SIMPLIFICATION: срок действия (30 дней) и период расчёта — константы в коде, как значения предложений T17.
  • # SIMPLIFICATION: хранится только последний результат по ИНН, без истории расчётов.
  • # SIMPLIFICATION: любой вошедший клиент может спросить предодобрение по любому ИНН, как и подать заявку: связи «пользователь → компания» пока нет (T25).