Skip to content

Instantly share code, notes, and snippets.

@FragsterAt
Created December 24, 2018 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FragsterAt/30a1e89ae709b12d16903ff9eeca6469 to your computer and use it in GitHub Desktop.
Save FragsterAt/30a1e89ae709b12d16903ff9eeca6469 to your computer and use it in GitHub Desktop.
#Область БазоваяФункциональность
Функция ПолучитьМаркиPDF417(Знач ДанныеОМарках, РегистрироватьОшибкиВЖурнале = Ложь) Экспорт
Если ДанныеОМарках = Неопределено Или ДанныеОМарках.Количество() = 0 Тогда
Возврат Новый Соответствие;
КонецЕсли;
// Определяем параметры выполнения.
Если ДанныеОМарках.Количество() < 1000 Тогда
ЧислоПотоков = 1;
Иначе
ОбъектРасширения = АСФРасширенияФункционала.ПолучитьОбъектРасширения();
ЧислоПотоков = Неопределено;
Если ОбъектРасширения <> Неопределено Тогда
Попытка
ЧислоПотоков = ОбъектРасширения.ПолучитьЧислоЯдерПроцессора();
Если ЧислоПотоков = Неопределено Тогда
ОписаниеОшибки = ОбъектРасширения.ОписаниеОшибки();
КонецЕсли;
Исключение
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
Иначе
ОписаниеОшибки = """Не удалось подключить внешнюю компоненту лицензирования""";
КонецЕсли;
Если ЧислоПотоков = Неопределено Тогда
ОписаниеОшибки = АСФОбщегоНазначенияКлиентСервер.ПодставитьПараметрыВСтроку("Не удалось получить информацию о количестве ядер сервера по причине: ""%1""" + Символы.ПС + "Получение/генерация марок будут выполнены в однопоточном режиме", ОписаниеОшибки);
ЗаписьЖурналаРегистрации("АСФ. Генерация марок", УровеньЖурналаРегистрации.Предупреждение, Метаданные.Справочники.АСФМаркиPDF417,, ОписаниеОшибки, РежимТранзакцииЗаписиЖурналаРегистрации.Независимая);
ЧислоПотоков = 1;
ИначеЕсли АСФОбщегоНазначенияКлиентСервер.ИнформационнаяБазаФайловая() Тогда
ЧислоПотоков = Мин(ЧислоПотоков, ?(АСФОбщегоНазначенияПовторноеИспользование.ФоновыеЗаданияТребуютОбработкиОжидания() = Истина, 1, 2));
КонецЕсли;
КонецЕсли;
// Готовим данные для запуска.
ТаблицаДанныхМарокШаблон = Новый ТаблицаЗначений;
ТаблицаДанныхМарокШаблон.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(150)));
ТаблицаДанныхМарокШаблон.Колонки.Добавить("Владелец");
ДанныеПоПотокам = Новый Массив;
МаксимальныйИндексПотока = ЧислоПотоков - 1;
Для ИндексПотока = 0 По МаксимальныйИндексПотока Цикл
Поток = Новый Структура("ТаблицаДанныхМарок, ИдентификаторФоновогоЗадания, АдресРезультата, ВыполненоУспешно, Результат", ТаблицаДанныхМарокШаблон.СкопироватьКолонки(),, ПоместитьВоВременноеХранилище(Неопределено, Новый УникальныйИдентификатор), Ложь, Новый Соответствие);
ДанныеПоПотокам.Добавить(Поток);
КонецЦикла;
КэшКодовМарок = Новый Соответствие;
ТекущийИндексПотока = 0;
Для Каждого ЭлементДанных Из ДанныеОМарках Цикл
Если ТипЗнч(ЭлементДанных) = Тип("Строка") Тогда
КодМарки = ЭлементДанных;
Владелец = Неопределено;
Иначе
КодМарки = ЭлементДанных.Код;
Владелец = ЭлементДанных.Владелец;
КонецЕсли;
КодМарки = ВРег(КодМарки);
Если Не ЗначениеЗаполнено(КодМарки) Тогда
Продолжить;
КонецЕсли;
// Если код марки уже встречался (не знаю, почему такое может быть, но раз ранее была предварительная свёртка массива, считаем что это неспроста) - игнорируем строку данных. Ибо нехер.
// Во избежание пересечения ключей блокировок и изобретания космических кораблей на ровном месте.
Если КэшКодовМарок.Получить(КодМарки) <> Неопределено Тогда
Продолжить;
КонецЕсли;
КэшКодовМарок.Вставить(КодМарки, Истина);
ТекущийПоток = ДанныеПоПотокам[ТекущийИндексПотока];
ТекущийИндексПотока = ?(ТекущийИндексПотока = МаксимальныйИндексПотока, 0, ТекущийИндексПотока + 1);
НоваяСтрока = ТекущийПоток.ТаблицаДанныхМарок.Добавить();
НоваяСтрока.Код = КодМарки;
НоваяСтрока.Владелец = Владелец;
КонецЦикла;
// Запуск потоков на исполнение.
МассивЗаданийНаОжидание = Новый Массив;
Для ИндексПотока = 0 По МаксимальныйИндексПотока Цикл
ТекущийПоток = ДанныеПоПотокам[ИндексПотока];
Если ИндексПотока = МаксимальныйИндексПотока Тогда
// Выполнение в основном потоке.
СоответствиеМарок = ПолучитьМаркиPDF417Служебный(ТекущийПоток.ТаблицаДанныхМарок, РегистрироватьОшибкиВЖурнале, Ложь);
ТекущийПоток.ВыполненоУспешно = Истина;
Иначе
// Выполнение в фоновом потоке.
ПараметрыВыполнения = Новый Массив;
ПараметрыВыполнения.Добавить(ТекущийПоток.ТаблицаДанныхМарок);
ПараметрыВыполнения.Добавить(ТекущийПоток.АдресРезультата);
ПараметрыВыполнения.Добавить(РегистрироватьОшибкиВЖурнале);
ПараметрыВыполнения.Добавить(Ложь);
ФоновоеЗадание = ФоновыеЗадания.Выполнить("АСФМаркировкаБазоваяФункциональность.ПолучитьМаркиPDF417ВФоне", ПараметрыВыполнения,, "АСФ. Получение/генерация марок");
ТекущийПоток.ИдентификаторФоновогоЗадания = ФоновоеЗадание.УникальныйИдентификатор;
МассивЗаданийНаОжидание.Добавить(ФоновоеЗадание);
КонецЕсли;
КонецЦикла;
// Ждём завершения, фиксируем результаты.
Пока МассивЗаданийНаОжидание.Количество() > 0 Цикл
Попытка
ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданийНаОжидание);
Исключение
КонецПопытки;
МассивЗаданийНаОжидание.Очистить();
Для ИндексПотока = 0 По МаксимальныйИндексПотока - 1 Цикл
ТекущийПоток = ДанныеПоПотокам[ИндексПотока];
Если Не ЗначениеЗаполнено(ТекущийПоток.ИдентификаторФоновогоЗадания) Тогда
Продолжить;
КонецЕсли;
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ТекущийПоток.ИдентификаторФоновогоЗадания);
Если ФоновоеЗадание = Неопределено Тогда
ТекущийПоток.ИдентификаторФоновогоЗадания = Неопределено;
ОписаниеОшибки = "Фоновое задание не найдено";
Иначе
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
МассивЗаданийНаОжидание.Добавить(ФоновоеЗадание);
Продолжить;
КонецЕсли;
ТекущийПоток.ИдентификаторФоновогоЗадания = Неопределено;
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
Результат = ПолучитьИзВременногоХранилища(ТекущийПоток.АдресРезультата);
Если ТипЗнч(Результат) = Тип("Соответствие") Тогда
ТекущийПоток.Результат = Результат;
ТекущийПоток.ВыполненоУспешно = Истина;
Продолжить;
КонецЕсли;
ОписаниеОшибки = "Не удалось получить результат работы фонового задания";
ИначеЕсли ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Отменено Тогда
ОписаниеОшибки = "Фоновое задание было отменено";
Иначе
ОписаниеОшибки = КраткоеПредставлениеОшибки(ФоновоеЗадание.ИнформацияОбОшибке);
КонецЕсли;
КонецЕсли;
ОписаниеОшибки = АСФОбщегоНазначенияКлиентСервер.ПодставитьПараметрыВСтроку("Получение/генерацию марок не удалось выполнить в фоновом режиме по причине: ""%1"". Процедура будет продолжена в основном потоке", ОписаниеОшибки);
ЗаписьЖурналаРегистрации("АСФ. Генерация марок", УровеньЖурналаРегистрации.Предупреждение, Метаданные.Справочники.АСФМаркиPDF417,, ОписаниеОшибки, РежимТранзакцииЗаписиЖурналаРегистрации.Независимая);
КонецЦикла;
КонецЦикла;
// Выполненяем в основном потоке неудавшиеся фоновые.
Для ИндексПотока = 0 По МаксимальныйИндексПотока - 1 Цикл
ТекущийПоток = ДанныеПоПотокам[ИндексПотока];
Если ТекущийПоток.ВыполненоУспешно Тогда
Продолжить;
КонецЕсли;
ТекущийПоток.Результат = ПолучитьМаркиPDF417Служебный(ТекущийПоток.ТаблицаДанныхМарок, РегистрироватьОшибкиВЖурнале, Истина);
КонецЦикла;
// Собираем результат.
Для ИндексПотока = 0 По МаксимальныйИндексПотока - 1 Цикл
ТекущийПоток = ДанныеПоПотокам[ИндексПотока];
РезультатЛокальный = ТекущийПоток.Результат;
Для Каждого ЭлементСоответствия Из РезультатЛокальный Цикл
СоответствиеМарок.Вставить(ЭлементСоответствия.Ключ, ЭлементСоответствия.Значение);
КонецЦикла;
КонецЦикла;
Возврат СоответствиеМарок;
КонецФункции
Процедура ПолучитьМаркиPDF417ВФоне(Знач ТаблицаДанныхМарок = Неопределено, АдресРезультата, РегистрироватьОшибкиВЖурнале = Ложь, ОтключатьИспользованиеЖурнала = Истина) Экспорт
Результат = ПолучитьМаркиPDF417Служебный(ТаблицаДанныхМарок, РегистрироватьОшибкиВЖурнале, ОтключатьИспользованиеЖурнала);
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецПроцедуры
Функция ПолучитьМаркиPDF417Служебный(Знач ТаблицаДанныхМарок = Неопределено, РегистрироватьОшибкиВЖурнале = Ложь, ОтключатьИспользованиеЖурнала = Истина) Экспорт
Если ТаблицаДанныхМарок = Неопределено Или ТаблицаДанныхМарок.Количество() = 0 Тогда
Возврат Новый Соответствие;
КонецЕсли;
СоответствиеМарок = Новый Соответствие;
СоответствиеМарокСПустымКодом = Новый Соответствие;
СоответствиеВладельцевИКодовАП = Новый Соответствие;
УстановитьПривилегированныйРежим(Истина);
УстановитьБлокировкуИнициироватьСоответствия(ТаблицаДанныхМарок, СоответствиеМарок, СоответствиеМарокСПустымКодом, СоответствиеВладельцевИКодовАП);
КоличествоМарок = ТаблицаДанныхМарок.Количество();
РегистрацияБылаОтключена = Ложь;
ИспользованиеСобытияЖурналаРегистрации = Новый ИспользованиеСобытияЖурналаРегистрации();
Для СчетчикМарок = 1 По КоличествоМарок Цикл
ИндексМарки = КоличествоМарок - СчетчикМарок;
ЭлементДанных = ТаблицаДанныхМарок[ИндексМарки];
КодМарки = ЭлементДанных.Код;
ВладелецМарки = ЭлементДанных.Владелец;
ТаблицаДанныхМарок.Удалить(ИндексМарки);
Если ТипЗнч(ВладелецМарки) = Тип("Строка") Тогда
КодАП = ВладелецМарки;
ИначеЕсли ВладелецМарки = Неопределено Тогда
КодАП = Неопределено;
Иначе
КодАП = СоответствиеВладельцевИКодовАП.Получить(ВладелецМарки);
КонецЕсли;
МаркаСсылка = СоответствиеМарок.Получить(КодМарки);
Если МаркаСсылка <> Неопределено Тогда
МаркаСсылкаСПустымКодом = СоответствиеМарокСПустымКодом.Получить(КодМарки);
Если МаркаСсылкаСПустымКодом = Неопределено Или КодАП = Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Если РегистрацияБылаОтключена И СчетчикМарок = КоличествоМарок Тогда
ИспользованиеСобытияЖурналаРегистрации.Использование = Истина;
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.New", ИспользованиеСобытияЖурналаРегистрации);
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.Update", ИспользованиеСобытияЖурналаРегистрации);
РегистрацияБылаОтключена = Ложь;
ИначеЕсли РегистрацияБылаОтключена = Ложь И СчетчикМарок > 1 И ОтключатьИспользованиеЖурнала = Истина Тогда
ИспользованиеСобытияЖурналаРегистрации.Использование = Ложь;
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.New", ИспользованиеСобытияЖурналаРегистрации);
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.Update", ИспользованиеСобытияЖурналаРегистрации);
РегистрацияБылаОтключена = Истина;
КонецЕсли;
Попытка
Если ЗначениеЗаполнено(МаркаСсылка) Тогда
МаркаОбъект = МаркаСсылка.ПолучитьОбъект();
Иначе
МаркаОбъект = Справочники.АСФМаркиPDF417.СоздатьЭлемент();
МаркаОбъект.Наименование = КодМарки;
КонецЕсли;
Если КодАП <> Неопределено Тогда
МаркаОбъект.Код = КодАП;
КонецЕсли;
Если Не ЗначениеЗаполнено(МаркаОбъект.Код) И СтрДлина(МаркаОбъект.Наименование) <> 150 Тогда
МаркаОбъект.Код = АСФОбщегоНазначенияКлиентСервер.ПолучитьКодАПИзКодаPDF417(МаркаОбъект.Наименование);
КонецЕсли;
МаркаОбъект.ОбменДанными.Загрузка = Истина;
МаркаОбъект.Записать();
СоответствиеМарок.Вставить(КодМарки,МаркаОбъект.Ссылка);
Исключение
Если РегистрироватьОшибкиВЖурнале = Истина Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
ИмяСобытия = "Не удалось записать марку";
КомментарийЖурнала = ИмяСобытия + Символы.ПС + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка, Метаданные.Справочники.АСФМаркиPDF417,, КомментарийЖурнала, РежимТранзакцииЗаписиЖурналаРегистрации.Независимая);
КонецЕсли;
ЗафиксироватьТранзакцию();
УстановитьБлокировкуИнициироватьСоответствия(ТаблицаДанныхМарок, СоответствиеМарок, СоответствиеМарокСПустымКодом, СоответствиеВладельцевИКодовАП);
КонецПопытки;
КонецЦикла;
Если РегистрацияБылаОтключена = Истина Тогда
ИспользованиеСобытияЖурналаРегистрации.Использование = Истина;
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.New", ИспользованиеСобытияЖурналаРегистрации);
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Data$_.Update", ИспользованиеСобытияЖурналаРегистрации);
КонецЕсли;
ЗафиксироватьТранзакцию();
Возврат СоответствиеМарок;
КонецФункции
Процедура УстановитьБлокировкуИнициироватьСоответствия(ТаблицаДанныхМарок, СоответствиеМарок, СоответствиеМарокСПустымКодом, СоответствиеВладельцевИКодовАП)
УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Справочник.АСФМаркиPDF417");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = ТаблицаДанныхМарок;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Наименование", "Код");
Блокировка.Заблокировать();
МассивИдентификаторовМарок = ТаблицаДанныхМарок.ВыгрузитьКолонку("Код");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| АСФМаркиPDF417.Ссылка КАК Ссылка,
| АСФМаркиPDF417.Наименование КАК Код,
| АСФМаркиPDF417.Код КАК АлкогольнаяПродукцияКод
|ИЗ
| Справочник.АСФМаркиPDF417 КАК АСФМаркиPDF417
|ГДЕ
| АСФМаркиPDF417.Наименование В(&МассивИдентификаторовМарок)";
Запрос.УстановитьПараметр("МассивИдентификаторовМарок", МассивИдентификаторовМарок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СоответствиеМарок.Вставить(ВРЕГ(Выборка.Код), Выборка.Ссылка);
Если Не ЗначениеЗаполнено(Выборка.АлкогольнаяПродукцияКод) Тогда
СоответствиеМарокСПустымКодом.Вставить(ВРЕГ(Выборка.Код), Выборка.Ссылка);
КонецЕсли;
КонецЦикла;
МассивВладельцевМарок = Новый Массив;
Для Каждого ЭлементДанных Из ТаблицаДанныхМарок Цикл
КодМарки = ЭлементДанных.Код;
МаркаСсылка = СоответствиеМарок.Получить(КодМарки);
Если МаркаСсылка <> Неопределено Тогда
МаркаСсылка = СоответствиеМарокСПустымКодом.Получить(КодМарки);
Если МаркаСсылка = Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ВладелецМарки = ЭлементДанных.Владелец;
Если ТипЗнч(ВладелецМарки) = Тип("Строка") Или ВладелецМарки = Неопределено Тогда
Продолжить;
КонецЕсли;
МассивВладельцевМарок.Добавить(ВладелецМарки);
КонецЦикла;
МассивВладельцевМарок = АСФОбщегоНазначенияКлиентСервер.ВыполнитьСверткуМассива(МассивВладельцевМарок, Истина);
Если МассивВладельцевМарок.Количество() > 0 Тогда
Если ТипЗнч(МассивВладельцевМарок[0]) = Тип("СправочникСсылка.АСФАлкогольнаяПродукция") Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникАлкогольнаяПродукция.Ссылка КАК Ссылка,
| СправочникАлкогольнаяПродукция.Код КАК Код
|ИЗ
| Справочник.АСФАлкогольнаяПродукция КАК СправочникАлкогольнаяПродукция
|ГДЕ
| СправочникАлкогольнаяПродукция.Ссылка В(&МассивВладельцевМарок)";
Запрос.УстановитьПараметр("МассивВладельцевМарок", МассивВладельцевМарок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СоответствиеВладельцевИКодовАП.Вставить(Выборка.Ссылка, Выборка.Код);
КонецЦикла;
ИначеЕсли ТипЗнч(МассивВладельцевМарок[0]) = Тип("СправочникСсылка.Номенклатура") Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникНоменклатура.Ссылка КАК Ссылка,
| ЕСТЬNULL(АСФСоответствияАлкогольнойПродукцииИНоменклатуры.АлкогольнаяПродукция.Код, СправочникНоменклатура.АСФКодЕГАИС) КАК Код
|ИЗ
| РегистрСведений.АСФСоответствияАлкогольнойПродукцииИНоменклатуры КАК АСФСоответствияАлкогольнойПродукцииИНоменклатуры
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
| ПО АСФСоответствияАлкогольнойПродукцииИНоменклатуры.Номенклатура = СправочникНоменклатура.Ссылка
|ГДЕ
| СправочникНоменклатура.Ссылка В(&МассивВладельцевМарок)";
Запрос.УстановитьПараметр("МассивВладельцевМарок", МассивВладельцевМарок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СоответствиеВладельцевИКодовАП.Вставить(Выборка.Ссылка, Выборка.Код);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ПолучитьМаркуPDF417(Знач КодМарки, РегистрироватьОшибкиВЖурнале = Ложь, Знач ВладелецМарки=Неопределено) Экспорт
Если Не ЗначениеЗаполнено(КодМарки) Тогда
Возврат Справочники.АСФМаркиPDF417.ПустаяСсылка();
КонецЕсли;
ДанныеОМарках = Новый Массив;
Если ЗначениеЗаполнено(ВладелецМарки) Тогда
ДанныеОМарке=Новый Структура;
ДанныеОМарке.Вставить("Код",КодМарки);
ДанныеОМарке.Вставить("Владелец",ВладелецМарки);
ДанныеОМарках.Добавить(ДанныеОМарке);
Иначе
ДанныеОМарках.Добавить(КодМарки);
КонецЕсли;
СоответствиеМарок = ПолучитьМаркиPDF417(ДанныеОМарках, РегистрироватьОшибкиВЖурнале);
Возврат СоответствиеМарок.Получить(КодМарки);
КонецФункции
#КонецОбласти
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment