Статья посвящена доработкам, призванным уменьшить количество обновлений конфигурации. Будет полезна для организаций, где тех. задания возникают на лету, базы огромные, работает более 1000 пользователей. Частое отключение базы нежелательно. А динамика часто приводит к краху базы. Доработка позволяет оперативно менять, отлаживать код без изменения конфигурации. Оперативно добавлять регламентные задания, оперативно добавлять методы HTTP-сервисов (можно и Веб, но тут не используется). И второй пункт ХранимыеЗначения – аналог констант в базе с возможностью хранить произвольные значения с произвольным именем.
Перед этим конфигурацию придется минимально доработать:
Для регламентного и сервисов нужно соответственно создать РАЗОВО универсальное регламентное и универсальный HTTP- сервис.
Для отладки или изменяемого кода нужно добавить РАЗОВО несколько строк в нужный блок программы.
Принцип работы – имеется справочник алгоритмов, в котором есть текстовое поле с исполняемым кодом. Идентифицируется по наименованию элемента. В алгоритм можно передать через структуру какие-то данные и получить через эту же структуру новые или обработанные данные – полученные по результату работы алгоритма. Ограничение на код алгоритма стандартные – нельзя использовать операторы Функция, Процедура, Возврат. Если у вас что-то очень сложное - поместите свой исполняемый код в обработку без всяких ограничений и вызовите обработку из алгоритма. Таким образом можно к примеру легко сделать рассылку отчета. Вся сложность заключается в том, что нужно заранее описать в конфигураторе передаваемые и получаемые данные. Здесь представлен самый универсальный вариант. Можно в принципе получить и выполнить код алгоритма напрямую - контекст будет ему виден, данные передавать не надо.
Соответственно на этом же справочнике основаны и регламентное и HTTPсервис. Регламентные задания различаются по параметрам – фактически в регламентном основная процедура исполняет код алгоритма – идентификация которого идет по параметру регламентного. Вы просто добавляете очередное регламентное, прописываете в параметре наименование нужного алгоритма, и он будет выполняться по расписанию.
HTTP –сервис имеет универсальный метод Execute, В качестве тела запроса передается структура с Ключом -Наименование алгоритма, и с допПараметрами – данными. ДопПараметры будут и в ответе сервиса. Метод по ключу находит алгоритм, передает в него допПараметр, алгоритм возвращает в допПараметре результат выполнения. Сервис возвращает допПараметр в ответе.
Ошибки отладки видно в Журнале регистрации
Реализация:
Справочник Алгоритмы
Описание, ТекстПрограммы – строковое неограниченное
Активный – булево, признак что алгоритм рабочий.
Ответственный, Автор – информационные поля, можно прицепить справочник пользователи, здесь строка.
ДатаАктивации – дата, информационное поле.
В модуль менеджера справочника добавляем Процедуру:
Процедура ВыполнитьАлгоритм(Ключ, ДопПараметры="") Экспорт
// Ключ, наименование алгоритма
//Доппараметры - структура(данные любые) которую можно передать в алгоритм- сюда же нужно положить результат выполнения если возвращается какое-то значение
УстановитьПривилегированныйРежим(Истина);
ЗапросАлгоритмы = Новый Запрос;
ЗапросАлгоритмы.УстановитьПараметр("ИмяАлг", Ключ);
ЗапросАлгоритмы.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Алгоритмы.Ссылка КАК Ссылка,
| Алгоритмы.ТекстПрограммы КАК ТекстПрограммы,
| Алгоритмы.Код КАК Код
|ИЗ
| Справочник.Алгоритмы КАК Алгоритмы
|ГДЕ
| НЕ Алгоритмы.ЭтоГруппа
| И Алгоритмы.Наименование = &ИмяАлг
| И Алгоритмы.Активный
| И НЕ Алгоритмы.ПометкаУдаления
|
|УПОРЯДОЧИТЬ ПО
| Код УБЫВ
|АВТОУПОРЯДОЧИВАНИЕ";
ВыборкаАлг = ЗапросАлгоритмы.Выполнить().Выбрать();
Если ВыборкаАлг.Следующий() Тогда
Код = ВыборкаАлг.Код;
Попытка
Выполнить ВыборкаАлг.ТекстПрограммы;
Исключение
стрОшибки =ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Ошибка алгоритма", , , стрОшибки);
Сообщить("---Ошибка АЛГОРИТМа Ключ - " + Ключ+": "+стрОшибки);
ДопПараметры =Новый Структура("Ошибка","!!!ошибка алгоритма: "+стрОшибки );
КонецПопытки;
Иначе
стрОшибки ="нет алгоритма по ключу - "+Ключ;
ЗаписьЖурналаРегистрации("Ошибка алгоритма", УровеньЖурналаРегистрации.Ошибка, , , стрОшибки);
Сообщить(стрОшибки);
ДопПараметры =Новый Структура("Ошибка",стрОшибки );
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Пример использования отладки кода:
Функция ПолучитьОстатки (ДанОп)
допПараметры =Новый Структура("ДанОп", даноп);
ВыполнитьАлгоритм("ОстаткиДляЧегото", допПараметры);
//В алгоритме ОстаткиДляЧегото на спискаНоменклатуры (переменная данОП) вычисляются
//остатки и помещаются в тз. Эта тз добавляется в структуру допПараметры под параметром рез.
Если допПараметры.Свойство("Рез") Тогда
Возврат допПараметры.Рез;
КонецЕсли;
//Если алгоритма нет или в нем ошибка выполняется типовой код
//….
//….
Возврат тзОстатки;
КонецФункции
Реализация HTTP-Сервиса:
Добавляем сервис
В модуль сервиса добавляем процедуры:
Функция GetclientsPost(Запрос)
Если Запрос.ОтносительныйURL = "/Execute" Тогда
ПолученныеДанные = Десериализовать(Запрос.ПолучитьТелоКакСтроку());
Результат = ОтветНаHTTP(ПолученныеДанные);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Результат);
Возврат Ответ;
Иначе
Ответ = Новый HTTPСервисОтвет(200);
Возврат Ответ;
КонецЕсли;
КонецФункции
Функция Десериализовать(XMLСтруктура) Экспорт
ЧтениеXMLДанных = Новый ЧтениеXML;
ЧтениеXMLДанных.УстановитьСтроку(XMLСтруктура);
ТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXMLДанных);
ЧтениеXMLДанных.Закрыть();
Возврат ТЗ;
КонецФункции
Функция Сериализовать(Структура) Экспорт
ДеревоВОбъекте = СериализаторXDTO.ЗаписатьXDTO(Структура);
МойXML = Новый ЗаписьXML;
МойXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(МойXML,ДеревоВОбъекте);
Возврат МойXML.Закрыть();
КонецФункции
Функция ОтветНаHTTP(ПолученныеДанные) Экспорт
Ответ="";
Если ПолученныеДанные.Свойство("Ключ") Тогда
Ответ =ВыполнениеПоАлгоритму(ПолученныеДанные);
Иначе
Ответ ="Запрос не определен";
КонецЕсли;
Возврат Сериализовать(Ответ);
КонецФункции
Функция ВыполнениеПоАлгоритму(ДанОп)
//Выполенние произвольного алагоритма по справочнику Алгоритмы
//Должно быть свойство ключ и допПараметры(тудасюдаха- будет передано В и вернется ИЗ алгоритма)
Если данОп.свойство("Ключ") Тогда
допПараметры =?(данОп.свойство("допПараметры"), ДанОп.допПараметры, "");
Справочники.Алгоритмы.ВыполнитьАлгоритм(данОп.Ключ, допПараметры);
Возврат (Новый Структура("Успешно, допПараметры", Истина, допПараметры));
КонецЕсли;
Возврат Новый структура("Успешно,допПараметры", ложь, ДанОп.допПараметры);
КонецФункции
По коду – при вызове метод сервиса uni/Execute, метод проверяет полученную структуру запроса, здесь должно быть 2 параметра – Ключ (имя алгоритма) и допПараметр (вложенная структура с данными). Алгоритм может переопределить эту переменную или добавить свои данные. Эта структура возвращаются в качестве ответа.
Пример вызова вебсервиса, код обработки:
&НаКлиенте
Процедура Команда1(Команда)
ответ =СделатьHTTPЗапрос(Новый Структура("Ключ, допПараметры", "СложитьСтр", Новый Структура("Текст1, текст2","раз", "два")));
Сообщить(Ответ);
КонецПроцедуры
&НаСервере
//Вход для запроса Execute
//структура с параметрами Ключ и Допппараметры
Функция СделатьHTTPЗапрос(Структура) Экспорт
// Вставить содержимое обработчика.
ТестовыйРежим = ПараметрыСеанса.ТестовыйРежим;
НастрБазы =Константы.ТестоваяБаза.Получить();
Запрос = Сериализовать(Структура);
Пользователь = "Admin";
Пароль = "1";
СоединениеHTTP = Новый HTTPСоединение("192.168.1.1", , Пользователь, Пароль);
HTTPЗапрос = Новый HTTPЗапрос("TabUPS/hs/uni/Execute");
HTTPЗапрос.УстановитьТелоИзСтроки(Запрос);
Попытка
HTTPОтвет = СоединениеHTTP.ОтправитьДляОбработки(HTTPЗапрос);
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
Возврат Десериализовать(Ответ);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецФункции
&НаСервере
Функция Десериализовать(XMLСтруктура)
ЧтениеXMLДанных = Новый ЧтениеXML;
ЧтениеXMLДанных.УстановитьСтроку(XMLСтруктура);
ТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXMLДанных);
ЧтениеXMLДанных.Закрыть();
Возврат ТЗ;
КонецФункции
&НаСервере
Функция Сериализовать(Объект)
ДеревоВОбъекте = СериализаторXDTO.ЗаписатьXDTO(Объект);
МойXML = Новый ЗаписьXML;
МойXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(МойXML, ДеревоВОбъекте);
Возврат МойXML.Закрыть();
КонецФункции
Итого если в основной базе будет алгоритм с именем «СложитьСтр»
В ответе сервиса вы получите структуру с 3 параметрами: п1, п2, рез.
Реализация регламентного (НЕТ в Расширении!!!).
Добавляем универсальное регламентное
В качестве процедуры:
Процедура УниверсальноеРегламентное(КлючРЗ="", Парам1="", Парам2="", Парам3="") Экспорт
Если не СокрЛП(КлючРЗ) ="" Тогда //это регламентное из алгоритма
Справочники.Алгоритмы.ВыполнитьАлгоритм(КлючРЗ, Новый Структура("Парам1, Парам2, Парам3", Парам1, Парам2, Парам3));
КонецЕсли;
КонецПроцедуры
Итого при создании регламентного в пользовательском режиме вам нужно указать первым параметром название алгоритма. Здесь прошито еще 3 параметра. Вы можете указать свои данные для регламентного – например, подразделение. Алгоритм видит эти параметры как ДопПараметры.Парам1, ДопПараметры.Парам2, ДопПараметры.Парам3
Вид созданного задания:
Здесь – АвтоФормирование это наименование алгоритма который будет выполняться из справочника Алгоритмы. Второй параметр произвольный – данные которые вы передаете в алгоритм. Здесь подразделение по которому нужно формировать чтото…
Второй механизм проще – аналог констант, регистр сведений ХранимыеЗначения. Периодический. Состав данных определите сами
Имя – Строка 20
ТипЗначения – Строка 100
Имя и типЗначения просто составной ключ для поиска нужного значения. В качестве типаЗначения используется тип данных для возврата пустого значения - если нет записи. В другом варианте сюда заносил подсистему к которой относится переменная – упрощает редактирование пользователю, особенно когда значений уже поднакопилось.
Значение - Составной тип данных: Строка, Число, и т.д.….
В модуль менеджера добавляем функцию:
Функция ПолучитьХран(Ключ, ТипЗнач="", Дата="") Экспорт
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ключ" , Ключ);
Запрос.УстановитьПараметр("Дата" ,?(Дата="", Дата('00010101'), Дата));
Запрос.УстановитьПараметр("ТипЗнач" ,ТипЗнач);
Запрос.Текст =
"ВЫБРАТЬ
| ХранимыеЗначенияСрезПоследних.Период КАК Период,
| ХранимыеЗначенияСрезПоследних.Имя КАК Имя,
| ХранимыеЗначенияСрезПоследних.ТипЗначения КАК ТипЗначения,
| ХранимыеЗначенияСрезПоследних.Значение КАК Значение,
| ХранимыеЗначенияСрезПоследних.Комментарий КАК Комментарий
|ИЗ
| РегистрСведений.ХранимыеЗначения.СрезПоследних(
| &Дата,
| ТипЗначения = &ТипЗнач
| И имя = &Ключ) КАК ХранимыеЗначенияСрезПоследних";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Значение;
ИначеЕсли ТипЗнач ="Дата" Тогда
Возврат Дата("00010101");
ИначеЕсли ТипЗнач ="Булево" Тогда
Возврат Дата(Ложь);
ИначеЕсли ТипЗнач ="Строка" Тогда
Возврат "";
Иначе
Возврат Неопределено;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
КонецФункции
Теперь из любого места конфигурации можем вызвать ее:
стрП =РегистрыСведений.ХранимыеЗначения.ПолучитьХран("ПолноеРедакт", "Строка");
В качестве значения может быть либо ссылка либо к примеру список кодов справочников через запятую. Их после получения придется обработать – но зато его может редактировать пользователь. Если очень надо через ЗначениеВСтрокуВнутр можно сохранять массивы, списки, таблицы значений и т.д..
По практике постоянно использую Хранимые, HTTPсервис и Регламентное.
В расширении абсолютно тот же код, еще и без регламентного. Выложено для тех кто не хочет заморачиваться с кодом. Не думаю что копипаст займет больше часа ).
Код тестировался на платформе 1С:Предприятие 8.3 (8.3.15.1830) на управляемых формах. В рабочей базе работает под обычными формами.