При разработке внешних обработок в 1С программисты часто сталкиваются с задачей массового изменения документов в закрытом периоде. Например, требуется проставить служебную отметку, изменить статус отправки или обновить дополнительный реквизит без перепроведения самого документа. Однако при попытке записать объект система выдает ошибку: "Редактирование данных этого периода запрещено. Изменения не могут быть записаны".
В этой статье мы подробно разберем, почему стандартные механизмы вроде УстановитьПривилегированныйРежим или ОбменДанными.Загрузка часто не помогают решить эту задачу напрямую, проанализируем опасные способы обхода ограничений и рассмотрим правильные, безопасные варианты решения этой проблемы на базе Библиотеки Стандартных Подсистем (БСП).
Давайте выясним причину, почему популярные приемы разработчиков не дают нужного результата при работе с закрытым периодом:
УстановитьПривилегированныйРежим(Истина) отключает проверку прав доступа на уровне платформы (RLS). Однако дата запрета изменения в современных конфигурациях проверяется программно — через подписки на события, разработанные в рамках БСП. Для программного кода БСП привилегированный режим не является автоматическим сигналом к тому, что проверку даты запрета нужно игнорировать. Кроме того, если этот метод вызывается в контексте клиентского приложения (например, в модуле формы обычной обработки), платформа его просто игнорирует.ОбменДанными.Загрузка = Истина действительно отключает большинство платформенных и прикладных проверок при записи. Но во многих типовых конфигурациях подписки на события, отвечающие за контроль дат запрета, намеренно игнорируют этот флаг, чтобы предотвратить случайное искажение исторических данных при обменах.ДокМар.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения", Истина) работает локально только для записываемого документа. Если при записи этого документа (например, "Реализация товаров и услуг") система пытается автоматически создать или перезаписать связанные объекты (например, подчиненный "Счет-фактура выданный" или движения по регистрам), на них это свойство не распространяется. В результате транзакция откатывается с ошибкой блокировки периода.На форумах часто встречается решение, связанное с временным отключением константы, отвечающей за применение дат запрета для пользователей с полными правами. Схематично этот код выглядит следующим образом:
ЗначениеКонстанты = Константы.ПрименятьДатуЗапретаДляПолныхПрав.Получить();
Константы.ПрименятьДатуЗапретаДляПолныхПрав.Установить(Ложь);
ПолныеПрава.УстановитьПараметрГраницыЗапретаИзмененияДанных();
// Выполнение записи документов в цикле...
Константы.ПрименятьДатуЗапретаДляПолныхПрав.Установить(ЗначениеКонстанты);
ПолныеПрава.УстановитьПараметрГраницыЗапретаИзмененияДанных();
Внимание! Мы настоятельно не рекомендуем использовать этот способ в работающих многопользовательских базах данных.
Рассмотрим подробнее, к каким тяжелым последствиям это может привести:
Для безопасного обхода ограничений БСП предоставляет штатные программные инструменты, которые временно отключают проверку даты запрета только для текущего сеанса. Работа остальных пользователей при этом никак не нарушается.
Рассмотрим безопасный шаблон кода, который рекомендуется использовать в конфигурациях на базе БСП версии 3.1.4 и выше. В нем используется общий модуль ДатыЗапретаИзменения:
// Шаг 1. Сохраняем текущее состояние проверки в сеансе
ПроверкаДатЗапретаОтключена = ДатыЗапретаИзменения.ПроверкаДатЗапретаОтключена();
// Шаг 2. Отключаем проверку дат запрета для ТЕКУЩЕГО сеанса
ДатыЗапретаИзменения.ОтключитьПроверкуДатЗапрета(Истина);
Попытка
Выборка = Документы.РеализацияТоваровУслуг.Выбрать(ДатаНач, ДатаКон);
Пока Выборка.Следующий() Цикл
ДокОбъект = Выборка.ПолучитьОбъект();
// Вносим необходимые изменения в реквизиты документа
ДокОбъект.ОтправленаВМаршрут = Истина;
// Записываем объект. Связанные подчиненные объекты также запишутся без ошибки дат запрета
ДокОбъект.Записать();
Сообщить("Успешно изменен документ: " + ДокОбъект.Ссылка);
КонецЦикла;
Исключение
// Шаг 3. В случае возникновения непредвиденной ошибки обязательно возвращаем исходное состояние
ДатыЗапретаИзменения.ОтключитьПроверкуДатЗапрета(ПроверкаДатЗапретаОтключена);
ВызватьИсключение;
КонецПопытки;
// Шаг 4. Возвращаем исходное состояние проверки после успешного завершения работы цикла
ДатыЗапретаИзменения.ОтключитьПроверкуДатЗапрета(ПроверкаДатЗапретаОтключена);
Если вы работаете в конфигурации со старой версией БСП, где в общем модуле ДатыЗапретаИзменения отсутствует экспортный метод отключения проверки, нам потребуется обратиться к служебному модулю. Этот способ напрямую воздействует на параметры сеанса:
// Отключаем проверку для текущего сеанса через служебный модуль
ДатыЗапретаИзмененияСлужебный.ПропуститьПроверкуЗапретаИзменения(Истина);
Попытка
// Выполняем аналогичный цикл выборки и записи документов...
Исключение
ДатыЗапретаИзмененияСлужебный.ПропуститьПроверкуЗапретаИзменения(Ложь);
ВызватьИсключение;
КонецПопытки;
// Восстанавливаем контроль дат запрета изменений
ДатыЗапретаИзмененияСлужебный.ПропуститьПроверкуЗапретаИзменения(Ложь);
Для успешного выполнения этого кода у текущего пользователя должны быть полные права, либо данный фрагмент кода должен выполняться в серверном контексте в привилегированном режиме.
Проанализируем еще несколько важных моментов, которые позволят сделать вашу обработку надежной и быстрой:
&НаСервере). Выполнение таких процедур непосредственно на клиенте замедляет работу и может вызывать ошибки контекста выполнения.