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

Что делает эта часть модуля

Это публичный API компании (для веб-кабинета и мобильных клиентов) поверх интеграции с сервисом автоштрафов. Он решает три задачи:
  1. Привязка автомобилей компании к сервису автоштрафов — компания выбирает свои единицы инвентаря, и по ним включается синхронизация штрафов.
  2. Просмотр штрафов, ограниченный только машинами этой компании, с богатой фильтрацией, сопоставлением штрафа с арендой и клиентом, агрегатами и постраничным списком.
  3. Ручное обновление штрафов с защитой от частых запросов и приёмник вебхука от сервиса автоштрафов.
Все ручки списков и привязок работают строго в рамках текущей компании: выборка всегда фильтруется по компании из контекста запроса.
Почти все адреса требуют авторизованного пользователя. Единственное исключение — приёмник вебхука: он открыт для внешнего сервиса и защищён отдельной аутентификацией по API-ключу, а не пользовательской сессией.

Привязка авто компании

Список и создание привязки

Список привязок отдаётся без постраничной разбивки — сразу все привязки текущей компании. Для каждой привязки в ответ подмешивается связанная единица инвентаря: система заранее строит карту «ID единицы инвентаря → карточка инвентаря» по всем автомобилям инвентаря и берёт из неё нужную запись по полю «ID единицы инвентаря» привязки. При создании привязки в запросе передаётся только ID единицы инвентаря (это идентификатор автомобиля в инвентаре компании). Остальное система достраивает сама.

Что происходит при создании привязки

Порядок шагов строго такой:
  1. Проверка на дубль. Если для этой компании уже есть привязка с таким же ID единицы инвентаря — возвращается ошибка «Этот автомобиль уже привязан к данному клиенту».
  2. Поиск единицы инвентаря. По переданному ID ищется автомобиль в инвентаре. Если не найден — ошибка «Автомобиль не найден.».
  3. Проверка формата госномера. Если у автомобиля заполнен номер, он должен соответствовать одному из двух шаблонов: либо 3 цифры + 2–3 буквы + 2 цифры, либо 1 буква + 6 цифр. Иначе — ошибка о неверном формате номера.
  4. Проверка формата техпаспорта. Если техпаспорт заполнен, он должен быть в формате 2 буквы + 8 цифр. Иначе — ошибка о неверном формате техпаспорта.
  5. Поиск или создание автомобиля в сервисе автоштрафов. Система ищет уже известный ей автомобиль сервиса автоштрафов по паре «номер + техпаспорт». Если такого нет — обращается к внешнему сервису автоштрафов: сначала спрашивает, есть ли там автомобиль; если нет — просит его создать. При ошибке от внешнего сервиса возвращается «Не удалось создать автомобиль. Попробуйте ещё раз.». По полученным данным создаётся или обновляется запись автомобиля сервиса автоштрафов (заполняются ID в сервисе автоштрафов, дата активации и признак активности).
  6. Сохранение привязки с проставленной компанией и найденным/созданным автомобилем сервиса автоштрафов.
Шаг создания привязки делает синхронный внешний вызов к сервису автоштрафов прямо во время запроса. Если внешний сервис недоступен или отвечает с ошибкой, привязка не создастся, и пользователь получит ошибку.

Просмотр и удаление одной привязки

Отдельная привязка (по её идентификатору) доступна только в рамках текущей компании: можно посмотреть её карточку (вместе с подмешанной единицей инвентаря) или удалить.

Просмотр штрафов

Все списки штрафов (полный список, счётчик и агрегаты) строятся на общей выборке. Она устроена одинаково для всех трёх и ограничивает штрафы только машинами текущей компании.

Как формируется выборка штрафов

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

Фильтры выборки

Часть фильтров применяется на уровне общей выборки (в самой логике представления), часть — в наборе фильтров штрафов. Дополнительно работает поиск по тексту (номер протокола, описание нарушения, адрес нарушения, госномер и техпаспорт автомобиля) и сортировка (по дате нарушения, сумме, дате создания, номеру протокола). По умолчанию список отсортирован по дате нарушения и дате создания в обратном порядке (сначала свежие).
Фильтры «по единице инвентаря», «по клиенту», «по аренде» и «по точке проката» в самом наборе фильтров ничего не делают — они объявлены как параметры, но фактическая фильтрация по ним выполняется в логике представления. Это сделано, чтобы параметры отображались в документации и валидировались как числа.

Сопоставление штрафа с арендой и клиентом по времени

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

Три представления над одной выборкой

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

Карточка и обновление штрафа

Отдельный штраф доступен для просмотра и частичного обновления. Большинство полей штрафа — только для чтения (они приходят из сервиса автоштрафов): реквизиты, суммы, документы, связи с автомобилем/водителем/компанией. Редактировать можно прикладные поля — признак «Просмотрен» и кастомный статус. Карточка отдельного штрафа строится на той же выборке, что и списки, поэтому открыть или изменить штраф чужой компании по прямому идентификатору нельзя — обращение к такому штрафу отвечает «не найдено».
Кастомный статус, который можно присвоить штрафу, выбирается только из статусов своей компании и общих статусов — ровно из того набора, который отдаёт список статусов. Присвоить своему штрафу приватный статус другой компании невозможно.

Кастомные статусы штрафов

Компания может завести свои статусы штрафов (название и цвет в HEX, по умолчанию белый). При создании статуса он автоматически привязывается к текущей компании. Здесь важно различать две операции:
  • Список статусов (то, из чего можно выбирать) включает как общие статусы, не привязанные ни к какой компании, так и статусы текущей компании.
  • Изменение и удаление доступны только для статусов своей компании. Общие статусы компания видит и может присваивать своим штрафам, но менять и удалять их нельзя — иначе правка одной компании затронула бы всех остальных.

Ручное обновление штрафов

Кнопка «обновить штрафы» запускает подтягивание штрафов из сервиса автоштрафов по всем автомобилям компании. Действие защищено ограничением по частоте.

Как работает ограничение по частоте

  • Ограничение — 3 часа на компанию.
  • Если с прошлого запуска прошло меньше 3 часов, обновление не выполняется, а в ответ возвращается время последнего запуска.
  • Если окно прошло — время «сейчас» записывается как момент последнего запуска, после чего идёт обращение к внешнему сервису для обновления штрафов.
  • При ошибке внешнего сервиса возвращается ответ со статусом «плохой шлюз» и текстом ошибки.
Метка времени последнего запуска записывается до обращения к внешнему сервису. Поэтому даже если внешний вызов завершился ошибкой, повторный запуск будет заблокирован на 3 часа.

Приёмник вебхука от сервиса автоштрафов

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

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

Типичный сценарий работы компании:
  1. Компания привязывает свои автомобили (по ID единиц инвентаря) — при этом каждая машина заводится/находится в сервисе автоштрафов.
  2. Штрафы приезжают двумя путями: автоматически через вебхук от сервиса автоштрафов и по кнопке ручного обновления (не чаще раза в 3 часа).
  3. В кабинете компания смотрит штрафы только по своим машинам, фильтрует их (по клиенту, аренде, точке, типу, датам, суммам, статусу), видит сводку и сопоставление каждого штрафа с арендой и клиентом.
  4. Прикладные поля штрафа (просмотрен, кастомный статус) редактируются вручную — статус выбирается из своих и общих статусов.

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

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

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

Глоссарий: API компании: авто и штрафы

Полный перечень полей привязок, штрафов, кастомных статусов и параметров фильтрации.

Сервис автоштрафов (штрафы и синхронизация авто)

Обзорная страница модуля интеграции с сервисом автоштрафов.

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

Справочные и транзакционные модели сервиса автоштрафов: авто, водители, нарушители, штрафы, привязки и логи синхронизации.

Синхронизация автомобилей

Выгрузка списка авто, сверка активных и неактивных, удаление осиротевших машин и включение/выключение отдельного авто.

Уведомления о штрафах

Сопоставление штрафа с активной арендой и отправка клиенту двуязычного сообщения в WhatsApp с документом.