Files
2026-10-07 12:29:29 +00:00

252 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ТЗ на доработку: оптимизация создания и обработки ЭТрН
**Дата:** 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 при анализе был частично недоступен.