Перенос бухгалтерских проводок между различными конфигурациями 1С — распространенная задача при смене учетных систем, объединении баз или интеграции специализированных отраслевых решений (например, систем доверительного управления или учета некредитных финансовых организаций — НФО) с типовыми конфигурациями «1С:Бухгалтерия предприятия».
Разберем детально, как устроена архитектура проводок в 1С, как правильно выгрузить движения из регистра бухгалтерии источника и как программно создать документы ОперацияБух в базе-приемнике, избежав типичных ошибок при работе с наборами записей.
Проанализируем базовый принцип работы подсистемы бухгалтерского учета платформы 1С:Предприятие:
Регистратор). В типовых документах проводки формируются при проведении.ОперацияБух. Сам документ выступает заголовком и носителем ссылки-регистратора, а сами проводки хранятся в наборе записей соответствующего регистра бухгалтерии (например, Хозрасчетный или отраслевого ЕПС).ОперацияБух (сумма, содержание, организация) являются информационными полями шапки. Реальный балансовый и аналитический учет строится исключительно на строках движений регистра.Для извлечения движений из регистра бухгалтерии источника с субконто и аналитикой наиболее эффективно использовать виртуальную таблицу ДвиженияССубконто. Рассмотрим пример запроса, который выбирает проводки с отбором по периоду и конкретному аналитическому разрезу (например, измерению Портфель):
ВЫБРАТЬ
ЕПСДвиженияССубконто.Период КАК Период,
ЕПСДвиженияССубконто.Регистратор КАК Регистратор,
ЕПСДвиженияССубконто.НомерСтроки КАК НомерСтроки,
ЕПСДвиженияССубконто.Активность КАК Активность,
ЕПСДвиженияССубконто.СчетДт КАК СчетДт,
ЕПСДвиженияССубконто.СубконтоДт1 КАК СубконтоДт1,
ЕПСДвиженияССубконто.ВидСубконтоДт1 КАК ВидСубконтоДт1,
ЕПСДвиженияССубконто.СубконтоДт2 КАК СубконтоДт2,
ЕПСДвиженияССубконто.ВидСубконтоДт2 КАК ВидСубконтоДт2,
ЕПСДвиженияССубконто.СчетКт КАК СчетКт,
ЕПСДвиженияССубконто.СубконтоКт1 КАК СубконтоКт1,
ЕПСДвиженияССубконто.ВидСубконтоКт1 КАК ВидСубконтоКт1,
ЕПСДвиженияССубконто.СубконтоКт2 КАК СубконтоКт2,
ЕПСДвиженияССубконто.ВидСубконтоКт2 КАК ВидСубконтоКт2,
ЕПСДвиженияССубконто.Организация КАК Организация,
ЕПСДвиженияССубконто.Сумма КАК Сумма,
ЕПСДвиженияССубконто.Содержание КАК Содержание
ИЗ
РегистрБухгалтерии.ЕПС.ДвиженияССубконто(&НачДата, &КонДата, Портфель = &Портфель, , ) КАК ЕПСДвиженияССубконто
УПОРЯДОЧИТЬ ПО
ЕПСДвиженияССубконто.Регистратор,
ЕПСДвиженияССубконто.НомерСтроки
Важный момент: при выгрузке обязательна сортировка по полю Регистратор, чтобы при последующей обработке проводки одного исходного документа группировались в одну целевую операцию.
Частая ошибка начинающих разработчиков — создание и запись набора записей регистра на каждой итерации цикла по строкам таблицы данных. Рассмотрим, к чему это приводит:
// ОШИБОЧНЫЙ КОД
Для Каждого СтрТ Из Таблица Цикл
// ... создание документа ОперацияБух ...
// ОШИБКА: набор создается заново на каждой строке
РегХозрасчетный = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
РегХозрасчетный.Отбор.Регистратор.Значение = ДокОперацияСсылка;
РегЗапись = РегХозрасчетный.Добавить();
// Заполнение полей РегЗапись...
// ОШИБКА: перезапись набора затирает все добавленные ранее проводки документа!
РегХозрасчетный.Записать();
КонецЦикла;
Вызов метода СоздатьНаборЗаписей() инициализирует пустой набор. При вызове Записать() платформа перезаписывает движения регистратора. В результате в документе остается только одна последняя обработанная проводка.
Разберем по шагам правильную структуру алгоритма:
ОперацияБух.НаборЗаписей с отбором по ссылке нового документа.Добавить().БухгалтерскийУчет.УстановитьСубконто.Посмотрим на пример корректной реализации алгоритма загрузки:
Процедура ЗагрузитьПроводкиВОперации(ТаблицаПроводок)
ЗагрОрг = Справочники.Организации.НайтиПоНаименованию("ОАО ""РОНИН Траст""");
Ответственный = ПараметрыСеанса.ТекущийПользователь;
ТекущийРегистраторНомер = "";
ДокОперацияОбъект = Неопределено;
НаборЗаписей = Неопределено;
СуммаПоОперации = 0;
Для Каждого СтрТ Из ТаблицаПроводок Цикл
Если ПустаяСтрока(СтрТ.Период) Тогда
Продолжить;
КонецЕсли;
НомерИсходногоДокумента = СтрЗаменить(СтрТ.РегистраторНомер, ",", "");
// Проверяем, начался ли новый документ
Если НомерИсходногоДокумента <> ТекущийРегистраторНомер Тогда
// Если предыдущий набор был открыт — записываем его
Если НаборЗаписей <> Неопределено И НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Записать();
// Актуализируем итоговую сумму в шапке документа
ДокОперацияОбъект.СуммаОперации = СуммаПоОперации;
ДокОперацияОбъект.Записать();
КонецЕсли;
// Создаем новый документ ОперацияБух
ДокОперацияОбъект = Документы.ОперацияБух.СоздатьДокумент();
ДокОперацияОбъект.Номер = НомерИсходногоДокумента;
ДокОперацияОбъект.Дата = Дата(СтрТ.Период);
ДокОперацияОбъект.Организация = ЗагрОрг;
ДокОперацияОбъект.Ответственный = Ответственный;
ДокОперацияОбъект.Содержание = "Перенос проводок из внешней системы";
ДокОперацияОбъект.Комментарий = "Загружено обработкой " + Строка(ТекущаяДата());
ДокОперацияОбъект.Записать();
ТекущийРегистраторНомер = НомерИсходногоДокумента;
СуммаПоОперации = 0;
// Инициализируем набор записей для нового регистратора
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокОперацияОбъект.Ссылка);
КонецЕсли;
// Добавляем строку проводки в набор
РегЗапись = НаборЗаписей.Добавить();
РегЗапись.Период = Дата(СтрТ.Период);
РегЗапись.Регистратор = ДокОперацияОбъект.Ссылка;
РегЗапись.Организация = ЗагрОрг;
РегЗапись.Содержание = СтрТ.Содержание;
// Счета дебета и кредита
РегЗапись.СчетДт = ПланыСчетов.Хозрасчетный.НайтиПоКоду(СтрЗаменить(СтрТ.СчетДт, ".", ""));
РегЗапись.СчетКт = ПланыСчетов.Хозрасчетный.НайтиПоКоду(СтрЗаменить(СтрТ.СчетКт, ".", ""));
// Установка субконто по Дебету
Если ЗначениеЗаполнено(СтрТ.ВидСубконтоДт1) И ЗначениеЗаполнено(РегЗапись.СчетДт) Тогда
ВидСубконтоДт = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НайтиПоНаименованию(СтрТ.ВидСубконтоДт1);
ЗначениеСубконто = НайтиВСПР(СтрТ.ВидСубконтоДт1, СтрТ.СубконтоДт1);
БухгалтерскийУчет.УстановитьСубконто(РегЗапись.СчетДт, РегЗапись.СубконтоДт, ВидСубконтоДт, ЗначениеСубконто);
КонецЕсли;
// Установка субконто по Кредиту
Если ЗначениеЗаполнено(СтрТ.ВидСубконтоКт1) И ЗначениеЗаполнено(РегЗапись.СчетКт) Тогда
ВидСубконтоКт = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НайтиПоНаименованию(СтрТ.ВидСубконтоКт1);
ЗначениеСубконто = НайтиВСПР(СтрТ.ВидСубконтоКт1, СтрТ.СубконтоКт1);
БухгалтерскийУчет.УстановитьСубконто(РегЗапись.СчетКт, РегЗапись.СубконтоКт, ВидСубконтоКт, ЗначениеСубконто);
КонецЕсли;
РегЗапись.Сумма = Число(СтрТ.Сумма);
СуммаПоОперации = СуммаПоОперации + РегЗапись.Сумма;
КонецЦикла;
// Записываем последний обработанный набор записей
Если НаборЗаписей <> Неопределено И НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Записать();
ДокОперацияОбъект.СуммаОперации = СуммаПоОперации;
ДокОперацияОбъект.Записать();
КонецЕсли;
КонецПроцедуры
При реализации переноса проводок между базами 1С следует сопоставить трудозатраты выбранного подхода: