Как убрать остаток по субконто со значением NULL в регистре бухгалтерии 1С?

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

В практике сопровождения баз 1С периодически возникает ситуация, когда в отчетах (например, в оборотно-сальдовой ведомости) или в результатах запроса к виртуальной таблице остатков регистра бухгалтерии появляется «зависшее» сальдо. При этом одно из субконто принимает значение NULL, а второе — Неопределено или пустое значение. Попытки закрыть такой остаток ручной операцией не приводят к успеху, так как интерактивно подставить NULL в аналитику проводки невозможно. Разберем архитектурные причины этой ошибки и пошаговые методы ее исправления.

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


ВЫБРАТЬ
    ТиповойОстатки.Субконто1 КАК Субконто1,
    ТиповойОстатки.Субконто2 КАК Субконто2,
    ТИПЗНАЧЕНИЯ(ТиповойОстатки.Субконто1) КАК ТипСубконто1,
    ТИПЗНАЧЕНИЯ(ТиповойОстатки.Субконто2) КАК ТипСубконто2,
    ТиповойОстатки.Организация КАК Организация,
    ТиповойОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
    РегистрБухгалтерии.Типовой.Остатки(&КонецПериода, Счет = &Счет, &МассивСубконто, ) КАК ТиповойОстатки

Архитектурная причина появления значения NULL в субконто

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

Разберем различия между типами пустых значений:

  1. Пустая ссылка — строка в таблице субконто существует и содержит ссылку на предопределенное пустое значение конкретного справочника или документа.
  2. Неопределено — строка в таблице субконто существует, но тип субконто является составным и конкретное значение не выбрано.
  3. NULL — в физической таблице значений субконто для данной проводки запись по соответствующему номеру субконто физически отсутствует. В результате левого соединения платформа возвращает NULL.

Выделим основные сценарии, приводящие к отсутствию строк в таблице субконто:

  1. Изменение состава субконто на счете плана счетов. Если к счету, по которому уже велся учет, добавили новый вид субконто или изменили их порядок, старые движения автоматически не дополняются новыми строками аналитики.
  2. Загрузка данных и обмены. При программном создании движений с установленным флагом ОбменДанными.Загрузка = Истина типовые механизмы платформы по автозаполнению пустых видов субконто отключаются.
  3. Ошибки при обновлении конфигурации или свертке базы. Обработки обновления или ввода остатков могли перенести суммы без полной инициализации всех субконто счета.

Почему стандартное тестирование и исправление (ТИИ) не помогает

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

Способ 1. Поиск регистратора и перепроведение документов

Если отчетный период открыт для редактирования, наиболее простым решением является поиск документов-регистраторов, сформировавших некорректные движения, и их перепроведение.

Разберем последовательность действий:

  1. Обратимся напрямую к физической таблице движений регистра (не к виртуальным таблицам остатков или оборотов), чтобы локализовать проблемные записи.
  2. Сформируем запрос к таблице движений за период возникновения остатка с отбором по счету:
    
    ВЫБРАТЬ
        Движения.Регистратор КАК Регистратор,
        Движения.Период КАК Период,
        Движения.НомерСтроки КАК НомерСтроки,
        Движения.СчетДт КАК СчетДт,
        Движения.СчетКт КАК СчетКт,
        Движения.СубконтоДт1 КАК СубконтоДт1,
        Движения.СубконтоКт1 КАК СубконтоКт1
    ИЗ
        РегистрБухгалтерии.Типовой КАК Движения
    ГДЕ
        Движения.Период МЕЖДУ &ДатаНач И &ДатаКон
        И (Движения.СчетДт = &Счет ИЛИ Движения.СчетКт = &Счет)
    
  3. Определим документы (часто это документы начисления заработной платы или отражения зарплаты в регл. учете), в которых поля субконто не заполнены.
  4. Выполним перепроведение найденных документов. При штатном проведении документ перезапишет движения, автоматически сформировав строки в таблице субконто с корректными пустыми ссылками нужного типа.

Способ 2. Программная перезапись наборов записей без перепроведения

Если документы находятся в закрытом периоде и выполнять повторное проведение нельзя, применим метод программной перезаписи наборов записей регистра бухгалтерии. При записи набора без флага загрузки данных платформа 1С автоматически приводит состав субконто к актуальной структуре счета.

Рассмотрим пример кода для программной корректировки набора записей:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	Движения.Регистратор КАК Регистратор
    |ИЗ
    |	РегистрБухгалтерии.Типовой КАК Движения
    |ГДЕ
    |	(Движения.СчетДт = &Счет ИЛИ Движения.СчетКт = &Счет)
    |	И Движения.Период МЕЖДУ &ДатаНач И &ДатаКон";

Запрос.УстановитьПараметр("Счет", НужныйСчет);
Запрос.УстановитьПараметр("ДатаНач", НачалоДня(ВыбДатаНач));
Запрос.УстановитьПараметр("ДатаКон", КонецДня(ВыбДатаКон));

Выборка = Запрос.Выполнить().Выбрать();

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

Способ 3. Адресное заполнение субконто в наборе записей

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

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


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

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

Набор.Записать();

После выполнения перезаписи наборов записей или перепроведения документов обязательно выполним контрольный запрос к виртуальной таблице Остатки. Значения NULL исчезнут, а аналитика схлопнется в корректное сальдо.

← На главную