В процессе сопровождения конфигурации 1С:Бухгалтерия государственного учреждения 2.0 (БГУ 2.0) программисты часто сталкиваются с необходимостью корректировки проводок, сформированных стандартными документами. Одной из типичных задач является замена контрагента или другого субконто в уже сформированных движениях. В некоторых случаях, когда правок много, эффективнее использовать готовые средства для группового изменения проводок, но часто требуется именно программное решение в логике проведения.
Рассмотрим ситуацию, когда стандартные методы переопределения движений в расширении через &После("ОбработкаПроведения") не приносят результата: данные в регистре остаются прежними, несмотря на программную подмену. Разберем по шагам, почему так происходит и как правильно реализовать эту задачу.
Проанализируем типичную ошибку. Часто разработчик пытается создать новый НаборЗаписей, установить отбор по регистратору, прочитать его, изменить значения и записать. Особенно это актуально, когда требуется массовое исправление КЭК в проводках или замена КОСГУ на детализированные в зависимости от типа контрагента. В контексте процедуры ОбработкаПроведения это может не сработать по следующим причинам:
&После("ОбработкаПроведения") платформа еще удерживает коллекцию Движения в оперативной памяти. После завершения вашего кода платформа может автоматически выполнить Движения.Записать(), что полностью перезапишет ваши ручные изменения в базе данных.ЗаписьДвиженийПриПроведении = ЗаписыватьВыбранные, то платформа сама управляет тем, когда данные попадут в базу.Вместо создания стороннего набора записей, наиболее правильно работать с коллекцией ЭтотОбъект.Движения. Подобная логика часто применяется, когда требуется специфическая автоматическая замена продуктов в учете питания или распределение списания по КПС. Рассмотрим пример кода, который можно разместить в расширении для документа (например, Платежное поручение):
&После("ОбработкаПроведения")
Процедура Ист_ПослеОбработкаПроведения(Отказ, РежимПроведения)
// Получаем доступ к движениям регистра бухгалтерии
Проводки = ЭтотОбъект.Движения.ЖурналПроводокЕПСБУ;
// Если движения еще не прочитаны из БД или не сформированы в памяти, читаем их
Если Проводки.Количество() = 0 Тогда
Проводки.Прочитать();
КонецЕсли;
// Определяем нужного контрагента (например, из регистра сведений или функции)
НужныйКонтрагент = Ист_ПолучитьКонтрагентаПоОрганизации(ЭтотОбъект.Организация);
Если ЗначениеЗаполнено(НужныйКонтрагент) Тогда
Для Каждого Запись Из Проводки Цикл
// Проверяем счет (например, 302.11)
Если Запись.СчетДт = ПланыСчетов.ЕПСБУ.НайтиПоКоду("302.11") Тогда
// Устанавливаем новое субконто
ВидСубКонтрагенты = ПланыВидовХарактеристик.ВидыСубконтоТиповые.Контрагенты;
Запись.СубконтоДт.Вставить(ВидСубКонтрагенты, НужныйКонтрагент);
КонецЕсли;
КонецЦикла;
// Устанавливаем флаг записи и фиксируем изменения
Проводки.Записывать = Истина;
// В некоторых случаях явный вызов Записать() необходим, если транзакция близится к завершению
Проводки.Записать();
КонецЕсли;
КонецПроцедуры
Выясним причину, почему метод выше может быть неудобен: если документ перепроводится из различных обработок или групповым изменением объектов, логика в модуле документа может быть пропущена или отработать некорректно. Данный подход часто рассматривается как образец для подражания при замене КПС или других реквизитов в движениях. Самым надежным способом перехвата любых изменений в регистре является использование события ПередЗаписью в модуле набора записей самого регистра бухгалтерии ЖурналПроводокЕПСБУ.
Рассмотрим, как это реализовать в расширении:
ЖурналПроводокЕПСБУ.ПередЗаписью для набора записей.
&Перед("ПередЗаписью")
Процедура Ист_ПередЗаписью(Отказ, Замещение)
// "ЭтотОбъект" здесь — это сам НаборЗаписей, который готовится к записи в БД
Для Каждого Запись Из ЭтотОбъект Цикл
// Проверяем, что регистратор — нужный нам тип документа
Если ТипЗнч(Запись.Регистратор) = Тип("ДокументСсылка.ПлатежноеПоручение") Тогда
// Логика поиска контрагента
Организация = Запись.Организация;
НужныйКонтрагент = Ист_СерверныйМодуль.НайтиСопоставленногоКонтрагента(Организация);
Если ЗначениеЗаполнено(НужныйКонтрагент) Тогда
// Работаем с субконто через метод Вставить
ВидСуб = ПланыВидовХарактеристик.ВидыСубконтоТиповые.Контрагенты;
// Проверяем наличие счета и субконто на нем
Если Запись.СчетДт.ВидыСубконто.Найти(ВидСуб) <> Неопределено Тогда
Запись.СубконтоДт.Вставить(ВидСуб, НужныйКонтрагент);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Данный метод гарантирует, что даже если "Типовая операция" или внешняя обработка попытается записать движения, ваша логика подменит данные в самый последний момент перед фиксацией в базе данных.
Проанализируем механизм работы с коллекцией Субконто. В регистре бухгалтерии 1С это не просто набор полей, а специальная структура. При программной установке значений важно помнить:
.Вставить(ВидСубконто, Значение). Если вид субконто уже существует в записи, значение будет обновлено. Если нет — добавлено.Плане Видов Характеристик для данного вида субконто.СчетДт или СчетКт) в настройках плана счетов действительно присутствует этот вид субконто, иначе программная ошибка может не возникнуть, но данные не сохранятся.Разберем ситуацию со стороны учета. БГУ 2.0 — это сложная система, где проводки по ЕПСБУ тесно связаны с забалансовыми счетами и регистрами накопления. Например, при уплате налогов важно корректно отражать ИФО в расшифровке платежа, чтобы данные аналитики совпадали во всех регистрах. Внимание! Если вы меняете контрагента только в основной проводке, но забываете про связанные записи (кассовое исполнение, расчеты по обязательствам), отчетность может стать некорректной.
После реализации программного изменения обязательно выполните следующие действия:
Таким образом, программное изменение движений в БГУ 2.0 требует не только знания кода, но и понимания архитектуры "Типовых операций" и взаимосвязей между различными регистрами учета.