Реализация ввода на основании в расширении конфигурации 1С — это задача, которая часто выходит за рамки простого добавления объекта в метаданные. Когда нам необходимо реализовать специфическую логику, например, заполнение 50% суммы от документа-основания, и при этом обеспечить корректную работу прав доступа в типовых конфигурациях на базе Библиотеки стандартных подсистем (БСП), мы сталкиваемся с рядом нюансов. В этой статье мы подробно разберем, как правильно реализовать этот функционал, сохранив документ незаписанным до момента принятия решения пользователем, и как решить критическую проблему "исчезающих" ролей в расширениях.
Для того чтобы при создании документа на основании данные заполнялись автоматически, но сам документ не записывался сразу в базу данных, мы должны использовать стандартное событие ОбработкаЗаполнения. Рассмотрим этот процесс на примере документа РасходИзКассы, который создается на основании документа ОтчетКомитенту.
Проанализируем ситуацию: если мы добавим логику в форму документа, она не сработает при программном создании объекта. Правильнее всего будет расширить модуль объекта создаваемого документа. Для этого создадим расширение и добавим в него документ-приемник. В модуле объекта этого документа используем аннотацию &После для процедуры ОбработкаЗаполнения.
Разберем пример кода, реализующий заполнение половины суммы:
&После("ОбработкаЗаполнения")
Процедура Расш1_ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Проверяем, что основанием является именно нужный нам документ
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ОтчетКомитенту") Тогда
// Реализуем логику: берем 50% от суммы документа-основания
ЭтотОбъект.СуммаДокумента = ДанныеЗаполнения.СуммаДокумента * 0.5;
// Заполняем остальные реквизиты, например, контрагента (комитента)
ЭтотОбъект.Контрагент = ДанныеЗаполнения.Комитент;
ЭтотОбъект.Организация = ДанныеЗаполнения.Организация;
ЭтотОбъект.ДокументОснование = ДанныеЗаполнения;
// Документ остается в памяти, форма откроется с этими данными, но записи в БД не произойдет
КонецЕсли;
КонецПроцедуры
Важно помнить: чтобы платформа автоматически вызвала это событие при интерактивном нажатии кнопки "Создать на основании", в метаданных расширения для документа-приемника в свойстве "Является основанием для" должен быть указан документ-источник. Однако в современных конфигурациях этого может быть недостаточно из-за динамического формирования меню БСП.
В современных типовых решениях (БП 3.0, УТ 11, ERP) подменю "Создать на основании" формируется программно. Если мы просто добавим связь в метаданных, кнопка может не появиться в общем списке. Нам необходимо зарегистрировать нашу новую команду в механизмах БСП.
Выясним причину: БСП использует специальные общие модули для формирования структуры команд. Нам нужно расширить общий модуль ВводНаОснованииПереопределяемый. В процедуре ПриОпределенииНастроекВводаНаОсновании (название может незначительно отличаться в зависимости от версии БСП) мы добавляем программную связь. Это гарантирует, что кнопка появится в интерфейсе и будет доступна пользователю.
Если же логика типового документа полностью перекрывает стандартный механизм, нам придется расширить форму документа-источника (ОтчетКомитенту) и в процедуре ПриСозданииНаСервере вручную добавить кнопку в группу ПодменюСоздатьНаОсновании, привязав её к команде расширения.
Одной из самых коварных проблем при использовании расширений является поведение БСП по отношению к новым ролям. Часто разработчики замечают, что добавленные в расширении права "слетают" у пользователей или вовсе не применяются для администраторов системы. Посмотрим на причину: типовой код БСП при обновлении ролей пользователей может игнорировать роли из расширений, считая их "некорректными" или лишними для профиля администратора.
Для решения этой проблемы коллеги предлагают использовать "костыли" в процедурах обновления прав. Рассмотрим способ корректировки общего модуля УправлениеДоступомСлужебный. Нам необходимо вмешаться в процедуру ОбновитьРолиПользователей, чтобы система не удаляла специфические роли расширения у пользователей с полными правами.
Проанализируем пример "заплатки", которая позволяет сохранить роли расширения для администраторов:
&ИзменениеИКонтроль("ОбновитьРолиПользователей")
Процедура Расш1_ОбновитьРолиПользователей(Знач ОписаниеПользователей, Знач ПарольПользователяСервиса, ЕстьИзменения)
// ... существующий код БСП ...
#Вставка
// Гарантируем, что специфические роли из расширения не будут удалены у администраторов
Если Администраторы[ТекущийПользователь] <> Неопределено Тогда
Для Каждого КлючИЗначение Из ОбязательныеРолиАдминистратора Цикл
Если НовыеРоли.Найти(КлючИЗначение.Значение, "РольСсылка") <> Неопределено Тогда
Продолжить;
КонецЕсли;
НовыеРоли.Добавить().РольСсылка = КлючИЗначение.Значение;
КонецЦикла;
КонецЕсли;
#КонецВставки
// ... продолжение кода ...
КонецПроцедуры
Также полезно использовать экспортные функции для проверки прав вместо стандартной РольДоступна(), если проверка идет по профилям доступа, созданным в расширении. Это позволяет избежать жесткой привязки к метаданным, которые БСП может не "видеть" до полного обновления вспомогательных данных.
После добавления новых объектов или команд в расширение, обязательно выполните обновление идентификаторов объектов метаданных. В БСП это критически важный шаг для того, чтобы подсистемы управления доступом и формирования интерфейса узнали о существовании ваших правок. Для этого можно воспользоваться методом:
Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеСправочника()
Или запустить внешнюю обработку "Обновление вспомогательных данных", которая входит в состав инструментов разработчика БСП.
Подведем итог: для успешного создания документа на основании в расширении мы используем ОбработкаЗаполнения в модуле объекта для вычисления 50% суммы, регистрируем команду в механизмах БСП через переопределяемые модули и внимательно следим за тем, чтобы подсистема управления доступом не блокировала наши новые роли, при необходимости применяя исправления в служебных модулях БСП.