Стандартный механизм 1С «Дата запрета изменения данных» — мощный инструмент, но иногда его гибкости недостаточно. Он устанавливает единую дату запрета для всех объектов или для всех пользователей. Но что делать, если нужно запретить пользователю редактировать только определенные виды документов до определенной даты, а остальные оставить доступными? В этой статье мы подробно разберем, как реализовать такой гибкий механизм контроля.
Проанализируем ситуацию: необходимо установить для конкретного пользователя дату запрета редактирования, которая будет действовать только на документы типа «Реализация товаров и услуг» и «Поступление товаров и услуг», не затрагивая при этом другие документы, например, «Заказ покупателя».
Рассмотрим два основных способа решения этой задачи: простой, но не самый оптимальный, и более сложный, но архитектурно правильный и масштабируемый.
ПередЗаписью в модуле документа (Простой метод)Самый быстрый способ — добавить проверку непосредственно в модуль каждого документа, для которого нужно установить ограничение. Для этого мы будем использовать обработчик события ПередЗаписью. Этот обработчик срабатывает каждый раз перед тем, как документ будет записан в базу данных, и в нем мы можем отменить запись, если наши условия не выполняются.
Разберем по шагам:
ПередЗаписью.Посмотрим на пример кода:
В этом примере мы жестко задаем имя пользователя и дату запрета прямо в коде. Это подходит для быстрой проверки, но не для реальной эксплуатации.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Получаем текущего пользователя
ТекущийПользователь = Пользователи.ТекущийПользователь();
// Задаем условия проверки "в лоб"
ИмяПользователяДляПроверки = "ИвановИИ";
ДатаЗапрета = '20230930'; // 30 сентября 2023 года
// Проверяем, совпадает ли текущий пользователь с тем, для кого установлено ограничение
Если ТекущийПользователь.Наименование = ИмяПользователяДляПроверки Тогда
// Проверяем, если дата документа меньше или равна дате запрета
Если ЭтаФорма.Объект.Дата <= ДатаЗапрета Тогда
// Выводим сообщение пользователю
Сообщить("Редактирование документов до " + Формат(ДатаЗапрета, "ДФ=dd.MM.yyyy") + " запрещено!");
// Отменяем запись документа
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущества этого метода:
Недостатки:
Этот метод можно использовать как временное решение, но для постоянной работы он не рекомендуется.
Этот подход является предпочтительным и соответствует лучшим практикам разработки в 1С. Его суть заключается в создании централизованного механизма проверки, который не требует изменения типовых объектов конфигурации.
Идея следующая:
ПередЗаписью. При срабатывании этого события будет автоматически вызываться наша общая процедура.Разберем реализацию по шагам:
Нам нужно место, где администратор системы сможет легко указать, для какого пользователя, для каких документов и какую дату запрета установить. Идеально для этого подходит непериодический регистр сведений.
ВыборочныеДатыЗапретаРедактирования.Пользователь (тип: СправочникСсылка.Пользователи)ДатаЗапрета (тип: Дата, состав даты: Дата)ТипДокумента с типом Строка или СправочникСсылка.ИдентификаторыОбъектовМетаданных. Это позволит задавать разные даты запрета для разных видов документов для одного и того же пользователя. Но для начала ограничимся вариантом попроще.Теперь у нас есть место, где можно в пользовательском режиме (или через обработку) задавать настройки.
Вся логика проверки должна быть вынесена в одно место. Для этого создадим общий модуль.
ПроверкаДатыЗапретаВыборочно.Пример кода для общего модуля:
Процедура ПроверитьДатуЗапретаПередЗаписью(Источник, Отказ, РежимЗаписи) Экспорт
// Эта проверка нужна, чтобы наш код не выполнялся при программном создании или обмене данными
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Получаем текущего пользователя
ТекущийПользователь = Пользователи.ТекущийПользователь();
// Ищем настройку для текущего пользователя в нашем регистре
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВыборочныеДатыЗапретаРедактирования.ДатаЗапрета
|ИЗ
| РегистрСведений.ВыборочныеДатыЗапретаРедактирования КАК ВыборочныеДатыЗапретаРедактирования
|ГДЕ
| ВыборочныеДатыЗапретаРедактирования.Пользователь = &Пользователь";
Запрос.УстановитьПараметр("Пользователь", ТекущийПользователь);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
ДатаЗапрета = Выборка.ДатаЗапрета;
// Если дата запрета установлена, выполняем проверку
Если ЗначениеЗаполнено(ДатаЗапрета) И Источник.Дата <= ДатаЗапрета Тогда
// Формируем понятное сообщение для пользователя
ТекстСообщения = "Для пользователя " + ТекущийПользователь.Наименование +
" запрещено редактирование документов с датой до " +
Формат(ДатаЗапрета, "ДФ=dd.MM.yyyy") + " включительно.";
ОбщегоНазначения.СообщитьОбОшибке(ТекстСообщения, Отказ);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Это финальный и самый важный шаг. Мы "свяжем" наши документы с нашей процедурой проверки.
КонтрольДатыЗапретаПриЗаписиДокумента.ДокументОбъект.РеализацияТоваровУслуг, ДокументОбъект.ПоступлениеТоваровУслуг и т.д.). Можно выбрать сразу несколько объектов.ПередЗаписью.ПроверкаДатыЗапретаВыборочно.ПроверитьДатуЗапретаПередЗаписью.Вот и всё! Теперь при попытке записать любой из документов, указанных в источнике подписки, система сначала вызовет нашу процедуру из общего модуля. Процедура проверит, есть ли настройка для текущего пользователя в регистре сведений, и если есть, сравнит дату документа с датой запрета. Если редактирование запрещено, запись будет отменена, а пользователь увидит сообщение.
Преимущества этого метода:
Еще один возможный, хотя и более сложный для этой конкретной задачи, способ — использование RLS. С помощью RLS можно написать правило, которое будет запрещать изменять (UPDATE) записи в таблицах документов, если текущий пользователь и дата документа соответствуют определенным условиям. Этот метод очень мощный, но его настройка и отладка сложнее, и он может повлиять на производительность. Для такой локальной задачи, как выборочная дата запрета, использование подписки на событие является более простым и прозрачным решением.
В итоге, мы рекомендуем использовать второй метод с созданием регистра сведений и подписки на событие. Он обеспечивает необходимую гибкость, легкость в поддержке и не создает проблем при обновлении конфигурации.