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

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

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

Анализируем суть проблемы

Рассмотрим стандартную ситуацию: в коде обработки или формы мы создаем новый объект (например, номенклатуру контрагента) и заполняем его реквизит, имеющий определяемый тип. В отладчике мы видим, что значение объект.Партнер успешно передано в НовыйТовар.ВладелецНоменклатуры. Однако, открыв созданную карточку в интерфейсе, мы обнаруживаем, что поле пустое. Это классический признак того, что в конфигурации срабатывает программный механизм перезаполнения или очистки данных в момент транзакции записи.

Шаг 1. Проверка связи со стандартным полем Владелец

В типовых решениях (ERP, УТ 11, КА) многие справочники имеют иерархию подчинения. Реквизиты, относящиеся к БЭД, часто дублируют или дополняют стандартную логику платформы. Разберем важный нюанс: если объект НоменклатураКонтрагента (или аналогичный) имеет системное поле Владелец (Owner), то приоритет при записи всегда отдается ему.

Проанализируем код в модуле объекта. Часто там можно встретить подобную логику:


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

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

Шаг 2. Исследование подписок на события

Если в модуле объекта явного кода очистки нет, нам необходимо проверить подписки на события. В современных конфигурациях логика БЭД вынесена в отдельные общие модули, которые вызываются через подписки на событие ПередЗаписью.

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

  1. Перейдем в дерево метаданных: Общие -> Подписки на события.
  2. Найдем подписки, в которых в качестве источника указан ваш справочник или определяемый тип, в который он входит.
  3. Обратим внимание на подписки с названиями вроде УстановитьСостояниеОбъектаБЭД или СинхронизироватьРеквизитыНоменклатуры.

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

Шаг 3. Использование отладчика для поиска точки очистки

Чтобы точно выяснить, в какой момент пропадает значение, применим методику «остановки по условию». Рассмотрим алгоритм работы:

  1. Откроем модуль объекта записываемого справочника.
  2. Поставим точку останова в самой первой строке процедуры ПередЗаписью.
  3. Запустим запись объекта.
  4. В табло отладчика добавим выражение ЭтотОбъект.ВладелецНоменклатуры.
  5. Будем проходить код по шагам (F8), заходя внутрь всех вызываемых процедур (F11).

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

Шаг 4. Особенности работы с формой

Иногда проблема кроется не в модуле объекта, а в модуле формы. Если вы вызываете Записать() из формы, могут срабатывать обработчики ПередЗаписьюНаСервере или ПриЗаписиНаСервере. Рассмотрим пример типичной ошибки:


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

Помните, что в момент записи на сервере данные из реквизита формы Объект копируются в ТекущийОбъект (тип СправочникОбъект). Если после этого копирования, но до физической записи, код формы изменяет Объект, а не ТекущийОбъект, ваши изменения не попадут в базу данных.

Резюме и рекомендации

Для успешного присвоения значения реквизиту определяемого типа в подсистеме БЭД, придерживайтесь следующих правил:

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

← На главную