Claude Skill

kd2-rules

Программная разработка правил обмена в «Конвертация данных 2.1» (КД 2.0) через MCP-toolkit к живой ИБ. Создание/чтение/изменение Конвертаций, ПКО, ПКС, ПКЗ, ПВД, ПОД в справочниках КД и выгрузка итогового XML штатными обработками КД (ВыгрузкаКонвертации, ВыгрузкаРегистрации, Загр

LLM Mart · 0 points · 15 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download Desko77-claude-code-skills-1c-skills_kd2-rules-eb281b4.zip · 41 KB
Part of desko77/claude-code-skills-1c — 48 skills

Install

skills CLI npx skills add https://github.com/Desko77/claude-code-skills-1c/tree/main/skills/kd2-rules
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install desko77-claude-code-skills-1c@llmmart
Git git clone https://github.com/Desko77/claude-code-skills-1c.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole desko77/claude-code-skills-1c collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

KD 2.0 - правила обмена через MCP-toolkit

Скилл описывает, как агент создает/изменяет правила обмена в живой ИБ "Конвертация данных 2.1" (КД 2.0) через MCP-toolkit HTTP API (порт по умолчанию 6003, в проектах часто 7003) и в финале выгружает XML штатными обработками КД.

Что такое КД 2.0

  • Конфигурация фирмы "1С", v2.1.8.2, обычные формы, режим совместимости 8.2.13. Программа для разработки правил обмена данными между парами конфигураций (например, БП КОРП -> УПП, УТ -> ERP).
  • Результат работы в КД - XML с правилами, который грузится в "Универсальный обмен данными в формате XML" в конфигурации-источнике.
  • Все правила хранятся в справочниках самой КД: Конвертации, ПравилаКонвертацииОбъектов, ПравилаКонвертацииСвойств, ПравилаКонвертацииЗначений, ПравилаВыгрузкиДанных, ПравилаОчисткиДанных, ПравилаРегистрацииОбъектов, плюс Конфигурации/Объекты/Свойства/Значения (теневая модель метаданных источника и приемника).

Архитектура работы

Claude (агент)
   ↕  MCP-протокол / прямые tool-вызовы
Скилл kd2-rules
   ↕  HTTP POST :6003/api/* (или :7003 если переопределен порт)
MCP-toolkit (обработка MCP_Toolkit.epf в живой ИБ)
   ↕  внутрипроцессно
ИБ КД 2.0
   ↕  через ВыгрузкаКонвертации.ВыполнитьВыгрузкуПравил()
Файл XML с правилами обмена

Низкоуровневый транспорт - MCP-toolkit (скилл 1c-mcp-toolkit). Главные эндпоинты, которые используются здесь:

  • POST /api/execute_query - читать справочники КД и их связи.
  • POST /api/execute_code - создавать/изменять элементы справочников, запускать экспортные методы обработок.
  • GET /api/health - проверка живости.

Предварительные требования

  1. Запущенная ИБ КД 2.0 в тонком/толстом клиенте с открытой обработкой MCP_Toolkit.epf (см. скилл 1c-mcp-toolkit). HTTP-сервер слушает localhost:6003 (или :7003 по настройке).
  2. В форме toolkit-а проверить и при необходимости снять защиту от записи: снять флажки на ключевые слова Записать, Удалить, УстановитьПривилегированныйРежим. Без этого работают только execute_query и read-only вызовы.
  3. Желательно тестовая копия ИБ КД, а не production - правила пишутся напрямую в справочники.

Быстрая проверка готовности

curl http://localhost:7003/health
# Ожидание: {"status":"healthy", ...}

curl -sS -X POST "http://localhost:7003/api/execute_query" \
  -H "Content-Type: application/json" \
  -d '{"query":"ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Кол ИЗ Справочник.Конвертации"}'

Карта references

Документ Что внутри Когда читать
references/helpers.md библиотека готовых BSL-заготовок для execute_code: списки ПКО/ПКС/ПКЗ, дамп обработчиков, флаги ПКО, ПКС по ссылке на Свойство, выгрузка комплекта XML, поиск объектов с учетом префикса типа, идиомы передачи значений нужен запрос или правка объектов КД - СНАЧАЛА сюда, не сочинять скрипт с нуля
references/architecture.md объектная модель КД, иерархия Владелец, полные списки реквизитов всех ключевых справочников проектирование новой операции, нужны типы и связи
references/methods.md экспортные методы обработок выгрузки/загрузки + file:line + параметры (реквизиты обработки) вызов конкретного метода через execute_code
references/workflows.md end-to-end сценарии: подготовка ИБ, загрузка метаданных, создание правил, выгрузка XML, импорт XML, автонастройка впервые делаешь полный цикл или сложный сценарий
references/xml-schema.md схема итогового XML правил обмена + маппинг полей справочника на XML надо понять, что КД ожидает увидеть в XML, или сверить результат с эталоном
references/troubleshooting.md типичные ошибки и ограничения toolkit-а, особенности КД 2.0 при ошибке execute_code/execute_query

5 базовых операций (краткий справочник)

1. Найти конвертацию по имени

Конв = Справочники.Конвертации.НайтиПоНаименованию("Имя_Конвертации");
Если Конв.Пустая() Тогда
    ВызватьИсключение "Конвертация не найдена";
КонецЕсли;
Результат = XMLСтрока(Конв);

2. Список ПКО в конвертации

curl -sS -X POST "http://localhost:7003/api/execute_query" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "ВЫБРАТЬ ПКО.Наименование, ПКО.ТипИсточника, ПКО.ТипПриемника, ПКО.Порядок ИЗ Справочник.ПравилаКонвертацииОбъектов КАК ПКО ГДЕ ПКО.Владелец.Наименование = &Конв И НЕ ПКО.ЭтоГруппа УПОРЯДОЧИТЬ ПО ПКО.Порядок",
    "params": {"Конв": "Имя_Конвертации"}
  }'

3. Создать ПКО

Конв = Справочники.Конвертации.НайтиПоНаименованию("МояКонвертация");
ОбъИст = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Источник);
ОбъПр  = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Приемник);

ПКО = Справочники.ПравилаКонвертацииОбъектов.СоздатьЭлемент();
ПКО.Владелец      = Конв;
ПКО.Наименование  = "Контрагенты";
ПКО.Источник      = ОбъИст;
ПКО.Приемник      = ОбъПр;
ПКО.ТипИсточника  = "СправочникСсылка.Контрагенты";
ПКО.ТипПриемника  = "СправочникСсылка.Контрагенты";
ПКО.Порядок       = 100;
ПКО.Записать();

Результат = Новый Структура("ссылка", XMLСтрока(ПКО.Ссылка));

4. Создать ПКС внутри ПКО

ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты", Истина, Конв);
СвИст = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Источник);
СвПр  = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Приемник);

ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
ПКС.Владелец     = ПКО;
ПКС.Источник     = СвИст;
ПКС.Приемник     = СвПр;
ПКС.ИмяИсточника = "Наименование";
ПКС.ИмяПриемника = "Наименование";
ПКС.ТипИсточника = "Строка";
ПКС.ТипПриемника = "Строка";
ПКС.ВидИсточника = "Свойство";
ПКС.ВидПриемника = "Свойство";
ПКС.Наименование = "Наименование --> Наименование";
ПКС.Порядок      = 100;
ПКС.Записать();

5. Выгрузить конвертацию в XML

Конв = Справочники.Конвертации.НайтиПоНаименованию("МояКонвертация");
Обр = Обработки.ВыгрузкаКонвертации.Создать();
Обр.КонвертацияДляВыгрузки         = Конв;
Обр.ИмяФайлаПравил                 = "C:\Output\rules.xml";
Обр.СжиматьФайлПравил              = Ложь;
Обр.ВыгружатьПравилаКорреспондента = Ложь;
Обр.ВыгружатьПравилаРегистрации    = Ложь;
Обр.ВыполнитьВыгрузкуПравил();

Файл = Новый Файл(Обр.ИмяФайлаПравил);
Результат = Новый Структура("ok,path,size", Истина, Обр.ИмяФайлаПравил, Файл.Размер());

Принципы работы

  1. Все справочники иерархические "Папки и элементы". ПКО-группы (ЭтоГруппа=true) используются для логической группировки правил внутри конвертации.

  2. Владелец = главная связь. ПКО подчинен Конвертации, ПКС/ПКЗ подчинены ПКО, Объекты подчинены Конфигурации, Свойства подчинены Объектам, Значения подчинены Свойствам.

  3. Денормализованные дубликаты. Поля типа ИмяИсточника/ТипИсточника в ПКО и ПКС - строковые копии данных из связанной ссылки (для быстрого поиска без join-ов). Заполняй их явно при создании.

  4. Поле Код в Конвертациях и ПКО - это "внутренний идентификатор" (UUID-подобная строка фиксированной длины 40 символов с trailing-пробелами). Используется в итоговом XML как <Ид> и <КодПравилаКонвертации>.

  5. Имя файла в ИмяФайлаПравил должно быть путем к существующему каталогу. КаталогВременныхФайлов() - надежный способ получить временную папку клиента.

  6. Гигиена скриптов. Одноразовые/отладочные BSL-скрипты класть только в tools/_tmp/ рабочего каталога КД и чистить после задачи. Устойчивые операции не копить в одноразовых файлах - брать из references/helpers.md и добавлять новые заготовки туда же.

Ограничения

  • Все ключевые методы КД работают через execute_code без явного execution_context (toolkit живет в клиентском контексте 1С, директива #Если Клиент Тогда не блокирует).
  • В стандартной конфигурации toolkit-а заблокированы ключевые слова Записать, Удалить, УстановитьПривилегированныйРежим. Для создания правил - отключить защиту в форме toolkit-а.
  • Возможны trailing-пробелы в строковых ссылочных полях (Код 40 символов с пробелами). При сравнениях использовать СокрЛП(...).
  • Обработка ВыгрузкаКонвертации использует переменную модуля мФормаПрогрессора.Значение - при программном запуске она остается не инициализированной, но падения не происходит.

Связанные скиллы

  • 1c-mcp-toolkit - HTTP API к живой ИБ 1С (этот скилл - надстройка поверх него).
  • composing-1c-queries - синтаксис языка запросов 1С для execute_query.
Files (claude-code-skills-1c)
  • references
    • architecture.md 17.3 KB
      # Объектная модель КД 2.0
      
      Все имена справочников и реквизитов получены выгрузкой `DumpConfigToFiles`
      конфигурации `КонвертацияДанныхРедакция21` v2.1.8.2.
      
      ## Иерархия Владелец / Родитель
      
      ```
      Конфигурации             (плоский справочник; описывает источник или приемник)
        └─ Объекты             (Владелец=Конфигурации) - объекты метаданных
             └─ Свойства       (Владелец=Объекты) - реквизиты объекта
                  └─ Значения  (Владелец=Свойства) - значения перечислений
      
      Конвертации              (плоский; пара "Источник -> Приемник")
        ├─ ПКО                 (Владелец=Конвертации, может иметь Родитель=ПКО-группа)
        │   ├─ ПКС             (Владелец=ПКО)
        │   └─ ПКЗ             (Владелец=ПКО)
        ├─ ПВД                 (Владелец=Конвертации)
        ├─ ПОД                 (Владелец=Конвертации)
        ├─ Алгоритмы           (Владелец=Конвертации)
        ├─ Запросы             (Владелец=Конвертации)
        └─ Параметры           (Владелец=Конвертации)
      
      Регистрации              (плоский)
        └─ ПРО                 (Владелец=Регистрации)
      ```
      
      Все основные справочники - иерархические `HierarchyFoldersAndItems` с
      `LevelCount=2`. Папки (`ЭтоГруппа=true`) используются для логической
      группировки внутри одной Конвертации/Регистрации.
      
      ## Аббревиатуры
      
      | Сокр. | Полное имя | Назначение |
      |---|---|---|
      | ПКО | Правило Конвертации Объекта | Конвертация объекта источника в объект приемника |
      | ПКС | Правило Конвертации Свойства | Конвертация одного реквизита |
      | ПКГС | Правило Конвертации Группы Свойств | ПКС с `ЭтоГруппа = Истина` |
      | ПКЗ | Правило Конвертации Значения | Конвертация значений перечислений |
      | ПРО | Правило Регистрации Объекта | Когда регистрировать объект к обмену |
      | ПВД | Правила Выгрузки Данных | Что и как выгружать |
      | ПОД | Правила Очистки Данных | Что удалять при загрузке |
      
      ## Справочник.Конфигурации
      
      Описание одной конфигурации-источника или конфигурации-приемника. Хранит
      имя, версию, и через подчиненные `Объекты` - теневую копию метаданных.
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | Наименование | string | Видимое имя (например `БухгалтерияПредприятияКОРП`) |
      | Имя | string | Программное имя (обычно совпадает с Наименование) |
      | Синоним | string | Русское описание |
      | Комментарий | string | |
      | Версия | string | Например `3.0.189.29` |
      | ДатаОбновления | dateTime | |
      | Приложение | EnumRef.Приложения | Например `Предприятие80` |
      
      ## Справочник.Объекты (Владелец=Конфигурации)
      
      Объекты метаданных конкретной конфигурации.
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | Наименование, Имя | string | Имя объекта (`АвансовыйОтчет`, `Контрагенты`) |
      | Синоним, Комментарий | string | |
      | Тип | EnumRef.ТипыОбъектов | `НаборКонстант`, `Число`, `Строка`, `Справочник`, `Документ`, `РегистрСведений` и т.д. |
      | Иерархический | boolean | |
      | ВидИерархии | string | |
      | ОграничиватьКоличествоУровней, КоличествоУровней | | |
      | СерииКодов, КонтрольУникальности, АвтоНумерация | | Для справочников |
      | Периодичность | string | Для регистров сведений |
      | Подчиненный | boolean | |
      
      Представление ссылок: `ДокументСсылка.АвансовыйОтчет`,
      `СправочникСсылка.Контрагенты`.
      
      ## Справочник.Свойства (Владелец=Объекты)
      
      Реквизиты объектов метаданных. Хранит тип, длину, ссылочность.
      
      ## Справочник.Значения (Владелец=Свойства)
      
      Значения перечислений, предопределенные значения справочников.
      
      ## Справочник.Конвертации
      
      24+ реквизита. Корневая сущность пары "источник -> приемник".
      
      ### Ключевые
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | Код | string(40) | UUID-like "внутренний идентификатор" с trailing-пробелами (`00000000-0000-0000-0000-000000000001    `). Идет в XML как `<Ид>` |
      | Наименование | string | Видимое имя |
      | Источник | CatalogRef.Конфигурации | Ссылка на конфигурацию-источник |
      | Приемник | CatalogRef.Конфигурации | Ссылка на конфигурацию-приемник |
      | ИмяИсточника, ИмяПриемника | string | Денормализованные дубликаты Имени Конфигураций |
      | Комментарий, Описание | string | |
      | ДатаОбновления | dateTime | |
      | РежимСовместимости | EnumRef.РежимСовместимости | `РежимСовместимостиСБСП20` ("Версия БСП 2.0 и ниже") |
      | ВыгружатьПараметрыПоВерсии2_01 | boolean | |
      | УдалятьСопоставленныеОбъектыВПриемникеПриИхУдаленииВИсточнике | boolean | |
      
      ### Алгоритмы (16 string-полей с BSL)
      
      `АлгоритмПередВыгрузкойДанных`, `АлгоритмПослеВыгрузкиДанных`,
      `АлгоритмПередЗагрузкойДанных`, `АлгоритмПослеЗагрузкиДанных`,
      `АлгоритмПередВыгрузкойОбъекта`, `АлгоритмПередКонвертациейОбъекта`,
      `АлгоритмПослеВыгрузкиОбъекта`, `АлгоритмПередЗагрузкойОбъекта`,
      `АлгоритмПослеЗагрузкиОбъекта`, `АлгоритмПослеЗагрузкиПравилОбмена`,
      `АлгоритмПередОтправкойИнформацииОбУдалении`,
      `АлгоритмПриПолученииИнформацииОбУдалении`,
      `АлгоритмПослеЗагрузкиПараметров`,
      `АлгоритмПередПолучениемИзмененныхОбъектов`,
      `АлгоритмПослеПолученияИнформацииОбУзлахОбмена`.
      
      ## Справочник.ПравилаКонвертацииОбъектов (ПКО)
      
      Владелец = Конвертации. 27+ реквизитов + 1 табчасть. Может быть в группе
      (Родитель = другая ПКО с `ЭтоГруппа=true`).
      
      ### Ключевые
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | Владелец | CatalogRef.Конвертации | Обязательно |
      | Родитель | CatalogRef.ПравилаКонвертацииОбъектов | Если ПКО в логической группе |
      | ЭтоГруппа | boolean | true для групп-папок |
      | Код | string(40) | UUID-like |
      | Наименование | string | Имя правила (часто = имя объекта) |
      | Источник | CatalogRef.Объекты | Ссылка на объект источника |
      | Приемник | CatalogRef.Объекты | Ссылка на объект приемника |
      | ТипИсточника | string | Дубликат: `ДокументСсылка.АвансовыйОтчет` |
      | ТипПриемника | string | Дубликат |
      | Порядок | decimal | Сортировка (обычно с шагом 50: 50, 100, 150, 200) |
      | Описание | string | |
      
      ### Поведение
      
      | Реквизит | Тип |
      |---|---|
      | НеЗамещать | boolean |
      | НеЗапоминатьВыгруженные | boolean |
      | СинхронизироватьПоИдентификатору | boolean |
      | НеВыгружатьОбъектыСвойствПоСсылкам | boolean |
      | ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли | boolean |
      | АлгоритмПоследовательностьПолейПоиска | string (BSL) |
      | НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска | boolean |
      | ИспользоватьБыстрыйПоискПриЗагрузке | boolean |
      | ГенерироватьНовыйНомерИлиКодЕслиНеУказан | boolean |
      | ВыгружатьОбъектТолькоПриНаличииНаНегоСсылки | boolean |
      | ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD | boolean (опечатка GIUD в платформе) |
      | ПриоритетОбъектовОбмена | EnumRef.ПриоритетОбъектовОбмена | `ПриоритетПоступившегоПриОбменеОбъектаВыше` ("Выше") и др. |
      | НеЗамещатьОбъектСозданныйВИнформационнойБазеПриемнике | boolean |
      
      ### Алгоритмы (7 string-полей с BSL)
      
      `АлгоритмПередВыгрузкойОбъекта`, `АлгоритмПриВыгрузкеОбъекта`,
      `АлгоритмПослеВыгрузкиОбъекта`, `АлгоритмПередЗагрузкойОбъекта`,
      `АлгоритмПриЗагрузкеОбъекта`, `АлгоритмПослеЗагрузкиОбъекта`,
      `АлгоритмПослеВыгрузкиОбъектаВФайлОбмена`.
      
      ### Табчасть `НастройкаВариантовПоискаОбъектов`
      
      | Реквизит | Тип |
      |---|---|
      | ИмяНастройкиДляАлгоритма | string(100) |
      | ИмяНастройкиДляПользователя | string |
      | ОписаниеНастройкиДляПользователя | string |
      
      ## Справочник.ПравилаКонвертацииСвойств (ПКС)
      
      Владелец = ПКО. 24+ реквизита.
      
      ### Ключевые
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | Владелец | CatalogRef.ПравилаКонвертацииОбъектов | Обязательно |
      | Источник | CatalogRef.Свойства | Может быть `null` если только заполняется алгоритмом |
      | Приемник | CatalogRef.Свойства | |
      | ИмяИсточника, ИмяПриемника | string | Дубликаты |
      | ТипИсточника, ТипПриемника | string | `Строка`, `Число`, ссылочный тип |
      | ВидИсточника, ВидПриемника | string | `Реквизит`, `Свойство`, `ТабличнаяЧасть` |
      | Порядок | decimal | |
      | ПравилоКонвертации | CatalogRef.ПравилаКонвертацииОбъектов | Для ссылочного типа: ПКО для конвертации значения ссылки |
      | ИмяПравилаКонвертации | string | Дубликат |
      | Поиск | boolean | Поле является поисковым (в XML: атрибут `Поиск="true"`) |
      | Отключить | boolean | |
      | НеЗамещать | boolean | |
      | ПолучитьИзВходящихДанных | boolean | |
      | АвтоматическиПриводитьЗначениеКДлинеПриемника | boolean | |
      | ИмяПараметраДляПередачи | string | |
      | ПоискПоДатеНаРавенство | boolean | |
      | ВыгружатьГруппуЧерезФайл | boolean | |
      
      ### Алгоритмы (5 string-полей с BSL)
      
      `АлгоритмПередВыгрузкойСвойства`, `АлгоритмПриВыгрузкеСвойства`,
      `АлгоритмПослеВыгрузкиСвойства`, `АлгоритмПередОбработкойВыгрузки`,
      `АлгоритмПослеОбработкиВыгрузки`.
      
      ### Группы свойств (ПКГС)
      
      Реализуется через `ЭтоГруппа=true` на ПКС. Дочерние ПКС имеют `Родитель=ПКГС`.
      
      ### Типичное наименование
      
      `<ИмяСвойства> --> <ИмяСвойства>`. Примеры:
      - `Наименование --> Наименование`
      - `Доп_НСИ_ГУИД --> Доп_НСИ_ГУИД`
      - `Владелец --> Владелец`
      
      ## Справочник.ПравилаКонвертацииЗначений (ПКЗ)
      
      Владелец = ПКО. 7 реквизитов.
      
      | Реквизит | Тип |
      |---|---|
      | Владелец | CatalogRef.ПравилаКонвертацииОбъектов |
      | Источник | CatalogRef.Значения |
      | Приемник | CatalogRef.Значения |
      | ЗначениеИсточник | string (имя значения перечисления) |
      | ЗначениеПриемник | string |
      | Комментарий, Описание | string |
      | Порядок | decimal |
      
      ## Справочник.ПравилаВыгрузкиДанных (ПВД) и ПравилаОчисткиДанных (ПОД)
      
      Владелец = Конвертации. Реквизиты не выписаны в полном объеме - смотри
      `<каталог выгрузки КД>\src\Catalogs\ПравилаВыгрузкиДанных.xml` и
      `<каталог выгрузки КД>\src\Catalogs\ПравилаОчисткиДанных.xml` при необходимости.
      
      ## Справочник.ПравилаРегистрацииОбъектов (ПРО)
      
      Владелец = Регистрации. Реквизиты в
      `<каталог выгрузки КД>\src\Catalogs\ПравилаРегистрацииОбъектов.xml`.
      
      ## Паттерны заполнения
      
      ### ПКО "АвансовыйОтчетВДокументыВИБ" (БП КОРП -> УПП)
      
      - Владелец = Конвертация `Тест: БП КОРП -> УПП`
      - Родитель = ПКО-группа `Документы`
      - Источник = Объекты `ДокументСсылка.АвансовыйОтчет` (из БП КОРП)
      - Приемник = Объекты `СправочникСсылка.ДокументыВИБ` (из УПП)
      - Порядок = 850
      - `ИспользоватьБыстрыйПоискПриЗагрузке = true`, остальные boolean = false
      - `ПриоритетОбъектовОбмена = ПриоритетПоступившегоПриОбменеОбъектаВыше`
      - Все алгоритмы пустые
      
      ### ПКС "Наименование --> Наименование" (внутри ПКО `Валюты`)
      
      - Владелец = ПКО `Валюты` (с trailing-пробелами в наименовании)
      - Источник/Приемник = Свойства из соответствующих Объекты
      - ТипИсточника/ТипПриемника = `Строка`
      - ВидИсточника/ВидПриемника = `Свойство`
      - Порядок = 100
      - `Поиск = false`, обычное копирование Строка->Строка
      
      ### Конвертация "Тест: БП КОРП -> УПП"
      
      - Код = `00000000-0000-0000-0000-000000000001    ` (UUID + trailing-пробелы)
      - РежимСовместимости = `РежимСовместимостиСБСП20`
      - Все 16 алгоритмов пустые
      - `ВыгружатьПараметрыПоВерсии2_01 = true`
      
      ## Источники XML-метаданных
      
      При необходимости получить полный список реквизитов или табчастей -
      читать XML конфигурации:
      
      - `<каталог выгрузки КД>\src\Catalogs\<имя>.xml` (выгрузка `DumpConfigToFiles`).
      
      Файлы XML содержат блоки `<Attribute>` с реквизитами, `<TabularSection>` с
      табчастями.
      
    • helpers.md 41.2 KB
      # Библиотека готовых BSL-заготовок для execute_code
      
      Параметризованные копипаст-готовые скрипты типовых операций с объектами КД 2.0
      через MCP-toolkit. Типовые одноразовые probe/diag/check/fix-скрипты почти
      всегда - вариации заготовок ниже.
      
      ## Правила пользования библиотекой
      
      1. **НЕ плодить одноразовые файлы `_probe_*` / `_diag_*` / `_check_*`.**
         Сначала взять заготовку отсюда и подставить параметры.
      2. Параметры помечены `<ПОДСТАВИТЬ:...>` - заменить текстуально до отправки.
      3. Понадобилась новая устойчивая операция (повторится в этой или другой задаче) -
         добавить ее заготовкой СЮДА, а не в новый одноразовый файл.
      4. Действительно одноразовый отладочный черновик - класть только в `tools/_tmp/`
         рабочего каталога КД и чистить после задачи.
      5. Запуск: сохранить BSL во временный файл и `python kd_exec.py code < file.bsl`
         (транспорт curl, см. troubleshooting.md раздел "Транспорт"). В заготовках
         `Запрос.Текст` однострочный - это работает в любом канале; многострочник
         с `|` выживает только при передаче через kd_exec.py (реальные переносы строк),
         при ручной склейке JSON ломается.
      6. Все заготовки - линейный top-level код без `Процедура`/`Функция` (ограничение
         `execute_code` = `Выполнить()`), результат в переменной `Результат`.
         Пишущие заготовки идемпотентны: повторный запуск не создает дублей.
      
      ---
      
      ## 1. Список ПКО конвертации
      
      **Когда использовать:** обзор правил конвертации - какие ПКО есть, типы
      источник/приемник, порядок, флаги поиска. Перед правкой флагов, диагностикой
      "объект не найден", сверкой покрытия.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      Если Конв.Пустая() Тогда
          ВызватьИсключение "Конвертация не найдена";
      КонецЕсли;
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Сс, Наименование КАК Нм, ТипИсточника КАК ТИ, ТипПриемника КАК ТП, Порядок КАК Пор, НеЗамещать КАК НЗ, СинхронизироватьПоИдентификатору КАК СинхрИд, ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли КАК ПродПоиск, НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска КАК НеСозд ИЗ Справочник.ПравилаКонвертацииОбъектов ГДЕ Владелец = &Конв И НЕ ЭтоГруппа И НЕ ПометкаУдаления УПОРЯДОЧИТЬ ПО Порядок";
      Запрос.УстановитьПараметр("Конв", Конв);
      Текст = "";
      К = 0;
      Выб = Запрос.Выполнить().Выбрать();
      Пока Выб.Следующий() Цикл
          К = К + 1;
          Текст = Текст + Строка(Выб.Пор) + "|" + Выб.Нм + "|" + Выб.ТИ + " -> " + Выб.ТП
              + "|UUID=" + XMLСтрока(Выб.Сс)
              + "|НеЗамещать=" + Строка(Выб.НЗ) + "|СинхрИд=" + Строка(Выб.СинхрИд)
              + "|ПродПоиск=" + Строка(Выб.ПродПоиск) + "|НеСоздавать=" + Строка(Выб.НеСозд) + ПС;
      КонецЦикла;
      Результат = Текст + "ИТОГО ПКО: " + Строка(К);
      ```
      
      ---
      
      ## 2. Список ПКС конкретного ПКО
      
      **Когда использовать:** состав правил свойств ПКО - что во что мапится, каким
      правилом конвертации, какие поля поисковые, где алгоритмы, что отключено или
      помечено на удаление, иерархия групп-табчастей.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      Если ПКО.Пустая() Тогда
          ВызватьИсключение "ПКО не найдено";
      КонецЕсли;
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ ИмяИсточника КАК ИИ, ИмяПриемника КАК ИП, ТипИсточника КАК ТИ, ТипПриемника КАК ТП, ИмяПравилаКонвертации КАК ПрК, Поиск КАК Пск, Отключить КАК Откл, ПометкаУдаления КАК ПУ, ЭтоГруппа КАК Гр, Родитель КАК Род, АлгоритмПередВыгрузкойСвойства КАК Алг ИЗ Справочник.ПравилаКонвертацииСвойств ГДЕ Владелец = &ПКО УПОРЯДОЧИТЬ ПО Родитель, ИмяПриемника";
      Запрос.УстановитьПараметр("ПКО", ПКО);
      Текст = "";
      К = 0;
      Выб = Запрос.Выполнить().Выбрать();
      Пока Выб.Следующий() Цикл
          К = К + 1;
          Метки = ?(Выб.Гр, "[ТЧ/ГРУППА]", "") + ?(Выб.Пск, "[ПОИСК]", "") + ?(Выб.Откл, "[ОТКЛ]", "")
              + ?(Выб.ПУ, "[УДАЛ]", "") + ?(ПустаяСтрока(Выб.Алг), "", "[АЛГ]");
          Род = ?(ЗначениеЗаполнено(Выб.Род), " (в группе '" + Строка(Выб.Род) + "')", "");
          Текст = Текст + Выб.ИИ + " -> " + Выб.ИП + " |" + Выб.ТИ + " -> " + Выб.ТП
              + ?(ПустаяСтрока(Выб.ПрК), "", " |ПКО:" + Выб.ПрК) + Род + " " + Метки + ПС;
      КонецЦикла;
      Результат = "ПКО: " + Строка(ПКО) + ПС + Текст + "ИТОГО ПКС: " + Строка(К);
      ```
      
      ---
      
      ## 3. Список ПКЗ ПКО-перечисления
      
      **Когда использовать:** сверка маппинга значений перечислений - что уже смаплено,
      что пропущено. Если ПКО-перечисление не находится по наименованию - искать через
      заготовку 5 (по `Код ПОДОБНО`, `СокрЛП` в языке запросов нет).
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      Если ПКО.Пустая() Тогда
          ВызватьИсключение "ПКО не найдено";
      КонецЕсли;
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ ЗначениеИсточник КАК ЗИ, ЗначениеПриемник КАК ЗП, Источник КАК Ист, Приемник КАК Прм ИЗ Справочник.ПравилаКонвертацииЗначений ГДЕ Владелец = &ПКО УПОРЯДОЧИТЬ ПО Порядок";
      Запрос.УстановитьПараметр("ПКО", ПКО);
      Текст = "";
      К = 0;
      Выб = Запрос.Выполнить().Выбрать();
      Пока Выб.Следующий() Цикл
          К = К + 1;
          Текст = Текст + "'" + Выб.ЗИ + "' -> '" + Выб.ЗП + "'"
              + " |ссылки: " + Строка(Выб.Ист) + " -> " + Строка(Выб.Прм) + ПС;
      КонецЦикла;
      Результат = "ПКО: " + Строка(ПКО) + ПС + Текст + "ИТОГО ПКЗ: " + Строка(К);
      ```
      
      ---
      
      ## 4. Дамп обработчиков событий ПКО
      
      **Когда использовать:** прочитать тексты алгоритмов событий ПКО перед правкой
      или для аудита. Индексатор `Объект["Имя"]` у объектов НЕ работает - поля
      перечислены явно (все 7 событий ПКО). Для ПКС аналогично, но полей 5
      (`АлгоритмПередВыгрузкойСвойства`, `АлгоритмПриВыгрузкеСвойства`,
      `АлгоритмПослеВыгрузкиСвойства`, `АлгоритмПередОбработкойВыгрузки`,
      `АлгоритмПослеОбработкиВыгрузки`); для Конвертации - см. перечень в architecture.md.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      Если ПКО.Пустая() Тогда
          ВызватьИсключение "ПКО не найдено";
      КонецЕсли;
      Текст = "ПКО: " + Строка(ПКО) + ПС;
      Текст = Текст + "<<<АлгоритмПередВыгрузкойОбъекта>>>" + ПС + ПКО.АлгоритмПередВыгрузкойОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПриВыгрузкеОбъекта>>>" + ПС + ПКО.АлгоритмПриВыгрузкеОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПослеВыгрузкиОбъекта>>>" + ПС + ПКО.АлгоритмПослеВыгрузкиОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПередЗагрузкойОбъекта>>>" + ПС + ПКО.АлгоритмПередЗагрузкойОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПриЗагрузкеОбъекта>>>" + ПС + ПКО.АлгоритмПриЗагрузкеОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПослеЗагрузкиОбъекта>>>" + ПС + ПКО.АлгоритмПослеЗагрузкиОбъекта + ПС;
      Текст = Текст + "<<<АлгоритмПослеВыгрузкиОбъектаВФайлОбмена>>>" + ПС + ПКО.АлгоритмПослеВыгрузкиОбъектаВФайлОбмена + ПС;
      Результат = Текст;
      ```
      
      ---
      
      ## 5. Поиск объекта КД по имени с учетом префикса типа
      
      **Когда использовать:** `НайтиПоНаименованию` в `Справочник.Объекты` вернул пусто.
      Наименования в теневой модели хранятся С ПРЕФИКСОМ типа
      (`СправочникСсылка.Контрагенты`, `ДокументСсылка.ПоступлениеНаРасчетныйСчет`) -
      заготовка перебирает известные префиксы, при неудаче ищет похожие по `ПОДОБНО`.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      Конфигурация = Конв.Источник;  // или Конв.Приемник
      ИмяКороткое = "<ПОДСТАВИТЬ:ИмяОбъектаБезПрефикса>";
      Текст = "";
      Префиксы = СтрРазделить("СправочникСсылка,ДокументСсылка,ПеречислениеСсылка,ПланСчетовСсылка,ПланВидовХарактеристикСсылка", ",");
      Для Каждого Преф Из Префиксы Цикл
          Объ = Справочники.Объекты.НайтиПоНаименованию(Преф + "." + ИмяКороткое, Истина, , Конфигурация);
          Если НЕ Объ.Пустая() Тогда
              Текст = Текст + Строка(Объ) + " |UUID=" + XMLСтрока(Объ) + ПС;
          КонецЕсли;
      КонецЦикла;
      Если ПустаяСтрока(Текст) Тогда
          Запрос = Новый Запрос;
          Запрос.Текст = "ВЫБРАТЬ Наименование КАК Нм ИЗ Справочник.Объекты ГДЕ Владелец = &Конф И Наименование ПОДОБНО &Шбл";
          Запрос.УстановитьПараметр("Конф", Конфигурация);
          Запрос.УстановитьПараметр("Шбл", "%" + ИмяКороткое + "%");
          Выб = Запрос.Выполнить().Выбрать();
          Пока Выб.Следующий() Цикл
              Текст = Текст + "похожее: " + Выб.Нм + ПС;
          КонецЦикла;
      КонецЕсли;
      Результат = ?(ПустаяСтрока(Текст), "НЕ найдено: " + ИмяКороткое, Текст);
      ```
      
      Смежное: `Свойства` ищутся по КОРОТКОМУ имени реквизита с Владельцем-Объектом
      (`НайтиПоНаименованию("ИНН", Истина, , Объект)` - Владелец 4-й параметр,
      3-й Родитель пропускается). Поиск ПКО по полю `Код` (строка фиксированной длины
      с trailing-пробелами) - только `Код ПОДОБНО &Шаблон` с `Шаблон = Имя + "%"`.
      
      ---
      
      ## 6. Установка флага у ПКО (массово по списку типов)
      
      **Когда использовать:** включить/снять поведенческий флаг ПКО - `НеЗамещать`,
      `СинхронизироватьПоИдентификатору`,
      `ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли`,
      `НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска`,
      `ИспользоватьБыстрыйПоискПриЗагрузке` и другие boolean-реквизиты
      (полный список - architecture.md). Имя флага подставляется ТЕКСТУАЛЬНО -
      индексатор по строке у объектов не работает.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      Типы = Новый Массив;
      Типы.Добавить("<ПОДСТАВИТЬ:ТипИсточникаПКО>");  // например "СправочникСсылка.Контрагенты"; добавить нужные
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Сс, Источник КАК Ист ИЗ Справочник.ПравилаКонвертацииОбъектов ГДЕ Владелец = &Конв И НЕ ПометкаУдаления";
      Запрос.УстановитьПараметр("Конв", Конв);
      Выб = Запрос.Выполнить().Выбрать();
      Текст = "";
      Счет = 0;
      Пока Выб.Следующий() Цикл
          Если Типы.Найти(Строка(Выб.Ист)) = Неопределено Тогда
              Продолжить;
          КонецЕсли;
          Объект = Выб.Сс.ПолучитьОбъект();
          Объект.<ПОДСТАВИТЬ:ИмяФлага> = Истина;
          Объект.Записать();
          Счет = Счет + 1;
          Текст = Текст + "OK: " + Строка(Выб.Ист) + ПС;
      КонецЦикла;
      Результат = Текст + "ИТОГО изменено ПКО: " + Строка(Счет);
      ```
      
      Для одного ПКО по наименованию - вместо запроса:
      `Объект = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("...", Истина, , Конв).ПолучитьОбъект();`.
      
      ---
      
      ## 7. Создание/правка ПКС со ссылкой на Свойство
      
      **Когда использовать:** добавить или поправить правило свойства. ОБЯЗАТЕЛЬНО
      через ссылки `Справочник.Свойства` (текстовые имена без ссылок КД сбрасывает
      в пустые - troubleshooting.md "Программное создание ПКС"). Идемпотентно:
      существующая ПКС правится, не дублируется.
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      ИмяИст = "<ПОДСТАВИТЬ:ИмяРеквизитаИсточника>";
      ИмяПрм = "<ПОДСТАВИТЬ:ИмяРеквизитаПриемника>";
      СвИст = Справочники.Свойства.НайтиПоНаименованию(ИмяИст, Истина, , ПКО.Источник);
      СвПрм = Справочники.Свойства.НайтиПоНаименованию(ИмяПрм, Истина, , ПКО.Приемник);
      Если СвИст.Пустая() ИЛИ СвПрм.Пустая() Тогда
          ВызватьИсключение "Свойство не найдено в теневой модели: ист_пусто=" + Строка(СвИст.Пустая()) + " прм_пусто=" + Строка(СвПрм.Пустая());
      КонецЕсли;
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.ПравилаКонвертацииСвойств ГДЕ Владелец = &ПКО И ИмяПриемника = &Имя И НЕ ПометкаУдаления";
      Запрос.УстановитьПараметр("ПКО", ПКО);
      Запрос.УстановитьПараметр("Имя", ИмяПрм);
      Выб = Запрос.Выполнить().Выбрать();
      Если Выб.Следующий() Тогда
          ПКС = Выб.Ссылка.ПолучитьОбъект();
      Иначе
          ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
          ПКС.Владелец = ПКО;
      КонецЕсли;
      ПКС.Источник = СвИст;
      ПКС.Приемник = СвПрм;
      // ПКС.ПравилоКонвертации = <ссылка на ПКО>;  // только для ссылочного типа реквизита
      // ПКС.Поиск = Истина;                        // только для поля поиска НСИ
      // ПКС.АлгоритмПередВыгрузкойСвойства = "Значение = ...;";  // если нужен алгоритм
      ПКС.Записать();  // ПередЗаписью сам заполнит Имя/Тип/Вид/Наименование/Порядок из ссылок
      Если ПустаяСтрока(ПКС.ИмяПриемника) Тогда
          ВызватьИсключение "ПКС записалась мусором (пустое ИмяПриемника) - свойство не резолвится";
      КонецЕсли;
      Результат = "OK " + Строка(ПКС.Ссылка) + " |" + ПКС.ИмяИсточника + " -> " + ПКС.ИмяПриемника;
      ```
      
      ПКС табличной части - через `СоздатьГруппу()` вместо `СоздатьЭлемент()`
      (`ЭтоГруппа` напрямую присвоить нельзя, см. troubleshooting.md).
      
      ---
      
      ## 8. ПКС поиска по реквизиту-ГУИД на все НСИ-ПКО (массово)
      
      **Когда использовать:** обеспечить поиск существующих элементов НСИ в приемнике
      по бизнес-ключу (реквизит-ГУИД) сразу для всех справочников конвертации.
      См. идиому И3 и troubleshooting.md "Поиск НСИ по ГУИД".
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ИмяГУИД = "<ПОДСТАВИТЬ:ИмяРеквизитаГУИД>";
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ Ссылка КАК Сс, Источник КАК Ист, Приемник КАК Прм, Наименование КАК Имя ИЗ Справочник.ПравилаКонвертацииОбъектов ГДЕ Владелец = &Конв И НЕ ПометкаУдаления И ТипПриемника ПОДОБНО ""СправочникСсылка%""";
      Запрос.УстановитьПараметр("Конв", Конв);
      Выб = Запрос.Выполнить().Выбрать();
      Создано = 0;
      Лог = "";
      Пока Выб.Следующий() Цикл
          СвИст = Справочники.Свойства.НайтиПоНаименованию(ИмяГУИД, Истина, , Выб.Ист);
          СвПрм = Справочники.Свойства.НайтиПоНаименованию(ИмяГУИД, Истина, , Выб.Прм);
          Если СвИст.Пустая() ИЛИ СвПрм.Пустая() Тогда
              Лог = Лог + " SKIP[" + Выб.Имя + "]";
              Продолжить;
          КонецЕсли;
          ЗапросД = Новый Запрос;
          ЗапросД.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.ПравилаКонвертацииСвойств ГДЕ Владелец = &ПКО И ИмяПриемника = &Имя";
          ЗапросД.УстановитьПараметр("ПКО", Выб.Сс);
          ЗапросД.УстановитьПараметр("Имя", ИмяГУИД);
          Если ЗапросД.Выполнить().Выбрать().Следующий() Тогда
              Лог = Лог + " EXISTS[" + Выб.Имя + "]";
              Продолжить;
          КонецЕсли;
          ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
          ПКС.Владелец = Выб.Сс;
          ПКС.Источник = СвИст;
          ПКС.Приемник = СвПрм;
          ПКС.Поиск = Истина;
          ПКС.Записать();
          Создано = Создано + 1;
          Лог = Лог + " OK[" + Выб.Имя + "]";
      КонецЦикла;
      Результат = "Создано ПКС поиска=" + Строка(Создано) + " |" + Лог;
      ```
      
      После - проверить на тех же ПКО связку `СинхронизироватьПоИдентификатору` /
      `ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли` (заготовки 1 и 6),
      иначе поиск по ГУИД не сработает.
      
      ---
      
      ## 9. Создание ПКО пачкой с НСИ-пресетом
      
      **Когда использовать:** развернуть каркас правил - несколько ПКО за один вызов.
      Пресет НСИ (искать существующие, не создавать, не замещать) или документ
      (быстрый поиск). Одиночное ПКО с ручным заполнением - SKILL.md операция 3.
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      Список = Новый Массив;
      // Имя ПКО, полный тип (совпадает у источника и приемника), порядок, НСИ-пресет
      Список.Добавить(Новый Структура("Имя,Тип,Порядок,НСИ", "<ПОДСТАВИТЬ:ИмяПКО>", "<ПОДСТАВИТЬ:ПолныйТип>", 100, Истина));
      // ... добавить строки по числу ПКО
      Создано = 0;
      Пропущено = 0;
      Лог = "";
      Для Каждого Эл Из Список Цикл
          ОбъИст = Справочники.Объекты.НайтиПоНаименованию(Эл.Тип, Истина, , Конв.Источник);
          ОбъПр  = Справочники.Объекты.НайтиПоНаименованию(Эл.Тип, Истина, , Конв.Приемник);
          Если ОбъИст.Пустая() ИЛИ ОбъПр.Пустая() Тогда
              Пропущено = Пропущено + 1;
              Лог = Лог + " NO_META[" + Эл.Имя + "]";
              Продолжить;
          КонецЕсли;
          Существ = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию(Эл.Имя, Истина, , Конв);
          Если НЕ Существ.Пустая() Тогда
              Пропущено = Пропущено + 1;
              Продолжить;
          КонецЕсли;
          ПКО = Справочники.ПравилаКонвертацииОбъектов.СоздатьЭлемент();
          ПКО.Владелец = Конв;
          ПКО.Наименование = Эл.Имя;
          ПКО.Источник = ОбъИст;
          ПКО.Приемник = ОбъПр;
          ПКО.Порядок = Эл.Порядок;
          Если Эл.НСИ Тогда
              ПКО.НеЗамещать = Истина;
              ПКО.НеВыгружатьОбъектыСвойствПоСсылкам = Истина;
              ПКО.НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска = Истина;
          Иначе
              ПКО.ИспользоватьБыстрыйПоискПриЗагрузке = Истина;
          КонецЕсли;
          ПКО.Записать();  // Код не задавать - сгенерируется сам (troubleshooting.md)
          Создано = Создано + 1;
          Лог = Лог + " OK[" + Эл.Имя + "]";
      КонецЦикла;
      Результат = "Создано=" + Строка(Создано) + " Пропущено=" + Строка(Пропущено) + " |" + Лог;
      ```
      
      ---
      
      ## 10. Upsert ПКЗ с гарантией Значений
      
      **Когда использовать:** добавить/обновить маппинги значений перечислений.
      Заготовка сама досоздает недостающие записи `Справочник.Значения` (теневая
      модель метаданных нередко отстает от живой конфигурации). У перечислений
      Владелец Значения = сам Объект-перечисление (2 уровня, troubleshooting.md).
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      Если ПКО.Пустая() Тогда
          ВызватьИсключение "ПКО-перечисление не найдено";
      КонецЕсли;
      Пары = Новый Массив;
      // формат: "ИмяЗначенияИсточника|ИмяЗначенияПриемника"
      Пары.Добавить("<ПОДСТАВИТЬ:ИмяИст>|<ПОДСТАВИТЬ:ИмяПрм>");
      // ... добавить пары
      Текст = "";
      Для Каждого Пара Из Пары Цикл
          Поз = СтрНайти(Пара, "|");
          ИмяИст = Лев(Пара, Поз - 1);
          ИмяПрм = Сред(Пара, Поз + 1);
          ЗнИст = Справочники.Значения.НайтиПоНаименованию(ИмяИст, Истина, , ПКО.Источник);
          Если ЗнИст.Пустая() Тогда
              НЗ = Справочники.Значения.СоздатьЭлемент();
              НЗ.Владелец = ПКО.Источник;
              НЗ.Наименование = ИмяИст;
              НЗ.Записать();
              ЗнИст = НЗ.Ссылка;
              Текст = Текст + "+Значение ист: " + ИмяИст + ПС;
          КонецЕсли;
          ЗнПрм = Справочники.Значения.НайтиПоНаименованию(ИмяПрм, Истина, , ПКО.Приемник);
          Если ЗнПрм.Пустая() Тогда
              НЗ = Справочники.Значения.СоздатьЭлемент();
              НЗ.Владелец = ПКО.Приемник;
              НЗ.Наименование = ИмяПрм;
              НЗ.Записать();
              ЗнПрм = НЗ.Ссылка;
              Текст = Текст + "+Значение прм: " + ИмяПрм + ПС;
          КонецЕсли;
          Запрос = Новый Запрос;
          Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.ПравилаКонвертацииЗначений ГДЕ Владелец = &ПКО И Источник = &Ист";
          Запрос.УстановитьПараметр("ПКО", ПКО);
          Запрос.УстановитьПараметр("Ист", ЗнИст);
          Выб = Запрос.Выполнить().Выбрать();
          Если Выб.Следующий() Тогда
              ПКЗ = Выб.Ссылка.ПолучитьОбъект();
          Иначе
              ПКЗ = Справочники.ПравилаКонвертацииЗначений.СоздатьЭлемент();
              ПКЗ.Владелец = ПКО;
              ПКЗ.Источник = ЗнИст;
          КонецЕсли;
          ПКЗ.Приемник = ЗнПрм;
          ПКЗ.ЗначениеИсточник = ИмяИст;
          ПКЗ.ЗначениеПриемник = ИмяПрм;
          ПКЗ.Наименование = ИмяИст + " --> " + ИмяПрм;
          ПКЗ.Записать();
          Текст = Текст + "OK " + ИмяИст + " -> " + ИмяПрм + ПС;
      КонецЦикла;
      Результат = Текст;
      ```
      
      ---
      
      ## 11. Замена маркированного блока в обработчике ПКО
      
      **Когда использовать:** итеративная доработка алгоритма события (вставка/замена
      своего блока кода) без риска затереть остальной обработчик. Блок обрамляется
      маркерами; повторный запуск заменяет блок целиком. Текущий текст смотреть
      заготовкой 4.
      
      ```bsl
      ПС = Символы.ПС;
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("<ПОДСТАВИТЬ:НаименованиеПКО>", Истина, , Конв);
      Если ПКО.Пустая() Тогда
          ВызватьИсключение "ПКО не найдено";
      КонецЕсли;
      МаркерСтарт = "//{++ <ПОДСТАВИТЬ:МеткаЗадачи>";
      МаркерКонец = "//}-- <ПОДСТАВИТЬ:МеткаЗадачи>";
      НовыйБлок = "<ПОДСТАВИТЬ:КодВставки>";  // многострочный код собирать конкатенацией через ПС
      Об = ПКО.ПолучитьОбъект();
      Алг = Об.АлгоритмПослеЗагрузкиОбъекта;  // или другое поле события из заготовки 4
      Поз1 = СтрНайти(Алг, МаркерСтарт);
      Если Поз1 = 0 Тогда
          Об.АлгоритмПослеЗагрузкиОбъекта = Алг + ПС + МаркерСтарт + ПС + НовыйБлок + ПС + МаркерКонец;
      Иначе
          Поз2 = СтрНайти(Алг, МаркерКонец);
          Если Поз2 = 0 Тогда
              ВызватьИсключение "Маркер конца не найден - блок поврежден, разобраться вручную";
          КонецЕсли;
          Об.АлгоритмПослеЗагрузкиОбъекта = Лев(Алг, Поз1 - 1) + МаркерСтарт + ПС + НовыйБлок + ПС + Сред(Алг, Поз2);
      КонецЕсли;
      Об.Записать();
      Результат = "OK, длина обработчика: " + Строка(СтрДлина(Об.АлгоритмПослеЗагрузкиОбъекта));
      ```
      
      ---
      
      ## 12. Выгрузка комплекта правил в XML (ВыгрузкаКонвертации)
      
      **Когда использовать:** финальная выгрузка ПОЛНОГО комплекта для БСП-обмена
      (ExchangeRules + CorrespondentExchangeRules + RegistrationRules, zip).
      Простая выгрузка одной конвертации без комплекта - SKILL.md операция 5.
      Заглушка прогрессора для комплекта ОБЯЗАТЕЛЬНА (troubleshooting.md
      "Переменная мФормаПрогрессора").
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяКонвертации>");
      КонвВстречная = Справочники.Конвертации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяВстречнойКонвертации>");
      Рег = Справочники.Регистрации.НайтиПоНаименованию("<ПОДСТАВИТЬ:ИмяРегистрации>");
      Если Конв.Пустая() ИЛИ Рег.Пустая() ИЛИ КонвВстречная.Пустая() Тогда
          ВызватьИсключение "Не найдено: Конв_пусто=" + Строка(Конв.Пустая()) + " Рег_пусто=" + Строка(Рег.Пустая())
              + " Встречная_пусто=" + Строка(КонвВстречная.Пустая());
      КонецЕсли;
      Обр = Обработки.ВыгрузкаКонвертации.Создать();
      Обр.мФормаПрогрессора = Новый Структура("Значение, КомментарийЗначения, МаксимальноеЗначение, КомментарийОбработкиДанных", 0, "", 0, "");
      Обр.КонвертацияДляВыгрузки = Конв;
      Обр.ВыгружатьПравилаКорреспондента = Истина;
      Обр.КонвертацияКорреспондентДляВыгрузки = КонвВстречная;  // встречная конвертация парного обмена (НЕ та же, что КонвертацияДляВыгрузки)
      Обр.ВыгружатьПравилаРегистрации = Истина;
      Обр.РегистрацияДляВыгрузки = Рег;
      Обр.СжиматьФайлПравил = Истина;  // комплект = zip из 3 файлов
      Обр.ИмяФайлаПравил = "<ПОДСТАВИТЬ:ПутьКФайлу.zip>";  // каталог должен существовать
      Обр.ВыполнитьВыгрузкуПравил();
      Файл = Новый Файл(Обр.ИмяФайлаПравил);
      Результат = "OK path=" + Обр.ИмяФайлаПравил + " size=" + Строка(Файл.Размер());
      ```
      
      ---
      
      ## Идиомы передачи значений через ПКС
      
      ### И1. Значение перечисления - строкой-именем, без ПКО и ПКЗ
      
      **Когда использовать:** реквизит приемника - перечисление, соответствие
      вычислимо кодом или имена значений совпадают (тождественные перечисления).
      
      В `АлгоритмПередВыгрузкойСвойства` присвоить `Значение` СТРОКУ - имя значения
      перечисления приемника:
      
      ```bsl
      Значение = "ОплатаПокупателя";  // имя значения в перечислении ПРИЕМНИКА
      ```
      
      КД при загрузке сама подставит значение по имени в перечислении из типа
      реквизита-приемника. `ПравилоКонвертации` у ПКС оставить ПУСТЫМ - для
      тождественных перечислений ПКО-перечисление и ПКЗ не нужны. ПКО+ПКЗ нужны
      только для табличного N:M маппинга без вычислимой логики. Развернутый пример:
      troubleshooting.md, раздел "Передача значения перечисления приемника без ПКО".
      
      ### И2. Строка в ссылочный реквизит - только через строку-прокси
      
      **Когда использовать:** на выгрузке известна строка (имя, код, представление),
      а реквизит приемника - ссылка на справочник/ПВХ приемной базы.
      
      Напрямую НЕЛЬЗЯ: подстановка по имени работает только для перечислений (И1).
      Для прочих ссылочных типов КД ожидает либо ПКО (выгрузка объекта по правилу),
      либо поля поиска. Паттерн "строка-прокси с последующим резолвом":
      
      1. На выгрузке ПКС кладет строку в СТРОКОВЫЙ реквизит-прокси приемника
         (служебный реквизит или временно свободное строковое поле с
         маркером-префиксом, чтобы отличить от штатного содержимого).
      2. В `АлгоритмПослеЗагрузкиОбъекта` ПКО приемника строка резолвится в ссылку
         (`НайтиПоНаименованию` / `НайтиПоКоду` / `Перечисления.Х[Имя]` в Попытке)
         и прокси-поле очищается.
      
      Пример: вид операции документа передается строкой в свободном реквизите
      `КодВалютнойОперации = "ВидОп:<ИмяЗначения>"`; обработчик ПослеЗагрузки парсит
      префикс `ВидОп:`, ставит `Объект.ВидОперации = Перечисления.Х[Имя]` в Попытке
      и очищает `КодВалютнойОперации`.
      
      ### И3. Поиск НСИ - по реквизиту-ГУИД, не по внутреннему GUID ссылки
      
      **Когда использовать:** НСИ в базах ведется независимо, нужен поиск
      существующих элементов приемника без создания новых.
      
      Правильно: ПКС по реквизиту-ГУИД с `Поиск = Истина` (заготовка 8) + НСИ-пресет
      ПКО (заготовка 9). НЕ полагаться на внутренний GUID ссылки
      (`СинхронизироватьПоИдентификатору`): при независимом ведении НСИ внутренние
      GUID в базах РАЗНЫЕ, а поиск по идентификатору без флага
      `ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли` перебивает поля
      поиска - объект "не находится". Матрица поведения флагов и фикс:
      troubleshooting.md, разделы "Поиск НСИ по ГУИД" и "Объекты НЕ находятся при
      загрузке".
      
    • methods.md 12.7 KB
      # Экспортные методы обработок КД 2.0
      
      Все методы в модулях объектов обработок (`src/DataProcessors/<Имя>/Ext/ObjectModule.bsl`)
      в выгрузке `<каталог выгрузки КД>\src\`. Контекст вызова через `execute_code`
      MCP-toolkit работает без явного `execution_context` для всех методов ниже
      (toolkit живет в клиентском контексте 1С).
      
      ## Выгрузка правил в XML
      
      ### `Обработки.ВыгрузкаКонвертации.ВыполнитьВыгрузкуПравил()`
      
      - file: `src/DataProcessors/ВыгрузкаКонвертации/Ext/ObjectModule.bsl:1898`
      - Главная точка выгрузки правил конвертации в XML.
      
      #### Реквизиты обработки
      
      | Реквизит | Тип | Назначение |
      |---|---|---|
      | КонвертацияДляВыгрузки | CatalogRef.Конвертации | **Обязательно** - ссылка на конвертацию |
      | ИмяФайлаПравил | string | **Обязательно** - путь к выходному XML (если `СжиматьФайлПравил=true`, расширение `.zip`) |
      | СжиматьФайлПравил | boolean | Если `true` - архивирует выход в .zip |
      | ВыгружатьПравилаКорреспондента | boolean | Парный обмен (2 конвертации в одном файле) |
      | КонвертацияКорреспондентДляВыгрузки | CatalogRef.Конвертации | Если `ВыгружатьПравилаКорреспондента=true` |
      | ВыгружатьПравилаРегистрации | boolean | Включить правила регистрации в файл |
      | РегистрацияДляВыгрузки | CatalogRef.Регистрации | Если `ВыгружатьПравилаРегистрации=true` |
      | ИмяФайлаМодуляВыгрузки | string | Опционально - путь к .txt с модулем обработчиков выгрузки (для отладки) |
      | ИмяФайлаМодуляЗагрузки | string | То же для модуля загрузки |
      | ИмяФайлаОбработчиковВыгрузки | string | Опционально |
      | ИмяФайлаОбработчиковЗагрузки | string | Опционально |
      | РежимСохраненияВерсии | decimal | Версия формата (обычно по умолчанию) |
      
      #### Минимальный BSL
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("Имя_Конвертации");
      Если Конв.Пустая() Тогда
          ВызватьИсключение "Конвертация не найдена";
      КонецЕсли;
      
      Обр = Обработки.ВыгрузкаКонвертации.Создать();
      Обр.КонвертацияДляВыгрузки         = Конв;
      Обр.ИмяФайлаПравил                 = "C:\Output\rules.xml";
      Обр.СжиматьФайлПравил              = Ложь;
      Обр.ВыгружатьПравилаКорреспондента = Ложь;
      Обр.ВыгружатьПравилаРегистрации    = Ложь;
      Обр.ВыполнитьВыгрузкуПравил();
      
      Файл = Новый Файл(Обр.ИмяФайлаПравил);
      Результат = Новый Структура("ok,path,size", Истина, Обр.ИмяФайлаПравил, Файл.Размер());
      ```
      
      ### Прочие экспортные методы `ВыгрузкаКонвертации`
      
      | Метод | file:line | Назначение |
      |---|---|---|
      | `ВыполнитьВыгрузкуМодуляОбработкиВыгрузки()` | `:2009` | Выгрузить текст модуля обработчиков выгрузки в .txt |
      | `ВыполнитьВыгрузкуМодуляОбработкиЗагрузки()` | `:2152` | То же для модуля загрузки |
      | `ВыгрузитьОбработчикиВКаталог(КаталогДляВыгрузки)` | `:2390` | Выгрузка всех обработчиков |
      | `ПроверитьНаличиеКаталога(ИмяКаталога, ПроверятьЧтоНайденныйФайлЭтоКаталог=Ложь)` | `:2223` | Утилита |
      
      ## Загрузка правил из XML
      
      ### `Обработки.ЗагрузкаКонвертации.ЗагрузитьПравилаОбмена(Источник="", ТипИсточника="XMLФайл")`
      
      - file: `src/DataProcessors/ЗагрузкаКонвертации/Ext/ObjectModule.bsl:1340`
      - Главная точка входа загрузки правил в КД.
      
      #### Минимальный BSL
      
      ```bsl
      Обр = Обработки.ЗагрузкаКонвертации.Создать();
      // перед вызовом могут потребоваться доп. реквизиты - проверить XML обработки
      Обр.ЗагрузитьПравилаОбмена("C:\Input\rules.xml", "XMLФайл");
      ```
      
      ### Прочие экспортные методы `ЗагрузкаКонвертации`
      
      | Метод | file:line | Назначение |
      |---|---|---|
      | `ПолучитьРеквизитыКонвертации(ИмяФайла)` | `:1642` | Превью реквизитов XML до полной загрузки |
      | `Сохранить(ФлагВариантЗагрузкиКонвертации, ФлагНовыйИсточник, ФлагНовыйПриемник)` | `:2473` | Финальное сохранение после `ЗагрузитьПравилаОбмена` |
      | `ПолучитьПолноеИмяФайла(ИмяКаталога, ИмяФайла)` | `:1583` | Утилита |
      | `ИнициализацияТаблицыПКС(Таб)` | `:1812` | Утилита |
      | `ИнициализацияТаблицыПКЗ(Таб)` | `:1873` | Утилита |
      | `ИнициализацияОбъектов(КонфигурацияИсточник, КонфигурацияПриемник)` | `:2045` | Утилита |
      
      ## Метаданные конфигураций
      
      ### `Обработки.ВыгрузкаМетаданных.ВыполнитьВыгрузку()`
      
      - file: `src/DataProcessors/ВыгрузкаМетаданных/Ext/ObjectModule.bsl:28`
      - **Запускается в ИБ источника/приемника**, не в КД. Создает XML с описанием
        метаданных текущей конфигурации (для последующей загрузки в КД через
        `ЗагрузкаСтруктурыМетаданных`).
      
      #### Реквизиты (через переменные модуля и реквизиты обработки)
      
      | Реквизит | Тип |
      |---|---|
      | ИмяФайлаВыгрузки | string |
      | НеВыгружатьРегистрыСведений | boolean |
      | НеВыгружатьРегистрыНакопления | boolean |
      | НеВыгружатьРегистрыБухгалтерии | boolean |
      
      #### Минимальный BSL (в ИБ источника)
      
      ```bsl
      Обр = Обработки.ВыгрузкаМетаданных.Создать();
      Обр.ИмяФайлаВыгрузки = "C:\Output\metadata_source.xml";
      Обр.НеВыгружатьРегистрыНакопления = Ложь;
      Обр.ВыполнитьВыгрузку();
      ```
      
      ### `Обработки.ЗагрузкаСтруктурыМетаданных.ВыполнитьЗагрузку()`
      
      - file: `src/DataProcessors/ЗагрузкаСтруктурыМетаданных/Ext/ObjectModule.bsl:19`
      - Загружает XML метаданных в КД. Создает элемент `Конфигурации` + подчиненные
        `Объекты`/`Свойства`/`Значения`.
      - Модуль помечен `#Если Клиент Тогда`, но через MCP-toolkit вызывается без
        проблем (ошибка возникает только если файл не существует - значит метод
        отработал до открытия файла).
      
      #### Параметры (через переменные модуля)
      
      | Переменная | Тип | Назначение |
      |---|---|---|
      | мЗагрузитьНовую | boolean | true - создать новую Конфигурации, false - обновить существующую |
      | мКонфигурация | CatalogRef.Конфигурации | Ссылка на существующую конфигурацию (если `мЗагрузитьНовую=false`) |
      | мКомментарий | string | Комментарий к загрузке |
      | ИмяФайлаЗагрузки | string | Путь к XML файлу метаданных |
      
      #### Использует `ВыполнятьЗагрузкуСтруктурыВОднойТранзакции` для атомарной загрузки.
      
      #### Минимальный BSL
      
      ```bsl
      Обр = Обработки.ЗагрузкаСтруктурыМетаданных.Создать();
      Обр.ИмяФайлаЗагрузки = "C:\Input\metadata_source.xml";
      Обр.мЗагрузитьНовую  = Истина;
      Обр.мКомментарий     = "Загрузка БП КОРП v3.0.189.29";
      Рез = Обр.ВыполнитьЗагрузку();
      Результат = ?(Рез = Ложь, "ошибка загрузки", "ok");
      ```
      
      ## Регистрация
      
      ### `Обработки.ВыгрузкаРегистрации.ВыполнитьВыгрузкуПравил()`
      
      - file: `src/DataProcessors/ВыгрузкаРегистрации/Ext/ObjectModule.bsl:25`
      - Выгрузка правил регистрации в XML.
      
      #### Реквизиты обработки
      
      | Реквизит | Тип |
      |---|---|
      | РегистрацияДляВыгрузки | CatalogRef.Регистрации |
      | ИмяФайлаПравил | string |
      
      #### Альтернатива
      
      | Метод | file:line | Назначение |
      |---|---|---|
      | `ВыгрузитьРегистрацию()` | `:67` | Альтернативный путь выгрузки (использует `мЗаписьXML`, может вызываться извне с уже открытым XML-стримом) |
      
      ### `Обработки.ЗагрузкаРегистрации.ВыполнитьЗагрузкуРегистрации()`
      
      - file: `src/DataProcessors/ЗагрузкаРегистрации/Ext/ObjectModule.bsl:57`
      
      | Метод | file:line | Назначение |
      |---|---|---|
      | `ПолучитьДанныеРегистрацииИзФайла()` | `:96` | Превью данных регистрации до полной загрузки |
      
      ## Автонастройка правил
      
      Полезно после загрузки метаданных источника и приемника - быстро создать
      "каркас" правил по совпадающим именам.
      
      | Обработка | Назначение |
      |---|---|
      | `АвтонастройкаПравилКонвертацииОбъектов` | ПКО по совпадающим именам объектов |
      | `АвтонастройкаПравилКонвертацииСвойств` | ПКС внутри ПКО по совпадающим именам реквизитов |
      | `АвтонастройкаПравилКонвертацииЗначений` | ПКЗ по совпадающим именам значений |
      
      Конкретные методы и реквизиты - смотри XML обработок в `src/DataProcessors/Автонастройка*/`.
      
      ## Обработчики (текстовые алгоритмы событий)
      
      | Обработка | Назначение |
      |---|---|
      | `ВыгрузкаОбработчиков` | Выгрузить тексты всех алгоритмов событий в .txt (для редактирования в IDE) |
      | `ЗагрузкаОбработчиков` | Загрузить отредактированный файл обратно |
      
      ## Прочие обработки
      
      | Обработка | Назначение |
      |---|---|
      | `ВыгрузкаЗагрузкаДанныхXML` | Универсальная выгрузка/загрузка данных по правилам (используется при тестовом обмене) |
      | `ПанельФункций` | Главное окно UI КД (не для программного вызова) |
      | `БыстроеОсвоение` | Помощник в UI |
      | `ГрупповаяОбработкаСправочниковИДокументов` | Утилита |
      
    • troubleshooting.md 49.5 KB
      # Типичные ошибки и ограничения
      
      ## Транспорт: curl, не urllib (Windows)
      
      Python `urllib.request` на примитивном HTTP-сервере toolkit рвет соединение
      при чтении заголовков ответа (`ConnectionResetError 10054`), даже на тривиальном
      коде. curl - толерантнее и работает. Надежный паттерн: Python формирует JSON
      (`json.dumps(ensure_ascii=False)` - корректное экранирование кириллицы) во
      временный UTF-8 файл, отправка через `curl --data-binary @file`. Готовый helper:
      `<каталог выгрузки КД>\tools\kd_exec.py` (`python kd_exec.py code < file.bsl`).
      
      ## execute_code = Выполнить(): только операторы
      
      `execute_code` исполняет код через `Выполнить()`. Это значит:
      
      - **НЕЛЬЗЯ объявлять `Функция`/`Процедура`** - ошибка "Ожидается последовательность
        операторов" в (1,1). Только линейный код + циклы. Хелперы разворачивать в цикл
        по массиву структур, не в функцию.
      - **`СокрЛП` в языке запросов недоступен** - в запросе нет функций trim. Для совпадения
        с полем фиксированной длины (например `Код` справочника КД) использовать `Код ПОДОБНО &Шаблон`
        с `Шаблон = ИскомоеИмя + "%"`.
      - Возврат результата - через переменную `Результат` (toolkit ее сериализует).
        `Возврат` на верхнем уровне недопустим (не функция).
      - **Весь типовой код платформы доступен в BSL-коде execute_code**: `СтрРазделить`,
        `СтрСоединить`, `СтрНайти`, `СтрЗаменить`, `СтрДлина` и пр. работают, несмотря на
        режим совместимости 8.2.13. Не строить "обходные" парсеры через `Найти + Лев + Сред`,
        когда есть готовое. Ошибка "Процедура или функция с указанным именем не определена"
        на типовой функции - почти всегда признак незапущенного или неотвечающего toolkit-а
        (curl возвращает ошибку компиляции), а НЕ отсутствия функции. См. диагностику ниже.
      
      ### Диагностика "функция не определена" в execute_code
      
      Перед выводом "функция недоступна в КД" проверить, что MCP toolkit запущен:
      
      ```bash
      curl -s --noproxy localhost http://localhost:7003/health  # должен вернуть статус
      ```
      
      Если toolkit не отвечает (`Connection refused`, пустой ответ, тайм-аут) или возвращает
      странные ошибки на простом коде - запустить 1С с обработкой `MCP_Toolkit.epf` через
      скрипт `scripts/start-1c.ps1` скилла `1c-mcp-toolkit`. **Только** после этого делать
      выводы о доступности типовых функций.
      
      ## Неявная транзакция toolkit - откат при любой ошибке
      
      Toolkit оборачивает `Выполнить()` в транзакцию. Если код упал на ЛЮБОЙ строке
      (даже после цикла записи, напр. на `СтрСоединить`) - **все `Записать()` в этом
      вызове откатываются**. Поэтому частичных записей не остается: при ошибке смотри
      ноль созданных объектов, исправляй и запускай заново целиком. Делать скрипты
      идемпотентными (проверка `НайтиПоНаименованию` перед созданием).
      
      ## Имена объектов/свойств в КД хранятся с ПРЕФИКСОМ типа
      
      В `Справочник.Объекты` поле `Наименование` = полное имя типа: `ДокументСсылка.ПоступлениеНаРасчетныйСчет`,
      `СправочникСсылка.Контрагенты`, `ПеречислениеСсылка.ВидыОперацийСписаниеДенежныхСредств`,
      `ПланСчетовСсылка.Хозрасчетный`. Поле `Имя` = короткое (`ПоступлениеНаРасчетныйСчет`).
      `НайтиПоНаименованию` искать по ПОЛНОМУ имени с префиксом, иначе вернет пусто. То же для типов в ПКО
      (`ТипИсточника`/`ТипПриемника`).
      
      ## Иерархия Значений: для перечислений короче, чем для документов
      
      - Документ/Справочник: `Значения.Владелец = Свойства`, `Свойства.Владелец = Объекты` (3 уровня до Объекта).
      - **Перечисление**: значения подчинены ОБЪЕКТУ-перечислению напрямую - `Значения.Владелец = Объекты`
        (2 уровня). Запрос значений перечисления: `ГДЕ Знач.Владелец = <Объект-перечисление>`.
        Обращение `Знач.Владелец.Владелец.Владелец` для перечисления упадет "Поле не найдено".
      
      ## Виды операций / ПКЗ (трансформация значений перечислений)
      
      Трансформация перечисления-источника в перечисление-приемник = **ПКО-перечисление + ПКЗ**:
      - ПКО: Источник=Объект-перечисление источника, Приемник=Объект-перечисление приемника.
      - ПКЗ (Владелец=ПКО-перечисление): `Источник`/`Приемник` = ссылки на `Значения`,
        `ЗначениеИсточник`/`ЗначениеПриемник` = строковые имена значений.
      - ПКС реквизита-перечисления в документе → `ПравилоКонвертации` = ПКО-перечисление (иначе значение не сконвертируется).
      - Если перечисления источника и приемника ТОЖДЕСТВЕННЫ (как в УХ и БП на одной платформе) - ПКЗ поле-в-поле
        по совпадению имен значений (автонастройка через Соответствие). Если РАЗНЫЕ (как УПП vs БП) - маппинг N→1.
      
      ## Поиск НСИ по ГУИД: Поиск=Истина, в XML `Поиск="true"`
      
      Для НСИ-справочников (поиск существующего элемента в приемнике, без создания) - ПКС с реквизитом-ГУИД
      (`Доп_НСИ_ГУИД`): Источник/Приемник=Свойство ГУИД, `Поиск=Истина`. В выгруженном XML атрибут английский -
      `<Свойство Поиск="true">`. Grep по "Истина" в XML НЕ найдет - искать `Поиск="true"`.
      ПКО НСИ при этом: `НеЗамещать=Истина`, `НеВыгружатьОбъектыСвойствПоСсылкам=Истина`,
      `НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска=Истина`.
      
      ## Объекты НЕ находятся при загрузке: связка СинхронизироватьПоИдентификатору + ПродолжитьПоиск
      
      Симптом: документ загрузился, но его ссылочные реквизиты (Контрагент, Договор, Организация,
      Валюта, СтатьяДДС, банк/счет) = "Объект не найден", ХОТЯ в ПКО справочника заданы поля поиска
      по бизнес-ключу (ПКС с `Поиск=Истина` по `Доп_НСИ_ГУИД`, см. секцию "Поиск НСИ по ГУИД" выше).
      
      Причина: два реквизита ПКО управляют ПОРЯДКОМ поиска объекта в приемнике, и поиск по
      внутреннему идентификатору ПЕРЕБИВАЕТ поля поиска:
      
      | СинхронизироватьПоИдентификатору | ПродолжитьПоиск...ЕслиПоИдентификаторуНеНашли | Поведение |
      |---|---|---|
      | Ложь | (неважно) | поиск ТОЛЬКО по полям поиска (ПКС с Поиск=Истина) - бизнес-ключ работает |
      | Истина | Ложь | поиск ТОЛЬКО по внутреннему GUID ссылки; не нашел - стоп, поля поиска НЕ используются |
      | Истина | Истина | поиск по GUID, не нашел - переход (fallback) на поля поиска |
      
      Внутренний GUID ссылки в источнике и приемнике РАЗНЫЙ, когда НСИ ведется независимо (не
      наполняется через этот обмен). Поэтому при `СинхронизироватьПоИдентификатору=Истина` без
      `ПродолжитьПоиск...` объект по GUID не находится, до полей поиска дело не доходит - "Объект
      не найден", хотя поля поиска заданы корректно.
      
      Фикс: на всех ПКО справочников НСИ с поиском по
      бизнес-ключу включить `ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли=Истина`
      (или вовсе снять `СинхронизироватьПоИдентификатору`, если синхронизация по внутреннему
      GUID не нужна). В выгруженном XML: `<ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли>true</...>`
      рядом с `<СинхронизироватьПоИдентификатору>true</...>`.
      
      ВАЖНО: правка флага ТОЛЬКО в макете/XML слетит при следующей выгрузке из КД. Флаг
      выставлять в САМОМ проекте КД - реквизит ПКО через UI ("Продолжить поиск по полям поиска,
      если по идентификатору объект не найден") или программно:
      
      ```bsl
      Объект = ПКО.Ссылка.ПолучитьОбъект();
      Объект.ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли = Истина;
      Объект.Записать();
      ```
      
      Тогда флаг попадет в каждую последующую выгрузку правил.
      
      ## Архитектура обмена КД 2.0: движения ОПЦИОНАЛЬНЫ; иначе документ ПРОВОДИТСЯ в приемнике
      
      Движения регистров передаются **опционально и явно**: для каждого ПКО документа можно указать, какие движения
      (по каким регистрам) и как передавать - в ПКО они задаются как **табличные части** (ПКС-группы по регистрам
      движений, рядом с ПКС реквизитов и табчастей самого документа). Два режима:
      - **Движения ВКЛЮЧЕНЫ в ПКО** → приемник получает готовые движения из обмена (документ можно не перепроводить).
      - **Движения НЕ включены** → они не передаются; документ загружается с `Объект.ОбменДанными.Загрузка = Истина`
        (запись без проведения), а ПОСЛЕ загрузки штатно ПРОВОДИТСЯ механизмом обмена → `ОбработкаПроведения`
        приемника формирует движения сама по своим счетам/виду операции.
      
      Если движения не передаем (например, УПП->БП - в ПКО только реквизиты + табчасти документа,
      регистров нет): обработчик `<ПослеЗагрузки>` ставит `ОбменДанными.Загрузка=Истина`, восстанавливает ключевые
      реквизиты (Контрагент из Договора, СтатьяДДС из табчасти), маркеры; счета НЕ переносим и НЕ заполняем вручную -
      приемник определит их при проведении по виду операции (поэтому важна трансформация вида операции через ПКЗ).
      Глобальные алгоритмы конвертации (`АлгоритмПослеЗагрузкиОбъекта/Данных`) обычно пустые - проведение делает
      механизм обмена.
      
      ## Ошибка: ТранспортСообщенийОбменаWS / DownloadData (FileExists)
      
      Причина известна - при повторном появлении НЕ переразбирать стек заново,
      сразу переходить к решению ниже.
      
      Симптом: обмен между базами (БСП, транспорт через веб-сервис) падает на этапе
      получения файла сообщения обмена. В стеке - модуль `ТранспортСообщенийОбменаWS`,
      операция `DownloadData`, падение на проверке/чтении файла (`FileExists`).
      
      Причина: в транспорт внесена оптимизация под LAN - когда источник и приемник
      видят общий файловый ресурс, файл сообщения обмена читается напрямую с диска,
      минуя веб-передачу. Когда файла по прямому пути нет (другая машина, шара
      недоступна, файл еще не создан) - прямое чтение падает на DownloadData/FileExists.
      
      Решение - graceful fallback вместо безусловного прямого чтения: проверка
      существования файла перед прямым чтением, при отсутствии - штатная передача
      через веб-сервис:
      
      ```bsl
      Файл = Новый Файл(ПутьПрямогоЧтения);
      Если Файл.Существует() Тогда
          // LAN-оптимизация: прямое чтение файла сообщения обмена с диска
      Иначе
          // файла нет по прямому пути - штатная передача через веб-сервис (DownloadData)
      КонецЕсли;
      ```
      
      Фикс вносится в модуль транспорта (доработка конфигурации), не в правила КД -
      в правилах обмена ничего менять не требуется.
      
      ## Язык запросов: BSL-функции в запросах НЕ работают
      
      В тексте запроса (`execute_query`, `Запрос.Текст`) НЕ использовать BSL-функции: `ПустаяСтрока(...)`,
      `СтрСоединить`, `СтрРазделить`. Для проверки пустой строки в запросе - сравнение `Поле <> ""`.
      `Объект[ИмяРеквизита]` (индексатор по строке) для реквизитов объекта НЕ работает - только через точку
      `Объект.ИмяРеквизита` (индексатор есть у Структуры/Соответствия, не у СправочникОбъект).
      
      ## execute_code
      
      ### Ошибка `Значение не является значением объектного типа (Имя)`
      
      Возникает при попытке прочитать `.Имя` у объекта Тип:
      
      ```bsl
      // Плохо - у Тип нет свойства Имя
      Результат = ТипЗнч(Обр).Имя;
      ```
      
      Использовать `Строка(ТипЗнч(...))`:
      
      ```bsl
      // Хорошо
      Результат = Строка(ТипЗнч(Обр));
      // Например: "Обработка объект: Выгрузка правил обмена"
      ```
      
      Если нужно именно имя метаданных объекта - использовать `.Метаданные().Имя`:
      
      ```bsl
      Результат = Обр.Метаданные().Имя;
      ```
      
      ### Запрещенные ключевые слова
      
      В стандартной конфигурации MCP-toolkit блокируется верхнеуровневое
      использование:
      
      - `Удалить`
      - `Записать`
      - `УстановитьПривилегированныйРежим`
      - `COMОбъект`
      - `УдалитьФайлы`
      
      Это значит, что `СоздатьЭлемент().Записать()` или `Объект.Удалить()` упадут
      с ошибкой проверки кода. Решения:
      
      1. **Снять защиту в форме toolkit-а** (правильный путь для разработки на
         тестовой ИБ) - см. форму обработки `MCP_Toolkit.epf`. После снятия
         защиты `Записать` и `УстановитьПометкуУдаления` работают корректно.
      2. Вызвать через **косвенный путь**: например, через экспортные функции
         общих модулей (если есть).
      3. Записать через **вложенный вызов**, который проверка не ловит:
      
         ```bsl
         ВнутренниеФункции(); // где Записать находится внутри функции
      
         Функция ВнутренниеФункции()
             Возврат Спр.Записать();
         КонецФункции
         ```
      
      ### `Удалить()` висит (timeout)
      
      **Симптом:** `Объект.Удалить()` зависает на 30+ секунд, тоолкит возвращает
      timeout. После снятия таймаута объект остается в БД (удаление не произошло).
      
      **Причина:** конфигурация работает в режиме модальности `Использовать` -
      платформа может ждать подтверждения "Удалить связанные объекты?", но UI нет.
      
      **Решение:** использовать `УстановитьПометкуУдаления(Истина)` вместо
      `Удалить()`. Запись помечается на удаление, физически остается в БД до
      запуска стандартной обработки "Удаление помеченных объектов" в UI КД.
      
      ```bsl
      // Плохо - висит
      Объ = Ссылка.ПолучитьОбъект();
      Объ.Удалить();
      
      // Хорошо
      Объ = Ссылка.ПолучитьОбъект();
      Объ.УстановитьПометкуУдаления(Истина);
      // Запись пометки и Записать() вызывается внутри УстановитьПометкуУдаления
      ```
      
      Альтернатива: для разовой расчистки тестовых записей - удалить через UI КД
      (меню "Все функции" -> "Стандартные" -> "Удаление помеченных объектов").
      
      ### Многострочный код в JSON
      
      В `curl -d` многострочный BSL передается через `\n`:
      
      ```sh
      curl ... -d '{"code":"Стр1;\nСтр2;\nРезультат = ...;"}'
      ```
      
      Парсер toolkit-а разворачивает `\n` в реальные переносы строк - работает
      без проблем.
      
      Альтернатива - использовать heredoc-стиль через временный файл:
      
      ```sh
      curl -sS -X POST "http://localhost:7003/api/execute_code" \
        -H "Content-Type: application/json" \
        --data-binary @body.json
      ```
      
      ### `Запрос.Текст` должен быть на одной строке
      
      Внутри строкового литерала `Запрос.Текст = "ВЫБРАТЬ ..."` многострочное
      форматирование через `\n` ломает парсер. Использовать однострочный текст:
      
      ```bsl
      // Правильно (одна строка)
      Запрос.Текст = "ВЫБРАТЬ Ссылка, Наименование ИЗ Справочник.Контрагенты";
      
      // Плохо - может сломаться
      Запрос.Текст = "ВЫБРАТЬ Ссылка,\n   Наименование ИЗ Справочник.Контрагенты";
      ```
      
      ### Функция `ДатаВремя` не существует
      
      В BSL `ДатаВремя` - **токен языка запросов**, не функция платформы:
      
      ```bsl
      // Плохо
      Д = ДатаВремя(2026, 1, 1);
      
      // Хорошо
      Д = Дата(2026, 1, 1);
      Д = Дата("20260101000000");
      ```
      
      ## Поведение КД 2.0
      
      ### ПКО.Код НЕ задавать вручную (генерируется платформой)
      
      Модуль объекта `ПравилаКонвертацииОбъектов.ПередЗаписью` (строка ~84) проверяет
      `глИмяКорректно(Код)`. GUID (с дефисами, с цифры) - НЕ корректное имя правила,
      запись отклоняется: "Не правильно указано имя правила!" + `Отказ`.
      
      - Для **ПКО/ПКС/ПКЗ** - оставлять `Код` пустым: при пустом Коде `СгенерироватьУникальныйКод()`
        заполнит его из имени объекта-приемника (`глИмяОбъекта(Приемник)`), напр.
        `ПоступлениеНаРасчетныйСчет00001`, и сделает уникальным.
      - Для **Конвертации** - наоборот, `Код` = GUID (40 символов с trailing-пробелами) корректен.
      
      Признак: `Записать()` падает с общим "Не удалось записать "Правила конвертации объектов"!",
      а `ПолучитьСообщенияПользователю()` возвращает 0 сообщений (СообщитьОбОшибке пишет
      не в общий стек). Причина почти всегда - некорректный Код или пустой Приемник.
      
      ### ПКС-табчасти создавать через СоздатьГруппу()
      
      `ЭтоГруппа` - системное поле, присваивать НЕЛЬЗЯ ("Поле объекта недоступно для записи").
      Для ПКС табличной части (Вид=ТабличнаяЧасть) использовать
      `Справочники.ПравилаКонвертацииСвойств.СоздатьГруппу()`, для обычного реквизита -
      `СоздатьЭлемент()`. Дочерние ПКС реквизитов табчасти: `ПКС.Родитель = <ПКС-группа>`.
      Модуль ПКС.ПередЗаписью (при `мУстанавливатьИмяИВидИсточникаПриемника=Истина`, по умолчанию)
      сам заполняет ИмяИсточника/ТипИсточника/ВидИсточника/Наименование/Порядок из ссылок
      Источник/Приемник - задавать вручную нужно только Источник, Приемник, ПравилоКонвертации
      (для ссылочных), Родитель. Тип свойства лежит в табчасти `Свойство.Типы[0].Тип`.
      
      ### Программное создание ПКС: ОБЯЗАТЕЛЬНО ссылки, а не текстовые имена
      
      Это самая частая ошибка при создании ПКС через `execute_code`. Если задать только текстовые
      `ИмяИсточника` и `ИмяПриемника`, КД в `ПередЗаписью` СБРОСИТ их в пустую строку, если у объекта
      в справочнике `Свойства` нет записи с таким именем. ПКС сохранится "мусором" (оба имени пустые),
      при выгрузке создаст параметр без имени, и загрузчик в приемнике упадет с ошибкой
      "**Поле объекта не обнаружено**" в типовом КД-загрузчике (`Обработка.КонвертацияОбъектовИнформационныхБаз`,
      строка `ИначеЕсли НЕ ЭтоПараметрДляОбъекта`).
      
      ПРАВИЛЬНО: задавать ССЫЛКИ `Источник` и/или `Приемник` (`Справочник.Свойства`), искать через
      `НайтиПоНаименованию` подчиненного объекту. Сигнатура: `(Наименование, ТочноеСоответствие, Родитель, Владелец)` - Владелец это **4-й параметр** (3-й Родитель пропускать).
      
      ```bsl
      // Получить ссылку на ПКО документа (источник/приемник = объект в справочнике Объекты)
      ОбъектИсточник = ПКО.Источник;  // CatalogRef.Объекты приемной/исходной конфигурации
      ОбъектПриемник = ПКО.Приемник;
      
      // Найти ссылку Свойства "Доп_НомерАСУФХД" подчиненного приемному объекту
      СвПриемник = Справочники.Свойства.НайтиПоНаименованию("Доп_НомерАСУФХД", Истина, , ОбъектПриемник);
      Если СвПриемник.Пустая() Тогда
          // Свойство еще не загружено в КД - выполнить ЗагрузкаСтруктурыМетаданных для нужной
          // конфигурации перед созданием ПКС
          ВызватьИсключение "Свойство не найдено в КД-метаданных";
      КонецЕсли;
      
      ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
      ПКС.Владелец = ПКО;
      ПКС.Приемник = СвПриемник;  // ИмяПриемника подтянется автоматически
      // ПКС.Источник = ... аналогично через НайтиПоНаименованию у ОбъектИсточник, если нужно поле-в-поле
      ПКС.АлгоритмПередВыгрузкойСвойства = "Значение = Источник.Номер;";  // если нужен алгоритм
      ПКС.Порядок = 1000;
      ПКС.Записать();  // имена заполнятся из ссылок
      ```
      
      После Записать проверять `ПКС.ИмяПриемника` - если пуст, значит свойство не найдено и ПКС записалось "мусором".
      
      ### Передача значения перечисления приемника без ПКО
      
      Если приемник реквизита - ссылка на перечисление другой ИБ (у источника такого перечисления нет
      или соответствие нужно вычислить алгоритмом), **НЕ нужен ПКО плана перечисления и ПКЗ**. Достаточно
      в `АлгоритмПередВыгрузкойСвойства` ПКС положить в переменную `Значение` **строку - имя значения
      приемного перечисления**. КД 2.0 на загрузке найдет значение с таким именем в указанном
      перечислении (по типу реквизита-приемника) и присвоит.
      
      ```bsl
      // На выгрузке (Источник - объект исходной ИБ, БП-перечисления недоступны)
      ИмяВидаОпер = "";
      Для Каждого МетаЗн Из Метаданные.Перечисления.ВидыОперацийПоступлениеДенежныхСредств.ЗначенияПеречисления Цикл
          Если Перечисления.ВидыОперацийПоступлениеДенежныхСредств[МетаЗн.Имя] = Источник.ВидОперации Тогда
              ИмяВидаОпер = МетаЗн.Имя;  // например, "ОплатаПокупателя"
              Прервать;
          КонецЕсли;
      КонецЦикла;
      Если ЗначениеЗаполнено(Источник.ВидОперацииРасш) И Источник.ВидОперацииРасш.Расш_Признак Тогда
          Значение = ИмяВидаОпер + "Расширенный";  // суффикс по доп.признаку расширения
      Иначе
          Значение = ИмяВидаОпер;
      КонецЕсли;
      // Значение - просто строка, КД сама подставит enum-значение в приемнике по имени
      ```
      
      Это работает, потому что КД 2.0 при загрузке для ссылочного приемника-перечисления ищет значение
      по имени в самом перечислении приемника. ПравилоКонвертации в ПКС в этом случае оставлять пустым.
      
      Когда нужны ПКО перечисления и ПКЗ: если имена значений в источнике и приемнике принципиально
      не совпадают (нужен явный N→M маппинг через таблицу), либо нужна сложная логика конвертации. Для
      простых случаев (имена совпадают или вычислимы) - этот вариант со строкой проще.
      
      ### Удаление ПКС: ограничения и обходные пути
      
      - `Удалить()` ВИСИТ (модальность подтверждения связанных объектов). Не использовать.
      - `УстановитьПометкуУдаления(Истина)` работает, но **помеченные на удаление ПКС все равно выгружаются**
        в XML правил.
      - `Отключить = Истина` (есть реквизит у ПКС) - ПКС помечен как отключенный, **но при выгрузке тоже
        попадает в XML**. НЕ помогает скрыть ПКС из правил.
      - Комбинация `УстановитьПометкуУдаления + Отключить` подряд дает **"Операция не может быть выполнена,
        так как данные объекта модифицированы"** - после изменения реквизита нужен `Записать()`, затем
        отдельный вызов `УстановитьПометкуУдаления`.
      - ПРАКТИЧЕСКИ: чтобы лишняя ПКС не выгружалась и не ломала загрузку - **очистить алгоритмы**
        (`АлгоритмПередВыгрузкойСвойства = ""`) и/или физически удалить через UI КД
        ("Все функции" → "Удаление помеченных объектов"). Очистка алгоритмов убирает мусорный код из XML,
        но сама запись с пустыми именами все равно может попасть в выгрузку.
      
      ### Метод `.Свойство()` есть только у Структуры, НЕТ у ДокументОбъект/СтрокаТЧ
      
      Частое ограничение. Метод `.Свойство(ИмяРеквизита)` (проверка наличия) есть только у коллекций-структур:
      **Структура, Соответствие, ДанныеФормыСтруктура**. У платформенных объектов конфигурации
      (`ДокументОбъект`, `ДокументТабличнаяЧастьСтрока`, `СправочникОбъект`, `РегистрСведенийНаборЗаписей` и т.п.)
      метода `.Свойство()` **НЕТ**.
      
      В обработчике `АлгоритмПослеЗагрузкиОбъекта` `Объект` - это `ДокументОбъект` (приемник), элементы
      табчасти `Объект.РасшифровкаПлатежа[i]` - `ДокументТабличнаяЧастьСтрока`. На обоих `.Свойство("...")`
      упадет с "**Метод объекта не обнаружен (Свойство)**".
      
      ```bsl
      // ПЛОХО - на обмене упадет:
      Если СтрокаТЧ.Свойство("СпособПогашенияЗадолженности") И СтрокаТЧ.СпособПогашенияЗадолженности.Пустая() Тогда
      
      // ХОРОШО - реквизиты документа известны из метаданных, проверять не надо:
      Если СтрокаТЧ.СпособПогашенияЗадолженности.Пустая() Тогда
          СтрокаТЧ.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;
      КонецЕсли;
      ```
      
      Если реквизиты различаются у Поступления/Списания (или их типов) - не использовать `.Свойство()`,
      а **разделять логику в коде** (если ЭтоПоступление / ЭтоСписание) и заранее проверять метаданные через
      mcp-edt `get_metadata_details`. То же ограничение ломает и типовые методы БП-формы вроде
      `СчетаУчетаВДокументахКлиентСервер.НачатьЗаполнениеРеквизита` - они вызывают
      `ПараметрыЗаполнения.ДанныеФормы.Объект.Свойство(...)`, и потому работают только с **ДанныеФормыСтруктура**,
      а не с **ДокументОбъект** напрямую.
      
      Когда защитная проверка нужна - использовать `Попытка/Исключение` вокруг присваивания:
      
      ```bsl
      Попытка
          Объект.Доп_НеизвестныйРеквизит = Значение;
      Исключение
          // реквизита нет у этого типа документа
      КонецПопытки;
      ```
      
      ### Заполнение типовых счетов учета в обмене: ТОЛЬКО внеформенный метод
      
      В БП 3.0 (типовая) подсистема "Счета учета" имеет два региона методов в `СчетаУчетаВДокументах`:
      - **`ЗаполнениеВФорме`** - `ЗаполнитьОбъектПриИзменении(ПараметрыЗаполнения)`. Внутри ожидает
        `ПараметрыЗаполнения.ДанныеФормы.Объект.Свойство(...)` - метод **Свойство() есть только у
        `ДанныеФормыСтруктура`**, у `ДокументОбъект` его нет. В обмене (где работаем с ДокументОбъектом
        напрямую) этот метод **упадет с ошибкой "Метод объекта не обнаружен (Свойство)"**.
      - **`ЗаполнениеВнеФормы`** - `Заполнить(Объект, Отбор)`, `ЗаполнитьПередЗаписью(Объект, РежимЗаписи)`.
        Принимают `ДокументОбъект` напрямую. Внутри привилегированный режим, заполнение по правилам
        менеджера документа. Это правильный метод для обработчика `АлгоритмПослеЗагрузкиОбъекта` в КД.
      
      Пример вызова в обработчике ПослеЗагрузки ПКО:
      ```bsl
      Отбор = Новый Структура("НеЗаполненныеРеквизиты", Истина);
      СчетаУчетаВДокументах.Заполнить(Объект, Отбор);  // заполнит только пустые реквизиты
      ```
      
      Признак выбора: если у метода в описании написано "**для контекстных вызовов из формы**" -
      он рассчитан на ДанныеФормы и в обмене не подходит. Искать парный метод во внеформенном регионе.
      
      ### ПВД (Правила Выгрузки Данных) создаются из ПКО
      
      ПВД - точки входа выгрузки данных (без них выгружаемый объект не "стартует"). Создавать для
      документов; НСИ-справочники ПВД не нужны (тянутся по ссылкам из документов). Реквизиты ПВД
      (`Справочник.ПравилаВыгрузкиДанных`, Владелец=Конвертации): `ОбъектВыборки` (= ПКО.Источник),
      `ПравилоКонвертации` (= ссылка на ПКО), `СпособОтбораДанных = Перечисления.СпособыОтбораДанных.СтандартнаяВыборка`.
      ПередЗаписью автозаполняет `ТипОбъектаВыборки`, `ИмяПравилаКонвертации`, `Код` (из имени ОбъектВыборки),
      `Наименование`, группу по умолчанию. В выгруженном XML ПВД лежат в `<ПравилаВыгрузкиДанных>` тегами
      `<Правило>` (тот же тег, что у ПКО - при подсчете через XML-парсер учитывать оба блока).
      
      ### Выгрузка НЕ пропускает помеченные на удаление; смена Владельца ПКО запрещена
      
      `ВыгрузкаКонвертации.ВыполнитьВыгрузкуПравил()` включает в XML и помеченные на удаление ПКО.
      Сменить `Владелец` у ПКО на другую конвертацию платформа не дает ("Значение поля Владелец не
      заполнено или заполнено неверно"). `Удалить()` зависает (модальность). Поэтому **дубли/лишние
      ПКО надо либо удалять через UI КД** ("Все функции" → "Удаление помеченных объектов") до выгрузки,
      **либо вырезать блок `<Правило>...</Правило>` из готового XML текстово** (Python). XML остается
      well-formed; дубль в ИБ удалить отдельно через UI.
      
      ### Trailing-пробелы в Код
      
      Реквизит `Код` в `Конвертации` (40 символов) и `ПравилаКонвертацииОбъектов`
      (50 символов) - строки **фиксированной длины** с trailing-пробелами:
      
      ```
      Код = "00000000-0000-0000-0000-000000000001    "  // 40 символов
      Код = "Контрагенты                                       "  // 50 символов
      ```
      
      При сравнениях использовать `СокрЛП()`:
      
      ```bsl
      // Плохо - не найдет из-за пробелов
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоКоду("Контрагенты");
      
      // Хорошо - искать по Наименованию
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты", Истина, Конв);
      
      // Если приходится сравнивать Коды - СокрЛП
      Если СокрЛП(ПКС.КодПравилаКонвертации) = СокрЛП(ПКО.Код) Тогда ...
      ```
      
      ### `#Если Клиент Тогда` не блокирует MCP-toolkit
      
      Метод `ЗагрузкаСтруктурыМетаданных.ВыполнитьЗагрузку()` имеет модуль с
      директивой `#Если Клиент Тогда` (строка 17 модуля). Тем не менее, через
      `execute_code` MCP-toolkit метод вызывается без проблем - toolkit живет в
      клиентском процессе 1С (тонкий или толстый клиент), поэтому клиентское
      условное компилирование не блокирует.
      
      Вызов с несуществующим файлом возвращает ошибку "файл не
      найден" от метода `ОткрытьФайл`, а не "метод не определен".
      
      ### Переменная `мФормаПрогрессора`
      
      Обработка `ВыгрузкаКонвертации` использует переменную модуля
      `мФормаПрогрессора.Значение = 0` (строка 1900 в `ВыполнитьВыгрузкуПравил`).
      При программном создании через `Обработки.ВыгрузкаКонвертации.Создать()`
      эта переменная не инициализирована из формы - но падения не происходит
      (выгрузка XML отрабатывает штатно).
      
      Возможные сценарии падения:
      - Если изменится поведение `мФормаПрогрессора.Значение` присваивания на
        Неопределено.
      - В таком случае предварительно установить заглушку-структуру (см. ниже).
      
      **Выгрузка КОМПЛЕКТА правил** (`ВыгружатьПравилаКорреспондента=Истина` и/или
      `ВыгружатьПравилаРегистрации=Истина`) обращается к прогрессору ШИРЕ, чем
      простая выгрузка одной конвертации - кроме `.Значение` еще `.КомментарийЗначения`,
      `.МаксимальноеЗначение`, `.КомментарийОбработкиДанных`. Заглушку создавать сразу
      со всеми 4 полями:
      
      ```bsl
      Обр.мФормаПрогрессора = Новый Структура(
          "Значение,КомментарийЗначения,МаксимальноеЗначение,КомментарийОбработкиДанных",
          0, "", 0, "");
      ```
      
      Относится к выгрузке 3-файлового ZIP-комплекта (ExchangeRules +
      CorrespondentExchangeRules + RegistrationRules) для БСП-обмена.
      
      ### `Состояние(...)` без UI
      
      Платформенная функция `Состояние("текст")` используется в обработках для
      показа прогресса. Без UI она просто игнорируется - падения не вызывает.
      
      ## execute_query
      
      ### Поля ссылочного типа в результатах
      
      В ответах поля ссылочного типа возвращаются как объект `_objectRef`:
      
      ```json
      {
        "_objectRef": true,
        "УникальныйИдентификатор": "00000000-...",
        "ТипОбъекта": "СправочникСсылка.Конвертации",
        "Представление": "УПП -> БП КОРП Файлы"
      }
      ```
      
      Использовать это как `params` для следующего запроса:
      
      ```sh
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{
          "query": "ВЫБРАТЬ Наименование ИЗ Справочник.Объекты ГДЕ Владелец = &К",
          "params": {
            "К": {
              "_objectRef": true,
              "УникальныйИдентификатор": "00000000-0000-0000-0000-000000000002",
              "ТипОбъекта": "СправочникСсылка.Конфигурации"
            }
          }
        }'
      ```
      
      ### `НайтиПоНаименованию` для иерархических справочников
      
      В подчиненных справочниках (`Объекты`, `Свойства`, `Значения`, `ПКО`, `ПКС`,
      `ПКЗ`) `НайтиПоНаименованию` требует указания Владельца, иначе вернет
      произвольный элемент:
      
      ```bsl
      // Плохо - может вернуть ПКО из другой Конвертации
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты");
      
      // Хорошо - явный Владелец
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию(
          "Контрагенты", Истина, Конв);
      ```
      
      Сигнатура: `НайтиПоНаименованию(Наименование, ТочноеСоответствие, Родитель, Владелец)`.
      
      ## Производительность
      
      ### Большое количество ПКС в одной ПКО
      
      В реальных конвертациях типа БП КОРП -> УПП могут быть 100+ ПКС внутри
      одной ПКО. При создании через цикл - использовать **транзакцию**:
      
      ```bsl
      НачатьТранзакцию();
      Попытка
          Для Каждого Поле Из Поля Цикл
              ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
              ПКС.Владелец = ПКО;
              // ... заполнение
              ПКС.Записать();
          КонецЦикла;
          ЗафиксироватьТранзакцию();
      Исключение
          ОтменитьТранзакцию();
          ВызватьИсключение;
      КонецПопытки;
      ```
      
      Без транзакции каждая запись - отдельная транзакция, медленно.
      
      ### Выгрузка XML
      
      Конвертации с 100+ ПКО и 800+ ПКС выгружаются в XML за единицы секунд.
      Особых оптимизаций не требуется.
      
      ## Безопасность
      
      ### Резервная копия перед массовыми изменениями
      
      КД не имеет "отмены последнего действия". Перед массовыми изменениями:
      
      1. Скопировать `1Cv8.1CD` в безопасное место (файловая ИБ - просто `cp -r`).
      2. Или выгрузить текущие правила через `ВыполнитьВыгрузкуПравил()` как
         backup.
      3. Работать на тестовой копии, не на production.
      
      ### Привилегированный режим
      
      Для системных операций (создание элементов справочников, запуск выгрузки)
      может потребоваться `УстановитьПривилегированныйРежим(Истина)`. По
      умолчанию в toolkit это ключевое слово заблокировано - снять защиту в
      форме обработки.
      
      ## Ссылки
      
      - Полный список эндпоинтов MCP-toolkit - см. скилл `1c-mcp-toolkit`.
      - Объектная модель КД - см. `references/architecture.md`.
      - Точки входа экспортных методов - см. `references/methods.md`.
      - Сценарии end-to-end - см. `references/workflows.md`.
      
    • workflows.md 16 KB
      # Сценарии работы с КД 2.0
      
      End-to-end сценарии с готовыми curl-командами к MCP-toolkit (порт `:7003`).
      Замени порт на свой, если toolkit запущен по другому адресу.
      
      ## W0. Проверка готовности
      
      ```sh
      # Toolkit живой?
      curl http://localhost:7003/health
      
      # КД отвечает?
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{"query":"ВЫБРАТЬ \"OK\" КАК Статус"}'
      
      # Сколько конвертаций уже есть?
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{"query":"ВЫБРАТЬ Наименование ИЗ Справочник.Конвертации ГДЕ НЕ ЭтоГруппа"}'
      
      # Список конфигураций?
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{"query":"ВЫБРАТЬ Наименование, Версия ИЗ Справочник.Конфигурации"}'
      ```
      
      ## W1. Загрузить метаданные конфигурации источника в КД
      
      Предусловие: у тебя есть XML с метаданными конфигурации (получен через
      `Обработки.ВыгрузкаМетаданных` в самой ИБ источника).
      
      ```sh
      curl -sS -X POST "http://localhost:7003/api/execute_code" \
        -H "Content-Type: application/json" \
        -d '{"code":"Обр = Обработки.ЗагрузкаСтруктурыМетаданных.Создать(); Обр.ИмяФайлаЗагрузки = \"C:\\\\Input\\\\metadata_source.xml\"; Обр.мЗагрузитьНовую = Истина; Обр.мКомментарий = \"Загрузка метаданных БП КОРП\"; Рез = Обр.ВыполнитьЗагрузку(); Результат = Новый Структура(\"ok,result\", Рез <> Ложь, Строка(Рез));"}'
      ```
      
      После загрузки:
      
      ```sh
      # Проверить, что Конфигурация появилась
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{"query":"ВЫБРАТЬ Наименование, Имя, Версия ИЗ Справочник.Конфигурации УПОРЯДОЧИТЬ ПО Наименование"}'
      
      # Сколько объектов под этой Конфигурации?
      curl -sS -X POST "http://localhost:7003/api/execute_query" \
        -H "Content-Type: application/json" \
        -d '{"query":"ВЫБРАТЬ Конфигурации.Наименование КАК Конфигурация, КОЛИЧЕСТВО(Объекты.Ссылка) КАК Кол ИЗ Справочник.Конфигурации КАК Конфигурации ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Объекты КАК Объекты ПО Объекты.Владелец = Конфигурации.Ссылка СГРУППИРОВАТЬ ПО Конфигурации.Наименование"}'
      ```
      
      ## W2. Создать конвертацию
      
      После того как обе Конфигурации (Источник, Приемник) загружены.
      
      ```sh
      curl -sS -X POST "http://localhost:7003/api/execute_code" \
        -H "Content-Type: application/json" \
        -d @- <<'JSON'
      {
        "code": "
      Источник = Справочники.Конфигурации.НайтиПоНаименованию(\"БухгалтерияПредприятияКОРП\");
      Приемник = Справочники.Конфигурации.НайтиПоНаименованию(\"УправлениеПроизводственнымПредприятием\");
      Если Источник.Пустая() ИЛИ Приемник.Пустая() Тогда
          ВызватьИсключение \"Источник или Приемник не найдены\";
      КонецЕсли;
      
      Конв = Справочники.Конвертации.СоздатьЭлемент();
      Конв.Наименование = \"Тест: БП КОРП -> УПП\";
      Конв.Источник = Источник;
      Конв.Приемник = Приемник;
      Конв.ИмяИсточника = Источник.Имя;
      Конв.ИмяПриемника = Приемник.Имя;
      Конв.Код = Строка(Новый УникальныйИдентификатор());
      Конв.РежимСовместимости = Перечисления.РежимСовместимости.РежимСовместимостиСБСП20;
      Конв.ВыгружатьПараметрыПоВерсии2_01 = Истина;
      Конв.Записать();
      
      Результат = Новый Структура(\"ссылка,код\", XMLСтрока(Конв.Ссылка), СокрЛП(Конв.Код));
      "
      }
      JSON
      ```
      
      ## W3. Создать ПКО
      
      Предполагаем, что Конвертация и оба объекта (Источник, Приемник) уже
      существуют в КД.
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("Тест: БП КОРП -> УПП");
      ОбъИст = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Источник);
      ОбъПр  = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Приемник);
      Если ОбъИст.Пустая() ИЛИ ОбъПр.Пустая() Тогда
          ВызватьИсключение "Объекты не найдены";
      КонецЕсли;
      
      ПКО = Справочники.ПравилаКонвертацииОбъектов.СоздатьЭлемент();
      ПКО.Владелец      = Конв;
      ПКО.Наименование  = "Контрагенты";
      ПКО.Источник      = ОбъИст;
      ПКО.Приемник      = ОбъПр;
      ПКО.ТипИсточника  = "СправочникСсылка.Контрагенты";
      ПКО.ТипПриемника  = "СправочникСсылка.Контрагенты";
      ПКО.Порядок       = 100;
      ПКО.Код           = Строка(Новый УникальныйИдентификатор());
      ПКО.НеЗамещать    = Истина;
      ПКО.НеВыгружатьОбъектыСвойствПоСсылкам = Истина;
      ПКО.НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска = Истина;
      ПКО.Записать();
      
      Результат = XMLСтрока(ПКО.Ссылка);
      ```
      
      ## W4. Создать ПКС внутри ПКО
      
      ```bsl
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты", Истина, Конв);
      СвИст = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Источник);
      СвПр  = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Приемник);
      
      ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
      ПКС.Владелец     = ПКО;
      ПКС.Источник     = СвИст;
      ПКС.Приемник     = СвПр;
      ПКС.ИмяИсточника = "Наименование";
      ПКС.ИмяПриемника = "Наименование";
      ПКС.ТипИсточника = "Строка";
      ПКС.ТипПриемника = "Строка";
      ПКС.ВидИсточника = "Свойство";
      ПКС.ВидПриемника = "Свойство";
      ПКС.Наименование = "Наименование --> Наименование";
      ПКС.Порядок      = 100;
      ПКС.Поиск        = Ложь;
      ПКС.Код          = Строка(Новый УникальныйИдентификатор());
      ПКС.Записать();
      ```
      
      ### ПКС с ссылочным свойством (через `ПравилоКонвертации`)
      
      Когда свойство имеет ссылочный тип (например `Владелец` у договора - ссылка
      на `Контрагенты`), указать `ПравилоКонвертации` - ссылку на ПКО для
      конвертации значения ссылки.
      
      ```bsl
      ПКОВладелец = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты", Истина, Конв);
      
      ПКС.Источник     = СвВладелец_Ист;
      ПКС.Приемник     = СвВладелец_Пр;
      ПКС.ИмяИсточника = "Владелец";
      ПКС.ИмяПриемника = "Владелец";
      ПКС.ТипИсточника = "СправочникСсылка.Контрагенты";
      ПКС.ТипПриемника = "СправочникСсылка.Контрагенты";
      ПКС.ВидИсточника = "Свойство";
      ПКС.ВидПриемника = "Свойство";
      ПКС.ПравилоКонвертации   = ПКОВладелец;
      ПКС.ИмяПравилаКонвертации = "Контрагенты";
      ПКС.Записать();
      ```
      
      ## W5. Создать ПКЗ (правило конвертации значения перечисления)
      
      ```bsl
      ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("СтатусыЗаказа", Истина, Конв);
      ЗнИст = Справочники.Значения.НайтиПоНаименованию("ВРаботе", Истина, СвойствоИсточника);
      ЗнПр  = Справочники.Значения.НайтиПоНаименованию("InProgress", Истина, СвойствоПриемника);
      
      ПКЗ = Справочники.ПравилаКонвертацииЗначений.СоздатьЭлемент();
      ПКЗ.Владелец         = ПКО;
      ПКЗ.Источник         = ЗнИст;
      ПКЗ.Приемник         = ЗнПр;
      ПКЗ.ЗначениеИсточник = "ВРаботе";
      ПКЗ.ЗначениеПриемник = "InProgress";
      ПКЗ.Порядок          = 100;
      ПКЗ.Записать();
      ```
      
      ## W6. Выгрузить итоговый XML
      
      ```bsl
      Конв = Справочники.Конвертации.НайтиПоНаименованию("Тест: БП КОРП -> УПП");
      
      Обр = Обработки.ВыгрузкаКонвертации.Создать();
      Обр.КонвертацияДляВыгрузки         = Конв;
      Обр.ИмяФайлаПравил                 = "C:\Output\test_rules.xml";
      Обр.СжиматьФайлПравил              = Ложь;
      Обр.ВыгружатьПравилаКорреспондента = Ложь;
      Обр.ВыгружатьПравилаРегистрации    = Ложь;
      Обр.ВыполнитьВыгрузкуПравил();
      
      Файл = Новый Файл(Обр.ИмяФайлаПравил);
      Результат = Новый Структура("ok,path,size", Истина, Обр.ИмяФайлаПравил, Файл.Размер());
      ```
      
      После - прочитать XML и сверить с эталоном при необходимости.
      
      ## W7. Импорт существующих правил из XML (для рефлексии)
      
      ```bsl
      Обр = Обработки.ЗагрузкаКонвертации.Создать();
      Обр.ЗагрузитьПравилаОбмена("C:\Input\existing_rules.xml", "XMLФайл");
      // При необходимости вызвать Обр.Сохранить(...) для финального сохранения
      ```
      
      После импорта - правила появятся в справочниках КД, можно изучать структуру.
      
      ## W8. Автонастройка правил (быстрый стартер)
      
      После того как обе Конфигурации в КД:
      
      ```bsl
      Обр = Обработки.АвтонастройкаПравилКонвертацииОбъектов.Создать();
      // Заполнить реквизиты (Конвертация-цель, режимы)
      // Запустить (имя метода - проверить в src/DataProcessors/АвтонастройкаПравилКонвертацииОбъектов/Ext/ObjectModule.bsl)
      ```
      
      Аналогично - `АвтонастройкаПравилКонвертацииСвойств` и
      `АвтонастройкаПравилКонвертацииЗначений`. Полезно сразу после `W1` создать
      каркас правил, а потом дорабатывать руками.
      
      ## W9. Полный цикл (от пустой КД до XML)
      
      ```
      1. W0 - проверить готовность toolkit-а и пустую/тестовую КД
      2. W1 - загрузить XML метаданных Источника (получить через ВыгрузкаМетаданных в ИБ источника)
      3. W1 - загрузить XML метаданных Приемника
      4. W2 - создать Конвертацию (Источник, Приемник)
      5. W8 - запустить АвтонастройкаПравилКонвертацииОбъектов (создать каркас ПКО)
      6. W8 - АвтонастройкаПравилКонвертацииСвойств (заполнить ПКС внутри ПКО)
      7. W8 - АвтонастройкаПравилКонвертацииЗначений (для перечислений)
      8. (опционально) W3-W5 - доработать правила руками
      9. W6 - выгрузить итоговый XML
      10. (опционально) ВыгрузкаОбработчиков - если есть алгоритмы событий
      ```
      
      ## Откат изменений
      
      КД не имеет "отмены последнего действия". Перед массовыми изменениями:
      - Сделать резервную копию ИБ (для файловой - просто копия каталога).
      - Или выгрузить текущее состояние через `W6` как backup.
      - Или работать на тестовой копии ИБ, а не на production.
      
      Если нужно удалить созданную тестовую конвертацию:
      
      ```bsl
      Ссылка = Справочники.Конвертации.НайтиПоНаименованию("Тест: БП КОРП -> УПП");
      Объ = Ссылка.ПолучитьОбъект();
      Объ.УстановитьПометкуУдаления(Истина);
      // Помеченные записи физически удаляются через UI КД:
      // "Все функции" -> "Стандартные" -> "Удаление помеченных объектов"
      ```
      
      **Важно:** прямое `Объ.Удалить()` через MCP-toolkit зависает (модальный
      диалог в обычных формах). Использовать `УстановитьПометкуУдаления`.
      
      Связанные ПКО/ПКС/ПКЗ нужно помечать отдельно - они подчинены Конвертации
      через `Владелец`, но автоматическое каскадное удаление не происходит:
      
      ```bsl
      // Пометить все ПКО конвертации
      Конв = Справочники.Конвертации.НайтиПоНаименованию("Тест: БП КОРП -> УПП");
      Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.ПравилаКонвертацииОбъектов ГДЕ Владелец = &К");
      Запрос.УстановитьПараметр("К", Конв);
      Выб = Запрос.Выполнить().Выбрать();
      Пока Выб.Следующий() Цикл
          Об = Выб.Ссылка.ПолучитьОбъект();
          Об.УстановитьПометкуУдаления(Истина);
      КонецЦикла;
      ```
      
    • xml-schema.md 13.5 KB
      # Схема итогового XML правил обмена
      
      Схема итогового XML (пример: БП КОРП -> УПП, формат BSP 2.01).
      
      ## Корневая структура
      
      ```xml
      <ПравилаОбмена>
          <ВерсияФормата РежимСовместимости="РежимСовместимостиСБСП20">2.01</ВерсияФормата>
          <Ид>00000000-0000-0000-0000-000000000001    </Ид>
          <Наименование>Тест: БП КОРП -> УПП</Наименование>
          <ДатаВремяСоздания>2025-01-01T00:00:00</ДатаВремяСоздания>
          <Источник ВерсияПлатформы="8.0" ВерсияКонфигурации="3.0.189.29"
                    СинонимКонфигурации="Бухгалтерия предприятия КОРП, редакция 3.0">
              БухгалтерияПредприятияКОРП
          </Источник>
          <Приемник ВерсияПлатформы="8.0" ВерсияКонфигурации=""
                    СинонимКонфигурации="">
              УправлениеПроизводственнымПредприятием
          </Приемник>
          <Параметры/>
          <Обработки/>
          <ПравилаКонвертацииОбъектов>...</ПравилаКонвертацииОбъектов>
          <ПравилаВыгрузкиДанных>...</ПравилаВыгрузкиДанных>
          <ПравилаОчистки>...</ПравилаОчистки>
          <Алгоритмы>...</Алгоритмы>
          <Запросы>...</Запросы>
      </ПравилаОбмена>
      ```
      
      ## Маппинг полей справочников на XML
      
      ### Конвертации -> корневые теги
      
      | Поле Справочник.Конвертации | XML |
      |---|---|
      | `Код` | `<Ид>` (с trailing-пробелами до 40 символов) |
      | `Наименование` | `<Наименование>` |
      | `РежимСовместимости` | атрибут `РежимСовместимости` в `<ВерсияФормата>` |
      | - (константа) | `<ВерсияФормата>2.01</ВерсияФормата>` |
      | (текущая дата при выгрузке) | `<ДатаВремяСоздания>` |
      
      ### Конфигурации (Источник/Приемник) -> атрибуты
      
      | Поле Справочник.Конфигурации | XML атрибут |
      |---|---|
      | `Имя` | текст элемента `<Источник>` или `<Приемник>` |
      | `Версия` | атрибут `ВерсияКонфигурации` |
      | `Синоним` | атрибут `СинонимКонфигурации` |
      | (фиксировано) | атрибут `ВерсияПлатформы="8.0"` |
      
      ## ПКО (`<Правило>` внутри `<ПравилаКонвертацииОбъектов>`)
      
      ```xml
      <ПравилаКонвертацииОбъектов>
          <Группа>
              <Код>Справочники</Код>
              <Наименование>Справочники</Наименование>
              <Порядок>50</Порядок>
              <Правило>
                  <Код>Валюты</Код>
                  <Наименование>Справочник: Валюты</Наименование>
                  <Порядок>50</Порядок>
                  <НеЗамещать>true</НеЗамещать>
                  <НеВыгружатьОбъектыСвойствПоСсылкам>true</НеВыгружатьОбъектыСвойствПоСсылкам>
                  <НеСоздаватьЕслиНеНайден>true</НеСоздаватьЕслиНеНайден>
                  <Источник>СправочникСсылка.Валюты</Источник>
                  <Приемник>СправочникСсылка.Валюты</Приемник>
                  <Свойства>...</Свойства>
                  <Значения/>
              </Правило>
          </Группа>
      </ПравилаКонвертацииОбъектов>
      ```
      
      ### Маппинг ПКО
      
      | Поле Справочник.ПравилаКонвертацииОбъектов | XML |
      |---|---|
      | `Наименование` (ПКО-группа с `ЭтоГруппа=true`) | контейнер `<Группа>` |
      | Обычная ПКО (`ЭтоГруппа=false`) | элемент `<Правило>` |
      | `Код` (имя для XML, не Наименование) | `<Код>` |
      | `Наименование` | `<Наименование>` |
      | `Порядок` | `<Порядок>` |
      | `ТипИсточника` | `<Источник>` (строкой, например `ДокументСсылка.АвансовыйОтчет`) |
      | `ТипПриемника` | `<Приемник>` |
      | `НеЗамещать=true` | `<НеЗамещать>true</НеЗамещать>` (false - не выводится) |
      | `НеВыгружатьОбъектыСвойствПоСсылкам=true` | то же |
      | `НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска=true` | `<НеСоздаватьЕслиНеНайден>` (имя в XML укорочено) |
      
      ## ПКС (`<Свойство>` внутри `<Свойства>`)
      
      ```xml
      <Свойства>
          <Свойство Поиск="true">
              <Код>2</Код>
              <Наименование>Доп_НСИ_ГУИД --> Доп_НСИ_ГУИД</Наименование>
              <Порядок>50</Порядок>
              <Источник Имя="Доп_НСИ_ГУИД" Вид="Реквизит" Тип="Строка"/>
              <Приемник Имя="Доп_НСИ_ГУИД" Вид="Реквизит" Тип="Строка"/>
          </Свойство>
          <Свойство>
              <Код>1</Код>
              <Наименование>Наименование --> Наименование</Наименование>
              <Порядок>100</Порядок>
              <Источник Имя="Наименование" Вид="Свойство" Тип="Строка"/>
              <Приемник Имя="Наименование" Вид="Свойство" Тип="Строка"/>
          </Свойство>
          <Свойство>
              <Код>2</Код>
              <Наименование>Владелец --> Владелец</Наименование>
              <Порядок>150</Порядок>
              <Источник Имя="Владелец" Вид="Свойство" Тип="СправочникСсылка.Контрагенты"/>
              <Приемник Имя="Владелец" Вид="Свойство" Тип="СправочникСсылка.Контрагенты"/>
              <КодПравилаКонвертации>Контрагенты                                       </КодПравилаКонвертации>
          </Свойство>
      </Свойства>
      ```
      
      ### Маппинг ПКС
      
      | Поле Справочник.ПравилаКонвертацииСвойств | XML |
      |---|---|
      | `Поиск=true` | атрибут `Поиск="true"` на `<Свойство>` (false - атрибут не выводится) |
      | (порядковый номер ПКС внутри ПКО) | `<Код>` (генерируется при выгрузке - не путать с реквизитом Код) |
      | `Наименование` | `<Наименование>` |
      | `Порядок` | `<Порядок>` |
      | `ИмяИсточника`, `ВидИсточника`, `ТипИсточника` | атрибуты `Имя`/`Вид`/`Тип` в `<Источник>` |
      | `ИмяПриемника`, `ВидПриемника`, `ТипПриемника` | атрибуты в `<Приемник>` |
      | `ПравилоКонвертации` (для ссылочного типа) | `<КодПравилаКонвертации>` (Код связанной ПКО с trailing-пробелами до 50 символов) |
      
      ### Значения атрибута `Вид`
      
      | Значение | Назначение |
      |---|---|
      | `Реквизит` | Реквизит объекта (справочника, документа) |
      | `Свойство` | Стандартное свойство (Наименование, Код, Дата, Номер) |
      | `ТабличнаяЧасть` | Табличная часть |
      
      ## ПКЗ (`<Значения>` внутри `<Правило>`)
      
      Структура (для перечислений):
      
      ```xml
      <Значения>
          <Значение>
              <Источник>ЗначениеПеречисленияИсточника</Источник>
              <Приемник>ЗначениеПеречисленияПриемника</Приемник>
          </Значение>
      </Значения>
      ```
      
      В исследованной конвертации `<Значения/>` пустые - конвертация на 100%
      справочников без перечислений.
      
      ## Алгоритмы и Запросы
      
      `<Алгоритмы>` и `<Запросы>` содержат именованные BSL-фрагменты и тексты
      запросов, которые потом используются в алгоритмах событий ПКО/ПКС/Конвертации.
      В исследованной конвертации они пустые.
      
      ## Особенности
      
      ### Trailing-пробелы в Код
      
      Реквизит `Код` в Конвертации (40 символов) и в ПКО (50 символов) - строки
      фиксированной длины с trailing-пробелами:
      
      ```
      <Ид>00000000-0000-0000-0000-000000000001    </Ид>
      <КодПравилаКонвертации>Контрагенты                                       </КодПравилаКонвертации>
      ```
      
      При сравнении со ссылкой на КодПравилаКонвертации использовать `СокрЛП()`.
      
      ### `<НеСоздаватьЕслиНеНайден>` vs `НеСоздаватьОбъектВПриемникеЕслиНеНайденПоПолямПоиска`
      
      Имя в XML укорочено по сравнению с именем реквизита справочника. Это пример
      несоответствия - всегда сверяйся с реальным маппингом, а не с именем реквизита.
      
      ### Порядок групп в XML
      
      В корне `<ПравилаОбмена>` группы идут в фиксированном порядке:
      1. `<ПравилаКонвертацииОбъектов>`
      2. `<ПравилаВыгрузкиДанных>`
      3. `<ПравилаОчистки>` (в реквизите справочника называется `ПравилаОчисткиДанных`)
      4. `<Алгоритмы>`
      5. `<Запросы>`
      
      ## Полный пример (укороченный)
      
      ```xml
      <?xml version="1.0" encoding="UTF-8"?>
      <ПравилаОбмена>
          <ВерсияФормата РежимСовместимости="РежимСовместимостиСБСП20">2.01</ВерсияФормата>
          <Ид>00000000-0000-0000-0000-000000000001    </Ид>
          <Наименование>Тест: БП КОРП -> УПП</Наименование>
          <ДатаВремяСоздания>2025-01-01T00:00:00</ДатаВремяСоздания>
          <Источник ВерсияПлатформы="8.0" ВерсияКонфигурации="3.0.189.29"
                    СинонимКонфигурации="Бухгалтерия предприятия КОРП">
              БухгалтерияПредприятияКОРП
          </Источник>
          <Приемник ВерсияПлатформы="8.0" ВерсияКонфигурации="" СинонимКонфигурации="">
              УправлениеПроизводственнымПредприятием
          </Приемник>
          <Параметры/>
          <Обработки/>
          <ПравилаКонвертацииОбъектов>
              <Группа>
                  <Код>Справочники</Код>
                  <Наименование>Справочники</Наименование>
                  <Порядок>50</Порядок>
                  <Правило>
                      <Код>Контрагенты</Код>
                      <Наименование>Контрагенты</Наименование>
                      <Порядок>100</Порядок>
                      <НеЗамещать>true</НеЗамещать>
                      <Источник>СправочникСсылка.Контрагенты</Источник>
                      <Приемник>СправочникСсылка.Контрагенты</Приемник>
                      <Свойства>
                          <Свойство Поиск="true">
                              <Код>1</Код>
                              <Наименование>ИНН --> ИНН</Наименование>
                              <Порядок>50</Порядок>
                              <Источник Имя="ИНН" Вид="Реквизит" Тип="Строка"/>
                              <Приемник Имя="ИНН" Вид="Реквизит" Тип="Строка"/>
                          </Свойство>
                      </Свойства>
                      <Значения/>
                  </Правило>
              </Группа>
          </ПравилаКонвертацииОбъектов>
          <ПравилаВыгрузкиДанных/>
          <ПравилаОчистки/>
          <Алгоритмы/>
          <Запросы/>
      </ПравилаОбмена>
      ```
      
  • SKILL.md 15 KB
    ---
    name: kd2-rules
    description: >
      Программная разработка правил обмена в "Конвертация данных 2.1" (КД 2.0)
      через MCP-toolkit к живой ИБ. Создание/чтение/изменение Конвертаций, ПКО,
      ПКС, ПКЗ, ПВД, ПОД в справочниках КД и выгрузка итогового XML штатными
      обработками КД (ВыгрузкаКонвертации, ВыгрузкаРегистрации, ЗагрузкаКонвертации,
      ЗагрузкаСтруктурыМетаданных). Содержит схему данных, шаблоны BSL для
      execute_code, схему итогового XML, типичные ошибки. Триггеры на русском:
      "работа с КД 2.0", "правила обмена в КД", "создать конвертацию", "настроить
      ПКО ПКС ПКЗ", "выгрузить правила обмена в XML", "конвертация данных 2.1",
      "загрузить метаданные конфигурации в КД", "автонастройка правил конвертации".
      Триггеры на английском: "1C data conversion rules", "KD 2.0", "create
      conversion rule", "PKO PKS PKZ", "export exchange rules XML".
    ---
    
    # KD 2.0 - правила обмена через MCP-toolkit
    
    Скилл описывает, как агент создает/изменяет правила обмена в живой ИБ
    "Конвертация данных 2.1" (КД 2.0) через `MCP-toolkit` HTTP API (порт по
    умолчанию `6003`, в проектах часто `7003`) и в финале выгружает XML
    штатными обработками КД.
    
    ## Что такое КД 2.0
    
    - Конфигурация фирмы "1С", v2.1.8.2, обычные формы, режим совместимости
      8.2.13. Программа для разработки правил обмена данными между парами
      конфигураций (например, БП КОРП -> УПП, УТ -> ERP).
    - Результат работы в КД - XML с правилами, который грузится в
      "Универсальный обмен данными в формате XML" в конфигурации-источнике.
    - Все правила хранятся в справочниках самой КД: `Конвертации`,
      `ПравилаКонвертацииОбъектов`, `ПравилаКонвертацииСвойств`,
      `ПравилаКонвертацииЗначений`, `ПравилаВыгрузкиДанных`,
      `ПравилаОчисткиДанных`, `ПравилаРегистрацииОбъектов`, плюс
      `Конфигурации`/`Объекты`/`Свойства`/`Значения` (теневая модель метаданных
      источника и приемника).
    
    ## Архитектура работы
    
    ```
    Claude (агент)
       ↕  MCP-протокол / прямые tool-вызовы
    Скилл kd2-rules
       ↕  HTTP POST :6003/api/* (или :7003 если переопределен порт)
    MCP-toolkit (обработка MCP_Toolkit.epf в живой ИБ)
       ↕  внутрипроцессно
    ИБ КД 2.0
       ↕  через ВыгрузкаКонвертации.ВыполнитьВыгрузкуПравил()
    Файл XML с правилами обмена
    ```
    
    Низкоуровневый транспорт - `MCP-toolkit` (скилл `1c-mcp-toolkit`). Главные
    эндпоинты, которые используются здесь:
    
    - `POST /api/execute_query` - читать справочники КД и их связи.
    - `POST /api/execute_code` - создавать/изменять элементы справочников,
      запускать экспортные методы обработок.
    - `GET /api/health` - проверка живости.
    
    ## Предварительные требования
    
    1. Запущенная ИБ КД 2.0 в тонком/толстом клиенте с открытой обработкой
       `MCP_Toolkit.epf` (см. скилл `1c-mcp-toolkit`). HTTP-сервер слушает
       `localhost:6003` (или `:7003` по настройке).
    2. В форме toolkit-а проверить и при необходимости снять защиту от записи:
       снять флажки на ключевые слова `Записать`, `Удалить`,
       `УстановитьПривилегированныйРежим`. Без этого работают только
       `execute_query` и read-only вызовы.
    3. Желательно тестовая копия ИБ КД, а не production - правила пишутся
       напрямую в справочники.
    
    ## Быстрая проверка готовности
    
    ```sh
    curl http://localhost:7003/health
    # Ожидание: {"status":"healthy", ...}
    
    curl -sS -X POST "http://localhost:7003/api/execute_query" \
      -H "Content-Type: application/json" \
      -d '{"query":"ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Кол ИЗ Справочник.Конвертации"}'
    ```
    
    ## Карта references
    
    | Документ | Что внутри | Когда читать |
    |---|---|---|
    | `references/helpers.md` | библиотека готовых BSL-заготовок для `execute_code`: списки ПКО/ПКС/ПКЗ, дамп обработчиков, флаги ПКО, ПКС по ссылке на Свойство, выгрузка комплекта XML, поиск объектов с учетом префикса типа, идиомы передачи значений | нужен запрос или правка объектов КД - СНАЧАЛА сюда, не сочинять скрипт с нуля |
    | `references/architecture.md` | объектная модель КД, иерархия Владелец, полные списки реквизитов всех ключевых справочников | проектирование новой операции, нужны типы и связи |
    | `references/methods.md` | экспортные методы обработок выгрузки/загрузки + file:line + параметры (реквизиты обработки) | вызов конкретного метода через `execute_code` |
    | `references/workflows.md` | end-to-end сценарии: подготовка ИБ, загрузка метаданных, создание правил, выгрузка XML, импорт XML, автонастройка | впервые делаешь полный цикл или сложный сценарий |
    | `references/xml-schema.md` | схема итогового XML правил обмена + маппинг полей справочника на XML | надо понять, что КД ожидает увидеть в XML, или сверить результат с эталоном |
    | `references/troubleshooting.md` | типичные ошибки и ограничения toolkit-а, особенности КД 2.0 | при ошибке `execute_code`/`execute_query` |
    
    ## 5 базовых операций (краткий справочник)
    
    ### 1. Найти конвертацию по имени
    
    ```bsl
    Конв = Справочники.Конвертации.НайтиПоНаименованию("Имя_Конвертации");
    Если Конв.Пустая() Тогда
        ВызватьИсключение "Конвертация не найдена";
    КонецЕсли;
    Результат = XMLСтрока(Конв);
    ```
    
    ### 2. Список ПКО в конвертации
    
    ```sh
    curl -sS -X POST "http://localhost:7003/api/execute_query" \
      -H "Content-Type: application/json" \
      -d '{
        "query": "ВЫБРАТЬ ПКО.Наименование, ПКО.ТипИсточника, ПКО.ТипПриемника, ПКО.Порядок ИЗ Справочник.ПравилаКонвертацииОбъектов КАК ПКО ГДЕ ПКО.Владелец.Наименование = &Конв И НЕ ПКО.ЭтоГруппа УПОРЯДОЧИТЬ ПО ПКО.Порядок",
        "params": {"Конв": "Имя_Конвертации"}
      }'
    ```
    
    ### 3. Создать ПКО
    
    ```bsl
    Конв = Справочники.Конвертации.НайтиПоНаименованию("МояКонвертация");
    ОбъИст = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Источник);
    ОбъПр  = Справочники.Объекты.НайтиПоНаименованию("Контрагенты", Истина, Конв.Приемник);
    
    ПКО = Справочники.ПравилаКонвертацииОбъектов.СоздатьЭлемент();
    ПКО.Владелец      = Конв;
    ПКО.Наименование  = "Контрагенты";
    ПКО.Источник      = ОбъИст;
    ПКО.Приемник      = ОбъПр;
    ПКО.ТипИсточника  = "СправочникСсылка.Контрагенты";
    ПКО.ТипПриемника  = "СправочникСсылка.Контрагенты";
    ПКО.Порядок       = 100;
    ПКО.Записать();
    
    Результат = Новый Структура("ссылка", XMLСтрока(ПКО.Ссылка));
    ```
    
    ### 4. Создать ПКС внутри ПКО
    
    ```bsl
    ПКО = Справочники.ПравилаКонвертацииОбъектов.НайтиПоНаименованию("Контрагенты", Истина, Конв);
    СвИст = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Источник);
    СвПр  = Справочники.Свойства.НайтиПоНаименованию("Наименование", Истина, ПКО.Приемник);
    
    ПКС = Справочники.ПравилаКонвертацииСвойств.СоздатьЭлемент();
    ПКС.Владелец     = ПКО;
    ПКС.Источник     = СвИст;
    ПКС.Приемник     = СвПр;
    ПКС.ИмяИсточника = "Наименование";
    ПКС.ИмяПриемника = "Наименование";
    ПКС.ТипИсточника = "Строка";
    ПКС.ТипПриемника = "Строка";
    ПКС.ВидИсточника = "Свойство";
    ПКС.ВидПриемника = "Свойство";
    ПКС.Наименование = "Наименование --> Наименование";
    ПКС.Порядок      = 100;
    ПКС.Записать();
    ```
    
    ### 5. Выгрузить конвертацию в XML
    
    ```bsl
    Конв = Справочники.Конвертации.НайтиПоНаименованию("МояКонвертация");
    Обр = Обработки.ВыгрузкаКонвертации.Создать();
    Обр.КонвертацияДляВыгрузки         = Конв;
    Обр.ИмяФайлаПравил                 = "C:\Output\rules.xml";
    Обр.СжиматьФайлПравил              = Ложь;
    Обр.ВыгружатьПравилаКорреспондента = Ложь;
    Обр.ВыгружатьПравилаРегистрации    = Ложь;
    Обр.ВыполнитьВыгрузкуПравил();
    
    Файл = Новый Файл(Обр.ИмяФайлаПравил);
    Результат = Новый Структура("ok,path,size", Истина, Обр.ИмяФайлаПравил, Файл.Размер());
    ```
    
    ## Принципы работы
    
    1. **Все справочники иерархические** "Папки и элементы". ПКО-группы (`ЭтоГруппа=true`)
       используются для логической группировки правил внутри конвертации.
    
    2. **Владелец = главная связь.** ПКО подчинен Конвертации, ПКС/ПКЗ подчинены ПКО,
       Объекты подчинены Конфигурации, Свойства подчинены Объектам, Значения
       подчинены Свойствам.
    
    3. **Денормализованные дубликаты.** Поля типа `ИмяИсточника`/`ТипИсточника` в ПКО и
       ПКС - строковые копии данных из связанной ссылки (для быстрого поиска без
       join-ов). Заполняй их явно при создании.
    
    4. **Поле `Код`** в Конвертациях и ПКО - это "внутренний идентификатор" (UUID-подобная
       строка фиксированной длины 40 символов с trailing-пробелами). Используется в
       итоговом XML как `<Ид>` и `<КодПравилаКонвертации>`.
    
    5. **Имя файла в `ИмяФайлаПравил`** должно быть путем к существующему каталогу.
       `КаталогВременныхФайлов()` - надежный способ получить временную папку клиента.
    
    6. **Гигиена скриптов.** Одноразовые/отладочные BSL-скрипты класть только в
       `tools/_tmp/` рабочего каталога КД и чистить после задачи. Устойчивые
       операции не копить в одноразовых файлах - брать из `references/helpers.md`
       и добавлять новые заготовки туда же.
    
    ## Ограничения
    
    - Все ключевые методы КД работают через `execute_code` без явного
      `execution_context` (toolkit живет в клиентском контексте 1С,
      директива `#Если Клиент Тогда` не блокирует).
    - В стандартной конфигурации toolkit-а заблокированы ключевые слова
      `Записать`, `Удалить`, `УстановитьПривилегированныйРежим`. Для создания
      правил - отключить защиту в форме toolkit-а.
    - Возможны trailing-пробелы в строковых ссылочных полях (`Код` 40 символов
      с пробелами). При сравнениях использовать `СокрЛП(...)`.
    - Обработка `ВыгрузкаКонвертации` использует переменную модуля
      `мФормаПрогрессора.Значение` - при программном запуске она остается
      не инициализированной, но падения не происходит.
    
    ## Связанные скиллы
    
    - `1c-mcp-toolkit` - HTTP API к живой ИБ 1С (этот скилл - надстройка
      поверх него).
    - `composing-1c-queries` - синтаксис языка запросов 1С для `execute_query`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related