Как запретить выбор незаполненных элементов справочника в документах 1С, сохранив возможность их редактирования?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Торговля и дистрибуция
← На главную

При работе с информационными системами на платформе 1С часто возникает задача, когда необходимо ограничить использование элементов справочника в документах, если они не полностью заполнены или не соответствуют определенным критериям. При этом очень важно сохранить для пользователя возможность просматривать и редактировать эти элементы. Эта ситуация характерна для многих бизнес-процессов, например, когда данные об объекте (контрагенте, номенклатуре) вносятся поэтапно различными сотрудниками или подразделениями, и до полного завершения ввода всей необходимой информации элемент не должен попадать в рабочие документы.

Решение этой задачи требует комплексного подхода, поскольку затрагивает несколько аспектов работы системы: от пользовательского интерфейса до проверки данных на серверном уровне. Рассмотрим различные методы, их плюсы и минусы, и выберем наиболее эффективные пути реализации.

Постановка задачи и ее нюансы

Основная цель состоит в том, чтобы пользователь НЕ МОГ выбрать элемент справочника в своих документах, если этот элемент не соответствует определенным условиям (например, не заполнены все требуемые поля). В то же время, пользователь ДОЛЖЕН иметь возможность просмотреть такой элемент и внести в него необходимые изменения, чтобы впоследствии он стал доступен для использования.

Почему это не так просто? Мы сталкиваемся с несколькими вызовами:

  1. Разные сценарии выбора: Элементы справочника могут выбираться через форму выбора, форму подбора, автоподбор текста, ввод по строке, а также программно. Необходимо охватить все эти точки.
  2. Предотвращение дублирования: Если мы просто скроем элемент из списка, пользователь может не найти его и создать дубль, что приведет к засорению базы данных.
  3. Удобство для пользователя: Важно, чтобы ограничения были понятны и не вызывали фрустрации. Пользователь должен понимать, почему элемент недоступен, и как это исправить.
  4. Программный обход: Ограничения на уровне интерфейса могут быть обойдены при помощи групповых обработок или прямым программным обращением к данным.

Наиболее эффективное решение будет сочетать несколько подходов, обеспечивая контроль на разных уровнях. Разберем предложенные варианты и сформируем комплексный метод.

Комплексный подход с использованием дополнительного реквизита и фильтрации

В основе этого подхода лежит идея маркировки элементов справочника, которые готовы к использованию, и применение этой маркировки для фильтрации и проверки.

  1. Создание дополнительного реквизита для элемента справочника

    Первым шагом мы добавим к справочнику булевый реквизит, который будет служить флагом готовности элемента к использованию. Назовем его, например, ГотовКИспользованию или ТребуемыеПоляЗаполнены. Этот реквизит будет автоматически устанавливаться в зависимости от заполненности ключевых полей.

    Перейдем в конфигуратор, выберем нужный справочник (например, МойСправочник) и добавим новый реквизит:

    
    // В конфигураторе, для нужного справочника ("МойСправочник")
    // Создадим новый реквизит:
    //   Имя: ГотовКИспользованию
    //   Тип: Булево
    //   Основное назначение: Использование в качестве флага готовности элемента
    //   Установите флажок "Индексировать" для лучшей производительности при фильтрации.
    
  2. Автоматическое заполнение реквизита ГотовКИспользованию

    Мы реализуем логику проверки заполненности необходимых полей в модуле объекта справочника. Это позволит гарантировать, что флаг ГотовКИспользованию всегда будет актуальным и устанавливаться при каждой записи элемента справочника.

    Откроем модуль объекта нашего справочника (МойСправочник) и добавим процедуру ПередЗаписью:

    
    // В модуле объекта справочника "МойСправочник"
    Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
        // Определяем условия готовности элемента.
        // Например, элемент считается готовым, если заполнены Наименование, ВидКонтрагента и ИНН.
        Если ЗначениеЗаполнено(ЭтотОбъект.Наименование) И
           ЗначениеЗаполнено(ЭтотОбъект.ВидКонтрагента) И
           НЕ ПустаяСтрока(ЭтотОбъект.ИНН) Тогда // Пример проверки нескольких полей
            ЭтотОбъект.ГотовКИспользованию = Истина;
        Иначе
            ЭтотОбъект.ГотовКИспользованию = Ложь;
        КонецЕсли;
    КонецПроцедуры
    

    Такой подход позволяет элементу быть сохраненным в недозаполненном состоянии (с флагом ГотовКИспользованию = Ложь), что соответствует исходному требованию автора: "можно было сохранить, но использовать в работе его было нельзя".

  3. Фильтрация элементов в формах выбора, подбора и при вводе по строке

    Это ключевой шаг для предотвращения выбора незаполненных элементов на уровне интерфейса. Мы рассмотрим несколько сценариев:

    1. Для форм выбора (открытие формы выбора по кнопке):

      Нам необходимо установить программный отбор в форме выбора справочника, чтобы она по умолчанию показывала только элементы, готовые к использованию. Это делается в событии ПриСозданииНаСервере или ПередОткрытием формы выбора.

      
      // В модуле формы выбора справочника "МойСправочник"
      Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
          // Параметр "НеПрименятьОтборПоГотовности" можно использовать для ролей,
          // которым разрешено видеть все элементы (например, администраторам или сотрудникам НСИ).
          Если НЕ Параметры.Свойство("НеПрименятьОтборПоГотовности") Тогда
              // Устанавливаем отбор по реквизиту ГотовКИспользованию
              Отбор.ГотовКИспользованию.Установить(Истина);
              Отбор.ГотовКИспользованию.ВидСравнения = ВидСравнения.Равно;
              Отбор.ГотовКИспользованию.Использование = Истина;
          КонецЕсли;
      КонецПроцедуры
      

      Чтобы обеспечить возможность отключения отбора для определенных ролей, мы можем передавать параметр в форму выбора, например, при открытии из общего списка или специальной обработки.

    2. Для автоподбора и ввода по строке:

      Когда пользователь начинает вводить текст в поле ввода, или система пытается автоматически подобрать значение, нам также нужно контролировать доступность элементов. Это достигается перехватом событий поля ввода в форме документа.

      Обработка события ОбработкаВыбора: Это событие срабатывает, когда значение уже выбрано (например, из открывшейся формы выбора или по кнопке выбора).

      
      // В модуле формы документа, где выбирается элемент справочника "МойСправочник" (например, реквизит Документ.Контрагент)
      // Название процедуры должно соответствовать имени поля: "ИмяПоляСправочникаОбработкаВыбора"
      Процедура КонтрагентОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
          СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку, чтобы управлять выбором вручную
      
          Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.МойСправочник") Тогда
              Если НЕ ВыбранноеЗначение.ГотовКИспользованию Тогда
                  Сообщить("Выбранный элемент справочника '" + ВыбранноеЗначение.Наименование + "' не заполнен до конца и не может быть использован.", СтатусСообщения.Важное);
                  Элемент.Значение = Неопределено; // Очищаем поле, если элемент не готов
              Иначе
                  Элемент.Значение = ВыбранноеЗначение; // Устанавливаем значение, если элемент готов
              КонецЕсли;
          Иначе
              // Обработка случаев, когда было выбрано что-то другое (например, пустое значение или отмена)
              Элемент.Значение = Неопределено;
          КонецЕсли;
      КонецПроцедуры
      

      Обработка событий АвтоПодборТекста и ОкончаниеВводаТекста: Эти события позволяют контролировать процесс ввода и подбора текста.

      
      // В модуле формы документа
      // Название процедуры должно соответствовать имени поля: "ИмяПоляСправочникаАвтоПодборТекста"
      Процедура КонтрагентАвтоПодборТекста(Элемент, Текст, ДополнительнаяИнформацияПроверки, Параметры)
          // Здесь можно программно изменить запрос для автоподбора,
          // добавив условие на ГотовКИспользованию.
          // Например, можно передать Параметры.Отбор.ГотовКИспользованию.Установить(Истина);
          // или вручную выполнить поиск и установить ДополнительнаяИнформацияПроверки.ОтображаемыеДанные.
      КонецПроцедуры
      
      // В модуле формы документа
      // Название процедуры должно соответствовать имени поля: "ИмяПоляСправочникаОкончаниеВводаТекста"
      Процедура КонтрагентОкончаниеВводаТекста(Элемент, Текст, ДополнительнаяИнформацияПроверки, СтандартнаяОбработка)
          СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
      
          // Попытаемся найти элемент по введенному тексту (по наименованию или коду)
          СсылкаНаЭлемент = Неопределено;
          Попытка
              СсылкаНаЭлемент = Справочники.МойСправочник.НайтиПоНаименованию(Текст);
              Если СсылкаНаЭлемент.Пустая() Тогда
                  СсылкаНаЭлемент = Справочники.МойСправочник.НайтиПоКоду(Текст);
              КонецЕсли;
          Исключение
              // Ошибка при поиске, возможно неверный формат текста
          КонецПопытки;
      
      
          Если НЕ СсылкаНаЭлемент.Пустая() Тогда
              // Если элемент найден, проверяем его готовность
              Если НЕ СсылкаНаЭлемент.ГотовКИспользованию Тогда
                  Сообщить("Элемент справочника '" + Текст + "' не заполнен до конца и не может быть использован.", СтатусСообщения.Важное);
                  Элемент.Значение = Неопределено; // Очищаем поле
              Иначе
                  Элемент.Значение = СсылкаНаЭлемент; // Устанавливаем значение
              КонецЕсли;
          Иначе
              // Если элемент не найден
              Сообщить("Элемент справочника с наименованием или кодом '" + Текст + "' не найден.", СтатусСообщения.Внимание);
              Элемент.Значение = Неопределено;
          КонецЕсли;
      КонецПроцедуры
      
  4. Условное оформление в формах списка справочника

    Для улучшения пользовательского опыта мы можем визуально выделять незаполненные элементы в общих списках справочника. Это позволит пользователям быстро находить такие элементы и переходить к их редактированию. Для этого используем механизм УсловноеОформление в форме списка справочника.

    
    // В модуле формы списка справочника "МойСправочник"
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        // Создаем элемент условного оформления
        ЭлементОформления = УсловноеОформление.Элементы.Добавить();
        ЭлементОформления.Использование = Истина;
    
        // Условие: если реквизит ГотовКИспользованию = Ложь
        Условие = ЭлементОформления.Условия.Добавить(Тип("ЭлементУсловногоОформленияКоллекцияСтрока"));
        Условие.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ГотовКИспользованию");
        Условие.ВидСравнения = ВидСравнения.Равно;
        Условие.ПравоеЗначение = Ложь;
    
        // Оформление: устанавливаем красный цвет текста
        ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", Новый Цвет(255, 0, 0)); // Красный цвет
        ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Шрифт", Новый Шрифт(,,Истина)); // Жирный шрифт
    
        // Указываем поля, к которым будет применяться оформление
        // Можно применить к Наименованию или ко всей строке
        Поле = ЭлементОформления.Поля.Добавить();
        Поле.Поле = Новый ПолеКомпоновкиДанных("Наименование");
        Поле.Использование = Истина;
    
        Поле = ЭлементОформления.Поля.Добавить();
        Поле.Поле = Новый ПолеКомпоновкиДанных("Ссылка"); // Оформляем всю строку
        Поле.Использование = Истина;
    КонецПроцедуры
    
  5. Контроль при записи и проведении документов

    Даже при наличии всех вышеописанных мер, всегда существует вероятность обхода ограничений (например, через групповое изменение реквизитов, программное создание документов, внешние обработки). Поэтому критически важно иметь последний рубеж обороны – проверку непосредственно при записи или проведении документов, использующих наш справочник.

    В типовых конфигурациях 1С (особенно в 1С:ERP Управление предприятием, 1С:Комплексная автоматизация) часто используется унифицированный механизм проверки заполнения, например, через процедуру ОбработкаПроверкиЗаполнения, которая может быть реализована как в модуле объекта документа, так и в модуле менеджера или через подписки на события.

    Рассмотрим пример реализации в модуле объекта документа:

    
    // В модуле объекта документа, где используется ссылка на "МойСправочник"
    Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
        // Выполняем стандартные проверки заполнения документа, если они есть.
        // Например, вызов общего функционала типовых конфигураций:
        // ИсправлениеДокументов.ОбработкаПроверкиЗаполнения(ЭтотОбъект, Отказ, ПроверяемыеРеквизиты);
    
        // Добавляем специфическую проверку для нашего справочника
        Если НЕ ЭтотОбъект.СсылкаНаМойСправочник.Пустая() Тогда
            Если НЕ ЭтотОбъект.СсылкаНаМойСправочник.ГотовКИспользованию Тогда
                // Если выбранный элемент не готов к использованию, формируем ошибку
                ДобавитьОшибку(Отказ, "Выбранный элемент справочника '" + ЭтотОбъект.СсылкаНаМойСправочник.Наименование + "' не заполнен до конца и не может быть использован в документе.", "СсылкаНаМойСправочник");
            КонецЕсли;
        КонецЕсли;
    
        // Вспомогательная процедура для добавления ошибки
        Процедура ДобавитьОшибку(Отказ, ТекстОшибки, ИмяПоля = "")
            Сообщение = Новое СообщениеПользователю;
            Сообщение.Текст = ТекстОшибки;
            Если ЗначениеЗаполнено(ИмяПоля) Тогда
                Сообщение.Поле = ИмяПоля;
                Сообщение.УстановитьДанные(ЭтотОбъект, ИмяПоля); // Привязка сообщения к полю формы
            КонецЕсли;
            Сообщение.Сообщить();
            Отказ = Истина;
        КонецПроцедуры
    
    КонецПроцедуры
    

    Такая проверка не позволит провести или записать документ, если в нем используется "неготовый" элемент справочника, даже если он был выбран обходными путями. Это минимизирует риски некорректного использования данных.

Дополнительный контроль: Ролевой подход и права доступа

Для более тонкого управления доступом и видимости можно использовать механизм ролей и ограничений прав доступа на уровне записей (RLS). Мы можем настроить права таким образом, чтобы пользователи, отвечающие за ввод и редактирование справочной информации, видели все элементы (включая незаполненные), а обычные пользователи, которые только используют элементы в документах, видели только "готовые" элементы.

  1. Создание или модификация ролей:

    Мы создаем или изменяем существующие роли. Например, роль "Менеджер по вводу НСИ" будет иметь полные права на справочник, а роль "Пользователь Документов" будет иметь ограниченные права.

  2. Настройка ограничений на уровне записей (RLS):

    Для роли "Пользователь Документов" (или аналогичной) мы устанавливаем ограничение доступа к данным для таблицы нашего справочника (МойСправочник). Ограничение будет использовать наш реквизит ГотовКИспользованию.

    Пример RLS для таблицы справочника МойСправочник:

    
    // В ограничении доступа к данным (RLS) для таблицы справочника "МойСправочник"
    // для чтения, изменения, добавления
    #Если &НаСервере Тогда
        "ГотовКИспользованию = ИСТИНА"
    #КонецЕсли
    

    Это выражение гарантирует, что для пользователей с данной ролью будут доступны только те записи справочника, у которых реквизит ГотовКИспользованию установлен в значение Истина. Таким образом, незаполненные элементы просто не будут видны в списках и не будут доступны для выбора в стандартных механизмах.

Альтернативный подход: Запрет сохранения элемента справочника до полного заполнения

Некоторые коллеги предлагают наиболее радикальный подход: вообще не позволять сохранять элемент справочника, если он не заполнен до конца. Этот метод гарантирует, что в базе данных никогда не появятся "неготовые" элементы, что исключает саму проблему их несанкционированного использования.

Реализация этого подхода также происходит в процедуре ПередЗаписью модуля объекта справочника:


// В модуле объекта справочника "МойСправочник"
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    // Проверяем заполненность всех критически важных полей
    Если НЕ ЗначениеЗаполнено(ЭтотОбъект.Наименование) ИЛИ
       НЕ ЗначениеЗаполнено(ЭтотОбъект.ВидКонтрагента) ИЛИ
       ПустаяСтрока(ЭтотОбъект.ИНН) Тогда
        Сообщить("Элемент справочника не может быть записан, так как не заполнены все требуемые поля (Наименование, Вид контрагента, ИНН).", СтатусСообщения.Важное);
        Отказ = Истина; // Запрещаем запись элемента
    КонецЕсли;
КонецПроцедуры

Плюсы этого подхода:

  1. Строгий контроль: Исключает появление "неправильных" данных в системе с самого начала.
  2. Простота: Не требует дополнительных механизмов фильтрации в формах или проверки при проведении документов, поскольку все элементы в справочнике априори "готовы".

Минусы этого подхода:

  1. Жесткость для бизнес-процессов: Может быть неприемлемым для компаний со сложными бизнес-процессами, где информация об одном и том же элементе вводится поэтапно разными отделами и на разных стадиях жизненного цикла. Например, сначала создается базовая запись, а затем к ней добавляются специфические характеристики, штрихкоды, данные о ценах и т.д.
  2. Пользовательский опыт: Пользователи могут быть недовольны, если не смогут сохранить элемент, чтобы вернуться к нему позже.

Подписки на события для централизованного контроля

Если в системе много документов и полей, ссылающихся на один и тот же справочник, поддерживать код в каждой форме документа может быть трудоемко. В этом случае на помощь приходят подписки на события. Мы можем создать подписку на событие ОбработкаВыбора для всех реквизитов, имеющих тип ссылки на наш справочник. Это позволит централизовать логику проверки и предотвращения выбора.


// Пример подписки на событие "ОбработкаВыбора"
// Создайте новую подписку на событие в конфигураторе
//   Имя: ПроверитьВыборМоегоСправочника
//   Событие: ОбработкаВыбора
//   Источник: РеквизитФормы (свойство "Тип значения" которого содержит ссылку на "МойСправочник")
//   Обработчик: ОбщийМодуль.МойОбщийМодуль.ПроверитьВыборЭлементаСправочника

// В Общем модуле "МойОбщийМодуль" (или другом подходящем модуле)
Процедура ПроверитьВыборЭлементаСправочника(Элемент, ВыбранноеЗначение, СтандартнаяОбработка) Экспорт
    Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.МойСправочник") Тогда
        Если НЕ ВыбранноеЗначение.ГотовКИспользованию Тогда
            Сообщить("Выбранный элемент справочника '" + ВыбранноеЗначение.Наименование + "' не заполнен до конца и не может быть использован.", СтатусСообщения.Важное);
            Элемент.Значение = Неопределено;
            СтандартнаяОбработка = Ложь; // Важно отменить стандартную обработку
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Этот подход значительно упрощает поддержку и снижает вероятность пропуска какого-либо поля, где может произойти выбор элемента.

Выбор оптимального решения

Как мы видим, задача имеет несколько решений, каждое из которых имеет свои преимущества и недостатки. Оптимальный выбор зависит от специфики бизнес-процессов вашей компании и требований к системе:

  1. Если требуется гибкость и поэтапный ввод информации: Рекомендуется комплексный подход с дополнительным реквизитом ГотовКИспользованию, фильтрацией форм выбора, условным оформлением и проверкой при записи/проведении документов. Это позволяет сохранять незаполненные элементы и постепенно доводить их до готовности.
  2. Если необходим строжайший контроль и отсутствие "черновиков" в справочнике: Выбирайте подход с запретом сохранения элемента до полного заполнения. Однако будьте готовы к тому, что это может потребовать пересмотра некоторых бизнес-процессов.
  3. Для улучшения управляемости и снижения трудозатрат на поддержку: Активно используйте подписки на события для централизации проверок.
  4. Для разграничения доступа: Используйте RLS совместно с дополнительным реквизитом, чтобы управлять видимостью элементов для различных ролей пользователей.

Сочетание дополнительного булевого реквизита, фильтрации в пользовательском интерфейсе, условного оформления и контроля при записи/проведении документов, дополненное ролевым подходом, представляет собой наиболее сбалансированное и гибкое решение. Оно обеспечивает необходимый контроль, сохраняет удобство для пользователя и предотвращает некорректное использование данных.

← На главную