При разработке собственной консоли запросов или инструментов администратора часто возникает задача отображения не только стандартных таблиц базы данных, но и виртуальных таблиц регистрации изменений. Эти таблицы создаются платформой автоматически для объектов, включенных в планы обмена. В рамках данной статьи мы подробно разберем, как работает механизм регистрации изменений "под капотом", как программно вычислить доступные таблицы и как правильно обращаться к ним в тексте запроса.
Прежде чем приступать к написанию кода, давайте проанализируем, что собой представляет таблица изменений. Если хотя бы один объект метаданных (справочник, документ или регистр) включен в состав хотя бы одного плана обмена, платформа 1С создает специальную таблицу для хранения записей о том, какой объект был изменен и для какого узла (получателя) это изменение предназначено.
Рассмотрим стандартный состав полей такой таблицы для ссылочных типов (справочники, документы):
Узел — ссылка на элемент плана обмена, для которого зарегистрировано изменение.НомерСообщения — числовое поле, которое содержит NULL, если изменение еще не было выгружено, или номер сообщения обмена, в которое это изменение было включено.Ссылка — ссылка на сам объект (например, на конкретную накладную или контрагента).Для регистров (сведений, накопления) структура меняется: вместо поля Ссылка в таблице изменений присутствуют все измерения данного регистра. Это необходимо для однозначной идентификации записи или набора записей, которые подлежат обмену.
Для того чтобы наша консоль запросов корректно отображала дерево доступных таблиц, нам необходимо программно перебрать метаданные и выяснить, какие из них участвуют в обмене. Рассмотрим алгоритм проверки на примере конкретного плана обмена.
Выясним, включен ли конкретный документ в состав плана обмена Полный. Для этого мы можем использовать коллекцию Состав объекта метаданных плана обмена. Разберем по шагам небольшой фрагмент кода:
Для Каждого Об_МД из Метаданные.Документы Цикл
// Проверяем, входит ли документ в состав конкретного плана обмена
Содержит = Метаданные.ПланыОбмена.Полный.Состав.Содержит(Об_МД);
Если Содержит Тогда
// Здесь мы добавляем логику отображения в дереве консоли
// Имя таблицы в запросе будет: Документ.ИмяДокумента.Изменения
КонецЕсли;
КонецЦикла;
Важный момент: в реальной конфигурации планов обмена может быть несколько. Чтобы сделать инструмент универсальным, нам следует обходить все доступные планы обмена в цикле и проверять вхождение объекта в каждый из них.
Теперь перейдем к более сложной задаче — интеграции этого поиска в интерфейс нашей обработки. Допустим, у нас есть дерево значений на форме, которое отображает структуру метаданных. Нам нужно дополнить его строками, соответствующими таблицам изменений.
Рассмотрим процедуру, которая обходит различные виды метаданных и формирует список типов, включая виртуальные таблицы изменений:
&НаСервере
Функция ПолучитьСписокТиповСтрокойПоКоллекцииМетаданных(КоллекцияМетаданных)
МассивИменТипов = Новый Массив;
Для Каждого МетаданныеОбъекта Из КоллекцияМетаданных Цикл
// Добавляем основную таблицу объекта
МассивИменТипов.Добавить(МетаданныеОбъекта.ПолноеИмя);
// Проверяем участие в планах обмена (например, в плане "Полный")
// Элементы.ДоступныеТаблицыИзменений.Пометка — это наш флаг отображения
Если Метаданные.ПланыОбмена.Полный.Состав.Содержит(МетаданныеОбъекта)
И Элементы.ДоступныеТаблицыИзменений.Пометка Тогда
// Формируем имя виртуальной таблицы изменений
МассивИменТипов.Добавить(МетаданныеОбъекта.ПолноеИмя + ".Изменения");
КонецЕсли;
КонецЦикла;
Возврат СтрСоединить(МассивИменТипов, ",");
КонецФункции
В данном примере мы используем свойство ПолноеИмя, чтобы получить путь вида Документ.РеализацияТоваровУслуг, и конкатенируем его с суффиксом .Изменения. Это именно тот формат, который понимает построитель запросов 1С.
Когда пользователь выбирает такую таблицу в вашей консоли, текст запроса должен формироваться по определенным правилам. Посмотрим на пример запроса к изменениям документа "Авансовый отчет":
ВЫБРАТЬ
АвансовыйОтчетИзменения.Узел КАК Узел,
АвансовыйОтчетИзменения.НомерСообщения КАК НомерСообщения,
АвансовыйОтчетИзменения.Ссылка КАК Ссылка
ИЗ
Документ.АвансовыйОтчет.Изменения КАК АвансовыйОтчетИзменения
ГДЕ
АвансовыйОтчетИзменения.Узел = &УзелПланаОбмена
Обратите внимание на псевдоним таблицы. При обращении к Документ.АвансовыйОтчет.Изменения мы получаем доступ к записям в физической таблице регистрации изменений (в СУБД она обычно имеет суффикс _ChngR). Мы можем накладывать фильтры на узел или на номер сообщения, что крайне полезно при отладке правил обмена или поиске "зависших" изменений.
Проанализируем ситуацию с константами. В отличие от документов, изменения всех констант, участвующих в обмене, регистрируются в одной общей таблице. В языке запросов к ней можно обратиться как Константы.Изменения. Поля этой таблицы включают Узел, НомерСообщения и технические идентификаторы, позволяющие платформе понять, какая именно константа изменилась.
Для создания полноценного инструмента "как в стандартной консоли", рекомендуем обратить внимание на следующие нюансы:
Для Каждого ПланОбмена Из Метаданные.ПланыОбмена.Авторегистрация (Разрешить/Запретить). Будет полезно выводить это свойство в подсказке к таблице, так как оно напрямую влияет на то, будут ли данные появляться в этой таблице автоматически.Используя приведенные выше методы и примеры кода, вы сможете расширить функционал своей консоли запросов, сделав её мощным инструментом для отладки систем синхронизации данных в среде 1С:Предприятие.