// Интерфейс для регистрации обработки. // Вызывается при добавлении обработки в справочник "ВнешниеОбработки" // // Возвращаемое значение: // Структура: // Вид - строка - возможные значения: "ДополнительнаяОбработка" // "ДополнительныйОтчет" // "ЗаполнениеОбъекта" // "Отчет" // "ПечатнаяФорма" // "СозданиеСвязанныхОбъектов" // // Назначение - массив строк имен объектов метаданных в формате: // <ИмяКлассаОбъектаМетаданного>.[ * | <ИмяОбъектаМетаданных>] // Например, "Документ.СчетЗаказ" или "Справочник.*" // Прим. параметр имеет смысл только для назначаемых обработок // // Наименование - строка - наименование обработки, которым будет заполнено // наименование справочника по умолчанию - краткая строка для // идентификации обработки администратором // // Версия - строка - версия обработки в формате <старший номер>.<младший номер> // используется при загрузке обработок в информационную базу // БезопасныйРежим – Булево – Если истина, обработка будет запущена в безопасном режиме. // Более подбробная информация в справке. // // Информация - Строка- краткая информация по обработке, описание обработки // // ВерсияБСП - Строка - Минимальная версия БСП, на которую рассчитывает код // дополнительной обработки. Номер версии БСП задается в формате «РР.ПП.ВВ.СС» // (РР – старший номер редакции; ПП – младший номер ре-дакции; ВВ – номер версии; СС – номер сборки). // // Команды - ТаблицаЗначений - команды, поставляемые обработкой, одная строка таблицы соотвествует // одной команде // колонки: // - Представление - строка - представление команды конечному пользователю // - Идентификатор - строка - идентефикатор команды. В случае печатных форм // перечисление через запятую списка макетов // - Использование - строка - варианты запуска обработки: // "ОткрытиеФормы" - открыть форму обработки // "ВызовКлиентскогоМетода" - вызов клиентского экспортного метода из формы обработки // "ВызовСерверногоМетода" - вызов серверного экспортного метода из модуля объекта обработки // - ПоказыватьОповещение – Булево – если Истина, требуется оказывать оповещение при начале // и при окончании запуска обработки. Прим. Имеет смысл только // при запуске обработки без открытия формы. // - Модификатор – строка - для печатных форм MXL, которые требуется // отображать в форме ПечатьДокументов подсистемы Печать // требуется установить как "ПечатьMXL" // // Предусмотрено 2 команды: // 1. "Открыть форму обработки" для загрузки прайс-листа в диалоговом режиме // 2. "Загрузить прайс-лист и сохранить протокол в файл" для загрузки прайс-листа по регламентному заданию и // сохранения протокола в файл. // Функция СведенияОВнешнейОбработке() Экспорт РегистрационныеДанные = Новый Структура; РегистрационныеДанные.Вставить("Наименование", "ирПортативныйСервер"); РегистрационныеДанные.Вставить("БезопасныйРежим", Ложь); РегистрационныеДанные.Вставить("Версия", "3.37.1"); РегистрационныеДанные.Вставить("ВерсияБСП", "1.2.1.4"); РегистрационныеДанные.Вставить("Вид", "ДополнительнаяОбработка"); РегистрационныеДанные.Вставить("Информация", ""); ТЗКоманд = Новый ТаблицаЗначений; ТЗКоманд.Колонки.Добавить("Идентификатор"); ТЗКоманд.Колонки.Добавить("Представление"); ТЗКоманд.Колонки.Добавить("Модификатор"); ТЗКоманд.Колонки.Добавить("ПоказыватьОповещение"); ТЗКоманд.Колонки.Добавить("Использование"); СтрокаКоманды = тзКоманд.Добавить(); СтрокаКоманды.Идентификатор = "ЗаписатьОбъектXMLЛкс"; СтрокаКоманды.Представление = "ЗаписатьОбъектXMLЛкс"; СтрокаКоманды.ПоказыватьОповещение = Ложь; СтрокаКоманды.Использование = "ВызовСерверногоМетода"; СтрокаКоманды = тзКоманд.Добавить(); СтрокаКоманды.Идентификатор = "ВыполнитьАлгоритм"; СтрокаКоманды.Представление = "ВыполнитьАлгоритм"; СтрокаКоманды.ПоказыватьОповещение = Ложь; СтрокаКоманды.Использование = "ВызовСерверногоМетода"; РегистрационныеДанные.Вставить("Команды", ТЗКоманд); Возврат РегистрационныеДанные; КонецФункции // Параметры // ОбъектыНазначения - массив - ссылоки на объекты информационной базы, для которых требуется вызвать обработку // ПараметрыВыполненияКоманды - структура - структура со свойством ДополнительнаяОбработкаСсылка (ссылка на // элемент справочника ДополнительныеОтчетыИОбработки, который связан с данной дополнительной обработкой) // Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыКоманды) Экспорт Если ИдентификаторКоманды = "ЗаписатьОбъектXMLЛкс" Тогда СтрокаXML = ПараметрыКоманды.СтрокаXML; ДополнительныеСвойства = ПараметрыКоманды.ДополнительныеСвойства; РежимЗаписи = ПараметрыКоманды.РежимЗаписи; ОтключатьКонтрольЗаписи = ПараметрыКоманды.ОтключатьКонтрольЗаписи; БезАвторегистрацииИзменений = ПараметрыКоманды.БезАвторегистрацииИзменений; ЗаписатьОбъектXMLЛкс(СтрокаXML, ДополнительныеСвойства, РежимЗаписи, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений); ПараметрыКоманды.СтрокаXML = СтрокаXML; ИначеЕсли ИдентификаторКоманды = "ВыполнитьАлгоритм" Тогда ВыполнитьАлгоритм(ПараметрыКоманды._ТекстДляВыполнения, ПараметрыКоманды._АлгоритмОбъект); КонецЕсли; КонецПроцедуры // Выполняет текст алгоритма. // // Параметры: // ТекстДляВыполнения – Строка; // _АлгоритмОбъект - СправочникОбъект // *СтруктураПараметров - Структура, *Неопределено. // Функция ВыполнитьАлгоритм(_ТекстДляВыполнения, _АлгоритмОбъект = Null, _Режим = Null, _П0 = Null, _П1 = Null, _П2 = Null, _П3 = Null, _П4 = Null, _П5 = Null, _П6 = Null, _П7 = Null, _П8 = Null, _П9 = Null) Экспорт Перем Результат; //Если Истина // И ирКэш.ЛиПортативныйРежимЛкс() // И ирПортативный.ЛиСерверныйМодульДоступенЛкс() //Тогда // ирПортативный.ВыполнитьСерверныйМетодЛкс("ВыполнитьАлгоритм", _АлгоритмОбъект); //Иначе Выполнить(_ТекстДляВыполнения); //КонецЕсли; Возврат Результат; КонецФункции // ПозиционныйМетод() Функция ЛиПортативныйРежимЛкс() Возврат Ложь; КонецФункции // Записывает объект с параметризованным контекстом (клиент/сервер). // Обеспечивает запись объекта с попытками. Позволяет обойти неинтенсивные дедлоки и превышения ожиданий блокировки. // Также обеспечивает обход оптимистичных объектных блокировок в случае, если в БД пишутся точно те же данные объекта, что и актуальные. // Эффективно для многопоточной записи объектов. Процедура ЗаписатьОбъектЛкс(Объект, НаСервере = Ложь, РежимЗаписи = Неопределено, РежимПроведения = Неопределено, ОтключатьКонтрольЗаписи = Неопределено, БезАвторегистрацииИзменений = Неопределено) Экспорт //Если НаСервере Тогда // ДополнительныеСвойства = СериализоватьДополнительныеСвойстваОбъектаЛкс(Объект); // СтрокаXML = СохранитьОбъектВВидеСтрокиXMLЛкс(Объект); // ЗаписатьОбъектXMLЛкс(СтрокаXML, ДополнительныеСвойства, РежимЗаписи, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений); // Объект = ВосстановитьОбъектИзСтрокиXMLЛкс(СтрокаXML); //Иначе НачалоПопыток = ТекущаяДата(); ПопытокЗаписиОбъекта = 4; ПредельнаяДлительность = 20; Для СчетчикПопыток = 1 По ПопытокЗаписиОбъекта Цикл УстановитьПараметрыЗаписиОбъектаЛкс(Объект, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений); Попытка Если РежимЗаписи = Неопределено Тогда Объект.Записать(); ИначеЕсли РежимЗаписи = "ПометкаУдаления" Тогда Объект.Записать(); Объект.ОбменДанными.Загрузка = Ложь; Объект.УстановитьПометкуУдаления(Не Объект.ПометкаУдаления); ИначеЕсли Истина И ТипЗнч(РежимЗаписи) = Тип("РежимЗаписиДокумента") И РежимЗаписи <> РежимЗаписиДокумента.Запись Тогда Объект.ОбменДанными.Загрузка = Ложь; Объект.Записать(РежимЗаписи, РежимПроведения); Иначе Объект.Записать(РежимЗаписи); КонецЕсли; Прервать; Исключение ОписаниеОшибки = ОписаниеОшибки(); // Если ВОписанииОшибкиЕстьПередачаМутабельногоЗначенияЛкс(ОписаниеОшибки, Ложь) Тогда // ВызватьИсключение; // КонецЕсли; Если Ложь Или СчетчикПопыток = ПопытокЗаписиОбъекта Или ТекущаяДата() - НачалоПопыток >= ПредельнаяДлительность Тогда ВызватьИсключение; КонецЕсли; Если Истина И РежимЗаписи = Неопределено И (Ложь Или Найти(ОписаниеОшибки, "несоответствия версии или отсутствия записи базы данных") > 0 Или Найти(ОписаниеОшибки, "version mismatch or lack of database record") > 0) Тогда ТекущийXML = СохранитьОбъектВВидеСтрокиXMLЛкс(Объект, Ложь); Объект.Прочитать(); НовыйXML = СохранитьОбъектВВидеСтрокиXMLЛкс(Объект, Ложь); Если ТекущийXML = НовыйXML Тогда Прервать; Иначе ВызватьИсключение; КонецЕсли; КонецЕсли; КонецПопытки; КонецЦикла; //КонецЕсли; КонецПроцедуры Процедура УстановитьПараметрыЗаписиОбъектаЛкс(Знач Объект, ОтключатьКонтрольЗаписи = Неопределено, БезАвторегистрацииИзменений = Неопределено) Экспорт Попытка лОбменДанными = Объект.ОбменДанными; Исключение лОбменДанными = Неопределено; КонецПопытки; Если лОбменДанными <> Неопределено Тогда Если ОтключатьКонтрольЗаписи <> Неопределено Тогда Объект.ОбменДанными.Загрузка = ОтключатьКонтрольЗаписи; КонецЕсли; Если БезАвторегистрацииИзменений <> Неопределено Тогда Объект.ОбменДанными.Получатели.Автозаполнение = Не БезАвторегистрацииИзменений; КонецЕсли; КонецЕсли; КонецПроцедуры // Параметры: // Объект - // ИспользоватьXDTO - // Функция СохранитьОбъектВВидеСтрокиXMLЛкс(Знач Объект, Знач ИспользоватьXDTO = Истина, ИмяФайла = "") Экспорт Поток = Новый ЗаписьXML; Если ЗначениеЗаполнено(ИмяФайла) Тогда Поток.ОткрытьФайл(ИмяФайла); Иначе Поток.УстановитьСтроку(); КонецЕсли; Попытка Если ИспользоватьXDTO Тогда СериализаторXDTO.ЗаписатьXML(Поток, Объект); Иначе ЗаписатьXML(Поток, Объект); КонецЕсли; Исключение Поток.Закрыть(); ВызватьИсключение; КонецПопытки; Результат = Поток.Закрыть(); Возврат Результат; КонецФункции // Копирует все элементы переданного массива, структуры, соответствия, списка значений или коллекции объектов метаданных // в однотипную коллекцию приемник (для метаданных в массив). Если коллекция приемник не указана, она будет создана. // Фиксированные коллекции превращаются в нефиксированные. // // Параметры: // КоллекцияИсходная - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных - исходная коллекция; // КоллекцияПриемник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных, *Неопределено - коллекция приемник. // // Возвращаемое значение: // КоллекцияПриемник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных - коллекция приемник. // Функция СкопироватьУниверсальнуюКоллекциюЛкс(КоллекцияИсходная, КоллекцияПриемник = Неопределено) Экспорт ТипКоллекции = ТипЗнч(КоллекцияИсходная); Если Ложь Или ТипКоллекции = Тип("Массив") Или ТипКоллекции = Тип("ФиксированныйМассив") #Если Не ТонкийКлиент И Не ВебКлиент Тогда Или ТипКоллекции = Тип("КоллекцияОбъектовМетаданных") #КонецЕсли Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Массив; КонецЕсли; Для Каждого Элемент Из КоллекцияИсходная Цикл КоллекцияПриемник.Добавить(Элемент); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли Ложь Или ТипКоллекции = Тип("Структура") Или ТипКоллекции = Тип("ФиксированнаяСтруктура") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Структура; КонецЕсли; Для Каждого Элемент Из КоллекцияИсходная Цикл КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли Ложь Или ТипКоллекции = Тип("Соответствие") Или ТипКоллекции = Тип("ФиксированноеСоответствие") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Соответствие; КонецЕсли; Для Каждого Элемент Из КоллекцияИсходная Цикл КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли ТипКоллекции = Тип("СписокЗначений") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый СписокЗначений; КонецЕсли; Для Каждого Элемент Из КоллекцияИсходная Цикл ЗаполнитьЗначенияСвойств(КоллекцияПриемник.Добавить(), Элемент); КонецЦикла; Возврат КоллекцияПриемник; #Если Не ТонкийКлиент И Не ВебКлиент Тогда ИначеЕсли ТипКоллекции = Тип("ТаблицаЗначений") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = КоллекцияИсходная.СкопироватьКолонки(); КонецЕсли; ЗагрузитьВТаблицуЗначенийЛкс(КоллекцияИсходная, КоллекцияПриемник); Возврат КоллекцияПриемник; #КонецЕсли Иначе Сообщить("Неверный тип универсальной коллекции для копирования """ + ТипКоллекции + """"); Возврат Неопределено; КонецЕсли; КонецФункции // СкопироватьУниверсальнуюКоллекциюЛкс() // Добавляет в таблицу значений строки из другой таблицы значений и // в них значения колонок с совпадающими наименованиями. // // Параметры: // ТаблицаИсточник - таблица значений, откуда берутся значения; // ТаблицаПриемник - таблица значений, куда добавляются строки; // *СтруктураЗначенийПоУмолчанию - Структура, *Неопределено - значения по умолчанию для добавляемых строк; // *СтруктураНовыхЗначений - Структура, *Неопределено - значения колонок для добавляемых строк, имеют высший приоритет. // Процедура ЗагрузитьВТаблицуЗначенийЛкс(ТаблицаИсточник, ТаблицаПриемник, СтруктураЗначенийПоУмолчанию = Неопределено, СтруктураНовыхЗначений = Неопределено) Экспорт СтрокаСовпадающихКолонок = ""; Разделитель = ","; Если ТипЗнч(ТаблицаИсточник) = Тип("ТаблицаЗначений") Тогда КолонкиИсточника = ТаблицаИсточник.Колонки; Иначе КолонкиИсточника = Метаданные.НайтиПоТипу(ТипЗнч(ТаблицаИсточник)).Реквизиты; КонецЕсли; ЛиПриемникТЧ = ТипЗнч(ТаблицаПриемник) <> Тип("ТаблицаЗначений"); Если ЛиПриемникТЧ Тогда КолонкиПриемника = ТаблицаПриемник.ВыгрузитьКолонки().Колонки; Иначе КолонкиПриемника = ТаблицаПриемник.Колонки; КонецЕсли; Для каждого Колонка Из КолонкиПриемника Цикл Если СтруктураНовыхЗначений <> Неопределено Тогда Если СтруктураНовыхЗначений.Свойство(Колонка.Имя) Тогда Продолжить; КонецЕсли; КонецЕсли; Если Истина И (Ложь Или Не ЛиПриемникТЧ Или Колонка.Имя <> "НомерСтроки") И КолонкиИсточника.Найти(Колонка.Имя) <> Неопределено Тогда СтрокаСовпадающихКолонок = СтрокаСовпадающихКолонок + Разделитель+ Колонка.Имя; КонецЕсли; КонецЦикла; СтрокаСовпадающихКолонок = Сред(СтрокаСовпадающихКолонок, СтрДлина(Разделитель) + 1); Для каждого СтрокаТаблицыИсточника Из ТаблицаИсточник Цикл СтрокаТаблицыПриемника = ТаблицаПриемник.Добавить(); Если СтруктураЗначенийПоУмолчанию <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтруктураЗначенийПоУмолчанию); КонецЕсли; // Заполним значения в совпадающих колонках. ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтрокаТаблицыИсточника, СтрокаСовпадающихКолонок); //Для каждого ЭлементМассива Из МассивСовпадающихКолонок Цикл // СтрокаТаблицыПриемника[ЭлементМассива] = СтрокаТаблицыИсточника[ЭлементМассива]; //КонецЦикла; Если СтруктураНовыхЗначений <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтруктураНовыхЗначений); КонецЕсли; КонецЦикла; КонецПроцедуры // ЗагрузитьВТаблицуЗначенийЛкс() Процедура ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, СтруктураДополнительныхСвойств) Экспорт Если СтруктураДополнительныхСвойств.Свойство("ОбменДанными") Тогда лОбменДанными = Объект.ОбменДанными; СтруктураОбменаДанными = СтруктураДополнительныхСвойств.ОбменДанными; ЗаполнитьЗначенияСвойств(лОбменДанными, СтруктураОбменаДанными); ЗаполнитьЗначенияСвойств(лОбменДанными.Получатели, СтруктураОбменаДанными.Получатели); лОбменДанными.Получатели.Очистить(); Для Каждого Получатель Из СтруктураОбменаДанными.Получатели.Узлы Цикл лОбменДанными.Получатели.Добавить(Получатель); КонецЦикла; КонецЕсли; Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта") Тогда СкопироватьУниверсальнуюКоллекциюЛкс(СтруктураДополнительныхСвойств.ДополнительныеСвойства, Объект.ДополнительныеСвойства); КонецЕсли; КонецПроцедуры // ВосстановитьПараметрыОбменаДаннымиЛкс() // Параметры: // XML - // Тип - // ИспользоватьXDTO - // СообщатьОбОшибках - // Функция ВосстановитьОбъектИзСтрокиXMLЛкс(Знач ФайлИлиXML = "", Знач Тип = "", Знач ИспользоватьXDTO = Истина, Знач СообщатьОбОшибках = Истина) Экспорт Если Ложь Или ТипЗнч(ФайлИлиXML) = Тип("Файл") Или ЗначениеЗаполнено(ФайлИлиXML) Тогда ЧтениеXML = Новый ЧтениеXML; Если ТипЗнч(ФайлИлиXML) = Тип("Файл") Тогда ЧтениеXML.ОткрытьФайл(ФайлИлиXML); Иначе ЧтениеXML.УстановитьСтроку(ФайлИлиXML); КонецЕсли; Попытка Если ИспользоватьXDTO Тогда Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеXML); Иначе Результат = ПрочитатьXML(ЧтениеXML); КонецЕсли; Исключение Если СообщатьОбОшибках Тогда Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное); КонецЕсли; ЧтениеXML.Закрыть(); КонецПопытки; // Антибаг платформы 8.2-8.3.6 СериализаторXDTO некорректно восстанавливает пустую табличную часть поверх непустой https://partners.v8.1c.ru/forum/t/1329468/m/1329468 Попытка Пустышка = Результат.Модифицированность(); МетаТЧи = Результат.Метаданные().ТабличныеЧасти; Исключение МетаТЧи = Новый Массив; КонецПопытки; Для Каждого МетаТЧ Из МетаТЧи Цикл ТЧ = Результат[МетаТЧ.Имя]; Если ТЧ.Количество() = 0 Тогда ТЧ.Вставить(0); ТЧ.Удалить(0); КонецЕсли; КонецЦикла; КонецЕсли; Если Результат = Неопределено Тогда Если ЗначениеЗаполнено(Тип) Тогда Результат = Новый (Тип); КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Процедура ЗаписатьОбъектXMLЛкс(СтрокаХМЛ, ДополнительныеСвойства, РежимЗаписи = Неопределено, ОтключатьКонтрольЗаписи = Неопределено, БезАвторегистрацииИзменений = Неопределено) Экспорт Объект = ВосстановитьОбъектИзСтрокиXMLЛкс(СтрокаХМЛ); ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, ДополнительныеСвойства); ЗаписатьОбъектЛкс(Объект, Ложь, РежимЗаписи, , ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений); СтрокаХМЛ = СохранитьОбъектВВидеСтрокиXMLЛкс(Объект); КонецПроцедуры