Как перенести данные о начислениях из 1С:Бухгалтерии в 1С:ЗУП с разделением на несколько документов?

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

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

Анализ ошибок в исходном коде

Выясним причину, почему исходный код автора не работает и вызывает ошибки выполнения:

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

    В тексте запроса указана секция СГРУППИРОВАТЬ ПО, однако не использованы агрегатные функции (например, СУММА(Сумма)). Кроме того, параметр Организация устанавливается в коде, но отсутствует в блоке ГДЕ.

  3. Некорректная работа с типами данных и коллекциями:

    Конструкция Если ТекСтрока = Поле пытается сравнить целую строку таблицы значений с неопределенной переменной. Для проверки булева признака необходимо обращаться к конкретному реквизиту строки: Если ТекСтрока.Поле Тогда.

    Присваивание ТЗ.Сотрудники = ... ошибочно, так как обращение идет ко всей таблице значений, а не к строке формируемой табличной части документа.

Варианты организации обмена между базами

Для передачи данных между разделенными конфигурациями выделим три основных подхода:

  1. Прямое COM-соединение (V83.COMConnector): база-источник подключается к базе-приемнику, находит необходимые элементы справочников и программно создает документы в ЗУП.
  2. Файловый обмен (JSON или XML): универсальный и платформонезависимый способ, при котором БП формирует файл выгрузки, а обработка в ЗУП загружает его.
  3. Использование HTTP-сервисов: передача данных через REST API без блокировок интерфейса и зависимости от разрядности операционной системы.

Особенности сопоставления объектов между БП и ЗУП

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

  1. Организации — по ИНН и КПП.
  2. Физические лица — по СНИЛС, ИНН или ФИО + Дате рождения.
  3. Сотрудники — поиск в ЗУП по физическому лицу, организации и трудовому договору или по табельному номеру (коду справочника Сотрудники).

Разделение строк на два документа

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


// Создаем два документа для разных условий
ДокументСПолем = БазаЗУП.Документы.РазовоеНачисление.СоздатьДокумент();
ДокументБезПоля = БазаЗУП.Документы.РазовоеНачисление.СоздатьДокумент();

Для Каждого СтрТЗ Из ТЗ Цикл
    Если СтрТЗ.Поле Тогда
        НоваяСтрока = ДокументСПолем.Начисления.Добавить();
    Иначе
        НоваяСтрока = ДокументБезПоля.Начисления.Добавить();
    КонецЕсли;
    
    // Заполнение реквизитов строки
    НоваяСтрока.Сотрудник = НайденныйСотрудникВЗУП;
    НоваяСтрока.Результат = СтрТЗ.Сумма;
КонецЦикла;

Пошаговый пример реализации выгрузки через COM-соединение

Разберем по шагам готовый код выгрузки данных из БП в ЗУП. Посмотрим на пример формирования корректного запроса и программного заполнения документов в подключенной базе:


Если НЕ ЗначениеЗаполнено(Организация) Тогда
    Сообщить("Не выбрана организация!");
    Возврат;
КонецЕсли;

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

Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ПериодРегистрации));
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ПериодРегистрации));

РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
    Сообщить("Данные для выгрузки отсутствуют.");
    Возврат;
КонецЕсли;

ТЗ = РезультатЗапроса.Выгрузить();

// 2. Подключаемся к базе-приемнику (ЗУП) через COM
Попытка
    V8 = Новый COMОбъект("V83.COMConnector");
    БазаЗУП = V8.Connect("File=""C:\Bases\ZUP"";Usr=""Admin"";Pwd=""123"";");
Исключение
    Сообщить("Ошибка подключения к ЗУП: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

// 3. Создаем два документа на стороне приемника
ДокФлагИстина = БазаЗУП.Документы.РегистрацияРазовыхНачисленийРаботниковОрганизаций.СоздатьДокумент();
ДокФлагИстина.Дата = ТекущаяДата();
ДокФлагИстина.ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
ДокФлагИстина.Комментарий = "Загрузка из БП (Питание: Поле = Истина)";

ДокФлагЛожь = БазаЗУП.Документы.РегистрацияРазовыхНачисленийРаботниковОрганизаций.СоздатьДокумент();
ДокФлагЛожь.Дата = ТекущаяДата();
ДокФлагЛожь.ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
ДокФлагЛожь.Комментарий = "Загрузка из БП (Питание: Поле = Ложь)";

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

// 5. Записываем заполненные документы
Если ДокФлагИстина.Начисления.Количество() > 0 Тогда
    ДокФлагИстина.Записать();
    Сообщить("Создан документ (Поле = Истина): " + Строка(ДокФлагИстина.Ссылка));
КонецЕсли;

Если ДокФлагЛожь.Начисления.Количество() > 0 Тогда
    ДокФлагЛожь.Записать();
    Сообщить("Создан документ (Поле = Ложь): " + Строка(ДокФлагЛожь.Ссылка));
КонецЕсли;

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

← На главную