Каталог решений - Обработка расширением на клиенте

Обработка расширением на клиенте

Обработка расширением на клиенте

В наличии

Описываю нетривиальный прием работы с расширением, который позволит относительно быстро реализовывать некоторые обработки данных.

Суть: обработка данных на клиенте с использованием методов, которые реализованы разработчиком конфигурации на форме объекта.

Если эти методы есть вне модуля формы объекта (общий модуль, модуль менеджера, модуль объекта)- лучше сделать обработку более простым способом.

Категория:

Описание

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

 

Кейсы: 

  1. загрузили через XML из старой системы в ERP контрагентов, хотим массово заполнить по ИНН,
  2. хотим массово по профилям заполнить группы доступа,
  3. загрузили через XML из старой системы в ERP пользователей, хотим массово создать пользователей ИБ, что бы при этом им были предоставлены доступы согласно настройкам профилей и групп доступа
  4. и так далее

Общий принцип работы

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

На примере кейса "ЗаполнениеПоИНН":
методы, без которых ничего не получится, написаны в форме элемента справочника "Контрагенты", писать их отдельно в своей обработке совсем не хочется, но хочется обратиться к ним. Если бы это была экспортная процедура либо функция из общего модуля, модуля менеджера или хотя бы из модуля какого-то объекта, то проблемы нет: взяли и вызвали этот метод в своей групповой обработке. Но если нужный метод написан в форме объекта, то добраться до него без открытия формы не получится.
Надо соответственно открывать каждую форму и там обращаться к этим методам, а потом записывать и закрывать.
Ниже изложено как это можно реализовать своими руками. 

Разработка по шагам 

Шаг 1: Создание расширения

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

Шаг 2: Заимствование

Нам надо заимствовать две формы в расширение: форма списка, из которой будет выполняться групповая обработка, форма объекта, в котором есть требуемые методы основной конфигурации.
Чаще всего это формы списка и объекта в одном и том же справочнике (документе и т.д., в тч регистре сведений), но могут быть формы списка и объекта относиться к разным объектам.

Шаг 3: Доработка формы списка

Добавляем команду "ГрупповоеЗаполнение" (или как нравится из контекста задачи, в моем примере "ЗаполнитьПоИНН_Списком"). Команду выводим на командную панель.

У команды клиентский обработчик после (без вызова сервера)

&НаКлиенте
Процедура ВД_ЗаполнитьПоИНН_СпискомПосле(Команда)
	МассивПройти = Новый Массив;
	Для Каждого ВыделеннаяСтрока Из Элементы.Список.ВыделенныеСтроки Цикл
		МассивПройти.Добавить(ВыделеннаяСтрока);
	КонецЦикла;
	ВД_ЗаполнитьПоИНН_Открыть(Неопределено, МассивПройти);
КонецПроцедуры

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

Основной рабочий метод в форме списка "ВД_ОткрытьЗаполнить" (или как в этом примере "ВД_ЗаполнитьПоИНН_Открыть") выполняется так же на клиенте, экспортный.

&НаКлиенте
Процедура ВД_ЗаполнитьПоИНН_Открыть(Результат, СтарыйМассивПройти) Экспорт
	Если ТипЗнч(Результат) = Тип("Структура") Тогда
		Сообщение = Новый СообщениеПользователю;
		ЗаполнитьЗначенияСвойств(Сообщение, Результат);
		Сообщение.Сообщить();
	КонецЕсли;
	МассивПройти = Новый Массив;
	ПервыйЕсть = ЛОЖЬ;
	Первый = Неопределено;
	Для Каждого ВыделеннаяСтрока Из СтарыйМассивПройти Цикл
		Если ПервыйЕсть Тогда
			МассивПройти.Добавить(ВыделеннаяСтрока);
		Иначе
			Первый = ВыделеннаяСтрока;
			ПервыйЕсть = Истина;
		КонецЕсли;
	КонецЦикла;
	Если НЕ Первый = Неопределено Тогда
		ПараметрыОткрытия = Новый Структура("Ключ, ВД_ЗаполнитьПоИНН", Первый, Истина);
		ОписаниеОповещения = Новый ОписаниеОповещения(
			"ВД_ЗаполнитьПоИНН_Открыть",
			ЭтотОбъект,
			МассивПройти);
		ОткрытьФорму("Справочник.Контрагенты.ФормаОбъекта",
			ПараметрыОткрытия,
			ЭтотОбъект,
			1,
			,
			,
			ОписаниеОповещения,
			РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	Иначе
		ПоказатьПредупреждение(,"Заполнение по ИНН завершено" );
	КонецЕсли;
КонецПроцедуры

Как работает:
метод работает как бы рекурсивно, через описание оповещения, в самом начале выводит в сообщения только что обработанный объект, выбирает первый элемент массива — его будет обрабатывать, откладывает на следующий вызов оставшуюся часть массива, выполняется, пока массив не закончится.
Можно обрабатывать с конца и оптимизировать.
Главное: при вызове формы объекта передать в нее параметр "ВД_ЗаполнитьЗаписатьЗакрыть" (или "ВД_ЗаполнитьПоИНН" как в моем примере), чтобы сообщить туда о необходимости выполнения обработки, а так же можно передать что-нибудь еще. Можно сделать создание нового, тогда вместо ключа надо передавать параметры заполнения.

Шаг 4: Доработка формы объекта

На форме добавляем параметры и реквизиты, которые мы передаем из списка (не считая предусмотренных разработчиком конфигурации).

При создании на сервере передаем параметры в реквизиты.

При открытии если параметр"ВД_ЗаполнитьЗаписатьЗакрыть" (или "ВД_ЗаполнитьПоИНН" как в моем примере), определяющий необходимость обработки = истина, то через обработчик ожидания с задержкой 0.2 секунды вызвать основной метод, который заполнит нужные поля и обратится к нужным методам формы, после чего запишет объект с передачей ссылки и комментария (для вывода в сообщения)

при создании на сервере переносим параметр в реквизит
 

&НаСервере
Процедура ВД_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
	Если Параметры.Свойство("ВД_ЗаполнитьПоИНН") Тогда
		ВД_ЗаполнитьПоИНН = Параметры.ВД_ЗаполнитьПоИНН;
	КонецЕсли;
КонецПроцедуры

при открытии запускаем обработчик ожидания (чтобы наш код выполнился в открытой и полностью инициализированной форме)

&НаКлиенте
Процедура ВД_ПриОткрытииПосле(Отказ)
	Если ВД_ЗаполнитьПоИНН Тогда
		ПодключитьОбработчикОжидания("ВД_ЗаполнитьПоИНН_Сразу", 0.2, Истина);
	КонецЕсли;
КонецПроцедуры

заполнение — основная часть данного расширения, в нем вызываются методы, которые определены только в самой форме (в данном примере нас интересуют методы "ЗаполнениеРеквизитовПоДаннымИННВозможно" и "ЗаполнитьРеквизитыКонтрагентаПоПолученнымДанным", в случае успешного выполнения записываем и закрываем)

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

&НаКлиенте
Процедура ВД_ЗаписатьСКомментариемИЗакрыть(Знач Записывать, Комментарий)
	Если ПустаяСтрока(Объект.ДополнительнаяИнформация) Тогда
		Объект.ДополнительнаяИнформация = Комментарий;
		Записывать = Истина;
	ИначеЕсли СтрНайти(Объект.ДополнительнаяИнформация, Комментарий) = 0 Тогда
		Объект.ДополнительнаяИнформация = Объект.ДополнительнаяИнформация + Символы.ПС + Комментарий;
		Записывать = Истина;
	КонецЕсли;
	Если Записывать Тогда
		Записать();
	КонецЕсли;
	Закрыть(Новый Структура("КлючДанных, Текст", Объект.Ссылка, Строка(Объект.Ссылка) + ": " + Комментарий));
КонецПроцедуры

Результат

открываем список контрагентов, выделяем нужных, запускаем, перед нами постоянно открывается форма контрагента и сразу закрывается, после окончания выводится предупреждение "Заполнение по ИНН завершено", и все объекты с комментариями в форме списка,
после выполнения расширение можно удалить: конфигурация заказчика останется на замке (ну по крайней мере без наших доработок), мы сэкономили время и не разбирались со сложным кодом и при этом получили инструмент, которым можно воспользоваться еще раз.

has been added to your cart:
Оформление заказа