Почему при повторном проведении документа в 1С исчезают записи регистра сведений и как это исправить

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

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

В этой статье разберем причины возникновения такой ошибки и рассмотрим правильные способы работы с наборами записей регистра сведений в процедурах проведения документов.

Анализ проблемы и причин очистки движений

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


&НаСервере
Процедура УАЗ_ПроведениеРабочихМест(Регистратор, ДанныеДвижений) Экспорт
    ткНаборЗаписей = РегистрыСведений.УАЗ_РаботникиОрганизаций.СоздатьНаборЗаписей();
    ткНаборЗаписей.Отбор.Регистратор.Установить(Регистратор.Ссылка);
    
    Для Каждого Строка Из ДанныеДвижений Цикл
        Элемент = ткНаборЗаписей.Добавить();
        Элемент.Регистратор      = Регистратор.Ссылка;
        Элемент.Организация      = Регистратор.Организация;
        Элемент.Период           = Регистратор.Дата;
        Элемент.Сотрудник        = Строка.Сотрудник;
        Элемент.УАЗ_РабочееМесто = Строка.УАЗ_РабочееМесто;
    КонецЦикла;    
    
    ткНаборЗаписей.Записать(Истина);
КонецПроцедуры

При отладке выясняется, что метод Записать(Истина) действительно физически записывает новые строки в базу данных. Однако в конце транзакции проведения документа записи всё равно исчезают. Рассмотрим основные причины такого поведения:

  1. Конфликт между ручным набором записей и встроенной коллекцией Движения: Если регистр сведений указан в конфигураторе на закладке «Движения» документа, платформа считает этот регистр подчиненным данному документу. Платформа 1С автоматически управляет движением по отмеченным регистрам. Когда срабатывает встроенный механизм проведения, платформа инициализирует собственную коллекцию Движения.УАЗ_РаботникиОрганизаций. Так как разработчик наполнял сторонний объект через РегистрыСведений.УАЗ_РаботникиОрганизаций.СоздатьНаборЗаписей(), штатная коллекция Движения документа осталась пустой. При завершении процедуры проведение с замещением перезаписывает записи базы данных пустой коллекцией.
  2. Перекрытие встроенных имен переменных: Использование системных имен (например, названий параметров процедуры или локальных переменных словом Движения) перекрывает доступ к контекстному свойству Движения объекта ДокументОбъект, что приводит к логическим ошибкам при обращении к свойствам проведения.
  3. Режим удаления движений: Если у документа в метаданных установлено свойство «Удаление движений» в значение Удалять автоматически, платформа предварительно очищает движения перед вызовом процедуры ОбработкаПро проведения. Если алгоритм повторного формирования движений опирается на предварительное считывание прошлых записей регистра, эти данные будут потеряны.

Способ 1. Использование штатной коллекции Движения (Рекомендуемый)

Если регистр сведений подчинен регистратору и указан в составе движений документа в Конфигураторе, формировать записи следует напрямую через коллекцию Движения документа в модуле объекта (в обработчике ОбработкаПро проведения).

Разберем по шагам, как написать правильный код:

  1. Обратитесь к набору записей регистра через свойство Движения.<ИмяРегистра>.
  2. Установите флаг Записывать = Истина у данного набора.
  3. Заполните строки движений из реквизитов или табличных частей документа.

Пример корректной реализации в модуле документа:


&НаСервере
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Получаем коллекцию движений документа по нужному регистру
    НаборЗаписей = Движения.УАЗ_РаботникиОрганизаций;
    НаборЗаписей.Записывать = Истина;
    
    // Заполняем записи регистра
    Для Каждого СтрокаТЧ Из Ссылка.Сотрудники Цикл
        Движение = НаборЗаписей.Добавить();
        Движение.Период           = Дата;
        Движение.Организация      = Организация;
        Движение.Сотрудник        = СтрокаТЧ.Сотрудник;
        Движение.УАЗ_РабочееМесто = СтрокаТЧ.УАЗ_РабочееМесто;
    КонецЦикла;

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

В этом случае платформа 1С самостоятельно выполнит запись набора в базу данных в единой транзакции проведения и не затрет результат.

Способ 2. Исключение регистра из состава движений документа

Если логика системы требует записи в регистр сведений исключительно через вызов независимых серверных процедур с помощью метода СоздатьНаборЗаписей(), необходимо отключить автоматический контроль движений со стороны платформы.

Для этого выполним следующие действия:

  1. Откройте Конфигуратор и найдите требуемый документ.
  2. Перейдите на вкладку Движения.
  3. В дереве регистров снимите флажок с регистра сведений УАЗ_РаботникиОрганизаций.

После исключения регистра из состава движений документа платформа перестанет автоматически управлять замещением записей по данному регистратору, и явная запись набора через СоздатьНаборЗаписей() и метод Записать(Истина) перестанет затираться.

Пример вызова процедуры явной записи (с исправленным именем параметра):


&НаСервере
Процедура УАЗ_ПроведениеРабочихМест(РегистраторСсылка, ДанныеТаблицы) Экспорт

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

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

Рекомендации по наименованию переменных и отладке

Для предотвращения подобных ошибок при разработке соблюдайте следующие правила:

  1. Не переопределяйте системные имена: Никогда не называйте локальные переменные и параметры процедур именами Движения, Ссылка, ЭтотОбъект, Отказ и т.п., так как это приводит к неоднозначности и перекрытию контекста платформы.
  2. Используйте отладчик: Если записи исчезают, установите точку останова в событии ПриЗаписи модуля набора записей регистра сведений. Это позволит отследить, какой именно стек вызовов производит повторную очистку или замену движений.
← На главную