Как обойти дату запрета редактирования при записи регистра сведений?

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

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

Почему МенеджерЗаписи не позволяет обойти дату запрета?

Рассмотрим ситуацию, когда разработчик пытается использовать СоздатьМенеджерЗаписи() для изменения данных. Основная проблема заключается в том, что механизм даты запрета изменений в Библиотеке стандартных подсистем (БСП) реализован через подписки на события ПередЗаписью. Чтобы подписка «поняла», что проверку нужно пропустить, ей необходимо передать специальный флаг.

Проанализируем структуру объекта РегистрСведенийМенеджерЗаписи. У данного объекта отсутствует свойство ДополнительныеСвойства. Хотя «под капотом» платформа при вызове метода Записать() создает набор из одной записи, программного доступа к свойствам этого неявного набора у нас нет. Следовательно, мы не можем передать в него ключ ПропуститьПроверкуЗапретаИзменения. Поэтому, как справедливо отмечено в обсуждении, через менеджер записи обойти ограничение напрямую невозможно.

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

Это самый надежный и «чистый» способ решения проблемы. Объект РегистрСведенийНаборЗаписей обладает коллекцией ДополнительныеСвойства, которая сохраняется на протяжении всей транзакции записи и доступна в обработчиках событий. Разберем по шагам, как правильно выполнить запись:

  1. Создаем набор записей с установкой необходимых отборов (по измерениям).
  2. Устанавливаем в ДополнительныеСвойства специальный маркер для БСП.
  3. Выполняем запись набора.

Посмотрим на пример кода:


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

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

// Устанавливаем ключ для обхода даты запрета (актуально для БСП)
Набор.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения", Истина);

// Записываем набор
Набор.Записать();

В этом случае подписка на событие БСП проверит наличие ключа ПропуститьПроверкуЗапретаИзменения в дополнительных свойствах и, если он равен Истина, пропустит выполнение проверки даты запрета.

Способ 2: Использование программного интерфейса БСП

В современных версиях конфигураций, построенных на БСП (версии 3.0 и выше), существует более элегантный способ временного отключения проверок для текущего сеанса. Мы можем вызвать метод глобального модуля, который установит соответствующий флаг в параметрах сеанса. Проанализируем этот подход:


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

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

// Возвращаем стандартный режим проверки
ДатыЗапретаИзменения.ПропуститьПроверкуЗапретаИзменения(Ложь);

Важный нюанс: Этот метод воздействует на весь текущий сеанс. Если вы забудете вернуть значение в Ложь, пользователь сможет редактировать любые данные в закрытом периоде до конца своей работы в программе. Поэтому использование блока Попытка...Исключение здесь является обязательным.

Способ 3: Флаг ОбменДанными.Загрузка

Часто программисты пытаются использовать свойство ОбменДанными.Загрузка = Истина. Выясним, насколько это эффективно. В теории, этот флаг предназначен для того, чтобы при загрузке данных из внешних систем не срабатывали прикладные проверки. Однако в типовых конфигурациях логика даты запрета часто настроена так, что она игнорирует этот флаг, если у пользователя нет административных прав.

Если вы решите использовать этот метод, код будет выглядеть так:


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

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

Мифы о привилегированном режиме

Существует заблуждение, что установка УстановитьПривилегированныйРежим(Истина) автоматически отключает дату запрета. Это не так. Дата запрета — это не ограничение прав доступа на уровне базы данных (RLS), а программный алгоритм. Программный код подписки на события будет выполнен системой в любом случае, независимо от режима привилегий. Единственное исключение — если в коде самой подписки разработчик конфигурации явно прописал условие: Если ПривилегированныйРежим() Тогда Возврат; КонецЕсли;. В типовых решениях от 1С такая логика встречается крайне редко.

Резюме и рекомендации

Подводя итог нашему анализу, выделим основные правила работы с датой запрета:

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

← На главную