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