При работе с конфигурацией 1С:Документооборот программисты часто сталкиваются с задачей программного обновления данных пользователя, таких как должность или подразделение. Эти сведения хранятся в непериодическом регистре сведений СведенияОПользователяхДокументооборот. Однако стандартные методы записи (через менеджер записи или набор записей) иногда отрабатывают без ошибок, но данные в базе остаются прежними. Разберем подробно, почему это происходит и как правильно реализовать обновление информации.
Рассмотрим типичную ситуацию: код выполняется, отладчик показывает верные значения в объектах, но после завершения транзакции в регистре ничего не меняется. Проанализируем основные способы записи в регистр сведений и выясним, где могут крыться подвохи.
Способ 1: Использование Набора записей
Этот метод считается наиболее надежным для работы с регистрами. Мы устанавливаем отбор по измерениям (в данном случае это Пользователь), создаем новую запись и записываем набор. Посмотрим на пример кода:
Набор = РегистрыСведений.СведенияОПользователяхДокументооборот.СоздатьНаборЗаписей();
Набор.Отбор.Пользователь.Установить(НовПольз.Ссылка);
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Пользователь = НовПольз.Ссылка;
НоваяЗапись.Должность = ДолжСсылка;
НоваяЗапись.Подразделение = ПодрСсылка;
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();
Важно понимать: когда мы используем Набор.Записать() с установленным отбором, 1С сначала удаляет все существующие записи, соответствующие этому отбору, а затем записывает те, что мы добавили в набор. Если после выполнения этого кода данные «откатываются», значит, существует сторонний процесс, который перезаписывает этот регистр сразу после вашего кода.
Способ 2: Использование Менеджера записи
Менеджер записи удобен, когда нужно изменить одну конкретную строку. Разберем по шагам его применение:
ЗаписьРегистра = РегистрыСведений.СведенияОПользователяхДокументооборот.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Пользователь = НовПольз.Ссылка;
ЗаписьРегистра.Прочитать(); // Считываем текущие данные из базы
ЗаписьРегистра.Должность = ДолжСсылка;
ЗаписьРегистра.Подразделение = ПодрСсылка;
ЗаписьРегистра.Записать(Истина); // Параметр Истина означает замещение существующей записи
Если ЗаписьРегистра.Прочитать() не находит запись, поля менеджера будут пустыми, и Записать() создаст новую строку. Если находит — обновит существующую.
Проанализируем ситуацию глубже. В 1С:Документооборот регистр СведенияОПользователяхДокументооборот тесно связан со справочником Пользователи и структурой предприятия. Основная причина, по которой прямая запись в регистр может «не работать», заключается в подписках на события.
СправочникОбъект.Пользователи.ПользовательОбъект.Записать(), то типовая подписка на событие просто перезапишет ваши данные в регистре теми, что хранятся в самом объекте пользователя.Сотрудники или кадровых документов. Проверьте, не перезаполняются ли данные регламентными заданиями или при открытии карточки пользователя.Чтобы изменения гарантированно сохранились, мы должны действовать в соответствии с архитектурой системы. Рассмотрим алгоритм правильного переноса пользователя в другое подразделение:
Процедура ПеренестиПользователяВПодразделение(Пользователь, Подразделение, Должность) Экспорт
НачатьТранзакцию();
Попытка
// 1. Блокируем данные для предотвращения конкурентного изменения
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Справочник.Пользователи");
ЭлементБлокировки.УстановитьЗначение("Ссылка", Пользователь);
Блокировка.Заблокировать();
// 2. Сначала меняем данные в самом справочнике Пользователи
// Так как регистр часто обновляется именно на основании данных этого справочника
ПользовательОбъект = Пользователь.ПолучитьОбъект();
Если ПользовательОбъект.Подразделение <> Подразделение Тогда
ПользовательОбъект.Подразделение = Подразделение;
// Можно также обновить должность, если такой реквизит есть в справочнике
ПользовательОбъект.Записать();
КонецЕсли;
// 3. Теперь принудительно обновляем регистр сведений
Набор = РегистрыСведений.СведенияОПользователяхДокументооборот.СоздатьНаборЗаписей();
Набор.Отбор.Пользователь.Установить(Пользователь);
Набор.Прочитать();
Если Набор.Количество() = 0 Тогда
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Пользователь = Пользователь;
Иначе
НоваяЗапись = Набор[0];
КонецЕсли;
НоваяЗапись.Подразделение = Подразделение;
НоваяЗапись.Должность = Должность;
// Отключаем проверки, если это необходимо для обхода типовых механизмов
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписатьЛогСобытий("Ошибка записи пользователя: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Если вышеуказанные действия не помогли, проанализируем следующие моменты:
Права доступа. В ряде случаев запись может блокироваться на уровне RLS или из-за отсутствия прав на конкретный регистр. Хотя автор упоминает отсутствие ошибок, попробуйте обернуть код в привилегированный режим:
УстановитьПривилегированныйРежим(Истина);
Типы данных. Проверьте типы значений ДолжСсылка и ПодрСсылка. Если в регистре ожидается ссылка на справочник Должности, а вы передаете строку или ссылку другого типа, запись может не произойти или очиститься. 1С:Документооборот чувствителен к типам данных в измерениях.
Кэширование. Иногда данные в базе обновляются, но в интерфейсе (в динамических списках или карточках) вы видите старые значения из-за кэша. Попробуйте обновить форму или перезайти в программу после программного изменения данных.
Использование API конфигурации. В типовых решениях, таких как 1С:ДО, лучше всего использовать методы общих модулей. Посмотрите в сторону модуля РаботаСПользователями. Там могут быть процедуры типа ОбновитьСведенияОПользователе, которые выполняют всю цепочку действий корректно, учитывая все внутренние зависимости системы.
Подводя итог, помните: программная работа с регистрами в сложных конфигурациях — это не только манипуляция объектом РегистрСведенийМенеджер, но и понимание того, как данные этого регистра связаны с основными объектами системы.