# ТЗ на доработку: оптимизация создания и обработки ЭТрН **Дата:** 07.10.2026 **Конфигурация:** ВесоваяАК (`ves2020`) **Версия конфигурации (на момент анализа):** 0.0.3.21 **Область:** контур электронных транспортных накладных (ЭТрН / ЭПД, API Санадор) **Тип работ:** оптимизация производительности без изменения бизнес-смысла процесса Документ сформирован по результатам анализа исходников. Правки в конфигурацию этим документом не вносятся. --- ## 1. Цель и критерии успеха ### 1.1. Цель Сократить время и нагрузку на СУБД/сеть при регламентной обработке очереди ЭТрН и при сборке payload титулов Т1/Т3, сохранив текущую модель: - проведение документов **не** обращается к внешнему API; - создание/отправка ЭТрН выполняется роботом `ак_ЭТрНРобот` по очереди в регистре `ак_СтатусыДокументовЭПД`; - опросы статусов остаются пакетными по организации. ### 1.2. Критерии приёмки | № | Критерий | Как проверить | |---|----------|---------------| | К1 | Один проход РЗ с той же порцией новых документов укладывается в бюджет времени стабильнее (меньше срабатываний «Исчерпан бюджет времени») | Журнал регистрации события робота до/после на сопоставимой нагрузке | | К2 | Запросы выборки очереди (`ДобавитьНовые` / `ДобавитьОпросы` / подсчёт неудач) не сканируют лишнюю историю без необходимости | План запроса / замер времени на тестовой ИБ с наполненным регистром | | К3 | На одну отправку Т1 уменьшено число точечных запросов к ИБ (адреса, телефоны, КИ, ТС и т.п.) | Сравнение числа запросов на документ в отладке / технологическом журнале | | К4 | Повторные чтения параметров авторизации ЭПД и создание нового HTTP-соединения на каждый вызов устранены или сведены к минимуму в рамках порции | Код-ревью + замер latency порции | | К5 | Поиск перевозки для Т3 без uuid не выполняет отдельный HTTP-запрос на каждый документ при одинаковых ключах поиска | Код-ревью сценария «только Т3» | | К6 | Поведение статусов, идемпотентность перепроведения и запрет повторной отправки Т1 при наличии uuid **не нарушены** | Регрессионные сценарии §6 | Нефункционально: изменения обратимы, без «тихих» смен контракта API Санадора. --- ## 2. Текущая архитектура (as-is) ### 2.1. Поток ```text Проведение (5 видов документов) ↓ ак_ЭТрНРобот.ЗарегистрироватьПриПроведении ↓ РС ак_СтатусыДокументовЭПД («К отправке» / «Не требуется») ↓ РЗ ак_ОбработкаОчередиЭТрН → ак_ЭТрНРобот.ОбработатьОчередь ↓ ак_ЭТрНОтправка (Т1 / Т3) ← ак_ЭТрНФормированиеТитулов ← ак_ЭТрНДанные ↓ ак_ПолучениеДанныхЭПД (синхронный HTTPS к Санадору) ``` ### 2.2. Ключевые объекты | Объект | Назначение | |--------|------------| | `ОбщийМодуль.ак_ЭТрНРобот` | Регистрация при проведении, очередь, регламент | | `ОбщийМодуль.ак_ЭТрНОтправка` | Сборка + отправка Т1/Т3, запись статусов | | `ОбщийМодуль.ак_ЭТрНФормированиеТитулов` | Payload титулов для API | | `ОбщийМодуль.ак_ЭТрНДанные` | Запросы к ИБ, `КешДанных` | | `ОбщийМодуль.ак_ЭТрНКлиентСервер` / `ак_ЭТрНПовтИсп` | Контекст, статусы, константы | | `ОбщийМодуль.ак_ПолучениеДанныхЭПД` | HTTP к API ЭПД | | `РС.ак_СтатусыДокументовЭПД` | Очередь и история статусов (период — секунда) | | `РС.ак_УчетныеЗаписиЭПД`, `ак_АбонентыЭПД` | Учётные записи / абоненты | | `РЗ.ак_ОбработкаОчередиЭТрН` | Метод: `ак_ЭТрНРобот.ОбработатьОчередь` | | `Обработка.ак_ВыбывшиеДокументыЭТрН` | РМ по застрявшим документам | Документы-основания: `РасходнаяНакладная`, `РасходПоСкладу`, `ПеремещениеСПоляНаЭлеватор`, `ПриходПоВесовой`, `ПриходПоСкладу`. Отдельного документа «Электронная транспортная накладная» в конфигурации нет: ЭТрН создаётся во внешнем сервисе. ### 2.3. Что уже сделано удачно (не ломать) - Проведение не ходит в сеть. - Разделение очередей «новые» / «опросы» по наличию `ИдентификаторСанадор` (защита от повторного Т1). - Пакетный опрос статусов по организации (порции uuid). - Раздельные лимиты порций новых и опросов, мягкий бюджет времени. - `КешДанных` на порцию (часть идентификаторов / auth / организация по контрагенту). - Ключ регламентного задания против параллельного запуска. --- ## 3. Проблемы (на основании анализа кода) | ID | Проблема | Где | Влияние | |----|----------|-----|---------| | P1 | Синхронный HTTP в цикле по документам порции; каждое соединение создаётся заново | `ОбработатьОчередь` → отправка → `ак_ПолучениеДанныхЭПД.ОтправитьHTTPЗапрос` | Основной риск исчерпания бюджета 300 с | | P2 | Auth (`ак_УчетныеЗаписиЭПД`) читается на каждый HTTP; кэш робота HTTP-слоем не используется | `ВызватьHTTPМетод` | Лишние обращения к РС на каждый вызов | | P3 | `СрезПоследних` без отбора по измерениям; итоги среза последних выключены; `ВТ_Неудачи` сканирует историю по регистру | `ДобавитьНовые`, `ДобавитьОпросы`, `ТекстВременнойТаблицыНеудач` | Рост стоимости РЗ с объёмом истории | | P4 | Фильтрация статусов по `.Наименование` (строка) | Запросы робота | Хуже для индексации/планов, хрупкость | | P5 | Много точечных запросов на сборку одного Т1 | `ак_ЭТрНДанные` + `ак_ЭТрНФормированиеТитулов` | Нагрузка на СУБД пропорционально порции × полям | | P6 | Поиск Т3 без uuid: HTTP-список АРМ на каждый документ | `ак_ЭТрНОтправка.ПеревозкаВСервисе` | Лишние сетевые вызовы при сценарии «только Т3» | | P7 | Мелкие накладные: ИНН через точечные чтения; `Метаданные.НайтиПоТипу` в цикле РМ | `ПеревозкаСторонняя`, `ДокументыСОшибками` | Вторичный эффект | --- ## 4. Объём доработки (to-be) Работы разбиты на этапы. Этапы можно сдавать отдельно при сохранении критериев §1.2 для затронутой части. ### Этап A — очередь и регистр статусов (P3, P4) — приоритет 1 **Задачи** 1. Оценить и при положительном результате **включить итоги среза последних** у `ак_СтатусыДокументовЭПД` (сейчас `EnableTotalsSliceLast = false`). Зафиксировать влияние на запись статусов и объём ИБ. 2. Переработать выборку кандидатов очереди: - не строить полный срез «всего регистра», если достаточно отбора по активным статусам / отдельной структуре очереди; - подсчёт неудач (`ВТ_Неудачи`) ограничить документами-кандидатами текущей выборки, а не всей историей ошибок. 3. По возможности заменить отбор по `Статус.Наименование` на отбор по ссылкам справочника `ак_СтатусыЭТРН` (предопределённые / кэшированные ссылки). 4. (Опционально, при росте объёма) ввести узкий регистр/механизм «активная очередь» (документ + вид очереди: новый/опрос), историю статусов оставить в текущем РС. **Ограничения** - Сохранить семантику: условие в параметрах `СрезПоследних` по статусу **нельзя** ставить так, чтобы возвращалась «последняя запись с таким статусом», а не последняя запись документа (это уже осознанно зафиксировано в комментариях модуля). - Не менять смысл границы «новый / опрос» по `ИдентификаторСанадор`. **Результат этапа:** ускорение `ДобавитьНовые` / `ДобавитьОпросы` / протокола ошибок на наполненном регистре. ### Этап B — HTTP и авторизация в рамках порции (P1, P2) — приоритет 1 **Задачи** 1. Переиспользовать `HTTPСоединение` (и при возможности параметры авторизации) **в рамках одной порции / одной организации**. 2. Пробросить/использовать кэш параметров авторизации (`КешДанных.ПараметрыАвторизации` или аналог) в `ак_ПолучениеДанныхЭПД.ВызватьHTTPМетод`, чтобы не читать `ак_УчетныеЗаписиЭПД` на каждый вызов. 3. Настроить/зафиксировать рекомендуемые параметры РЗ: меньшая порция новых (ориентир 10–20) при отдельном/более частом запуске опросов — без изменения кода бизнес-логики титулов, если достаточно настроек расписания и параметров метода. **Ограничения** - Параллельный запуск нескольких экземпляров робота по-прежнему не допускается без отдельного архитектурного решения (ключ РЗ). - Контракт API (URL, заголовки Bearer / `counterparty-uuid`, тела Т1/Т3) не менять. **Результат этапа:** снижение latency порции отправки при том же числе документов. ### Этап C — пакетная подготовка данных титула Т1 (P5) — приоритет 2 **Задачи** 1. Расширить prefetch на порцию: один или несколько пакетных запросов по массиву документов вместо серии точечных вызовов (`РабочийТелефонВодителя`, `АдресВесовой`, адреса/телефоны сторон, координаты, `ДокументЗакрепленияТС`, даты прибытия/убытия и т.п. — по фактическому использованию в `ПараметрыОтправкиТ1`). 2. Расширить `КешДанных` ключами по ссылкам (адреса КИ, телефоны, коды регионов, закрепления ТС), с заполнением из prefetch. 3. По возможности дополнить уже существующий `ДанныеПоДокументам` (UNION по видам документов) полями, которые сейчас читаются повторно при сборке payload. **Ограничения** - Состав и смысл полей JSON payload Т1/Т3 не менять (кроме явно согласованных дефектов данных). - Ошибки заполнения полей по-прежнему фиксируются в результате формирования / статусах. **Результат этапа:** меньше запросов к ИБ на документ при отправке Т1. ### Этап D — батч поиска перевозки для Т3 (P6) — приоритет 2 **Задачи** 1. Группировать вызовы `ПолучитьСписокДокументовДляАРМ` по ключу (организация, водитель, номер ТС, окно дат) внутри порции. 2. Разбирать общую таблицу ответа локально для нескольких документов группы. 3. Где в данных есть uuid связанной перевозки / ранее сохранённый идентификатор — использовать его и не вызывать поиск АРМ. **Ограничения** - Правила различения нескольких перевозок «Груз в пути» (входящий номер / номер документа) сохранить. - Состояния ожидания Т2 по-прежнему блокируют отправку Т3. **Результат этапа:** меньше HTTP при сценарии документов только с Т3 без uuid. ### Этап E — мелкие оптимизации (P7) — приоритет 3 **Задачи** 1. Пакетное/кэшируемое чтение ИНН сторон в `ПеревозкаСторонняя`. 2. В `ДокументыСОшибками` — соответствие тип → синоним вместо `Метаданные.НайтиПоТипу` на каждую строку. 3. Оценить необходимость двух записей статуса после успешного Т1 («Черновик…» + «Ожидается Т2…»); менять только при согласовании с пользователями РМ/отчётами по истории. --- ## 5. Вне объёма - Изменение формата обмена с Санадором / новых титулов ЭПД. - Перенос создания ЭТрН в интерактивный режим «по кнопке» вместо робота. - Оптимизация бумажных макетов `ПФ_MXL_ТранспортнаяНакладная*`. - Параллельная обработка очереди несколькими рабочими процессами (требует отдельного ТЗ по блокировкам и идемпотентности API). - Рефакторинг модулей `сндОбменДаннымиСанадор*` вне контура ЭТрН. --- ## 6. Регрессионные сценарии | № | Сценарий | Ожидание | |---|----------|----------| | R1 | Проведение документа со сторонней перевозкой и включённой настройкой Т1/Т3 | Статус «К отправке», сеть не вызывается | | R2 | Проведение при внутренней перевозке / выключенных настройках | «Не требуется» или отсутствие постановки по текущим правилам | | R3 | Повторное проведение документа уже в процессе | Статус/очередь не дублируют отправку | | R4 | РЗ: новый документ → Т1 | Черновик в сервисе, заполнен `ИдентификаторСанадор`, статус ожидания Т2 | | R5 | РЗ: опрос при готовности к Т3 | Отправка Т3, корректный статус | | R6 | РЗ: документ с ошибкой первой отправки, неудач < максимума | Повторная попытка как «новый» | | R7 | Документ с uuid и ошибкой Т3 | Не уходит в очередь «новых», не создаётся второй Т1 | | R8 | РМ «Выбывшие документы ЭТрН» → вернуть в очередь | Счётчик неудач сбрасывается логикой `ВернутьВОчередь`, история сохраняется | | R9 | Исчерпание бюджета времени | Текущий документ дорабатывается, остальные подхватываются следующим запуском | --- ## 7. Порядок внедрения и оценка Рекомендуемый порядок: **A → B → C → D → E**. | Этап | Ориентир трудозатрат | Зависимости | |------|----------------------|-------------| | A | 2–5 чел·дн (без нового РС); +2–4 при введении узкой очереди | Решение по итогам среза / метаданным РС | | B | 1–3 чел·дн | Согласование сигнатур HTTP-обёрток | | C | 3–6 чел·дн | Этап B желателен, не обязателен | | D | 1–3 чел·дн | — | | E | 0,5–1,5 чел·дн | — | Оценки ориентировочные; уточняются после замера текущего времени `ДобавитьНовые`/`ДобавитьОпросы` и средней длительности HTTP на тестовой/боевой статистике. --- ## 8. Риски | Риск | Митигация | |------|-----------| | Включение итогов среза увеличит стоимость каждой записи статуса | Замер записи до/после; при неприемлемости — узкая очередь без итогов | | Кэш auth устареет при смене токена в середине порции | Инвалидация кэша по организации при 401/ошибке авторизации и один повтор | | Prefetch полей титула разъедется с ветвлениями по видам документов | Покрыть R4–R5 на всех 5 видах документов | | Батч поиска Т3 склеит чужие перевозки | Сохранить текущие правила уточнения по номерам; не укрупнять ключ сверх (орг+водитель+ТС+даты) | --- ## 9. Поставка 1. Описание изменений по модулям/метаданным. 2. Результаты замеров до/после (хотя бы время порции РЗ и число запросов/HTTP на документ). 3. Протокол прохождения сценариев §6. 4. При изменении метаданных РС — инструкция обновления ИБ и оценка времени пересчёта итогов (если применимо). --- ## 10. Источники анализа - `ves2020/CommonModules/ак_ЭТрНРобот/Ext/Module.bsl` - `ves2020/CommonModules/ак_ЭТрНОтправка/Ext/Module.bsl` - `ves2020/CommonModules/ак_ЭТрНФормированиеТитулов/Ext/Module.bsl` - `ves2020/CommonModules/ак_ЭТрНДанные/Ext/Module.bsl` - `ves2020/CommonModules/ак_ПолучениеДанныхЭПД/Ext/Module.bsl` - `ves2020/InformationRegisters/ак_СтатусыДокументовЭПД.xml` - `ves2020/ScheduledJobs/ак_ОбработкаОчередиЭТрН.xml` **Memory:** локальный `memory.md` (постоянных записей по ЭТрН нет). **Template:** проверка шаблонов MCP в сессии недоступна — «no fitting template». **Docs / Metadata tooling:** разбор по исходникам выгрузки; live MCP user-1c при анализе был частично недоступен.