Почему не записываются данные в подчиненный регистр сведений при проведении документа?

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

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

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

Ошибка №1: Использование независимого набора записей в транзакции проведения

Рассмотрим код, с которого часто начинают начинающие разработчики (именно этот вариант описан в первом сообщении темы):


НаборЗаписей = РегистрыСведений.РаботникиОрганизаций.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ЭтотОбъект.Ссылка);
НаборЗаписей.Прочитать();

НовЗапись = НаборЗаписей.Добавить();
НовЗапись.Период = стр.ДатаПриема;
НовЗапись.Сотрудник = стр.Сотрудник;
НовЗапись.Организация = Организация;
НовЗапись.ПодразделениеОрганизации = стр.ПодразделениеОрганизации;
НовЗапись.Должность = стр.Должность;
НовЗапись.ПервичныйДокумент = ЭтотОбъект.Ссылка;
НовЗапись.Регистратор = ЭтотОбъект.Ссылка;

НаборЗаписей.Записать(Истина);

Выясним причину, почему этот код не работает.

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

Когда мы пишем код создания независимого набора записей через менеджер регистра РегистрыСведений.РаботникиОрганизаций.СоздатьНаборЗаписей() и вызываем метод Записать(Истина), платформа выполняет запись непосредственно в базу данных в рамках текущей транзакции. Однако сразу после успешного завершения процедуры ОбработкаПроведения платформа автоматически переходит к этапу записи движений документа.

На этом этапе система берет коллекцию Движения документа из оперативной памяти и записывает её в базу данных. По умолчанию свойство Записывать для регистра РаботникиОрганизаций в коллекции Движения равно Ложь, а сама коллекция пуста. Платформа видит, что новых движений по этому регистру документ не сформировал, и автоматически очищает (перезаписывает) все существующие в базе данных записи по данному регистратору. Таким образом, наши ручные записи, добавленные через независимый набор записей, бесследно удаляются в ту же секунду.

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

Решение проблемы: Правильное использование коллекции Движения

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


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

// 2. Считываем текущие движения из базы данных (если необходимо)
Движения.РаботникиОрганизаций.Прочитать();

// 3. Добавляем новую запись в коллекцию движений
Движение = Движения.РаботникиОрганизаций.Добавить();
Движение.Период = стр.ДатаПриема;
Движение.Сотрудник = стр.Сотрудник;
Движение.Организация = Организация;
Движение.ПодразделениеОрганизации = стр.ПодразделениеОрганизации;
Движение.Должность = стр.Должность;

Разберем этот код по шагам:

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

В чем разница между методами Прочитать() и Очистить()

Часто в процессе разработки возникает дилемма: какой метод использовать перед добавлением новых движений — Прочитать() или Очистить()?

Проблема «Исчезновения» движений из-за фильтра по организации

В сообщении №17 автор темы отмечает важный нюанс: «Прикол в том что движение видно, когда выключаешь фильтр по организации». Это очень распространенная проблема, с которой сталкиваются программисты при отладке кадровых и финансовых регистров.

Рассмотрим основные причины, почему записи в регистре могут «исчезать» при установленном отборе по организации:

  1. Незаполненный реквизит организации в документе. Если в коде используется конструкция Движение.Организация = Организация;, но на форме документа или в его объекте реквизит Организация пуст (например, пользователь забыл его выбрать или он очистился программно), то в регистр сведений запишется пустое значение (пустая ссылка). При просмотре регистра с установленным фильтром по конкретной организации такие записи отображаться не будут.
  2. Ограничение прав доступа на уровне записей (RLS). Если в базе данных включено ограничение прав по организациям, и система записывает пустую организацию или организацию, к которой у текущего пользователя нет доступа, платформа скроет эти записи из стандартных списков. При этом под пользователем с полными правами (или при отключенном фильтре) эти записи будут отлично видны.
  3. Несоответствие кадровых данных. В кадровом учете 1С существует жесткая связь между сотрудником и его организацией. Если в движении указана одна организация, а в карточке сотрудника — другая, стандартные отчеты и формы списков конфигурации могут отфильтровывать такие некорректные записи как ошибочные.

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


Если НЕ ЗначениеЗаполнено(Организация) Тогда
    ВызватьИсключение "Не заполнена организация в документе! Движения не могут быть сформированы.";
КонецЕсли;

Резюме

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

← На главную