При переносе бухгалтерских проводок между конфигурациями 1С (например, из специализированной базы расчета зарплаты в ERP или Бухгалтерию предприятия) разработчики часто сталкиваются с неприятным эффектом: в оборотно-сальдовой ведомости базы-приемника по некоторым счетам «раздваиваются» строки с пустыми субконто. При этом остатки по дебету и кредиту не закрываются между собой, хотя визуально аналитика выглядит абсолютно одинаково — пустые поля. Выясняется, что в одном случае значением является Неопределено (или пустая ссылка), а в другом — физический NULL на уровне базы данных СУБД.
В этой статье мы подробно разберем, почему возникает эта проблема, как на нее влияет свойство ОбменДанными.Загрузка = Истина, и рассмотрим практические варианты ее решения как на уровне правил обмена данными, так и программными средствами.
Для того чтобы понять природу возникновения проблемы, проанализируем устройство таблиц регистра бухгалтерии на уровне базы данных SQL. Платформа «1С:Предприятие» хранит движения регистра не в одной плоской таблице, а разделяет их на несколько связанных сущностей:
_AccRg). Здесь хранятся ключевые реквизиты проводки: период, регистратор, номер строки, счета дебета и кредита, валюта, количество, сумма._AccRgED). В ней хранятся конкретные аналитические разрезы для каждой проводки. Записи в ней связаны с основной таблицей по полям периода, регистратора и номера строки. Количество строк в этой таблице зависит от того, сколько субконто определено для счета в проводке и заполнены ли они.При формировании бухгалтерских отчетов или обращении к виртуальным таблицам (например, ОстаткиИОбороты) платформа выполняет левое соединение (LEFT JOIN) основной таблицы движений со вспомогательной таблицей значений субконто. Если в таблице значений субконто отсутствует запись для конкретного разреза аналитики, результатом левого соединения становится значение NULL.
Выясним причину, почему при обычном проведении документов в пользовательском режиме аналитика заполняется корректно, а при обмене данными возникает сбой. Все дело во флаге ОбменДанными.Загрузка:
ОбменДанными.Загрузка = Ложь (Обычная запись):Неопределено или пустой ссылкой соответствующего типа. Благодаря этому при последующем соединении таблиц в запросах всегда возвращается корректное пустое значение, а не NULL.ОбменДанными.Загрузка = Истина (Режим загрузки данных):NULL.Поскольку при обмене данными через конвертацию (КД 2.1 или КД 3.0) штатный XML-сериализатор выгружает пустые значения и значения с типом Неопределено как отсутствующие узлы, в базу-приемник они приходят в виде пустых коллекций. Рассмотрим, как решить эту проблему несколькими способами.
Самый логичный путь — настроить правила обмена так, чтобы в файл выгрузки попадали явные значения пустых субконто. Для этого проанализируем обработчики событий в правилах конвертации свойств (ПКС) для коллекции субконто регистра бухгалтерии.
В ПКС для субконто (например, СубконтоДт и СубконтоКт) мы можем программно инициализировать коллекцию перед непосредственной выгрузкой данных. Пример кода для обработчика ПередВыгрузкой свойства:
// Проверим, заполнены ли субконто у счета дебета
Для Каждого ВидСубконто Из НомерПроводки.СчетДт.ВидыСубконто Цикл
КлючСубконто = ВидСубконто.ВидСубконто;
Если Не НомерПроводки.СубконтоДт.Свойство(КлючСубконто) Тогда
// Принудительно вставляем пустое значение Неопределено
НомерПроводки.СубконтоДт.Вставить(КлючСубконто, Неопределено);
КонецЕсли;
КонецЦикла;
Аналогичный код необходимо написать и для субконто кредита СубконтоКт. При таком подходе в XML-файл выгрузки будут записаны явные указания видов субконто со значениями, которые платформа-приемник сможет корректно обработать даже в режиме Загрузка = Истина.
Если по каким-то причинам изменить правила выгрузки на стороне источника невозможно, мы можем скорректировать поведение при загрузке. Нам потребуется обработать загруженный документ в базе-приемнике. Однако напрямую в обработчике ПослеЗагрузки ПКО документа вызывать перепроведение или запись движений не рекомендуется, так как это сильно замедлит процесс импорта данных.
Вместо этого мы применим методику отложенной перезаписи наборов движений. Разберем этот алгоритм по шагам:
Шаг 1. В обработчике ПослеЗагрузки ПКО документа собираем ссылки на все загруженные документы в специальный массив параметров:
Если Не Параметры.Свойство("ДокументыДляИсправленияСубконто") Тогда
Параметры.Вставить("ДокументыДляИсправленияСубконто", Новый Массив);
КонецЕсли;
Параметры.ДокументыДляИсправленияСубконто.Добавить(Объект.Ссылка);
Шаг 2. В глобальном обработчике конвертации ПослеЗагрузкиДанных (который выполняется один раз в самом конце, когда весь файл обмена уже прочитан и все транзакции завершены) мы обходим накопленный массив документов и перезаписываем их движения в обычном режиме:
Если Параметры.Свойство("ДокументыДляИсправленияСубконто") Тогда
Для Каждого СсылкаДок Из Параметры.ДокументыДляИсправленияСубконто Цикл
// Создаем набор записей для регистра бухгалтерии
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаДок);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
// Устанавливаем режим Загрузка в Ложь, чтобы платформа
// автоматически заполнила пустые значения субконто в СУБД
НаборЗаписей.ОбменДанными.Загрузка = Ложь;
Попытка
НаборЗаписей.Записать();
Исключение
ЗаписьЖурналаРегистрации("ОбменДанными.ИсправлениеСубконто",
УровеньЖурналаРегистрации.Ошибка,
,
СсылкаДок,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
При перезаписи набора записей с установленным свойством ОбменДанными.Загрузка = Ложь платформа самостоятельно проанализирует структуру метаданных счетов, найдет все незаполненные субконто и добавит строки по умолчанию во вспомогательную таблицу СУБД. Проблема с NULL будет полностью решена.
Если обмен данными уже был произведен, в базе накопилось огромное количество документов с битыми движениями, а отчеты (ОСВ, Карточка счета) показывают некорректные остатки, не спешите писать сложные групповые обработки по перепроведению документов. В современных конфигурациях, работающих под управлением «1С:Библиотеки стандартных подсистем» (БСП), предусмотрен штатный механизм исправления таких ситуаций.
Рассмотрим, как запустить этот инструмент в пользовательском режиме:
NULL), и автоматически создаст для них пустые записи-заглушки.Преимущество этого метода заключается в том, что исправление происходит быстро, точечно и не требует монопольного режима работы пользователей, а также не приводит к изменению дат и авторов документов-регистраторов.
Подводя итог, отметим, что для предотвращения проблемы в будущем наиболее надежным является Решение 2 с использованием отложенной перезаписи наборов движений. Оно гарантирует, что даже при изменении структуры метаданных (например, при добавлении новых субконто на счета в базе-приемнике) движения загруженных документов автоматически приведутся к правильному виду.