Как изменить движения документа в расширении 1С:Бухгалтерия 3.0 без снятия с поддержки?

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

При разработке расширений для типовых конфигураций, таких как 1С:Бухгалтерия предприятия 3.0, программисты часто сталкиваются с ситуацией, когда код по корректировке движений в обработчике проведения выполняется без ошибок, но результат в регистре не сохраняется. Кажется, что происходит какая-то "мистика": при включении флага "Ручная корректировка" изменения применяются, а в обычном режиме — игнорируются. В этой статье мы подробно разберем, почему это происходит, как работает механизм записи наборов записей в расширениях и как правильно изменять проводки, сохраняя конфигурацию на полной поддержке.

Анализ проблемы: почему движения не записываются

Рассмотрим стандартную ситуацию. Нам необходимо добавить забалансовую проводку или скорректировать суммы существующих проводок в документе. Мы создаем расширение, добавляем подписку на событие ОбработкаПроведения или расширяем сам метод ОбработкаПроведения в модуле объекта с помощью аннотации &После. Код выглядит логично: мы получаем набор записей, выгружаем его в таблицу значений, меняем данные и загружаем обратно. Однако после завершения транзакции в регистре Хозрасчетный остаются старые данные.

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

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

Решение через подписку на событие в расширении

Начиная с версии платформы 8.3.17, у разработчиков появилась возможность создавать подписки на события непосредственно внутри расширений. Это отличный способ избежать изменения модуля объекта документа. Разберем, как правильно реализовать корректировку через подписку.

Допустим, мы хотим изменить сумму всех проводок на 1 рубль для теста. Посмотрим на правильный алгоритм реализации в процедуре-обработчике подписки:


Процедура еаю_ПодпискаНаПроведение(Источник, Отказ, РежимПроведения) Экспорт
    // Получаем доступ к движениям по хозрасчетному регистру
    Проводки = Источник.Движения.Хозрасчетный;
    
    // Выгружаем в таблицу значений для удобства обработки
    ТЗ = Проводки.Выгрузить();
    
    Для каждого Стр Из ТЗ Цикл
        Стр.Сумма = 1; // Устанавливаем тестовую сумму
    КонецЦикла;
    
    // Загружаем измененные данные обратно в набор
    Проводки.Загрузить(ТЗ);
    
    // КРИТИЧЕСКИ ВАЖНЫЙ МОМЕНТ:
    // Указываем платформе, что набор записей нужно записать в БД
    Проводки.Записывать = Истина;
КонецПроцедуры

Именно строка Проводки.Записывать = Истина; является ключом к решению проблемы. Без неё все манипуляции с таблицей значений ТЗ останутся только в оперативной памяти и будут уничтожены при выходе из процедуры.

Использование расширения модуля объекта через аннотацию &После

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

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


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

КонецПроцедуры

Обратите внимание на использование переменной Движения. В модуле объекта она доступна напрямую. Установка Движения.Хозрасчетный.Записывать = Истина гарантирует, что ваши изменения "выживут" после окончания транзакции проведения.

Особенности механизма в 1С:Бухгалтерия 3.0

Проанализируем, почему в БП 3.0 часто возникают сложности с этим механизмом. В данной конфигурации активно используется метод отложенного проведения и выполнение кода в фоновых заданиях. Кроме того, существует процедура ТекстОтраженияВРеглУчете в модулях менеджеров, которая отвечает за генерацию текстов запросов для формирования движений. Если вы пытаетесь вмешаться в этот процесс, важно понимать следующие нюансы:

  1. Ручная корректировка: Когда пользователь устанавливает флаг РучнаяКорректировка = Истина, типовые алгоритмы ОбработкаПроведения просто пропускаются. В этом случае набор записей считывается из базы "как есть", и если ваше расширение его правит, изменения сохраняются, потому что флаг Записывать часто устанавливается формой документа автоматически.
  2. Замещение vs Добавление: Метод Проводки.Загрузить(ТЗ) полностью очищает текущий набор в памяти и заменяет его данными из ТЗ. Если в этот момент типовой код еще не закончил формирование всех движений (что бывает при сложных цепочках вызовов), вы можете случайно удалить важные проводки. Безопаснее использовать цикл Для Каждого или метод Добавить().
  3. Порядок выполнения подписок: Помните, что подписки в расширениях выполняются после подписок основной конфигурации. Если основная конфигурация в своей подписке устанавливает какие-то финальные проверки, ваше расширение может их нарушить.

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

Если ваша задача — добавить именно забалансовые проводки, рассмотрите возможность использования метода Добавить(). Это позволит не затрагивать существующие балансовые проводки, созданные типовым механизмом. Проанализируем пример добавления записи на забалансовый счет МЦ.04:


Проводка = Движения.Хозрасчетный.Добавить();
Проводка.Период = ЭтотОбъект.Дата;
Проводка.СчетДт = ПланыСчетов.Хозрасчетный.ИнвентарьИХозяйственныеПринадлежностиВЭксплуатации; // МЦ.04
Проводка.Организация = ЭтотОбъект.Организация;
Проводка.Содержание = "Отражение инвентаря в эксплуатации (расширение)";
// Установка субконто через типовой механизм
БухгалтерскийУчет.УстановитьСубконто(Проводка.СчетДт, Проводка.СубконтоДт, "Номенклатура", ВыбНоменклатура);
Проводка.КоличествоДт = 1;
Проводка.Сумма = 100;

Движения.Хозрасчетный.Записывать = Истина;

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

Заключение

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

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

← На главную