При работе в крупных холдинговых структурах часто возникает ситуация, когда в единой базе 1С:Зарплата и управление персоналом 3.1 ведется учет по десяткам организаций, а обмен данными настроен с единой базой 1С:Управление холдингом 3.0 (или 1С:Бухгалтерия предприятия КОРП 3.0). В таких условиях стандартная синхронизация, выгружающая абсолютно все зарегистрированные изменения скопом, становится неэффективной и неудобной.
Представим сценарий: бухгалтеры по расчету заработной платы разных филиалов хотят запускать синхронизацию независимо друг от друга и выгружать только «свои» организации. При этом важно, чтобы объекты других организаций оставались зарегистрированными к обмену и не затирались. В этой статье мы подробно разберем, как решить эту задачу, обойдя ключевые ограничения платформы «1С:Предприятие 8.3» и Библиотеки стандартных подсистем (БСП).
---
Первый вопрос, который возникает у разработчика при реализации выборочной выгрузки: можно ли наложить фильтр по реквизиту прямо в методе получения изменений? Обратимся к синтаксису платформы.
Метод ПланыОбмена.ВыбратьИзменения(СсылкаНаУзел, НомерСообщения, ФильтрВыборки) действительно имеет параметр ФильтрВыборки. Однако платформа накладывает жесткое ограничение: в этот параметр нельзя передать произвольный SQL-запрос или условие вида Организация = &НашаОрганизация. В качестве фильтра можно использовать только:
Для реализации нашей задачи мы применим обходной путь: предварительный запрос к таблицам изменений + передача массива ссылок в фильтр выборки. Рассмотрим этот алгоритм на практике.
Сначала мы пишем запрос к виртуальной таблице изменений интересующего нас объекта (например, документа ОтражениеЗарплатыВБухучете), соединяя ее с основной таблицей этого же документа. Это позволит нам отфильтровать зарегистрированные изменения по реквизиту Организация.
Посмотрим на пример реализации функции сбора таких ссылок:
Функция ПолучитьМассивСсылокИзмененийСОтбором(УзелОбмена, ВыбраннаяОрганизация) Экспорт
МассивСсылок = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Изменения.Ссылка КАК Ссылка
|ИЗ
| Документ.ОтражениеЗарплатыВБухучете.Изменения КАК Изменения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтражениеЗарплатыВБухучете КАК ОтражениеЗарплаты
| ПО Изменения.Ссылка = ОтражениеЗарплаты.Ссылка
|ГДЕ
| Изменения.Узел = &Узел
| И ОтражениеЗарплаты.Организация = &Организация";
Запрос.УстановитьПараметр("Узел", УзелОбмена);
Запрос.УстановитьПараметр("Организация", ВыбраннаяОрганизация);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
МассивСсылок.Добавить(Выборка.Ссылка);
КонецЦикла;
Возврат МассивСсылок;
КонецФункции
Далее, при формировании сообщения обмена, мы передаем полученный массив в метод ПланыОбмена.ВыбратьИзменения:
Процедура ВыгрузитьИзмененияПоОрганизации(УзелОбмена, НомерСообщения, ВыбраннаяОрганизация)
МассивСсылок = ПолучитьМассивСсылокИзмененийСОтбором(УзелОбмена, ВыбраннаяОрганизация);
Если МассивСсылок.Количество() = 0 Тогда
ЗаписатьВЛог("Нет зарегистрированных изменений для выбранной организации.");
Возврат;
КонецЕсли;
// Формируем структуру фильтра выборки
ФильтрВыборки = Новый Структура;
ФильтрВыборки.Вставить("Документ.ОтражениеЗарплатыВБухучете", МассивСсылок);
// Получаем выборку изменений только по нужным документам
ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСообщения, ФильтрВыборки);
// Производим стандартную запись сообщения обмена XML...
КонецПроцедуры
Важная особенность механизма: при использовании такого подхода платформа автоматически присвоит номер отправленного сообщения НомерСообщения только тем объектам, ссылки на которые были переданы в массиве. Все остальные зарегистрированные изменения (по другим организациям) останутся нетронутыми и будут ждать своей очереди при последующих сеансах синхронизации.
---
Часто в обсуждениях предлагают простое решение: «Создайте для каждой организации отдельную настройку синхронизации (отдельный узел плана обмена)». Однако при попытке сделать это через стандартный помощник настройки БСП вы столкнетесь с ошибкой: система потребует уникальные префиксы информационных баз для каждого нового узла. Так как физически баз всего две (одна ЗУП и одна БУХ/УХ), префиксы у них одинаковые, и БСП заблокирует создание дублирующих настроек.
Проанализируем, как обойти это ограничение. Проверка уникальности префиксов — это ограничение экранных форм БСП, а не самой платформы. Сама платформа 1С позволяет создавать сколько угодно узлов в рамках одного плана обмена. Мы можем решить эту проблему двумя путями:
УХ_ОРГ1, УХ_ОРГ2), но сохраняем корректные настройки подключения.Х1). После завершения создания узла мы программно или через обработку «Регистрация изменений для обмена» меняем код узла на требуемый.Пример кода для программного создания узла плана обмена:
Процедура СоздатьНовыйУзелОбменаПрограммно(КодУзла, НаименованиеУзла)
ПланОбменаМенеджер = ПланыОбмена.ОбменЗарплата3Бухгалтерия3;
// Проверим, нет ли уже узла с таким кодом
НайденныйУзел = ПланОбменаМенеджер.НайтиПоКоду(КодУзла);
Если ЗначениеЗаполнено(НайденныйУзел) Тогда
Возврат;
КонецЕсли;
НовыйУзел = ПланОбменаМенеджер.СоздатьУзел();
НовыйУзел.Код = КодУзла;
NewУзел.Наименование = НаименованиеУзла;
НовыйУзел.Записать();
ЗаписатьВЛог("Узел " + КодУзла + " успешно создан.");
КонецПроцедуры
Важное предупреждение: если вы решите пойти по пути создания нескольких узлов обмена, вам придется переписать Правила регистрации объектов (ПРО). В противном случае любое изменение справочника (например, «Физические лица» или «Сотрудники») будет регистрироваться на всех созданных узлах, что приведет к избыточному дублированию данных в очередях выгрузки.
---
Если базы обмениваются напрямую через веб-сервисы, инициация процесса на стороне ЗУП автоматически вызывает ответную выгрузку/загрузку на стороне УХ. Как передать информацию о том, по какой именно организации пользователь запустил обмен в данный момент?
Рассмотрим наиболее надежные архитектурные варианты решения этой проблемы.
Мы создаем в обеих базах непериодический регистр сведений НастройкиСеансовОбменаДанными с измерениями УзелИнформационнойБазы и ресурсом ОрганизацияДляВыгрузки.
Перед тем как вызвать стандартный метод БСП ВыполнитьОбменДанными(), интерактивная кнопка «Синхронизировать» под управлением текущего пользователя записывает выбранную организацию в этот регистр.
Поскольку при веб-подключении база-корреспондент выполняет код в контексте того же узла обмена, при выгрузке данных на своей стороне она может легко прочитать текущую организацию из регистра и применить аналогичный фильтр к своим изменениям.
Используя механизм расширений конфигурации, мы можем внедрить перехватчик в общий модуль БСП ОбменДаннымиСервер (или в специализированный модуль плана обмена) с аннотацией &Вместо или &Перед.
Разберем пример модификации процедуры выгрузки данных через расширение:
&Вместо("ВыгрузитьДанныеДляУзлаОбмена")
Процедура Расш_ВыгрузитьДанныеДляУзлаОбмена(УзелИнформационнойБазы, ПараметрыВыгрузки)
// Получаем выбранную пользователем организацию из параметров сеанса или нашего регистра настроек
ТекущаяОрганизация = ПолучитьАктивнуюОрганизациюДляУзла(УзелИнформационнойБазы);
Если ЗначениеЗаполнено(ТекущаяОрганизация) Тогда
// Подменяем стандартный алгоритм формирования выборки изменений
ВыгрузитьДанныеСОграничениемПоОрганизации(УзелИнформационнойБазы, ТекущаяОрганизация, ПараметрыВыгрузки);
Иначе
// Если организация не выбрана, вызываем стандартный типовой метод БСП
ПродолжитьВызов(УзелИнформационнойБазы, ПараметрыВыгрузки);
КонецЕсли;
КонецПроцедуры
---
Подводя итог, выделим ключевые шаги по реализации точечного обмена по организациям: