Почему на невалютном счете появляется валюта в виде пустой ссылки и как это исправить

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

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

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

Различие между Неопределено, NULL и Пустой ссылкой

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

  1. NULL — это отсутствие значения в поле базы данных. В запросах к регистру бухгалтерии для невалютного счета поле Валюта обычно возвращает NULL, если запись не предполагает валютного учета.
  2. Неопределено — это специальное значение платформы, означающее отсутствие значения для составного типа или типа «Любая ссылка». Именно его мы видим в отладчике, когда обращаемся к свойству Валюта записи регистра.
  3. Пустая ссылка — это объектное значение конкретного типа (в нашем случае СправочникСсылка.Валюты), которое физически записано в базу данных как уникальный идентификатор (GUID), состоящий из нулей.

Проблема заключается в том, что для платформы 1С «Пустая ссылка» — это валидное значение типа СправочникСсылка.Валюты. Если оно попадает в измерение или ресурс, система считает поле заполненным, что ломает логику запросов, построенных на проверке ЕСТЬNULL или ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка).

Причина №1: Использование механизма ОбменДанными.Загрузка

Это самая распространенная причина. Рассмотрим ситуацию, когда данные загружаются из внешней системы или другой базы через правила обмена (КД 2.0 или КД 3.0). При записи набора записей регистра обычно устанавливается флаг:


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

Когда ОбменДанными.Загрузка = Истина, платформа отключает большинство стандартных проверок и обработчиков событий (ПередЗаписью, ПриЗаписи). Если в загружаемых данных (XML или JSON) для поля валюты была передана пустая ссылка, платформа запишет её «как есть», не проверяя, является ли счет валютным в текущем плане счетов. В обычном режиме записи платформа стремится привести значения к соответствию метаданным, но в режиме загрузки бизнес-логика игнорируется.

Причина №2: Изменение признака счета «Валютный» в процессе эксплуатации

Проанализируем сценарий, когда счет изначально был создан как валютный. По нему были сделаны проводки, где поле Валюта было заполнено (например, «USD»). Позже бухгалтер понимает, что валютный учет на этом счете не нужен, и снимает флаг Валютный в Плане счетов.

В этот момент платформа не производит ревизию миллионов записей в регистре бухгалтерии, так как это была бы крайне ресурсоемкая операция. Значение «USD» остается в таблице БД. При последующем перепроведении документов или программной записи набора, если в коде явно не указано очищение, старое значение может трансформироваться в пустую ссылку или остаться висеть «мусором», который виден в запросах.

Причина №3: Ошибки в правилах конвертации данных (КД 2.0)

Выясним, как настройки ПКО (Правил Конвертации Объектов) влияют на результат. Если в правилах обмена для свойства Валюта не прописано условие проверки счета, может возникнуть следующая ситуация:

  1. В базе-источнике значение валюты не заполнено (равно NULL).
  2. При выгрузке ПКО преобразует это в пустую ссылку типа СправочникСсылка.Валюты.
  3. База-приемник получает этот объект и записывает его в измерение регистра.

Чтобы избежать этого, в ПКС (Правилах Конвертации Свойств) для валюты часто добавляют код, проверяющий Счет.Валютный. Если проверка отсутствует, «пустышка» гарантированно попадет в базу.

Причина №4: Соединения в запросах и виртуальные таблицы

Иногда «пустая ссылка» появляется только в результатах запроса, хотя в самих данных её нет. Разберем пример:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ЕСТЬNULL(ХозрасчетныйОстатки.Валюта, ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)) КАК ВалютаДляОтчета
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , , ) КАК ХозрасчетныйОстатки

Если счет не валютный, поле Валюта в виртуальной таблице будет NULL. Функция ЕСТЬNULL заменит его на пустую ссылку, которую вы указали. В дальнейшем, если этот результат запроса используется для заполнения набора записей (например, при свертке базы или корректировке остатков), пустая ссылка запишется в регистр как физическое значение.

Как смоделировать и исправить проблему программно

Если вам нужно воспроизвести этот косяк для отладки, попробуйте записать набор записей с установленным признаком загрузки, принудительно подставив пустую ссылку:


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

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

Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();

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


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

Подведем итоги

Появление пустой ссылки на невалютном счете — это результат отключения стандартной бизнес-логики платформы при записи данных. Чаще всего это происходит при обменах или некорректной программной манипуляции наборами записей.

Основные выводы для работы:

Проанализировав эти причины, мы можем сделать вывод, что «магия» исчезновения или появления данных всегда имеет под собой четкое техническое обоснование, связанное с режимами записи объектов в 1С.

← На главную