Добавить этрн.md
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
# ТЗ на доработку: оптимизация создания и обработки ЭТрН
|
||||
|
||||
**Дата:** 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 при анализе был частично недоступен.
|
||||
Reference in New Issue
Block a user