При разработке и кастомизации типовых конфигураций 1С (особенно таких как УПП 1.3, УТ 10.3, КА 1.1 или ERP) программисты часто сталкиваются с необходимостью изменить поведение общей формы ФормаЦеныИВалюта. Эта форма отвечает за выбор типа цен, валюты, налоговых режимов (НДС) и скидок для табличных частей различных документов. Основная сложность заключается в том, что форма универсальна, и если нам требуется заблокировать или скрыть определенные поля только для одного конкретного документа (например, для «Поступления товаров и услуг»), стандартные методы не всегда очевидны.
В этой статье мы подробно разберем, как определить, из какого именно документа была открыта общая форма, как управлять доступностью её реквизитов программно и как правильно использовать предопределенный механизм структуры запрещенных реквизитов.
Когда общая форма открывается из формы документа, свойство ВладелецФормы (или ЭтаФорма.ВладелецФормы) ссылается не на сам прикладной объект метаданных, а на его клиентскую форму. Напрямую получить тип документа через обычное обращение к метаданным владельца нельзя. Однако мы можем безопасно извлечь объект документа или проанализировать имя его формы.
Рассмотрим два варианта реализации этого метода в зависимости от типа используемого приложения.
Вариант А: Для обычного приложения (УПП 1.3, УТ 10.3, КА 1.1)
В обычных формах у формы-владельца практически всегда присутствует свойство ДокументОбъект. Мы можем попытаться прочитать это свойство в процедуре ПриОткрытии общей формы цен и валют. Проанализируем следующий пример безопасного кода:
Если ТипЗнч(ЭтаФорма.ВладелецФормы) = Тип("Форма") Тогда
Попытка
// Пытаемся получить объект документа через форму-владельца
ДокументОбъект = ЭтаФорма.ВладелецФормы.ДокументОбъект;
ИмяДокумента = ДокументОбъект.Метаданные().Имя;
// Если форма вызвана из документа ПоступлениеТоваровУслуг, блокируем поля
Если ИмяДокумента = "ПоступлениеТоваровУслуг" Тогда
ЭлементыФормы.НовыйТипЦен.Доступность = Ложь;
ЭлементыФормы.НовыйСпособЗачетаАвансов.Доступность = Ложь;
КонецЕсли;
Исключение
// Исключение сработает, если владельцем является не форма документа
КонецПопытки;
КонецЕсли;
Вариант Б: Для управляемого приложения (ERP, КА 2, УТ 11, БП 3.0)
В управляемых формах обращение к свойству ВладелецФормы.Объект на сервере не всегда безопасно, так как объект может находиться в состоянии данных формы (ДанныеФормыСтруктура) или вовсе еще не быть записан в базу данных. В управляемом интерфейсе гораздо надежнее и быстрее проанализировать строковое свойство ИмяФормы у владельца. Разберем, как это сделать в процедуре ПриСозданииНаСервере:
Если ЭтаФорма.ВладелецФормы <> Неопределено Тогда
ИмяФормыВладельца = ЭтаФорма.ВладелецФормы.ИмяФормы;
// Значение будет иметь вид: "Документ.ПоступлениеТоваровУслуг.Форма.ФормаДокумента"
Если СтрНайти(ИмяФормыВладельца, "Документ.ПоступлениеТоваровУслуг") > 0 Тогда
// Отключаем доступность управляемых элементов на форме цен и валют
Элементы.НДСВключенВСтоимость.Доступность = Ложь;
Элементы.ПорядокРегистрацииЦен.Доступность = Ложь;
КонецЕсли;
КонецЕсли;
Почему ключи в структуре запрещенных реквизитов, передаваемые при открытии формы, часто не совпадают с именами элементов на самой форме ФормаЦеныИВалюта? С этим вопросом часто сталкиваются начинающие разработчики.
Выясним причину этого поведения. Разработчики фирмы 1С проектировали общую форму цен и валют как независимый универсальный конструктор. Чтобы не привязывать форму к реквизитам конкретных документов, был реализован трансляционный механизм:
СтруктураЗапрещенных (в некоторых конфигурациях — СтруктураНередактируемыхРеквизитов). В нее помещаются имена реквизитов самого документа-источника (например, УчитыватьНДС, СуммаВключаетНДС).Ценообразование) или в модуле самой формы происходит сопоставление переданной структуры с элементами формы. На форме элементы часто имеют префиксы (например, флаг на форме называется НовыйУчитыватьНДС или НовыйТипЦен).
ФормаЦеныВалюты.ЭлементыФормы.НовыйУчитыватьНДС.Доступность =
НЕ СтруктураНередактируемыхРеквизитов.Свойство("УчитыватьНДС");
Поэтому правильный, архитектурно верный способ ограничить доступность полей без изменения кода общей формы — это передать нужные ключи в структуру запрещенных реквизитов еще на этапе вызова метода открытия из модуля формы вашего документа.
Посмотрим на пример вызова из формы документа «Поступление товаров и услуг»:
// Определяем структуру запрещенных к изменению реквизитов документа
СтруктураЗапрещенных = Новый Структура;
СтруктураЗапрещенных.Вставить("УчитыватьНДС"); // Заблокирует флаг НДС на форме
СтруктураЗапрещенных.Вставить("СуммаВключаетНДС"); // Заблокирует флаг включения НДС в сумму
СтруктураЗапрещенных.Вставить("РегистрироватьЦеныПоставщика"); // Заблокирует флаг регистрации цен
// Вызываем типовой метод открытия формы цен и валют
Ценообразование.ОткрытьФормуЦеныИВалюта(
ДокументОбъект,
СтруктураРеквизитовДокумента,
мВалютаРегламентированногоУчета,
СтруктураЗапрещенных,
"Товары"
);
При таком подходе общая форма цен и валют автоматически заблокирует соответствующие связанные элементы, и нам не придется писать сложный код обхода элементов внутри самой общей формы.
Если вы работаете в современной конфигурации на управляемом интерфейсе (например, 1С:ERP или Комплексная автоматизация) и вам необходимо внедрить логику блокировки элементов формы цен без изменения типовой конфигурации (чтобы сохранить ее на полной поддержке), наилучшим решением будет использование Расширений конфигурации.
Выполним задачу по шагам:
ФормаЦеныИВалюта.ПриСозданииНаСервере с аннотацией &После.Проанализируем программный код, который будет выполняться после стандартной инициализации формы:
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем наличие владельца формы
Если ЭтотОбъект.ВладелецФормы <> Неопределено Тогда
ИмяФормы = ЭтотОбъект.ВладелецФормы.ИмяФормы;
// Проверяем, что форма открыта именно из документа ПоступлениеТоваровУслуг
Если СтрНайти(ИмяФормы, "Документ.ПоступлениеТоваровУслуг") > 0 Тогда
// Отключаем доступность реквизита "РегистрироватьЦеныПоставщика"
ЭлементФормы = Элементы.Найти("РегистрироватьЦеныПоставщика");
Если ЭлементФормы <> Неопределено Тогда
ЭлементФормы.Доступность = Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Использование расширений гарантирует, что при последующих обновлениях типовой конфигурации ваши доработки не затрутся, а логика программы останется стабильной и прозрачной для других разработчиков.