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