Как настроить отбор выгружаемых объектов по организации при синхронизации 1С:ЗУП 3.1 и 1С:УХ (БП КОРП)

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При работе в крупных холдинговых структурах часто возникает ситуация, когда в единой базе 1С:Зарплата и управление персоналом 3.1 ведется учет по десяткам организаций, а обмен данными настроен с единой базой 1С:Управление холдингом 3.0 (или 1С:Бухгалтерия предприятия КОРП 3.0). В таких условиях стандартная синхронизация, выгружающая абсолютно все зарегистрированные изменения скопом, становится неэффективной и неудобной.

Представим сценарий: бухгалтеры по расчету заработной платы разных филиалов хотят запускать синхронизацию независимо друг от друга и выгружать только «свои» организации. При этом важно, чтобы объекты других организаций оставались зарегистрированными к обмену и не затирались. В этой статье мы подробно разберем, как решить эту задачу, обойдя ключевые ограничения платформы «1С:Предприятие 8.3» и Библиотеки стандартных подсистем (БСП).

---

1. Анализ и обход ограничений метода ПланыОбмена.ВыбратьИзменения

Первый вопрос, который возникает у разработчика при реализации выборочной выгрузки: можно ли наложить фильтр по реквизиту прямо в методе получения изменений? Обратимся к синтаксису платформы.

Метод ПланыОбмена.ВыбратьИзменения(СсылкаНаУзел, НомерСообщения, ФильтрВыборки) действительно имеет параметр ФильтрВыборки. Однако платформа накладывает жесткое ограничение: в этот параметр нельзя передать произвольный SQL-запрос или условие вида Организация = &НашаОрганизация. В качестве фильтра можно использовать только:

Для реализации нашей задачи мы применим обходной путь: предварительный запрос к таблицам изменений + передача массива ссылок в фильтр выборки. Рассмотрим этот алгоритм на практике.

Сначала мы пишем запрос к виртуальной таблице изменений интересующего нас объекта (например, документа ОтражениеЗарплатыВБухучете), соединяя ее с основной таблицей этого же документа. Это позволит нам отфильтровать зарегистрированные изменения по реквизиту Организация.

Посмотрим на пример реализации функции сбора таких ссылок:


Функция ПолучитьМассивСсылокИзмененийСОтбором(УзелОбмена, ВыбраннаяОрганизация) Экспорт
    
    МассивСсылок = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Изменения.Ссылка КАК Ссылка
        |ИЗ
        |	Документ.ОтражениеЗарплатыВБухучете.Изменения КАК Изменения
        |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтражениеЗарплатыВБухучете КАК ОтражениеЗарплаты
        |		ПО Изменения.Ссылка = ОтражениеЗарплаты.Ссылка
        |ГДЕ
        |	Изменения.Узел = &Узел
        |	И ОтражениеЗарплаты.Организация = &Организация";
        
    Запрос.УстановитьПараметр("Узел", УзелОбмена);
    Запрос.УстановитьПараметр("Организация", ВыбраннаяОрганизация);
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        МассивСсылок.Добавить(Выборка.Ссылка);
    КонецЦикла;
    
    Возврат МассивСсылок;
    
КонецФункции

Далее, при формировании сообщения обмена, мы передаем полученный массив в метод ПланыОбмена.ВыбратьИзменения:


Процедура ВыгрузитьИзмененияПоОрганизации(УзелОбмена, НомерСообщения, ВыбраннаяОрганизация)
    
    МассивСсылок = ПолучитьМассивСсылокИзмененийСОтбором(УзелОбмена, ВыбраннаяОрганизация);
    
    Если МассивСсылок.Количество() = 0 Тогда
        ЗаписатьВЛог("Нет зарегистрированных изменений для выбранной организации.");
        Возврат;
    КонецЕсли;
    
    // Формируем структуру фильтра выборки
    ФильтрВыборки = Новый Структура;
    ФильтрВыборки.Вставить("Документ.ОтражениеЗарплатыВБухучете", МассивСсылок);
    
    // Получаем выборку изменений только по нужным документам
    ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСообщения, ФильтрВыборки);
    
    // Производим стандартную запись сообщения обмена XML...
    
КонецПроцедуры

Важная особенность механизма: при использовании такого подхода платформа автоматически присвоит номер отправленного сообщения НомерСообщения только тем объектам, ссылки на которые были переданы в массиве. Все остальные зарегистрированные изменения (по другим организациям) останутся нетронутыми и будут ждать своей очереди при последующих сеансах синхронизации.

---

2. Обход ограничения БСП на уникальность префиксов

Часто в обсуждениях предлагают простое решение: «Создайте для каждой организации отдельную настройку синхронизации (отдельный узел плана обмена)». Однако при попытке сделать это через стандартный помощник настройки БСП вы столкнетесь с ошибкой: система потребует уникальные префиксы информационных баз для каждого нового узла. Так как физически баз всего две (одна ЗУП и одна БУХ/УХ), префиксы у них одинаковые, и БСП заблокирует создание дублирующих настроек.

Проанализируем, как обойти это ограничение. Проверка уникальности префиксов — это ограничение экранных форм БСП, а не самой платформы. Сама платформа 1С позволяет создавать сколько угодно узлов в рамках одного плана обмена. Мы можем решить эту проблему двумя путями:

  1. Программное создание узлов обмена. Мы пишем внешнюю обработку, которая создает узлы плана обмена напрямую, минуя валидацию форм БСП. Для каждого узла мы задаем уникальный код (например, УХ_ОРГ1, УХ_ОРГ2), но сохраняем корректные настройки подключения.
  2. Временная подмена префикса. При создании новой синхронизации в мастере временно указывается фиктивный префикс (например, Х1). После завершения создания узла мы программно или через обработку «Регистрация изменений для обмена» меняем код узла на требуемый.

Пример кода для программного создания узла плана обмена:


Процедура СоздатьНовыйУзелОбменаПрограммно(КодУзла, НаименованиеУзла)
    
    ПланОбменаМенеджер = ПланыОбмена.ОбменЗарплата3Бухгалтерия3;
    
    // Проверим, нет ли уже узла с таким кодом
    НайденныйУзел = ПланОбменаМенеджер.НайтиПоКоду(КодУзла);
    Если ЗначениеЗаполнено(НайденныйУзел) Тогда
        Возврат;
    КонецЕсли;
    
    НовыйУзел = ПланОбменаМенеджер.СоздатьУзел();
    НовыйУзел.Код = КодУзла;
    NewУзел.Наименование = НаименованиеУзла;
    НовыйУзел.Записать();
    
    ЗаписатьВЛог("Узел " + КодУзла + " успешно создан.");
    
КонецПроцедуры

Важное предупреждение: если вы решите пойти по пути создания нескольких узлов обмена, вам придется переписать Правила регистрации объектов (ПРО). В противном случае любое изменение справочника (например, «Физические лица» или «Сотрудники») будет регистрироваться на всех созданных узлах, что приведет к избыточному дублированию данных в очередях выгрузки.

---

3. Передача параметров отбора при синхронизации через Интернет (Web-сервисы)

Если базы обмениваются напрямую через веб-сервисы, инициация процесса на стороне ЗУП автоматически вызывает ответную выгрузку/загрузку на стороне УХ. Как передать информацию о том, по какой именно организации пользователь запустил обмен в данный момент?

Рассмотрим наиболее надежные архитектурные варианты решения этой проблемы.

Вариант А. Использование регистра сведений для хранения активной сессии

Мы создаем в обеих базах непериодический регистр сведений НастройкиСеансовОбменаДанными с измерениями УзелИнформационнойБазы и ресурсом ОрганизацияДляВыгрузки.

Перед тем как вызвать стандартный метод БСП ВыполнитьОбменДанными(), интерактивная кнопка «Синхронизировать» под управлением текущего пользователя записывает выбранную организацию в этот регистр.

Поскольку при веб-подключении база-корреспондент выполняет код в контексте того же узла обмена, при выгрузке данных на своей стороне она может легко прочитать текущую организацию из регистра и применить аналогичный фильтр к своим изменениям.

Вариант Б. Расширение модулей БСП для перехвата сессии обмена

Используя механизм расширений конфигурации, мы можем внедрить перехватчик в общий модуль БСП ОбменДаннымиСервер (или в специализированный модуль плана обмена) с аннотацией &Вместо или &Перед.

Разберем пример модификации процедуры выгрузки данных через расширение:


&Вместо("ВыгрузитьДанныеДляУзлаОбмена")
Процедура Расш_ВыгрузитьДанныеДляУзлаОбмена(УзелИнформационнойБазы, ПараметрыВыгрузки)
    
    // Получаем выбранную пользователем организацию из параметров сеанса или нашего регистра настроек
    ТекущаяОрганизация = ПолучитьАктивнуюОрганизациюДляУзла(УзелИнформационнойБазы);
    
    Если ЗначениеЗаполнено(ТекущаяОрганизация) Тогда
        // Подменяем стандартный алгоритм формирования выборки изменений
        ВыгрузитьДанныеСОграничениемПоОрганизации(УзелИнформационнойБазы, ТекущаяОрганизация, ПараметрыВыгрузки);
    Иначе
        // Если организация не выбрана, вызываем стандартный типовой метод БСП
        ПродолжитьВызов(УзелИнформационнойБазы, ПараметрыВыгрузки);
    КонецЕсли;
    
КонецПроцедуры

---

4. Итоговые рекомендации и выводы

Подводя итог, выделим ключевые шаги по реализации точечного обмена по организациям:

  1. Откажитесь от множества узлов, если не хотите увязнуть в постоянной отладке правил регистрации общих справочников. Гораздо проще доработать один типовой узел обмена.
  2. Реализуйте фильтрацию выгрузки документов на базе алгоритма «Запрос по таблице изменений + массив ссылок». Это гарантирует сохранность регистрации неотправленных объектов.
  3. Используйте механизм расширений для хранения и передачи текущего контекста обмена (выбранной организации) между базами. Это позволит сохранить вашу конфигурацию на замке поддержки и значительно упростит последующие обновления баз 1С:ЗУП и 1С:УХ.
← На главную