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