Почему при проведении документа из списка не заполняется измерение регистра, а из формы все работает?

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

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

Анализ причины: разделение контекста формы и модуля объекта

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

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

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

Способ 1. Перенос инициализации в обработчик «ОбработкаЗаполнения»

Для автоматической подстановки значений по умолчанию при создании новых документов платформа предоставляет специальный обработчик уровня объекта — ОбработкаЗаполнения. Он вызывается как при интерактивном создании нового документа, так и при программном вызове метода Заполнить().

Откроем модуль объекта документа и перенесем получение константы в процедуру ОбработкаЗаполнения:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    // Заполняем реквизит только если он еще не заполнен
    Если Не ЗначениеЗаполнено(Склад) Тогда
        Склад = Константы.СкладОприходования.Получить();
    КонецЕсли;
    
КонецПроцедуры

Таким образом, реквизит Склад будет гарантированно предзаполнен уже в момент первоначального создания объекта, еще до открытия формы.

Способ 2. Контроль и автозаполнение перед записью документа

Если реквизит является обязательным для проведения документа и должен подставляться автоматически, даже если документ создавался программно без вызова заполнения, вынесем логику в обработчик ПередЗаписью модуля объекта.

Разберем реализацию проверки и автоподстановки:


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

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

Способ 3. Получение резервного значения в обработке проведения

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

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


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

Способ 4. Использование подписки на событие

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

  1. Создадим в дереве метаданных новый объект ПодпискаНаСобытие.
  2. В свойстве Источник укажем ДокументОбъект.ИмяДокумента.
  3. В качестве события выберем ПередЗаписью.
  4. Создадим процедуру в общем серверном модуле и выполним проверку значения Источник.Склад.

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

Платформенные нюансы и очистка серверного кэша

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

  1. Динамическое обновление конфигурации: при обновлении без перезапуска кластера серверов рабочие процессы могут кэшировать старые версии модулей. Клиентские сеансы и серверные фоновые задания при этом могут исполнять разные версии скомпилированного байт-кода. Решением является перезапуск рабочих процессов кластера «1С» и очистка серверного кэша.
  2. Специфика сборок платформы: в некоторых ранних сборках ветки 8.3.10 встречались ошибки десинхронизации серверного контекста при выполнении групповых операций над документами. Обновление технологической платформы до актуального стабильного релиза устраняет подобные сбои кэширования метаданных.
← На главную