Почему программно созданная группа номенклатуры исчезает из базы 1С:Комплексная автоматизация?

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

При разработке механизмов автоматизации в 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда объект (например, группа номенклатуры) успешно создается в коде, его можно увидеть при отладке, он даже фиксируется в Журнале регистрации, но после завершения работы алгоритма объект бесследно исчезает. Вместо него в системе остаются лишь «битые» ссылки вида <Объект не найден>. Рассмотрим подробно, почему так происходит, проанализируем внутренние механизмы платформы и разберем правильный подход к программному созданию элементов в сложных конфигурациях, таких как 1С:Комплексная автоматизация 2.5 или 1С:ERP.

Разбор исходной ситуации: механизм появления «фантомных» объектов

Представим ситуацию: мы пишем обработку для загрузки структуры каталога номенклатуры. Код выглядит логично, используется метод СоздатьГруппу(), заполняются реквизиты, вызывается метод Записать(). В процессе выполнения мы видим сообщение в консоли: «Создана новая группа». Однако, открыв справочник в пользовательском интерфейсе, мы не обнаруживаем созданного элемента. Проверка Журнала регистрации подтверждает: событие «Добавление» было зафиксировано, указан GUID нового объекта, но при попытке перейти по ссылке мы получаем ошибку.

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

Выясним, почему Журнал регистрации вводит в заблуждение. Журнал регистрации фиксирует факт обращения к объекту в момент вызова метода Записать(). Если после этого выполнение кода прерывается (например, из-за ошибки) или процедура просто завершается без явной фиксации открытой транзакции, платформа инициирует автоматический откат (Rollback). При откате записи из таблиц базы данных удаляются, но запись в Журнале регистрации, которая уже была сформирована, остается неизменной. В итоге мы имеем запись о создании объекта, которого фактически нет в базе.

Анализ программного кода создания группы

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


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

В приведенном коде на первый взгляд все верно. Однако, если эта логика вложена в другую процедуру, где ранее была вызвана функция НачатьТранзакцию(), и разработчик забыл закрыть её парой ЗафиксироватьТранзакцию(), то выполнение Нов.Записать() пройдет успешно, но результат не сохранится.

Как правильно работать с транзакциями

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

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

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


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

Специфика справочника Номенклатура в 1С:КА 2.5 и ERP 2.5

Справочник Номенклатура в современных конфигурациях на базе подсистемы «Библиотека стандартных подсистем» (БСП) имеет свои особенности, которые нужно учитывать при программном создании элементов:

1. Реквизит КодДляПоиска. В конфигурации Комплексная автоматизация 2.5 этот реквизит используется для индексации и быстрого подбора. Если вы создаете элементы программно и не заполняете его (или заполняете некорректно), это может привести к проблемам при работе в формах списка. Рекомендуется дублировать в него очищенный от префиксов числовой код или использовать типовые методы конфигурации для генерации этого значения.

2. Режим ОбменДанными.Загрузка. При массовом создании групп номенклатуры крайне важно устанавливать свойство Нов.ОбменДанными.Загрузка = Истина. Это отключает «тяжелые» проверки в модуле объекта и модуле менеджера, а также предотвращает запуск дополнительных подписок на события, которые могут инициировать собственные транзакции или проверки прав доступа (RLS).

Рассмотрим, как это выглядит в коде:


НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.ОбменДанными.Загрузка = Истина;
НоваяГруппа.Наименование = "Новая папка";
НоваяГруппа.Записать();

3. Иерархия. Убедитесь, что реквизит Родитель является ссылкой именно на группу (иерархия групп и элементов). В 1С:КА 2.5 справочник номенклатуры поддерживает иерархию групп, поэтому при программной установке родителя важно предварительно найти его и убедиться, что ссылка ЭтоГруппа = Истина.

Методы диагностики проблем

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

  1. Глобальный поиск по коду. Выполните поиск по строке НачатьТранзакцию во всем модуле или конфигурации. Проверьте, что на каждый вызов этого метода существует соответствующий вызов ЗафиксироватьТранзакцию или ОтменитьТранзакцию. Часто ошибка кроется в использовании условий (Если...Тогда), из-за которых код обходит строку фиксации.
  2. Использование функции ТранзакцияАктивна(). В процессе отладки, прямо перед выходом из процедуры, добавьте проверку: Если ТранзакцияАктивна() Тогда ВызватьИсключение "Транзакция не закрыта!"; КонецЕсли;. Это позволит моментально обнаружить проблему на этапе разработки.
  3. Проверка прав доступа (RLS). Выясним ситуацию с ограничениями доступа. Иногда объект физически записывается в базу, но из-за настроек RLS (Access Control List) текущий пользователь не имеет прав на чтение созданной группы в конкретном родителе. В этом случае для пользователя объект будет выглядеть как <Объект не найден>, хотя в базе он существует. Попробуйте проверить наличие объекта под пользователем с полными правами.

Итоги и рекомендации

Мы проанализировали ситуацию, когда программно созданная группа номенклатуры в 1С:КА 2.5 исчезает из базы. Основной причиной является незавершенная транзакция, которая откатывается платформой по завершении выполнения кода. Помните, что запись в Журнал регистрации не гарантирует физического сохранения данных в таблицах СУБД, если не была выполнена команда фиксации.

Для стабильной работы ваших алгоритмов всегда используйте явное управление транзакциями, устанавливайте флаг ОбменДанными.Загрузка = Истина для снижения нагрузки на систему и корректно заполняйте специфические реквизиты конфигурации, такие как КодДляПоиска. Такой подход гарантирует целостность данных и отсутствие «битых» ссылок в справочниках.

← На главную