Как правильно реализовать запись в регистр сведений по условию из документа 1С?

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

При разработке механизмов учета в системе 1С:Предприятие часто возникает задача записи данных в самописный регистр сведений (РС) только при выполнении определенных условий в документе. Например, если в документе ПриобретениеУслугПрочихАктивов установлен флаг «Транспортные расходы» и выбрана конкретная статья расходов. Однако начинающие разработчики часто сталкиваются с тем, что данные в регистре либо дублируются, либо не очищаются при изменении условий проведения. Рассмотрим подробно, как правильно спроектировать такую логику, разберем типичные ошибки и выберем оптимальный архитектурный подход.

Выбор режима записи регистра: Независимый или Подчиненный?

Проанализируем ситуацию: изначально автор пытался использовать независимый регистр сведений. При записи в него программно через СоздатьНаборЗаписей возникают две основные проблемы:

  1. Дублирование записей: Если в регистре не настроен уникальный набор измерений или если дата документа (Период) изменилась хотя бы на секунду, система не найдет старую запись для замещения и создаст новую.
  2. Транзакционность: Если документ не проведется из-за ошибки в другом месте, запись в независимый регистр может сохраниться, что приведет к рассинхронизации данных.

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

Реализация записи по условию в модуле документа

Выясним причину, по которой данные могут не записываться или не очищаться. Допустим, у нас есть условие: записывать данные в регистр ТранспортныеРасходы только если реквизит ТранспортныеРасходыПризнак (Булево) равен Истина.

Рассмотрим пример кода в процедуре ОбработкаПроведения, который часто пишут новички (и который содержит ошибку):


Если ТранспортныеРасходыПризнак Тогда
    Набор = Движения.ФФБТранспортныеРасходы;
    Для Каждого ТекСтрока Из Расходы Цикл
        НоваяЗапись = Набор.Добавить();
        НоваяЗапись.Период = Дата;
        // Заполнение остальных полей...
    КонецЦикла;
    Набор.Записывать = Истина;
КонецЕсли;

Проанализируем проблему: Если мы сначала провели документ с флагом Истина (записи создались), а затем сняли флаг и снова провели документ — условие Если не сработает. Код внутри блока не выполнится, и свойство Записывать = Истина не будет установлено. В результате старые записи в регистре останутся, так как платформа не получила команду на обновление набора записей для этого регистратора.

Правильный алгоритм очистки и записи движений

Для корректной работы механизма «условной записи» нам необходимо гарантировать, что набор записей будет обновлен (перезаписан) в любом случае — даже если он станет пустым. Разберем, как это сделать правильно:


// 1. Указываем, что регистр всегда должен обновляться при проведении
Движения.ФФБТранспортныеРасходы.Записывать = Истина;

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

При таком подходе, если флаг ТранспортныеРасходыПризнак снят, цикл добавления записей не сработает, набор останется пустым, но благодаря флагу Записывать = Истина платформа запишет в базу данных этот пустой набор, эффективно удалив все старые записи по этому документу.

Типичные ошибки при проверке условий

Разберем важный технический нюанс, упомянутый в обсуждении. Часто для проверки булевых реквизитов ошибочно используют функцию ЗначениеЗаполнено().

Важно помнить: для типа Булево значение Ложь считается «заполненным» значением. Поэтому ЗначениеЗаполнено(Ложь) всегда вернет Истина.
Правильно использовать прямую проверку:

Работа с независимыми регистрами (если нельзя изменить тип)

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


НаборЗаписей = РегистрыСведений.ФФБТранспортныеРасходы.СоздатьНаборЗаписей();
// Устанавливаем отбор по ключевому полю (например, ДокументОснование)
НаборЗаписей.Отбор.ДокументОснование.Установить(Ссылка);

Если ТранспортныеРасходыПризнак Тогда
    Для Каждого ТекСтрока Из Расходы Цикл
        НоваяЗапись = НаборЗаписей.Добавить();
        НоваяЗапись.ДокументОснование = Ссылка;
        // Заполнение полей...
    КонецЦикла;
КонецЕсли;

// Метод Записать(Истина) сначала удалит все старые записи по данному отбору, 
// а затем запишет новые (или просто очистит, если набор пуст)
НаборЗаписей.Записать(Истина);

Рекомендации для сложных конфигураций (ERP, КА)

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

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

Подведем итоги:

  1. Используйте Подчиненный регистратору регистр для данных, порождаемых документами.
  2. Всегда устанавливайте флаг Движения.ИмяРегистра.Записывать = Истина вне условий, чтобы гарантировать очистку при перепроведении.
  3. Проверяйте булевы флаги напрямую (Если Флаг Тогда), избегая ЗначениеЗаполнено().
  4. При проверке справочников (статей расходов) старайтесь обращаться к предопределенным элементам, чтобы избежать ошибок при изменении наименований пользователями.
← На главную