Редактирование реквизитов в документах, период которых уже закрыт для изменений, является стандартной, но технически сложной задачей для разработчика 1С. Основная сложность заключается в том, что в современных конфигурациях (ERP, КА, УТ 11, БП 3.0) за это отвечает встроенная подсистема Даты запрета изменения из состава Библиотеки стандартных подсистем (БСП). В этой статье мы подробно рассмотрим, как программно обойти этот запрет и как правильно управлять интерфейсом формы, чтобы позволить пользователю вносить правки без возникновения ошибок платформы.
Прежде чем приступать к написанию кода, проанализируем ситуацию. Когда в системе установлена дата запрета изменения, подсистема БСП автоматически делает форму документа доступной только для чтения. Это происходит обычно в процедуре ПриЧтенииНаСервере или ПриСозданииНаСервере модуля формы. Платформа устанавливает свойство ТолькоПросмотр = Истина для всей формы, что блокирует любые изменения реквизитов.
Если же мы попытаемся программно переопределить доступность отдельных элементов, мы можем столкнуться с ошибкой, так как не все элементы формы (например, декорации или группы) поддерживают свойства Доступность или ТолькоПросмотр. Чтобы избежать ручного написания кода для каждого поля, можно использовать готовое расширение для настройки доступности элементов формы или специализированный инструмент для открытия видимости и снятия блокировок со всех элементов формы.
Если наша задача — оставить форму закрытой, но разрешить редактирование одного конкретного поля (например, даты), нам нужно обойти установку ЭтаФорма.ТолькоПросмотр = Истина и вместо этого программно заблокировать все элементы, кроме нужного. Разберем по шагам, как реализовать безопасный перебор элементов формы, чтобы не вызвать исключение при отсутствии нужного свойства у элемента.
Для решения этой задачи в модуле формы можно использовать следующий алгоритм:
// В процедуре ПриЧтенииНаСервере или после типовых проверок
Если ПериодЗакрыт Тогда
// Снимаем общий запрет редактирования формы
ЭтаФорма.ТолькоПросмотр = Ложь;
Для Каждого Элемент Из ЭтаФорма.Элементы Цикл
// Пропускаем элемент "Дата", который нам нужно оставить доступным
Если Элемент.Имя = "Дата" Тогда
Продолжить;
КонецЕсли;
// Используем Попытку для обхода элементов без нужных свойств
Попытка
Элемент.ТолькоПросмотр = Истина;
Исключение
// Если свойство ТолькоПросмотр недоступно, пробуем Доступность
Попытка
Элемент.Доступность = Ложь;
Исключение
// Элемент не поддерживает блокировку (например, Группа или Декорация)
КонецПопытки;
КонецПопытки;
КонецЦикла;
КонецЕсли;
Также рассмотрим более изящный метод проверки наличия свойства у объекта без использования блока Попытка...Исключение, что считается более правильным тоном в разработке 1С:
Функция ЕстьСвойство(Объект, ИмяСвойства) Экспорт
Результат = Ложь;
НачальноеЗначение = Новый УникальныйИдентификатор();
СтруктураПроверки = Новый Структура(ИмяСвойства, НачальноеЗначение);
// ЗаполнитьЗначенияСвойств копирует только существующие свойства
ЗаполнитьЗначенияСвойств(СтруктураПроверки, Объект);
Если СтруктураПроверки[ИмяСвойства] <> НачальноеЗначение Тогда
Результат = Истина;
КонецЕсли;
Возврат Результат;
КонецФункции
Даже если нам удалось изменить дату на форме, при попытке записи документа подсистема БСП снова проверит дату запрета и выдаст ошибку "Редактирование данных в закрытом периоде запрещено". Стоит отметить, что иногда проблемы возникают и при работе с системными датами, например, может потребоваться исправление ошибки записи данных на дату "31.12.1899", которая также блокирует работу с объектом.
Чтобы успешно записать изменения, мы должны сообщить объекту документа, что проверку нужно пропустить. В современных конфигурациях на БСП предусмотрен специальный механизм использования ДополнительныеСвойства объекта. Рассмотрим пример кода, который позволяет записать документ в закрытом периоде:
ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
ОбъектДокумента.Дата = НоваяДата;
// Передаем "волшебное свойство" для подсистемы ДатыЗапретаИзменения
ОбъектДокумента.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения", Истина);
// В некоторых версиях БСП может потребоваться также этот ключ:
// ОбъектДокумента.ДополнительныеСвойства.Вставить("ОтключитьПроверкуДатыЗапрета", Истина);
Попытка
ОбъектДокумента.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Дата успешно изменена в закрытом периоде.");
Исключение
Сообщить("Ошибка записи: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Для специфических документов в ERP и КА 2.5, таких как Отражение зарплаты, можно использовать специализированный механизм блокировки и разблокировки формы документа, работающий через расширение. Важно помнить: использование РежимЗаписиДокумента.Проведение в закрытом периоде может привести к пересчету движений по регистрам накопления, что крайне нежелательно.
Проанализируем еще один классический способ — установку свойства ОбменДанными.Загрузка. Этот флаг отключает практически все проверки в модуле объекта и модулях наборов записей регистров, включая проверки дат запрета.
ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
ОбъектДокумента.Дата = НоваяДата;
ОбъектДокумента.ОбменДанными.Загрузка = Истина;
ОбъектДокумента.Записать();
Внимание: это самый радикальный метод. При его использовании не будут выполнены никакие бизнес-проверки, не обновятся связанные регистры и не сработают подписки на события. Используйте этот метод только в том случае, если вы четко понимаете последствия и уверены, что изменение даты не нарушит целостность учета.
Выясним причину, по которой опытные разработчики и бухгалтеры выступают против таких манипуляций. Изменение даты документа в закрытом периоде влечет за собой следующие риски:
Проанализировав ситуацию, мы рекомендуем вместо прямого редактирования использовать механизм Корректировок или выполнять групповое изменение реквизитов прямо с формы через штатные инструменты, либо временно открывать период для конкретного ответственного пользователя через настройки БСП, чтобы все действия фиксировались в журнале регистрации и проходили через штатные механизмы контроля.