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