В процессе сопровождения крупных систем на базе 1С:Предприятие часто возникает задача по ограничению использования устаревших данных. Одной из таких задач является запрет проведения документов, в которых выбрано НаправлениеДеятельности со статусом "Не используется". Если таких типов документов в системе несколько десятков, ручное добавление проверки в каждый из них через расширение становится трудозатратным и неэффективным процессом. В этой статье мы подробно разберем, как реализовать универсальный механизм контроля, используя возможности платформы.
Когда перед нами стоит задача ограничить проведение в 20 или более видах документов, классический подход «зайти в каждый модуль объекта» имеет ряд критических недостатков:
Проанализируем ситуацию: нам нужно решение, которое будет работать автоматически для любого документа, где присутствует реквизит НаправлениеДеятельности.
Самым правильным архитектурным решением в данной ситуации является использование объекта метаданных Подписка на событие. Рассмотрим по шагам, как это реализовать.
1. Создадим новую подписку на событие в конфигурации или расширении. Назовем ее, например, КонтрольСтатусаНаправленияДеятельностиПриПроведении.
2. В поле Источник выберем тип ДокументОбъект. Это позволит обработчику срабатывать при проведении любого документа системы.
3. В поле Событие выберем ОбработкаПроведения.
4. Создадим общий модуль (если его нет) с установленными свойствами Сервер и Вызов сервера, где будет располагаться процедура-обработчик.
Теперь разберем код обработчика. Основная сложность заключается в том, что не у всех документов есть реквизит НаправлениеДеятельности. Чтобы избежать ошибок исполнения (Runtime errors), мы должны использовать проверку метаданных.
Процедура КонтрольСтатусаНаправленияДеятельностиПриПроведении(Источник, Отказ, РежимПроведения) Экспорт
// Проверяем наличие реквизита в шапке документа через метаданные
МетаданныеДокумента = Источник.Метаданные();
РеквизитНаправление = МетаданныеДокумента.Реквизиты.Найти("НаправлениеДеятельности");
Если РеквизитНаправление <> Неопределено Тогда
ПроверитьСтатусНаправления(Источник.НаправлениеДеятельности, Отказ);
КонецЕсли;
// Важно: направление деятельности часто встречается в табличных частях
Если Не Отказ Тогда
Для Каждого ТЧ Из МетаданныеДокумента.ТабличныеЧасти Цикл
РеквизитТЧ = ТЧ.Реквизиты.Найти("НаправлениеДеятельности");
Если РеквизитТЧ <> Неопределено Тогда
ИмяТЧ = ТЧ.Имя;
Для Каждого СтрокаТЧ Из Источник[ИмяТЧ] Цикл
ПроверитьСтатусНаправления(СтрокаТЧ.НаправлениеДеятельности, Отказ);
Если Отказ Тогда Прервать; КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Отказ Тогда Прервать; КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСтатусНаправления(ЗначениеНаправления, Отказ)
Если ЗначениеЗаполнено(ЗначениеНаправления) Тогда
// Обращаемся к статусу направления.
// В типовых решениях (ERP, КА) статус может быть перечислением
Если ЗначениеНаправления.Статус = ПредопределенноеЗначение("Перечисление.СтатусыНаправленийДеятельности.НеИспользуется") Тогда
ТекстСообщения = СтрШаблон("Проведение запрещено! Направление деятельности '%1' имеет статус 'Не используется'.", ЗначениеНаправления);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если документов в базе много, постоянное обращение к реквизиту Статус через точку (ЗначениеНаправления.Статус) может замедлить проведение из-за лишних запросов к базе данных. Проанализируем, как это оптимизировать.
Рекомендуется создать Модуль повторного использования, в котором будет функция, возвращающая соответствие ссылок и их статусов. Это позволит системе один раз прочитать данные о статусах и использовать их для всех строк документа мгновенно.
Как отмечалось в обсуждении, иногда эффективнее делать проверку перед записью набора записей регистров (например, регистра бухгалтерии или регистров накопления). Если НаправлениеДеятельности является измерением регистра, мы можем создать подписку на событие ПередЗаписью для набора записей этого регистра.
Преимущества этого метода:
Недостатки: пользователь получит ошибку уже после того, как документ попытается сформировать движения, что иногда сложнее диагностировать.
Выясним, можно ли решить задачу без программирования. В современных конфигурациях (ERP 2.5, УТ 11.5) можно настроить RLS (Row Level Security) — ограничение доступа на уровне записей. Вы можете настроить профиль групп доступа таким образом, чтобы пользователям было запрещено изменение документов, где значение НаправлениеДеятельности.Статус равно Не используется. Однако этот метод требует тщательной настройки прав и может существенно снизить производительность системы при больших объемах данных.
Для реализации качественного запрета проведения мы рекомендуем следовать следующим правилам:
ДокументОбъект, чтобы не загромождать расширение лишними объектами.ОбработкаВыбора в формах или настройку связей параметров выбора в самих реквизитах справочника.Такой комплексный подход обеспечит чистоту данных в системе и избавит вас от необходимости поддерживать сложный и разветвленный код в расширениях.