Почему не перезаписывается регистр сведений Сведения о пользователях в 1С:Документооборот

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

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

Анализ проблемы и стандартных методов записи

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

Способ 1: Использование Набора записей

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


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

НоваяЗапись = Набор.Добавить();
НоваяЗапись.Пользователь = НовПольз.Ссылка;
НоваяЗапись.Должность = ДолжСсылка;
НоваяЗапись.Подразделение = ПодрСсылка;

Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();

Важно понимать: когда мы используем Набор.Записать() с установленным отбором, 1С сначала удаляет все существующие записи, соответствующие этому отбору, а затем записывает те, что мы добавили в набор. Если после выполнения этого кода данные «откатываются», значит, существует сторонний процесс, который перезаписывает этот регистр сразу после вашего кода.

Способ 2: Использование Менеджера записи

Менеджер записи удобен, когда нужно изменить одну конкретную строку. Разберем по шагам его применение:


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

ЗаписьРегистра.Должность = ДолжСсылка;
ЗаписьРегистра.Подразделение = ПодрСсылка;
ЗаписьРегистра.Записать(Истина); // Параметр Истина означает замещение существующей записи

Если ЗаписьРегистра.Прочитать() не находит запись, поля менеджера будут пустыми, и Записать() создаст новую строку. Если находит — обновит существующую.

Выясняем причину: особенности архитектуры 1С:Документооборот

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

  1. Связь со справочником: В конфигурации реализована логика, согласно которой сведения в регистре должны соответствовать реквизитам объекта СправочникОбъект.Пользователи.
  2. Подписки на события: При записи объекта пользователя (или связанных с ним кадровых данных) срабатывает механизм автоматического обновления сведений. Если вы в коде сначала меняете регистр, а в конце выполняете ПользовательОбъект.Записать(), то типовая подписка на событие просто перезапишет ваши данные в регистре теми, что хранятся в самом объекте пользователя.
  3. Синхронизация данных: Часто должность и подразделение тянутся из справочника Сотрудники или кадровых документов. Проверьте, не перезаполняются ли данные регламентными заданиями или при открытии карточки пользователя.

Рекомендуемое решение: комплексный подход

Чтобы изменения гарантированно сохранились, мы должны действовать в соответствии с архитектурой системы. Рассмотрим алгоритм правильного переноса пользователя в другое подразделение:


Процедура ПеренестиПользователяВПодразделение(Пользователь, Подразделение, Должность) Экспорт
    
    НачатьТранзакцию();
    Попытка
        // 1. Блокируем данные для предотвращения конкурентного изменения
        Блокировка = Новый БлокировкаДанных;
        ЭлементБлокировки = Блокировка.Добавить("Справочник.Пользователи");
        ЭлементБлокировки.УстановитьЗначение("Ссылка", Пользователь);
        Блокировка.Заблокировать();
        
        // 2. Сначала меняем данные в самом справочнике Пользователи
        // Так как регистр часто обновляется именно на основании данных этого справочника
        ПользовательОбъект = Пользователь.ПолучитьОбъект();
        Если ПользовательОбъект.Подразделение <> Подразделение Тогда
            ПользовательОбъект.Подразделение = Подразделение;
            // Можно также обновить должность, если такой реквизит есть в справочнике
            ПользовательОбъект.Записать(); 
        КонецЕсли;

        // 3. Теперь принудительно обновляем регистр сведений
        Набор = РегистрыСведений.СведенияОПользователяхДокументооборот.СоздатьНаборЗаписей();
        Набор.Отбор.Пользователь.Установить(Пользователь);
        Набор.Прочитать();
        
        Если Набор.Количество() = 0 Тогда
            НоваяЗапись = Набор.Добавить();
            НоваяЗапись.Пользователь = Пользователь;
        Иначе
            НоваяЗапись = Набор[0];
        КонецЕсли;
        
        НоваяЗапись.Подразделение = Подразделение;
        НоваяЗапись.Должность = Должность;
        
        // Отключаем проверки, если это необходимо для обхода типовых механизмов
        Набор.ОбменДанными.Загрузка = Истина;
        Набор.Записать();
        
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ЗаписатьЛогСобытий("Ошибка записи пользователя: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке()));
        ВызватьИсключение;
    КонецПопытки;
    
КонецПроцедуры

Дополнительные факторы проверки

Если вышеуказанные действия не помогли, проанализируем следующие моменты:

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

УстановитьПривилегированныйРежим(Истина);

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

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

Использование API конфигурации. В типовых решениях, таких как 1С:ДО, лучше всего использовать методы общих модулей. Посмотрите в сторону модуля РаботаСПользователями. Там могут быть процедуры типа ОбновитьСведенияОПользователе, которые выполняют всю цепочку действий корректно, учитывая все внутренние зависимости системы.

Подводя итог, помните: программная работа с регистрами в сложных конфигурациях — это не только манипуляция объектом РегистрСведенийМенеджер, но и понимание того, как данные этого регистра связаны с основными объектами системы.

← На главную