Как заполнить нетиповое субконто в проводках документа, если стандартные механизмы этого не делают?

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

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

Выясним причину: ключевой момент, который нужно понять, — это то, что в момент выполнения кода внутри процедуры ОбработкаПроведения сами записи движений еще не существуют в базе данных. Они формируются в оперативной памяти в виде специальной коллекции Движения. Любые запросы к базе данных на этом этапе просто не увидят этих новых проводок. Поэтому для модификации движений нужно работать напрямую с этой коллекцией или выполнять действия уже после фактической записи документа.

Рассмотрим два основных способа решения этой проблемы.

Решение 1: Работа с коллекцией "Движения" напрямую в "ОбработкаПроведения"

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

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

Разберем по шагам:

  1. Вызывается стандартная логика проведения, которая заполняет коллекцию Движения.Хозрасчетный основными проводками.
  2. Далее в этой же процедуре мы организуем цикл, который перебирает все записи в этой коллекции.
  3. Внутри цикла мы проверяем условия: например, ищем проводку по определенному счету (Дт или Кт).
  4. Когда нужная проводка найдена, мы обращаемся к ее субконто и заполняем наше нетиповое субконто нужным значением.

Посмотрим на пример. Допустим, нам нужно в проводках по дебету счета 60.01 заполнить дополнительное субконто "НашеСубконто".


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

Важный момент: напрямую обращаться к коллекции Движения.Хозрасчетный — это единственно верный способ изменить формируемые проводки внутри самой процедуры ОбработкаПроведения.

Решение 2: Использование объекта "НаборЗаписей" после записи документа

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

Суть метода: мы подписываемся на событие, которое происходит после записи документа (например, событие формы ПослеЗаписи или подписка на событие объекта ОбработкаПроведения с источником-документом). В обработчике этого события мы читаем из базы данных только что созданные движения, изменяем их и записываем обратно.

Разберем этот процесс подробнее:

  1. Документ успешно проводится и записывается вместе со всеми своими движениями в базу данных.
  2. Срабатывает наш обработчик (например, в расширении в модуле формы документа в процедуре ПослеЗаписиНаСервере).
  3. Мы создаем объект НаборЗаписей для регистра бухгалтерии: РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей().
  4. В созданном наборе мы устанавливаем отбор по регистратору. В качестве регистратора выступает ссылка на наш только что записанный документ.
  5. Выполняем метод Прочитать(). Этот метод загружает из базы данных все проводки, сделанные нашим документом, в объект НаборЗаписей.
  6. Теперь, как и в первом способе, перебираем записи уже в этом наборе, находим нужные и заполняем субконто.
  7. В конце вызываем метод Записать() для набора записей. Это сохранит наши изменения в базе данных.

Посмотрим на пример реализации в расширении для события формы ПослеЗаписи:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    
    // Создаем набор записей для нужного регистра
    НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
    
    // Устанавливаем отбор по нашему документу
    НаборЗаписей.Отбор.Регистратор.Установить(ТекущийОбъект.Ссылка);
    
    // Читаем существующие движения документа из базы данных
    НаборЗаписей.Прочитать();
    
    // Перебираем прочитанные записи
    Для Каждого Запись Из НаборЗаписей Цикл
        
        // Анализируем запись и вносим изменения
        Если Запись.СчетДт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками Тогда
            
            ВидСубконтоНаше = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НашеСубконто;
            Запись.СубконтоДт[ВидСубконтоНаше] = СсылкаНаОбъектДляСубконто;
            
        КонецЕсли;
        
    КонецЦикла;
    
    // Записываем измененный набор обратно в базу данных
    НаборЗаписей.Записать();
    
КонецПроцедуры

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

← К списку