Как прочитать движения документа в подписке на событие "ОбработкаПроведения"?

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

Разработчики часто сталкиваются с ситуацией, когда в подписке на событие ОбработкаПроведения коллекция движений документа (например, Источник.Движения.ЖурналПроводокЕПСБУ) оказывается пустой либо содержит старые записи, существовавшие до текущего проведения. Попытки прочитать движения запросом к базе данных или через метод Прочитать() набора записей также не приносят результата.

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

Почему движения не видны в подписке?

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

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

Решение 1: Получение движений из оперативной памяти

Чтобы прочитать проводки, которые документ подготовил к записи, нельзя обращаться к базе данных или считывать набор заново. Данные уже сформированы в памяти и находятся непосредственно в объекте документа. Чтобы получить их, мы должны использовать метод Выгрузить().

Рассмотрим пример кода в подписке на событие:


// Получаем движения, сформированные в оперативной памяти
ТаблицаПроводок = Источник.Движения.ЖурналПроводокЕПСБУ.Выгрузить();

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

Метод Выгрузить() позволяет безопасно скопировать текущее состояние набора записей регистра в таблицу значений без обращения к СУБД и без риска затереть кэш транзакции.

Решение 2: Обход очистки проводок в БГУ 2.0

Если вы работаете в БГУ 2.0 и ваши программно созданные движения очищаются общим модулем проведения БГУ, необходимо сообщить системе, что проведение выполняется в ручном режиме (как бухгалтерская операция). Это делается путем добавления специального флага в структуру дополнительных свойств источника.

Добавим в код формирования движений или непосредственно в начало обработчика подписки следующий блок:


// Предотвращаем автоматическую очистку движений механизмами БГУ 2.0
Если Не Источник.ДополнительныеСвойства.Свойство("ДанныеАвтопроведения") Тогда
    Источник.ДополнительныеСвойства.Вставить("ДанныеАвтопроведения", Новый Структура("ЭтоБухоперация", Истина));
Иначе
    Источник.ДополнительныеСвойства.ДанныеАвтопроведения.ЭтоБухоперация = Истина;
КонецЕсли;

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

Решение 3: Альтернативный архитектурный подход (подписка на регистр)

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

Гораздо надежнее и правильнее использовать подписку на событие ПередЗаписью набора записей самого регистра (в данном случае РегистрБухгалтерииНаборЗаписей.ЖурналПроводокЕПСБУ).

Разберем преимущества этого подхода:

  1. В этот момент все движения гарантированно сформированы документом.
  2. Вы можете напрямую модифицировать строки набора, так как в качестве параметра Источник в обработчик передается сам набор записей регистра.
  3. Ссылка на документ-регистратор легко получается через отбор набора.

Пример кода для обработчика подписки на событие ПередЗаписью регистра бухгалтерии:


Процедура ПередЗаписьюРегистраБухгалтерииПередЗаписью(Источник, Отказ, Замещение) Экспорт
    
    // Получаем ссылку на документ-регистратор
    Регистратор = Источник.Отбор.Регистратор.Значение;
    
    // Проверяем тип документа, если обработка нужна только для конкретного вида
    Если ТипЗнч(Регистратор) = Тип("ДокументСсылка.ПоступлениеМЗ") Тогда
        
        // Анализируем и модифицируем проводки напрямую в источнике
        Для Каждого Запись Из Источник Цикл
            // Пример модификации субконто
            // Запись.СубконтоДт[ПараметрСубконто] = Значение;
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры

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

← На главную