При разработке механизмов учета в системе 1С:Предприятие часто возникает задача записи данных в самописный регистр сведений (РС) только при выполнении определенных условий в документе. Например, если в документе ПриобретениеУслугПрочихАктивов установлен флаг «Транспортные расходы» и выбрана конкретная статья расходов. Однако начинающие разработчики часто сталкиваются с тем, что данные в регистре либо дублируются, либо не очищаются при изменении условий проведения. Рассмотрим подробно, как правильно спроектировать такую логику, разберем типичные ошибки и выберем оптимальный архитектурный подход.
Проанализируем ситуацию: изначально автор пытался использовать независимый регистр сведений. При записи в него программно через СоздатьНаборЗаписей возникают две основные проблемы:
Посмотрим на решение: для задач, где данные регистра жестко привязаны к документу, наиболее правильным является перевод регистра в режим Подчинение регистратору. В этом случае платформа берет на себя управление уникальностью (по регистратору) и автоматическую очистку движений при отмене проведения.
Выясним причину, по которой данные могут не записываться или не очищаться. Допустим, у нас есть условие: записывать данные в регистр ТранспортныеРасходы только если реквизит ТранспортныеРасходыПризнак (Булево) равен Истина.
Рассмотрим пример кода в процедуре ОбработкаПроведения, который часто пишут новички (и который содержит ошибку):
Если ТранспортныеРасходыПризнак Тогда
Набор = Движения.ФФБТранспортныеРасходы;
Для Каждого ТекСтрока Из Расходы Цикл
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Период = Дата;
// Заполнение остальных полей...
КонецЦикла;
Набор.Записывать = Истина;
КонецЕсли;
Проанализируем проблему: Если мы сначала провели документ с флагом Истина (записи создались), а затем сняли флаг и снова провели документ — условие Если не сработает. Код внутри блока не выполнится, и свойство Записывать = Истина не будет установлено. В результате старые записи в регистре останутся, так как платформа не получила команду на обновление набора записей для этого регистратора.
Для корректной работы механизма «условной записи» нам необходимо гарантировать, что набор записей будет обновлен (перезаписан) в любом случае — даже если он станет пустым. Разберем, как это сделать правильно:
// 1. Указываем, что регистр всегда должен обновляться при проведении
Движения.ФФБТранспортныеРасходы.Записывать = Истина;
// 2. Проверяем основное условие проведения
Если ТранспортныеРасходыПризнак Тогда
// Проходим по табличной части и проверяем дополнительные условия (например, статью расходов)
Для Каждого ТекСтрока Из Расходы Цикл
// Условие по конкретной статье (лучше использовать предопределенные значения)
Если ТекСтрока.СтатьяРасходов = Справочники.СтатьиРасходов.ТранспортныеУслуги Тогда
НоваяЗапись = Движения.ФФБТранспортныеРасходы.Добавить();
НоваяЗапись.Период = Дата;
НоваяЗапись.СтатьяРасходов = ТекСтрока.СтатьяРасходов;
НоваяЗапись.Сумма = ТекСтрока.Сумма;
// Заполнение других измерений и ресурсов
КонецЕсли;
КонецЦикла;
КонецЕсли;
При таком подходе, если флаг ТранспортныеРасходыПризнак снят, цикл добавления записей не сработает, набор останется пустым, но благодаря флагу Записывать = Истина платформа запишет в базу данных этот пустой набор, эффективно удалив все старые записи по этому документу.
Разберем важный технический нюанс, упомянутый в обсуждении. Часто для проверки булевых реквизитов ошибочно используют функцию ЗначениеЗаполнено().
Важно помнить: для типа Булево значение Ложь считается «заполненным» значением. Поэтому ЗначениеЗаполнено(Ложь) всегда вернет Истина.
Правильно использовать прямую проверку:
Если Реквизит Тогда — проверка на истинность.Если Не Реквизит Тогда — проверка на ложность.Если по каким-то причинам регистр обязан оставаться независимым, нам придется вручную управлять очисткой. Посмотрим на пример кода, обеспечивающего перезапись данных:
НаборЗаписей = РегистрыСведений.ФФБТранспортныеРасходы.СоздатьНаборЗаписей();
// Устанавливаем отбор по ключевому полю (например, ДокументОснование)
НаборЗаписей.Отбор.ДокументОснование.Установить(Ссылка);
Если ТранспортныеРасходыПризнак Тогда
Для Каждого ТекСтрока Из Расходы Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ДокументОснование = Ссылка;
// Заполнение полей...
КонецЦикла;
КонецЕсли;
// Метод Записать(Истина) сначала удалит все старые записи по данному отбору,
// а затем запишет новые (или просто очистит, если набор пуст)
НаборЗаписей.Записать(Истина);
В современных конфигурациях, таких как ERP 2.5 или Комплексная автоматизация 2.5, прямое редактирование движений в модуле документа считается плохим тоном. Вместо этого проанализируем механизм ДополнительныеСвойства.
Обычно в ОбработкаПроведения вызывается процедура инициализации дополнительных свойств, куда передаются таблицы с данными для отражения в регистрах. Это позволяет системе выполнять записи централизованно, обеспечивая высокую производительность и корректную работу блокировок.
Подведем итоги:
Движения.ИмяРегистра.Записывать = Истина вне условий, чтобы гарантировать очистку при перепроведении.Если Флаг Тогда), избегая ЗначениеЗаполнено().