При доработке алгоритмов проведения документов разработчики нередко сталкиваются с ситуацией, когда добавление собственной проводки в коллекцию Движения.Хозрасчетный приводит к полной очистке всех типовых проводок документа. Особенно ярко данное поведение проявляется в регламентных операциях конфигурации «Бухгалтерия предприятия» при закрытии счетов затрат (20, 23, 25, 26). Разберем по шагам, почему возникает эта ошибка и какие существуют корректные способы добавления движений в регламентные документы.
Проанализируем ситуацию, возникающую при стандартном обращении к коллекции движений. В типовых документах проведения проводки формируются непосредственно в объекте Движения.Хозрасчетный. Как только мы обращаемся к методу Добавить(), платформа неявно выставляет свойство Движения.Хозрасчетный.Записывать = Истина. При завершении транзакции проведения платформа автоматически выполняет запись набора с режимом замещения по умолчанию (Замещать = Истина).
В регламентных операциях закрытия месяца логика формирования проводок устроена значительно сложнее, чем в обычных первичных документах:
Движения.Хозрасчетный.Записать(Ложь) либо формироваться в промежуточных таблицах значений. После сброса в базу коллекция в оперативной памяти может очищаться для экономии ресурсов.Движения.Хозрасчетный.Прочитать() полностью считывает текущее (еще пустое) состояние таблицы из базы и тем самым безвозвратно стирает все сформированные до этого строки.РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей() и его ручная запись внутри проведения не решают проблему. Даже если отдельный набор запишет данные, при выходе из процедуры платформа сбросит системный набор Движения.Хозрасчетный, который затрет ранее сохраненную информацию.Наиболее надежный и архитектурно правильный способ добавления движений в регламентные документы — вынос логики в подписку на событие ОбработкаПроведения документа РегламентнаяОперация. Это позволяет гарантировать, что типовой алгоритм закрытия счетов уже завершил свои расчеты и зафиксировал все движения в регистре.
Рассмотрим порядок реализации данного решения:
ОбработкаПроведения.Посмотрим на пример программного кода в общем модуле подписки:
Процедура ДобавитьДвиженияПриПроведении(Источник, Отказ, РежимПроведения) Экспорт
// Проверяем вид регламентной операции, чтобы код срабатывал только для закрытия счетов затрат
Если Источник.ВидОперации <> Перечисления.ВидыРегламентныхОпераций.ЗакрытиеСчетов20_23_25_26 Тогда
Возврат;
КонецЕсли;
// Считываем движения, уже сформированные типовым кодом
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Источник.Ссылка);
НаборЗаписей.Прочитать();
// Добавляем требуемую проводку
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = Источник.Дата;
НоваяЗапись.Регистратор = Источник.Ссылка;
НоваяЗапись.Организация = Источник.Организация;
НоваяЗапись.СчетДт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("41.01");
НоваяЗапись.СчетКт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("20.01");
НоваяЗапись.Сумма = 1000;
НоваяЗапись.Содержание = "Корректировка стоимости (кастомная)";
// Записываем обновленный набор целиком с замещением
НаборЗаписей.Записать(Истина);
// Отключаем повторную автозапись стандартного набора движений документа
Источник.Движения.Хозрасчетный.Записывать = Ложь;
КонецПроцедуры
Если внесение изменений производится непосредственно внутри модуля документа или типового общего модуля процедуры ЗакрытиеСчетов20_23_25_26, необходимо корректно управлять флагами записи набора. Разберем по шагам, как предотвратить удаление существующих проводок:
Движения.Хозрасчетный.Посмотрим на пример реализации:
// Создаем движение непосредственно перед завершением процедуры закрытия
Движение = Движения.Хозрасчетный.Добавить();
Движение.Период = ЭтотОбъект.Дата;
Движение.Организация = ЭтотОбъект.Организация;
Движение.СчетДт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("41.01");
Движение.СчетКт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("20.01");
Движение.Сумма = СуммаПроводки;
// Записываем порцию проводок в базу данных БЕЗ замещения ранее записанных
Движения.Хозрасчетный.Записать(Ложь);
// Запрещаем платформе автоматически перезаписывать набор при выходе из процедуры
Движения.Хозрасчетный.Записывать = Ложь;
Внесение прямых проводок вида Дт 41.01 Кт 20.01 в процедуру закрытия счетов несет серьезные риски: может нарушиться порядок распределения прямых расходов, возникнуть зависшее сальдо по счету 20 или образоваться неверная база для расчета в следующих месяцах. Рассмотрим типовые альтернативы, исключающие вмешательство в программный код закрытия:
Отчет производства за смену или Акт об оказании производственных услуг, после чего регламентная процедура закрытия месяца автоматически скорректирует их стоимость до фактической себестоимости.