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