Files
SSL/SSL/src/CommonModules/ОбновлениеИнформационнойБазы/Module.bsl
T
2023-08-25 12:16:00 +03:00

6755 lines
480 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Область ПрограммныйИнтерфейс
////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции для использования в обработчиках обновления.
//
// Записывает изменения в переданном объекте.
// Для использования в обработчиках обновления.
//
// Параметры:
// Данные - Произвольный - объект, набор записей или менеджер константы, который
// необходимо записать.
// РегистрироватьНаУзлахПлановОбмена - Булево - включает регистрацию на узлах планов обмена при записи объекта.
// ВключитьБизнесЛогику - Булево - включает бизнес-логику при записи объекта.
//
Процедура ЗаписатьДанные(Знач Данные, Знач РегистрироватьНаУзлахПлановОбмена = Неопределено,
Знач ВключитьБизнесЛогику = Ложь) Экспорт
Данные.ОбменДанными.Загрузка = Не ВключитьБизнесЛогику;
Данные.ДополнительныеСвойства.Вставить("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ", РегистрироватьНаУзлахПлановОбмена);
Если РегистрироватьНаУзлахПлановОбмена = Неопределено
Или Не РегистрироватьНаУзлахПлановОбмена Тогда
Данные.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
КонецЕсли;
Данные.Записать();
Если ОбъектРегистрируетсяНаПланеОбмена(Данные) Тогда
ОтметитьВыполнениеОбработки(Данные);
КонецЕсли;
КонецПроцедуры
// Записывает изменения в переданном объекте ссылочного типа.
// Для использования в обработчиках обновления.
//
// Параметры:
// Объект - Произвольный - записываемый объект ссылочного типа. Например, СправочникОбъект.
// РегистрироватьНаУзлахПлановОбмена - Булево - включает регистрацию на узлах планов обмена при записи объекта.
// ВключитьБизнесЛогику - Булево - включает бизнес-логику при записи объекта.
// ДокументРежимЗаписи - РежимЗаписиДокумента - имеет смысл только для данных типа ДокументОбъект - режим
// записи документа.
// Если параметр не передан, то документ записывается в режиме "Запись".
//
Процедура ЗаписатьОбъект(Знач Объект, Знач РегистрироватьНаУзлахПлановОбмена = Неопределено,
Знач ВключитьБизнесЛогику = Ложь, ДокументРежимЗаписи = Неопределено) Экспорт
Объект.ДополнительныеСвойства.Вставить("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ", РегистрироватьНаУзлахПлановОбмена);
Объект.ОбменДанными.Загрузка = Не ВключитьБизнесЛогику;
Если РегистрироватьНаУзлахПлановОбмена = Неопределено
Или Не РегистрироватьНаУзлахПлановОбмена
И Не Объект.ЭтоНовый() Тогда
Объект.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
КонецЕсли;
Если ДокументРежимЗаписи <> Неопределено Тогда
Если ТипЗнч(ДокументРежимЗаписи) <> Тип("РежимЗаписиДокумента") Тогда
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Неправильный тип параметра %1'"),
"ДокументРежимЗаписи");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
Объект.ОбменДанными.Загрузка = Объект.ОбменДанными.Загрузка
И Не ДокументРежимЗаписи = РежимЗаписиДокумента.Проведение
И Не ДокументРежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения;
Объект.Записать(ДокументРежимЗаписи);
Иначе
Объект.Записать();
КонецЕсли;
Если ОбъектРегистрируетсяНаПланеОбмена(Объект) Тогда
ОтметитьВыполнениеОбработки(Объект);
КонецЕсли;
КонецПроцедуры
// Записывает изменения в переданном наборе записей.
// Для использования в обработчиках обновления.
//
// Параметры:
// НаборЗаписей - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей - набор записей, который необходимо записать.
// Замещать - Булево - определяет режим замещения существующей записи в соответствии с
// текущими установками отбора. Истина - перед записью существующие
// записи будут удалены. Ложь - записи будут дописаны к уже существующим
// в информационной базе записям.
// РегистрироватьНаУзлахПлановОбмена - Булево - включает регистрацию на узлах планов обмена при записи объекта.
// ВключитьБизнесЛогику - Булево - включает бизнес-логику при записи объекта.
//
Процедура ЗаписатьНаборЗаписей(Знач НаборЗаписей, Замещать = Истина, Знач РегистрироватьНаУзлахПлановОбмена = Неопределено,
Знач ВключитьБизнесЛогику = Ложь) Экспорт
НаборЗаписей.ДополнительныеСвойства.Вставить("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ", РегистрироватьНаУзлахПлановОбмена);
НаборЗаписей.ОбменДанными.Загрузка = Не ВключитьБизнесЛогику;
Если РегистрироватьНаУзлахПлановОбмена = Неопределено
Или Не РегистрироватьНаУзлахПлановОбмена Тогда
НаборЗаписей.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
КонецЕсли;
НаборЗаписей.Записать(Замещать);
Если ОбъектРегистрируетсяНаПланеОбмена(НаборЗаписей) Тогда
ОтметитьВыполнениеОбработки(НаборЗаписей);
КонецЕсли;
КонецПроцедуры
// Удаляет переданный объект.
// Для использования в обработчиках обновления.
//
// Параметры:
// Данные - Произвольный - объект, который необходимо удалить.
// РегистрироватьНаУзлахПлановОбмена - Булево - включает регистрацию на узлах планов обмена при записи объекта.
// ВключитьБизнесЛогику - Булево - включает бизнес-логику при записи объекта.
//
Процедура УдалитьДанные(Знач Данные, Знач РегистрироватьНаУзлахПлановОбмена = Неопределено,
Знач ВключитьБизнесЛогику = Ложь) Экспорт
Данные.ДополнительныеСвойства.Вставить("РегистрироватьНаУзлахПлановОбменаПриОбновленииИБ", РегистрироватьНаУзлахПлановОбмена);
Данные.ОбменДанными.Загрузка = Не ВключитьБизнесЛогику;
Если РегистрироватьНаУзлахПлановОбмена = Неопределено
Или Не РегистрироватьНаУзлахПлановОбмена Тогда
Данные.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
КонецЕсли;
Данные.Удалить();
КонецПроцедуры
// Возвращает строковую константу для формирования сообщений журнала регистрации.
//
// Возвращаемое значение:
// Строка - текст события журнала регистрации.
//
Функция СобытиеЖурналаРегистрации() Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебный.СобытиеЖурналаРегистрации();
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции для проверки доступности объекта при выполнении отложенного обновления.
//
// Вызывает исключение или блокирует форму от редактирования, если
// имеются незавершенные отложенные обработчики обновления,
// которые в данный момент обрабатывают переданный объект Данные.
//
// При вызове из отложенного обработчика обновления (случай проверки в программном интерфейсе)
// проверка не выполняется, если не указан параметр ИмяОтложенногоОбработчика, так как
// предполагается, что порядок обновления уже учтен при построении очередей.
//
// Параметры:
// Данные - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланСчетовОбъект
// - ПланВидовРасчетаОбъект
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей
// - ЛюбаяСсылка
// - ДанныеФормыСтруктура - ссылка на объект, сам объект, набор записей или полное имя объекта
// метаданных, обработку которого необходимо проверить.
// Форма - ФормаКлиентскогоПриложения - если объект не обработан, то у переданной формы
// будет установлено свойство ТолькоПросмотр. Если форма не была
// передана, то будет вызвано исключение.
//
// ИмяОтложенногоОбработчика - Строка - если заполнено, тогда при вызове из другого отложенного обработчика
// проверяется, что указанный отложенный обработчик имеет номер очереди меньше, чем текущий.
// Если это не так, тогда вызывается исключение о недопустимости использования
// программного интерфейса, указанного в параметре ИмяПроцедурыПрограммногоИнтерфейса.
//
// ИмяПроцедурыПрограммногоИнтерфейса - Строка - имя процедуры программного интерфейса,
// которое выводится в тексте исключения, вызываемого при проверке номера очереди
// отложенного обработчика обновления, указанного в параметре ИмяОтложенногоОбработчика.
//
// Пример:
// Блокировка формы объекта в обработчике ПриСозданииНаСервере модуля формы:
// ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(Объект, ЭтотОбъект);
//
// Блокировка записи объекта в обработчике ПередЗаписью модуля объекта (набора записей):
// ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(ЭтотОбъект);
//
// Проверить, что обновлен конкретный объект и вызвать исключение о недопустимости вызова
// процедуры ЭлектроннаяПодпись.ОбновитьПодпись, если он еще не обработан указанным обработчиком
// Справочник.ЭлектронныеПодписи.ОбработатьДанныеДляПереходаНаНовуюВерсию:
//
// ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(ПодписанныйОбъект,,
// "Справочник.ЭлектронныеПодписи.ОбработатьДанныеДляПереходаНаНовуюВерсию",
// "ЭлектроннаяПодпись.ОбновитьПодпись");
//
// Проверить и вызвать исключение, если обновлены не все объекты требуемого типа:
// ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан("Документ.ЗаказПокупателя");
//
Процедура ПроверитьОбъектОбработан(Данные, Форма = Неопределено, ИмяОтложенногоОбработчика = "", ИмяПроцедурыПрограммногоИнтерфейса = "") Экспорт
Если Не ЭтоВызовИзОбработчикаОбновления() Тогда
Результат = ОбъектОбработан(Данные);
Если Результат.Обработан Тогда
Возврат;
КонецЕсли;
Если Форма = Неопределено Тогда
ВызватьИсключение Результат.ТекстИсключения;
КонецЕсли;
Форма.ТолькоПросмотр = Истина;
Форма.Команды.Добавить("ОбновлениеВерсииИБ_ОбъектЗаблокирован");
ОбщегоНазначения.СообщитьПользователю(Результат.ТекстИсключения);
Возврат;
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяОтложенногоОбработчика) Тогда
Возврат;
КонецЕсли;
Если ИмяОтложенногоОбработчика = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ИмяОбработчика Тогда
Возврат;
КонецЕсли;
ОчередьТребуемогоОбработчика = ОчередьОтложенногоОбработчикаОбновления(ИмяОтложенногоОбработчика);
ОчередьТекущегоОбработчика = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ОчередьОтложеннойОбработки;
Если ОчередьТекущегоОбработчика > ОчередьТребуемогоОбработчика Тогда
Возврат;
КонецЕсли;
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Недопустимо вызывать %1
|из обработчика обновления
|%2
|так как его номер очереди меньше или равен номеру очереди обработчика обновления
|%3'"),
ИмяПроцедурыПрограммногоИнтерфейса,
ПараметрыСеанса.ПараметрыОбработчикаОбновления.ИмяОбработчика,
ИмяОтложенногоОбработчика);
КонецПроцедуры
// Проверяет, имеются ли отложенные обработчики обновления,
// которые в данный момент обрабатывают переданный объект Данные.
//
// Параметры:
// Данные - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланСчетовОбъект
// - ПланВидовРасчетаОбъект
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей
// - ЛюбаяСсылка
// - ДанныеФормыСтруктура - ссылка на объект, сам объект, набор записей или полное имя объекта метаданных,
// блокировку которого необходимо проверить.
//
// Возвращаемое значение:
// Структура:
// * Обработан - Булево - признак того, что переданный объект обработан.
// * ТекстИсключения - Строка - текст исключения, если объект еще не обработан,
// содержит список незавершенных обработчиков.
//
// Пример:
// Проверить, что обновлены все объекты требуемого типа:
// ВсеЗаказыОбработаны = ОбновлениеИнформационнойБазы.ОбъектОбработан("Документ.ЗаказПокупателя");
//
Функция ОбъектОбработан(Данные) Экспорт
Результат = Новый Структура;
Результат.Вставить("Обработан", Истина);
Результат.Вставить("ТекстИсключения", "");
Результат.Вставить("НевыполненныеОбработчикиСтрокой", "");
Если Данные = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Если ОтложенноеОбновлениеЗавершено() Тогда
Возврат Результат;
КонецЕсли;
СведенияОБлокируемыхОбъектах = ОбновлениеИнформационнойБазыСлужебный.СведенияОБлокируемыхОбъектах();
МетаданныеИОтбор = Неопределено;
Если ТипЗнч(Данные) = Тип("Строка") Тогда
ПолноеИмя = Данные;
Иначе
МетаданныеИОтбор = МетаданныеИОтборПоДанным(Данные);
ПолноеИмя = МетаданныеИОтбор.Метаданные.ПолноеИмя();
КонецЕсли;
РазблокированныеОбъекты = СведенияОБлокируемыхОбъектах.РазблокированныеОбъекты;
ДоступныеДляРедактирования = РазблокированныеОбъекты[ПолноеИмя];
Если МетаданныеИОтбор <> Неопределено
И ДоступныеДляРедактирования <> Неопределено
И ДоступныеДляРедактирования.Найти(МетаданныеИОтбор.Отбор) <> Неопределено Тогда
Возврат Результат; // Объект разблокирован для редактирования.
КонецЕсли;
БлокироватьИзменение = Ложь;
ТекстСообщения = "";
ОбновлениеИнформационнойБазыПереопределяемый.ПриВыполненииПроверкиОбъектОбработан(ПолноеИмя, БлокироватьИзменение, ТекстСообщения);
ПроверяемыйОбъект = СтрЗаменить(ПолноеИмя, ".", "");
ОбработчикиОбъекта = СведенияОБлокируемыхОбъектах.БлокируемыеОбъекты[ПроверяемыйОбъект];
Если ОбработчикиОбъекта = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Обработан = Истина;
НезавершенныеОбработчики = Новый Массив;
Для Каждого Обработчик Из ОбработчикиОбъекта Цикл
СвойстваОбработчика = СведенияОБлокируемыхОбъектах.Обработчики[Обработчик];
Если СвойстваОбработчика.Выполнен Тогда
Обработан = Истина;
ИначеЕсли ТипЗнч(Данные) = Тип("Строка") Тогда
Обработан = Ложь;
Иначе
// АПК:488-выкл безопасный режим не требуется
Обработан = Вычислить(СвойстваОбработчика.ПроцедураПроверки + "(МетаданныеИОтбор)");
// АПК:488-вкл
КонецЕсли;
Результат.Обработан = Обработан И Результат.Обработан;
Если Не Обработан Тогда
НезавершенныеОбработчики.Добавить(Обработчик);
КонецЕсли;
КонецЦикла;
Если НезавершенныеОбработчики.Количество() > 0 Тогда
ЧастиИсключения = Новый Массив;
ЧастиИсключения.Добавить(НСтр("ru = 'Действия с объектом временно запрещены, так как не завершен переход на новую версию программы.
|Это плановый процесс, который скоро завершится.'"));
ЧастиИсключения.Добавить(СтрСоединить(СтрРазделить(НСтр("ru = 'Для включения возможности редактирования можно нажать Еще - Разблокировать.
|Разблокировку следует применять только в крайних случаях, так как документ может быть
|записан некорректно.'"), Символы.ПС), " "));
ЧастиИсключения.Добавить(НСтр("ru = 'Следующие процедуры обработки данных не завершены'"));
ТекстИсключения = СтрСоединить(ЧастиИсключения, Символы.ПС + Символы.ПС) + ":";
НевыполненныеОбработчикиСтрокой = "";
Для Каждого НезавершенныйОбработчик Из НезавершенныеОбработчики Цикл
НевыполненныеОбработчикиСтрокой = НевыполненныеОбработчикиСтрокой + Символы.ПС + НезавершенныйОбработчик;
КонецЦикла;
Результат.ТекстИсключения = ТекстИсключения + НевыполненныеОбработчикиСтрокой;
Результат.НевыполненныеОбработчикиСтрокой = НевыполненныеОбработчикиСтрокой;
КонецЕсли;
Возврат Результат;
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции для использования в отложенных обработчиках обновления
// с режимом выполнения "Параллельно".
//
// Отмечает, что переданные данные обновлены.
//
// Параметры:
// Данные - ЛюбаяСсылка
// - Массив
// - РегистрСведенийНаборЗаписей, РегистрНакопленияНаборЗаписей, РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей - данные, по которым нужно зарегистрировать изменения.
// - ТаблицаЗначений - значения измерений независимого регистра сведений. Требования:
// а) все измерения регистра должны входить в основной отбор;
// б) в таблице должны быть только колонки, соответствующие по именам измерениям регистра,
// по которым ранее регистрировалась необходимость обработки;
// в) запись наборов в процессе обновления должна проходить с тем же отбором,
// что и регистрация необходимости обработки;
// г) в ДополнительныеПараметры нужно передать соответствующий признак и полное имя регистра.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки.
// Очередь - Число
// - Неопределено - очередь обработки, в которой выполняется текущий обработчик. По умолчанию очередь передавать
// не нужно, т.к. она будет взята из параметров сеанса, в котором запущен обработчик обновления.
//
Процедура ОтметитьВыполнениеОбработки(Данные, ДополнительныеПараметры = Неопределено, Очередь = Неопределено) Экспорт
Если Очередь = Неопределено Тогда
Если ПараметрыСеанса.ПараметрыОбработчикаОбновления.РежимВыполнения <> "Отложенно"
Или ПараметрыСеанса.ПараметрыОбработчикаОбновления.РежимВыполненияОтложенныхОбработчиков <> "Параллельно" Тогда
Возврат;
КонецЕсли;
Очередь = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ОчередьОтложеннойОбработки;
КонецЕсли;
Если Не ПараметрыСеанса.ПараметрыОбработчикаОбновления.ЕстьОбработанныеОбъекты Тогда
НовыеПараметрыСеанса = ОбновлениеИнформационнойБазыСлужебный.НовыеПараметрыОбработчикаОбновления();
ЗаполнитьЗначенияСвойств(НовыеПараметрыСеанса, ПараметрыСеанса.ПараметрыОбработчикаОбновления);
НовыеПараметрыСеанса.ЕстьОбработанныеОбъекты = Истина;
ИдентификаторТранзакции = Новый УникальныйИдентификатор;
МенеджерЗаписи = РегистрыСведений.ФиксацияОбработкиДанныхОбработчиками.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторТранзакции = ИдентификаторТранзакции;
МенеджерЗаписи.Записать();
НовыеПараметрыСеанса.ИдентификаторТранзакции = ИдентификаторТранзакции;
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыСеанса);
КонецЕсли;
КопияДанных = Данные;
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыОтметкиОбработки();
КонецЕсли;
Если (ТипЗнч(Данные) = Тип("Массив")
Или ТипЗнч(Данные) = Тип("ТаблицаЗначений"))
И Данные.Количество() = 0 Тогда
ТекстИсключения = НСтр("ru = 'В процедуру %1 передан пустой массив. Не возможно отметить выполнение обработки.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ОбновлениеИнформационнойБазы.ОтметитьВыполнениеОбработки");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
Узел = ОчередьСсылкой(Очередь);
Если ДополнительныеПараметры.ЭтоДвижения Тогда
УдалитьРегистрациюИзмененийПодчиненногоРегистра(Узел, Данные, ДополнительныеПараметры.ПолноеИмяРегистра);
ИначеЕсли ДополнительныеПараметры.ЭтоНезависимыйРегистрСведений Тогда
УдалитьРегистрациюИзмененийНезависимогоРегистра(Узел, Данные, ДополнительныеПараметры.ПолноеИмяРегистра);
Иначе
Если ТипЗнч(Данные) = Тип("ОбъектМетаданных") Тогда
ТекстИсключения = НСтр("ru = 'Не поддерживается отметка выполнения обработки обновления целиком объекта метаданных. Нужно отмечать обработку конкретных данных.'");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
Если ТипЗнч(Данные) <> Тип("Массив") Тогда
ТипЗначенияОбъекта = ТипЗнч(Данные);
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗначенияОбъекта);
Если ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеОбъекта)
И МетаданныеОбъекта.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
Набор = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(МетаданныеОбъекта.ПолноеИмя()).СоздатьНаборЗаписей();
Для Каждого ЭлементОтбора Из Данные.Отбор Цикл
Набор.Отбор[ЭлементОтбора.Имя].Значение = ЭлементОтбора.Значение;
Набор.Отбор[ЭлементОтбора.Имя].Использование = ЭлементОтбора.Использование;
КонецЦикла;
УстановитьНедостающиеОтборыВНаборе(Набор, МетаданныеОбъекта, Данные.Отбор);
ИначеЕсли (ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта)
И Не ОбщегоНазначения.ЭтоСсылка(ТипЗначенияОбъекта)
И Данные.ЭтоНовый())
Или ОбщегоНазначения.ЭтоКонстанта(МетаданныеОбъекта) Тогда
Возврат;
Иначе
Набор = Данные;
КонецЕсли;
ЗаписатьПрогрессВыполненияОбработчика(Данные, Узел, МетаданныеОбъекта);
ПланыОбмена.УдалитьРегистрациюИзменений(Узел, Набор);
КопияДанных = Набор;
Иначе
ЗаписатьПрогрессВыполненияОбработчика(Данные, Узел, МетаданныеОбъекта);
УдалитьРегистрациюИзмененийОбъекта(Узел, Данные);
КонецЕсли;
КонецЕсли;
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
РегистрыСведений.ДанныеОбработанныеВЦентральномУзлеРИБ.ОтметитьВыполнениеОбработки(Очередь, КопияДанных, ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
// Дополнительные параметры функций ОтметитьКОбработке и ОтметитьВыполнениеОбработки.
//
// Возвращаемое значение:
// Структура:
// * ЭтоДвижения - Булево - в параметре Данные функции переданы ссылки на регистраторы, по которым нужно обновить движения.
// Значение по умолчанию - Ложь.
// * ПолноеИмяРегистра - Строка - полное имя регистра, по которому нужно обновить данные. Например, РегистрНакопления.ТоварыНаСкладах.
// * ОтметитьВсеРегистраторы - Булево - необходимо отметить к обработке все проведенные документы переданного во
// втором параметре типа.
// В этом случае в параметре Данные процедуры можно передавать
// ОбъектМетаданных:Документ или ДокументСсылка.
// * ЭтоНезависимыйРегистрСведений - Булево - в параметре Данные функции передана таблица со значениями измерений,
// по которым нужно обновлять данные, значение по умолчанию - Ложь.
//
Функция ДополнительныеПараметрыОтметкиОбработки() Экспорт
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ЭтоДвижения", Ложь);
ДополнительныеПараметры.Вставить("ОтметитьВсеРегистраторы", Ложь);
ДополнительныеПараметры.Вставить("ЭтоНезависимыйРегистрСведений", Ложь);
ДополнительныеПараметры.Вставить("ПолноеИмяРегистра", "");
Возврат ДополнительныеПараметры;
КонецФункции
// Основные параметры процедуры ОбновлениеИнформационнойБазы.ОтметитьКОбработке,
// которые инициализируются механизмом регистрации изменений
// и не должны переопределяться в коде процедур отметки к обработке обработчиков обновления.
//
// Возвращаемое значение:
// Структура:
// * Очередь - Число - очередь обработки, в которой выполняется текущий обработчик.
// * ЗаписьИзмененийДляПодчиненногоУзлаРИБСФильтрами - ЗаписьFastInfoset - параметр
// существует, только если внедрена подсистема ОбменДанными.
// * ПараметрыВыборки - см. ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
//
Функция ОсновныеПараметрыОтметкиКОбработке() Экспорт
Параметры = Новый Структура;
Параметры.Вставить("Очередь", 0);
Параметры.Вставить("ИмяОбработчика", "");
Параметры.Вставить("ПовторнаяРегистрация", Ложь);
Параметры.Вставить("ПараметрыВыборки");
Параметры.Вставить("АктуальныеДанные", ПараметрыВыборкиАктуальныхДанных());
Параметры.Вставить("ЗарегистрированныеТаблицыРегистраторов", Новый Соответствие);
Параметры.Вставить("ВерсияПодсистемыНаНачалоОбновления", Неопределено);
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
Параметры.Вставить("ИмяФайлаСИзменениями", Неопределено);
Параметры.Вставить("ЗаписьИзмененийДляПодчиненногоУзлаРИБСФильтрами", Неопределено);
КонецЕсли;
Возврат Параметры;
КонецФункции
// Возвращает информацию о переданных данных в нормализованном виде.
// Для использования в процедурах проверки блокировки данных отложенных обработчиков обновления.
//
// Параметры:
// Данные - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланСчетовОбъект
// - ПланВидовРасчетаОбъект
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей
// - ЛюбаяСсылка
// - ДанныеФормыСтруктура - значение входящего параметра Данные.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки
//
// Возвращаемое значение:
// Структура:
// * Данные - СправочникОбъект
// - ДокументОбъект
// - ПланВидовХарактеристикОбъект
// - ПланСчетовОбъект
// - ПланВидовРасчетаОбъект
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей
// - ЛюбаяСсылка
// - ДанныеФормыСтруктура - данные, которые нужно проанализировать.
// * МетаданныеОбъекта - ОбъектМетаданных - объект метаданных, соответствующий параметру Данные.
// * ПолноеИмя - Строка - полное имя объекта метаданных (см. метод ОбъектМетаданных.ПолноеИмя).
// * Отбор - ЛюбаяСсылка - если Данные - это ссылочный объект, то значение ссылки,
// если регистр подчиненный регистратору, - значение отбора по регистратору.
// - Структура - если Данные - это независимый регистр сведений, то структура, соответствующая
// установленным отборам по измерениям.
// * ЭтоНовый - Булево - если Данные - это ссылочный объект, то признак нового объекта.
// Для других типов - всегда Ложь.
//
Функция МетаданныеИОтборПоДанным(Данные, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыОтметкиОбработки();
КонецЕсли;
Если ДополнительныеПараметры.ЭтоДвижения Тогда
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ДополнительныеПараметры.ПолноеИмяРегистра);
Иначе
МетаданныеОбъекта = Неопределено;
КонецЕсли;
Отбор = Неопределено;
ТипДанных = ТипЗнч(Данные);
ЭтоНовый = Ложь;
Если ТипЗнч(Данные) = Тип("Строка") Тогда
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Данные);
ИначеЕсли ТипДанных = Тип("ДанныеФормыСтруктура") Тогда
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Данные, "Ссылка") Тогда
Если МетаданныеОбъекта = Неопределено Тогда
МетаданныеОбъекта = Данные.Ссылка.Метаданные();
КонецЕсли;
Отбор = Данные.Ссылка;
Если Не ЗначениеЗаполнено(Отбор) Тогда
ЭтоНовый = Истина;
КонецЕсли;
ИначеЕсли ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Данные, "ИсходныйКлючЗаписи") Тогда
Если МетаданныеОбъекта = Неопределено Тогда
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(Данные.ИсходныйКлючЗаписи)); // ОбъектМетаданныхРегистрСведений
КонецЕсли;
Отбор = Новый Структура;
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Отбор.Вставить(Измерение.Имя, Данные[Измерение.Имя]);
КонецЦикла;
Иначе
ТекстИсключения = НСтр("ru = 'Процедура %1 не может быть использована для этой формы.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ОбновлениеИнформационнойБазы.МетаданныеИОтборПоДанным");
КонецЕсли;
Иначе
Если МетаданныеОбъекта = Неопределено Тогда
МетаданныеОбъекта = Данные.Метаданные();
КонецЕсли;
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
Если ОбщегоНазначения.ЭтоСсылка(ТипДанных) Тогда
Отбор = Данные;
Иначе
Отбор = Данные.Ссылка;
Если Данные.ЭтоНовый() Тогда
ЭтоНовый = Истина;
КонецЕсли;
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеОбъекта)
И МетаданныеОбъекта.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
Отбор = Новый Структура;
Для Каждого ЭлементОтбора Из Данные.Отбор Цикл
Если ЭлементОтбора.Использование Тогда
Отбор.Вставить(ЭлементОтбора.Имя, ЭлементОтбора.Значение);
КонецЕсли;
КонецЦикла;
ИначеЕсли ОбщегоНазначения.ЭтоРегистр(МетаданныеОбъекта) Тогда
Если ДополнительныеПараметры.ЭтоДвижения Тогда
Отбор = Данные;
Иначе
Отбор = Данные.Отбор.Регистратор.Значение;
КонецЕсли;
Иначе
ТекстИсключения = НСтр("ru = 'Для этого типа метаданных не поддерживается анализ в функции %1.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ОбновлениеИнформационнойБазы.МетаданныеИОтборПоДанным");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Данные", Данные);
Результат.Вставить("Метаданные", МетаданныеОбъекта);
Результат.Вставить("ПолноеИмя", МетаданныеОбъекта.ПолноеИмя());
Результат.Вставить("Отбор", Отбор);
Результат.Вставить("ЭтоНовый", ЭтоНовый);
Возврат Результат;
КонецФункции
// Отмечает, что переданные данные необходимо обновить.
// Важно: не рекомендуется передавать в параметр Данные сразу все данные, которые
// необходимо зарегистрировать к обработке, т.к. большие коллекции типа Массив
// или ТаблицаЗначений могут занять существенный объем памяти сервера и привести
// к сильному снижению производительности системы. Рекомендуется получать и передавать
// данные небольшими порциями, например по 1000 объектов.
//
// Параметры:
// ОсновныеПараметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Данные - ЛюбаяСсылка
// - Массив
// - РегистрСведенийНаборЗаписей, РегистрНакопленияНаборЗаписей, РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей - данные, по которым нужно зарегистрировать изменения.
// - ТаблицаЗначений - значения измерений независимого регистра сведений. Требования:
// а) нет измерений с именем "Узел";
// б) все измерения регистра должны входить в основной отбор;
// в) в таблице должны быть только колонки, соответствующие по именам измерениям регистра,
// по которым нужно регистрировать необходимость обработки;
// г) запись наборов в процессе обновления должна проходить с тем же отбором,
// что и регистрация необходимости обработки;
// д) в ДополнительныеПараметры нужно передать соответствующий признак и полное имя регистра.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки.
//
Процедура ОтметитьКОбработке(ОсновныеПараметры, Данные, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыОтметкиОбработки();
КонецЕсли;
Если (ТипЗнч(Данные) = Тип("Массив")
Или ТипЗнч(Данные) = Тип("ТаблицаЗначений"))
И Данные.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Если ОсновныеПараметры.Свойство("ПараметрыВыборки")
И ТипЗнч(ОсновныеПараметры.ПараметрыВыборки) = Тип("Структура") Тогда
ПолныеИменаОбъектов = Неопределено;
ПолныеИменаРегистров = Неопределено;
ОсновныеПараметры.ПараметрыВыборки.Свойство("ПолныеИменаОбъектов", ПолныеИменаОбъектов);
ОсновныеПараметры.ПараметрыВыборки.Свойство("ПолныеИменаРегистров", ПолныеИменаРегистров);
МассивИмен = СтрРазделить(ПолныеИменаОбъектов, ",", Ложь);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(МассивИмен, СтрРазделить(ПолныеИменаРегистров, ",", Ложь));
Несуществующие = Новый Массив;
Для Каждого ПолноеИмяОбъекта Из МассивИмен Цикл
ПолноеИмяОбъекта = СокрЛП(ПолноеИмяОбъекта);
ОбъектСуществует = (ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта) <> Неопределено);
Если Не ОбъектСуществует Тогда
Несуществующие.Добавить(ПолноеИмяОбъекта);
КонецЕсли;
КонецЦикла;
Если Несуществующие.Количество() <> 0 Тогда
ТекстИсключения = НСтр("ru = 'В свойстве %1 процедуры заполнения данных отложенного обработчика указаны несуществующие объекты:
|%2.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
"ПараметрыВыборки", СтрСоединить(Несуществующие, ", "));
ВызватьИсключение ТекстИсключения;
КонецЕсли;
КонецЕсли;
Если ОсновныеПараметры.Свойство("ПерезапускОбновления")
И ОсновныеПараметры.ПерезапускОбновления = Истина Тогда
Узел = ОчередьСсылкой(ОсновныеПараметры.Очередь, Истина);
Иначе
Узел = ОчередьСсылкой(ОсновныеПараметры.Очередь);
КонецЕсли;
Если ДополнительныеПараметры.ЭтоДвижения Тогда
ПолноеИмяРегистра = ДополнительныеПараметры.ПолноеИмяРегистра;
Если ДополнительныеПараметры.ОтметитьВсеРегистраторы Тогда
Если ТипЗнч(Данные) = Тип("ОбъектМетаданных") Тогда
МетаданныеДокумента = Данные;
ИначеЕсли ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Данные)) Тогда
МетаданныеДокумента = Данные.Метаданные();
Иначе
ТекстИсключения = НСтр("ru = 'Для регистрации всех регистраторов регистра необходимо в параметре ""Данные"" передать объект метаданных документ или ссылку на документ.'");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
ПолноеИмяДокумента = МетаданныеДокумента.ПолноеИмя();
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаДокумента.Ссылка КАК Ссылка
|ИЗ
| #ТаблицаДокумента КАК ТаблицаДокумента
|ГДЕ
| ТаблицаДокумента.Проведен";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаДокумента", ПолноеИмяДокумента);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Регистраторы = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
Иначе
Регистраторы = Данные;
// Сохранение списка таблиц, по которым выполнялась регистрация.
Для Каждого Регистратор Из Регистраторы Цикл
ТипТаблицы = ТипЗнч(Регистратор);
Если ОсновныеПараметры.ЗарегистрированныеТаблицыРегистраторов[ТипТаблицы] = Неопределено Тогда
ПолноеИмяТаблицы = Регистратор.Метаданные().ПолноеИмя();
ОсновныеПараметры.ЗарегистрированныеТаблицыРегистраторов.Вставить(ТипТаблицы, ПолноеИмяТаблицы);
КонецЕсли;
КонецЦикла;
КонецЕсли;
ЗарегистрироватьИзмененияПодчиненногоРегистра(ОсновныеПараметры,
Узел,
Регистраторы,
"ПодчиненныйРегистр",
ПолноеИмяРегистра);
ИначеЕсли ДополнительныеПараметры.ЭтоНезависимыйРегистрСведений Тогда
ЗарегистрироватьИзмененияНезависимогоРегистра(ОсновныеПараметры,
Узел,
Данные,
"НезависимыйРегистр",
ДополнительныеПараметры.ПолноеИмяРегистра);
Иначе
Если ТипЗнч(Данные) = Тип("Массив") Или ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Данные)) Тогда
ЗарегистрироватьИзмененияОбъекта(ОсновныеПараметры, Узел, Данные, "Ссылка");
Иначе
Если ТипЗнч(Данные) = Тип("ОбъектМетаданных") Тогда
ТекстИсключения = НСтр("ru = 'Не поддерживается регистрация к обновлению целиком объекта метаданных. Нужно обновлять конкретные данные.'");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(Данные));
Если ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеОбъекта)
И МетаданныеОбъекта.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
УстановитьНедостающиеОтборыВНаборе(Данные, МетаданныеОбъекта, Данные.Отбор);
КонецЕсли;
ЗарегистрироватьИзменения(ОсновныеПараметры, Узел, Данные, "НезависимыйРегистр", МетаданныеОбъекта.ПолноеИмя());
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Отмечает, что по переданным регистраторам нужно переформировать движения.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Регистраторы - Массив - массив ссылок регистраторов.
// ПолноеИмяРегистра - Строка - полное имя регистра, для которого необходимо обновить движения.
//
Процедура ОтметитьРегистраторыКОбработке(Параметры, Регистраторы, ПолноеИмяРегистра) Экспорт
ДополнительныеПараметры = ДополнительныеПараметрыОтметкиОбработки();
ДополнительныеПараметры.ЭтоДвижения = Истина;
ДополнительныеПараметры.ПолноеИмяРегистра = ПолноеИмяРегистра;
ОтметитьКОбработке(Параметры, Регистраторы, ДополнительныеПараметры);
КонецПроцедуры
// Дополнительные параметры выборки данных для обработки.
//
// Возвращаемое значение:
// Структура:
// * ВыбиратьПорциями - Булево - выбирать данные для обработки порциями.
// Если выбираются документы, то порция определяется с учетом упорядочивания по убыванию
// по дате документа. Если выбираются регистраторы регистра, то порция определяется с
// учетом упорядочивания по убыванию по дате регистратора, если передано полное имя документа.
// Если полное имя документа не передано - упорядочивание происходит по периоду регистра:
// а) берется максимальная дата по каждому регистратору;
// б) если по регистратору нет записей, он в топе.
// * ИмяВременнойТаблицы - Строка - параметр актуален для методов, создающих временные таблицы. Если имя не задано
// (поведение по умолчанию), то временная таблица будет создана с именем, указанным
// в описании каждого метода.
// * ДополнительныеИсточникиДанных - Соответствие из КлючИЗначение - параметр актуален для методов, выбирающих
// регистраторы и ссылки для обработки. В ключах соответствия может быть только один
// из следующих видов данных:
// 1. Пути к реквизитам шапки документа или реквизитам табличных частей, которые
// участвуют в соединениях с другими таблицами (в т.ч. неявных соединениях при
// обращении "через точку").
// 2. Имена ссылочных объектов метаданных (Строка), в значениях которых находится
// соответствие, в котором ключ - это имя регистра (Строка), а в значении
// соответствие в ключах которого то же, что и в п. 1, т.е.
// иерархия соответствий "Объект" -> "Регистр" -> "Источники".
// Процедуры проверяют блокировку данных этих таблиц обработчиками меньших
// очередей. Формат имен источников: <ИмяРеквизита> или
// <ИмяТабличной>.<ИмяРеквизитаТабличнойЧасти>. Для удобства заполнения
// см. УстановитьИсточникДанных() и см. ПолучитьИсточникДанных().
// * ПоляУпорядочивания - Массив - имена полей независимого регистра сведений, используется для упорядочивания
// результата запроса.
// * МаксимумВыборки - Число - максимальное количество выбираемых записей.
// * ИмяИзмеренияДляОтбора - Строка - имя измерения независимого регистра сведений, которому подчинены записи набора,
// (аналог регистратора для регистров, подчиненных регистраторам).
//
Функция ДополнительныеПараметрыВыборкиДанныхДляОбработки() Экспорт
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("ВыбиратьПорциями", Истина);
ДополнительныеПараметры.Вставить("ИмяВременнойТаблицы", "");
ДополнительныеПараметры.Вставить("ДополнительныеИсточникиДанных", Новый Соответствие);
ДополнительныеПараметры.Вставить("ПоляУпорядочивания", Новый Массив);
ДополнительныеПараметры.Вставить("МаксимумВыборки", МаксимальноеКоличествоЗаписейВВыборке());
ДополнительныеПараметры.Вставить("ИмяИзмеренияДляОтбора", "Регистратор");
Возврат ДополнительныеПараметры;
КонецФункции
// Параметры, используемые для выборки актуальных данных обработчика при выполнении обновления.
// Используется для обработчиков с обычным порядком. Данные, которые не удовлетворяют условию
// будут обрабатываться в порядке некритичных обработчиков.
//
// Возвращаемое значение:
// Структура:
// * ПолеОтбора - Строка - имя реквизита, по которому устанавливается отбор.
// * ВидСравнения - ВидСравнения - допустимые значения - Больше, Меньше, Равно,
// БольшеИлиРавно, МеньшеИлиРавно.
// * Значение - Произвольный - значение, по которому будет выполняться сравнение.
//
Функция ПараметрыВыборкиАктуальныхДанных() Экспорт
Параметры = Новый Структура;
Параметры.Вставить("ПолеОтбора");
Параметры.Вставить("ВидСравнения");
Параметры.Вставить("Значение");
Возврат Параметры;
КонецФункции
// Дополнительные параметры выборки данных для многопоточной обработки.
//
// Возвращаемое значение:
// Структура - поля из ДополнительныеПараметрыВыборкиДанныхДляОбработки(), дополненные следующими полями:
// * ПолныеИменаОбъектов - Строка - полные имена обновляемых объектов (например, документов), разделенные запятыми.
// * ПолныеИменаРегистров - Строка - полные имена регистров, разделенные запятыми.
// * ПоляУпорядочиванияПриРаботеПользователей - Массив - поля упорядочивания, используемые при обновлении
// с приоритетом работы пользователей.
// * ПоляУпорядочиванияПриОбработкеДанных - Массив - поля упорядочивания, используемые при обновлении
// с приоритетом обработки данных.
// * СпособВыборки - Строка - один из способов выборки:
// ОбновлениеИнформационнойБазы.СпособВыборкиИзмеренияНезависимогоРегистраСведений(),
// ОбновлениеИнформационнойБазы.СпособВыборкиРегистраторыРегистра(),
// ОбновлениеИнформационнойБазы.СпособВыборкиСсылки().
// * ПоследняяВыбраннаяЗапись - СписокЗначений - конец предыдущей выборки (служебное поле).
// * ПерваяЗапись - СписокЗначений - начало выборки (служебное поле).
// * ПоследняяЗапись - СписокЗначений - конец выборки (служебное поле).
// * ОптимизироватьВыборкуПоСтраницам - Булево - если Истина, то выборка выполняется без ИЛИ, значение Ложь может
// быть полезно, если исходный запрос не оптимален, тогда с ИЛИ будет быстрее.
//
Функция ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки() Экспорт
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметры.Вставить("ПолныеИменаОбъектов");
ДополнительныеПараметры.Вставить("ПолныеИменаРегистров");
ДополнительныеПараметры.Вставить("ПоляУпорядочиванияПриРаботеПользователей", Новый Массив);
ДополнительныеПараметры.Вставить("ПоляУпорядочиванияПриОбработкеДанных", Новый Массив);
ДополнительныеПараметры.Вставить("СпособВыборки");
ДополнительныеПараметры.Вставить("ПоследняяВыбраннаяЗапись");
ДополнительныеПараметры.Вставить("ПерваяЗапись");
ДополнительныеПараметры.Вставить("ПоследняяЗапись");
ДополнительныеПараметры.Вставить("ОптимизироватьВыборкуПоСтраницам", Истина);
Возврат ДополнительныеПараметры;
КонецФункции
// Установить параметр ДополнительныеИсточникиДанных в структуре, возвращаемой функцией
// ДополнительныеПараметрыВыборкиДанныхДляОбработки().
//
// Используется, когда источники данных нужно установить в разрезе документов и регистров.
// Применяется при многопоточном обновлении.
//
// Параметры:
// ДополнительныеИсточникиДанных - см. ДополнительныеПараметрыВыборкиДанныхДляОбработки
// Источник - см. ДополнительныеПараметрыВыборкиДанныхДляОбработки
// Объект - Строка - имя документа (полное или короткое).
// Регистр - Строка - имя регистра (полное или короткое).
//
Процедура УстановитьИсточникДанных(ДополнительныеИсточникиДанных, Источник, Объект = "", Регистр = "") Экспорт
ИмяОбъекта = ИмяОбъектаМетаданных(Объект);
ИмяРегистра = ИмяОбъектаМетаданных(Регистр);
Если ПустаяСтрока(ИмяОбъекта) И ПустаяСтрока(ИмяРегистра) Тогда
ДополнительныеИсточникиДанных.Вставить(Источник);
Иначе
РегистрыОбъекта = ДополнительныеИсточникиДанных[ИмяОбъекта];
Если РегистрыОбъекта = Неопределено Тогда
РегистрыОбъекта = Новый Соответствие;
ДополнительныеИсточникиДанных[ИмяОбъекта] = РегистрыОбъекта;
КонецЕсли;
ИсточникиДанных = РегистрыОбъекта[ИмяРегистра];
Если ИсточникиДанных = Неопределено Тогда
ИсточникиДанных = Новый Соответствие;
РегистрыОбъекта[ИмяРегистра] = ИсточникиДанных;
КонецЕсли;
ИсточникиДанных.Вставить(Источник);
КонецЕсли;
КонецПроцедуры
// Получить значение параметра ДополнительныеИсточникиДанных из структуры, возвращаемой
// функцией ДополнительныеПараметрыВыборкиДанныхДляОбработки().
//
// Можно использовать, когда источники данных нужно получить в разрезе документов и регистров.
// Применяется при многопоточном обновлении.
//
// Параметры:
// ДополнительныеИсточникиДанных - см. ДополнительныеПараметрыВыборкиДанныхДляОбработки
// Объект - Строка - имя документа (полное или короткое).
// Регистр - Строка - имя регистра (полное или короткое).
//
// Возвращаемое значение:
// Соответствие - источники данных для указанного документа и регистра.
//
Функция ИсточникиДанных(ДополнительныеИсточникиДанных, Объект = "", Регистр = "") Экспорт
Если ЭтоПростойИсточникДанных(ДополнительныеИсточникиДанных) Тогда
Возврат ДополнительныеИсточникиДанных;
Иначе
ИмяОбъекта = ИмяОбъектаМетаданных(Объект);
ИмяРегистра = ИмяОбъектаМетаданных(Регистр);
РегистрыОбъекта = ДополнительныеИсточникиДанных[ИмяОбъекта];
ТипСоответствие = Тип("Соответствие");
Если ТипЗнч(РегистрыОбъекта) = ТипСоответствие Тогда
ИсточникиДанных = РегистрыОбъекта[ИмяРегистра];
Если ТипЗнч(ИсточникиДанных) = ТипСоответствие Тогда
Возврат ИсточникиДанных;
КонецЕсли;
КонецЕсли;
Возврат Новый Соответствие;
КонецЕсли;
КонецФункции
// Создает временную таблицу ссылок, которые не обработаны в текущей очереди
// и не заблокированы меньшими очередями.
// Имя таблицы: ВТДляОбработки<ИмяРегистра>, например ВТДляОбработкиТоварыНаСкладах.
// Колонки таблицы:
// Регистратор - ДокументСсылка.
//
// Параметры:
// Очередь - Число - очередь обработки, в которой выполняется текущий обработчик.
// ПолноеИмяДокумента - Строка - имя документа, движения по которому нужно переформировать.
// Если движения формируются не по данным документа, то нужно передать Неопределено -
// тогда не будет проверяться блокировка таблицы документа.
// Например, "Документ.ПриходныйОрдерНаТовары".
// ПолноеИмяРегистра - Строка - имя регистра, движения по которому нужно переформировать.
// Например, "РегистрНакопления.ТоварыНаСкладах".
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// Структура - результат формирования временной таблицы:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись.
// Записей может не быть по двум причинам:
// все обработано или все, что нужно обработать, еще заблокировано
// обработчиками с меньшей очередью.
// * ЕстьДанныеДляОбработки - Булево - в очереди есть ссылки для обработки, т.е. еще не все обработано.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуРегистраторовРегистраДляОбработки(Очередь, ПолноеИмяДокумента, ПолноеИмяРегистра, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ИмяРегистра = СтрРазделить(ПолноеИмяРегистра,".",Ложь)[1];
ТекущаяОчередь = ОчередьСсылкой(Очередь);
Если ПолноеИмяДокумента = Неопределено Тогда
Если ДополнительныеПараметры.ВыбиратьПорциями Тогда
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| ТаблицаРегистраИзменения.Регистратор КАК Регистратор,
| МАКСИМУМ(ЕСТЬNULL(ТаблицаРегистра.Период, ДАТАВРЕМЯ(3000, 1, 1))) КАК Период
|ПОМЕСТИТЬ #ВТДляОбработкиРегистратор
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
| ЛЕВОЕ СОЕДИНЕНИЕ #ТаблицаДвиженийРегистра КАК ТаблицаРегистра
| ПО ТаблицаРегистраИзменения.Регистратор = ТаблицаРегистра.Регистратор
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоРегистратор КАК ВТЗаблокированоРегистратор
| ГДЕ
| ТаблицаРегистраИзменения.Регистратор = ВТЗаблокированоРегистратор.Регистратор)
| И &УсловиеПоДопИсточникамРегистрам
|
|СГРУППИРОВАТЬ ПО
| ТаблицаРегистраИзменения.Регистратор
|
|УПОРЯДОЧИТЬ ПО
| МАКСИМУМ(ЕСТЬNULL(ТаблицаРегистра.Период, ДАТАВРЕМЯ(3000, 1, 1)))
|
|ИНДЕКСИРОВАТЬ ПО
| Регистратор
|
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТЗаблокированоРегистратор"; // @query-part
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаДвиженийРегистра", ПолноеИмяРегистра);
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаРегистраИзменения.Регистратор КАК Регистратор
|ПОМЕСТИТЬ #ВТДляОбработкиРегистратор
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоРегистратор КАК ВТЗаблокированоРегистратор
| ГДЕ
| ТаблицаРегистраИзменения.Регистратор = ВТЗаблокированоРегистратор.Регистратор)
| И &УсловиеПоДопИсточникамРегистрам
|
|ИНДЕКСИРОВАТЬ ПО
| Регистратор
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТЗаблокированоРегистратор";
КонецЕсли;
Иначе
ФрагментыЗапроса = Новый Массив;
ФрагментЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| ТаблицаДокумента.Ссылка КАК Регистратор
|ПОМЕСТИТЬ #ВТДляОбработкиРегистратор
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ПолноеИмяДокумента КАК ТаблицаДокумента
| ПО ТаблицаРегистраИзменения.Регистратор = ТаблицаДокумента.Ссылка
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоРегистратор КАК ВТЗаблокированоРегистратор
| ГДЕ
| ТаблицаДокумента.Ссылка = ВТЗаблокированоРегистратор.Регистратор)
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоСсылка КАК ВТЗаблокированоСсылка
| ГДЕ
| ТаблицаДокумента.Ссылка = ВТЗаблокированоСсылка.Ссылка)
| И &УсловиеПоДопИсточникамСсылкам
| И &УсловиеПоДопИсточникамРегистрам";
ФрагментыЗапроса.Добавить(ФрагментЗапроса);
Если ДополнительныеПараметры.ВыбиратьПорциями Тогда
ФрагментЗапроса =
"
|УПОРЯДОЧИТЬ ПО
| ТаблицаДокумента.Дата УБЫВ";
ФрагментыЗапроса.Добавить(ФрагментЗапроса);
КонецЕсли;
ФрагментЗапроса =
"
|ИНДЕКСИРОВАТЬ ПО
| Регистратор
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТЗаблокированоРегистратор
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТЗаблокированоСсылка";
ФрагментыЗапроса.Добавить(ФрагментЗапроса);
ТекстЗапроса = СтрСоединить(ФрагментыЗапроса, Символы.ПС);
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = "ВТЗаблокированоСсылка";
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяДокумента, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ);
КонецЕсли;
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТДляОбработки" + ИмяРегистра;
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаРегистраИзменения", ПолноеИмяРегистра + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТДляОбработкиРегистратор", ИмяВременнойТаблицы);
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = "ВТЗаблокированоРегистратор";
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяРегистра, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ);
ДобавитьПроверкуБлокировкиДополнительныхИсточников(Очередь, ТекстЗапроса, ПолноеИмяДокумента, ПолноеИмяРегистра, МенеджерВременныхТаблиц, Истина, ДополнительныеПараметры);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ПолноеИмяДокумента", ПолноеИмяДокумента);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ТекущаяОчередь);
РезультатЗапроса = Запрос.ВыполнитьПакет();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице,ЕстьДанныеДляОбработки,ИмяВременнойТаблицы", Ложь, Ложь, "");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса[0].Выгрузить()[0].Количество <> 0;
Если Результат.ЕстьЗаписиВоВременнойТаблице Тогда
Результат.ЕстьДанныеДляОбработки = Истина;
Иначе
Результат.ЕстьДанныеДляОбработки = ЕстьДанныеДляОбработки(Очередь, ПолноеИмяРегистра);
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает порцию регистраторов, по которым нужно переформировать движения.
// Данные берутся из зарегистрированных в очереди, учитываются заблокированные более приоритетными очередями данные.
// Блокировка по другим очередям делается по документу и по регистру.
// Регистраторы в выборке упорядочены по дате регистратора по убыванию, если передано полное имя документа.
// Если полное имя документа не передано - упорядочивание происходит по периоду регистра:
// - берется максимальная дата по каждому регистратору;
// - если по регистратору нет записей - он в топе.
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные, которые он будет обрабатывать.
// ПолноеИмяДокумента - Строка - имя документа, движения по которому нужно переформировать. Если движения формируются не по данным
// документа, то нужно передать Неопределено - тогда не будет проверяться блокировка таблицы документа.
// Например, Документ.ПриходныйОрдерНаТовары.
// ПолноеИмяРегистра - Строка - имя регистра, движения по которому нужно переформировать.
// Например, РегистрНакопления.ТоварыНаСкладах.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// ВыборкаИзРезультатаЗапроса - выборка регистраторов, которые нужно обработать, поля выборки:
// * Регистратор - ДокументСсылка.
// * Период - Дата - дата документа, если передано полное имя документа, максимальный период по регистратору,
// если полное имя документа не передано.
// * Проведен - Булево
// - Неопределено - значение реквизита Проведен документа, если передано полное имя документа,
// или Неопределено, если имя документа не передано.
// ТаблицаЗначений - данные, которые нужно обработать, имена колонок соответствуют именам измерений регистра.
//
Функция ВыбратьРегистраторыРегистраДляОбработки(Очередь, ПолноеИмяДокумента, ПолноеИмяРегистра, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ПараметрыОбработчикаОбновления = Неопределено;
ДополнительныеПараметры.Свойство("ПараметрыОбработчикаОбновления", ПараметрыОбработчикаОбновления);
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();
ПроверитьПараметрыВыборки(ДополнительныеПараметры);
ПараметрыПостроения = ПараметрыПостроенияВыборки(ДополнительныеПараметры);
ЕстьФильтр = Ложь;
Если ПолноеИмяДокумента = Неопределено Тогда
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| &ВыбираемыеПоля
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
| ЛЕВОЕ СОЕДИНЕНИЕ #ТаблицаДвиженийРегистра КАК ТаблицаРегистра
| ПО ТаблицаРегистраИзменения.Регистратор = ТаблицаРегистра.Регистратор
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоРегистратор КАК ВТЗаблокированоРегистратор
| ГДЕ
| ТаблицаРегистраИзменения.Регистратор = ВТЗаблокированоРегистратор.Регистратор)
| И &УсловиеПоДопИсточникамРегистрам
|
|СГРУППИРОВАТЬ ПО
| ТаблицаРегистраИзменения.Регистратор";
Если ПараметрыПостроения.ПостраничнаяВыборка Тогда
ТекстЗапроса = ТекстЗапроса + "
|
|ИМЕЮЩИЕ
| &УсловиеПоСтраницам"
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|
|УПОРЯДОЧИТЬ ПО
| &ПорядокВыборки";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаДвиженийРегистра", ПолноеИмяРегистра);
УстановитьПоляУпорядочиванияРегистра(ПараметрыПостроения);
Иначе
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| &ВыбираемыеПоля
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ПолноеИмяДокумента КАК ТаблицаДокумента
| ПО ТаблицаРегистраИзменения.Регистратор = ТаблицаДокумента.Ссылка
|
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоРегистратор КАК ВТЗаблокированоРегистратор
| ГДЕ
| ТаблицаРегистраИзменения.Регистратор = ВТЗаблокированоРегистратор.Регистратор)
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ВТЗаблокированоСсылка КАК ВТЗаблокированоСсылка
| ГДЕ
| ТаблицаРегистраИзменения.Регистратор = ВТЗаблокированоСсылка.Ссылка)
| И &УсловиеПоДопИсточникамСсылкам
| И &УсловиеПоДопИсточникамРегистрам
| И &УсловиеПоСтраницам
| И &УсловиеАктуальныеДанные
|
|УПОРЯДОЧИТЬ ПО
| &ПорядокВыборки";
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = "ВТЗаблокированоСсылка";
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяДокумента, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ);
УстановитьПоляУпорядочиванияРегистраПоДокументу(ПараметрыПостроения);
ФильтрАктуальныхДанных = ОбновлениеИнформационнойБазыСлужебный.ФильтрАктуальныхДанных(ПараметрыОбработчикаОбновления, "ТаблицаДокумента");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
ЕстьФильтр = Истина;
ТекстЗапросаПроверки =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| #ТаблицаРегистраИзменения КАК ТаблицаРегистраИзменения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ПолноеИмяДокумента КАК ТаблицаДокумента
| ПО ТаблицаРегистраИзменения.Регистратор = ТаблицаДокумента.Ссылка
|ГДЕ
| ТаблицаРегистраИзменения.Узел = &ТекущаяОчередь
| И &УсловиеАктуальныеДанные";
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаРегистраИзменения", ПолноеИмяРегистра + ".Изменения");
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ПолноеИмяДокумента", ПолноеИмяДокумента);
ЗапросПроверки = Новый Запрос;
ЗапросПроверки.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
ЗапросПроверки.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
ЗапросПроверки.Текст = ТекстЗапросаПроверки;
ОбработаныВсеАктуальныеДанные = ЗапросПроверки.Выполнить().Пустой();
УстановитьПараметрыОбработчикаПриВыборкеДанных(ДополнительныеПараметры, ОбработаныВсеАктуальныеДанные, ПараметрыОбработчикаОбновления, ПолноеИмяДокумента);
КонецЕсли;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаРегистраИзменения", ПолноеИмяРегистра + ".Изменения");
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = "ВТЗаблокированоРегистратор";
ИмяИзмеренияДляОтбора = ДополнительныеПараметры.ИмяИзмеренияДляОтбора;
Если ВРег(ИмяИзмеренияДляОтбора) <> ВРег("Регистратор") Тогда
ДополнительныеПараметрыСозданияВТ.ИмяИзмеренияДляОтбора = ИмяИзмеренияДляОтбора;
Измерение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(".%1", ИмяИзмеренияДляОтбора);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ".Регистратор", Измерение);
КонецЕсли;
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяРегистра, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ);
УстановитьРазмерВыборки(ТекстЗапроса, ДополнительныеПараметры);
ДобавитьПроверкуБлокировкиДополнительныхИсточников(Очередь, ТекстЗапроса, ПолноеИмяДокумента, ПолноеИмяРегистра, МенеджерВременныхТаблиц, Ложь, ДополнительныеПараметры);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ПолноеИмяДокумента", ПолноеИмяДокумента);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
Если ЕстьФильтр Тогда
Запрос.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
КонецЕсли;
УстановитьПоляПоСтраницам(Запрос, ПараметрыПостроения);
УстановитьПорядокПоСтраницам(Запрос, ПараметрыПостроения);
Возврат ВыбратьДанныеДляОбработки(Запрос, ПараметрыПостроения);
КонецФункции
// Возвращает порцию ссылок, по которым нужно произвести обработку.
// Данные берутся из зарегистрированных в очереди, учитываются заблокированные более приоритетными очередями данные.
// Ссылки на документы возвращаются упорядоченными по убыванию по дате.
//
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные, которые он будет
// обрабатывать.
// ПолноеИмяОбъекта - Строка - имя объекта, который нужно обработать. Например, Документ.ПриходныйОрдерНаТовары.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// ВыборкаИзРезультатаЗапроса - выборка ссылок, которые нужно обработать, поля выборки:
// * Ссылка - ЛюбаяСсылка.
// ТаблицаЗначений - данные, которые нужно обработать, имена колонок соответствуют именам измерений регистра.
//
Функция ВыбратьСсылкиДляОбработки(Очередь, ПолноеИмяОбъекта, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ПараметрыОбработчикаОбновления = Неопределено;
ДополнительныеПараметры.Свойство("ПараметрыОбработчикаОбновления", ПараметрыОбработчикаОбновления);
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта,".",Ложь)[1];
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
ЭтоДокумент = ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта)
Или ОбщегоНазначения.ЭтоЗадача(МетаданныеОбъекта);
ПроверитьПараметрыВыборки(ДополнительныеПараметры);
ПараметрыПостроения = ПараметрыПостроенияВыборки(ДополнительныеПараметры);
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| &ВыбираемыеПоля
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаОбъекта КАК ТаблицаОбъекта
| ПО ТаблицаИзменений.Ссылка = ТаблицаОбъекта.Ссылка
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #ВТЗаблокированоСсылка КАК ВТЗаблокированоСсылка
| ГДЕ
| ТаблицаИзменений.Ссылка = ВТЗаблокированоСсылка.Ссылка)
| И &УсловиеПоДопИсточникамСсылкам
| И &УсловиеПоДопИсточникамРегистрам
| И &УсловиеПоСтраницам
| И &УсловиеАктуальныеДанные";
Если ЭтоДокумент Или ПараметрыПостроения.ПостраничнаяВыборка Тогда
ТекстЗапроса = ТекстЗапроса + "
|
|УПОРЯДОЧИТЬ ПО
| &ПорядокВыборки";
КонецЕсли;
ФильтрАктуальныхДанных = ОбновлениеИнформационнойБазыСлужебный.ФильтрАктуальныхДанных(ПараметрыОбработчикаОбновления, "ТаблицаОбъекта");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
ТекстЗапросаПроверки =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаОбъекта КАК ТаблицаОбъекта
| ПО ТаблицаИзменений.Ссылка = ТаблицаОбъекта.Ссылка
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И &УсловиеАктуальныеДанные";
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаОбъекта", ПолноеИмяОбъекта);
ЗапросПроверки = Новый Запрос;
ЗапросПроверки.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
ЗапросПроверки.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
ЗапросПроверки.Текст = ТекстЗапросаПроверки;
ОбработаныВсеАктуальныеДанные = ЗапросПроверки.Выполнить().Пустой();
УстановитьПараметрыОбработчикаПриВыборкеДанных(ДополнительныеПараметры, ОбработаныВсеАктуальныеДанные, ПараметрыОбработчикаОбновления)
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|;
|УНИЧТОЖИТЬ
| #ВТЗаблокированоСсылка";
УстановитьПоляУпорядочиванияСсылок(ПараметрыПостроения, ЭтоДокумент);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТЗаблокированоСсылка","ВТЗаблокировано" + ИмяОбъекта);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаОбъекта", ПолноеИмяОбъекта);
УстановитьРазмерВыборки(ТекстЗапроса, ДополнительныеПараметры);
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц);
ДобавитьПроверкуБлокировкиДополнительныхИсточников(Очередь, ТекстЗапроса, ПолноеИмяОбъекта, Неопределено, МенеджерВременныхТаблиц, Ложь, ДополнительныеПараметры);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
Запрос.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
КонецЕсли;
УстановитьПоляПоСтраницам(Запрос, ПараметрыПостроения);
Если ЭтоДокумент Или ПараметрыПостроения.ПостраничнаяВыборка Тогда
УстановитьПорядокПоСтраницам(Запрос, ПараметрыПостроения);
КонецЕсли;
Возврат ВыбратьДанныеДляОбработки(Запрос, ПараметрыПостроения);
КонецФункции
// Создает временную таблицу ссылок, которые не обработаны в текущей очереди
// и не заблокированы меньшими очередями.
// Имя таблицы: ВТДляОбработки<ИмяОбъекта>, например ВТДляОбработкиНоменклатура.
// Колонки таблицы:
// Ссылка - ЛюбаяСсылка.
//
// Параметры:
// Очередь - Число - очередь обработки, в которой выполняется текущий обработчик.
// ПолноеИмяОбъекта - Строка - полное имя объекта, для которого выполняется проверка, например Справочник.Номенклатура.
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// Структура - результат формирования временной таблицы:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись. Записей может не быть по
// двум причинам:
// все обработано или все, что нужно обработать, еще заблокировано
// обработчиками с меньшей очередью.
// * ЕстьДанныеДляОбработки - Булево - в очереди есть ссылки для обработки, т.е. еще не все обработано.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуСсылокДляОбработки(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта,".",Ложь)[1];
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
ФрагментыЗапроса = Новый Массив;
ФрагментЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| ТаблицаОбъекта.Ссылка КАК Ссылка
|ПОМЕСТИТЬ #ВТДляОбработкиСсылка
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаОбъекта КАК ТаблицаОбъекта
| ПО ТаблицаИзменений.Ссылка = ТаблицаОбъекта.Ссылка
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #ВТЗаблокированоСсылка КАК ВТЗаблокированоСсылка
| ГДЕ
| ТаблицаОбъекта.Ссылка = ВТЗаблокированоСсылка.Ссылка)
| И &УсловиеПоДопИсточникамСсылкам
| И &УсловиеПоДопИсточникамРегистрам
| И &УсловиеАктуальныеДанные";
Если Не ДополнительныеПараметры.ВыбиратьПорциями Тогда
ФрагментЗапроса = СтрЗаменить(ФрагментЗапроса, "ВЫБРАТЬ ПЕРВЫЕ 10000", "ВЫБРАТЬ"); // @query-part-1 @query-part-2
КонецЕсли;
ФильтрАктуальныхДанных = ОбновлениеИнформационнойБазыСлужебный.ФильтрАктуальныхДанных(Неопределено, "ТаблицаОбъекта");
ФрагментЗапроса = СтрЗаменить(ФрагментЗапроса, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
ТекстЗапросаПроверки =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаОбъекта КАК ТаблицаОбъекта
| ПО ТаблицаИзменений.Ссылка = ТаблицаОбъекта.Ссылка
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И &УсловиеАктуальныеДанные";
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаОбъекта", ПолноеИмяОбъекта);
ЗапросПроверки = Новый Запрос;
ЗапросПроверки.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
ЗапросПроверки.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
ЗапросПроверки.Текст = ТекстЗапросаПроверки;
ОбработаныВсеАктуальныеДанные = ЗапросПроверки.Выполнить().Пустой();
УстановитьПараметрыОбработчикаПриВыборкеДанных(ДополнительныеПараметры, ОбработаныВсеАктуальныеДанные, Неопределено)
КонецЕсли;
ФрагментыЗапроса.Добавить(ФрагментЗапроса);
ЭтоСсылка = ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта) Или ОбщегоНазначения.ЭтоЗадача(МетаданныеОбъекта);
Если ДополнительныеПараметры.ВыбиратьПорциями И ЭтоСсылка Тогда
ФрагментыЗапроса.Добавить("УПОРЯДОЧИТЬ ПО
| ТаблицаОбъекта.Дата УБЫВ");
КонецЕсли;
ФрагментЗапроса =
"ИНДЕКСИРОВАТЬ ПО
| Ссылка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ #ВТЗаблокированоСсылка";
ФрагментыЗапроса.Добавить(ФрагментЗапроса);
ТекстЗапроса = СтрСоединить(ФрагментыЗапроса, Символы.ПС);
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТДляОбработки" + ИмяОбъекта;
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТЗаблокированоСсылка","ВТЗаблокировано" + ИмяОбъекта);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТДляОбработкиСсылка",ИмяВременнойТаблицы);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц);
ДобавитьПроверкуБлокировкиДополнительныхИсточников(Очередь, ТекстЗапроса, ПолноеИмяОбъекта, Неопределено, МенеджерВременныхТаблиц, Истина, ДополнительныеПараметры);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаОбъекта", ПолноеИмяОбъекта);
ТекущаяОчередь = ОчередьСсылкой(Очередь);
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ТекущаяОчередь);
РезультатЗапроса = Запрос.ВыполнитьПакет();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице,ЕстьДанныеДляОбработки,ИмяВременнойТаблицы", Ложь, Ложь,"");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса[0].Выгрузить()[0].Количество <> 0;
Если Результат.ЕстьЗаписиВоВременнойТаблице Тогда
Результат.ЕстьДанныеДляОбработки = Истина;
Иначе
Результат.ЕстьДанныеДляОбработки = ЕстьДанныеДляОбработки(Очередь, ПолноеИмяОбъекта);
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает значения измерений независимого регистра сведений для обработки.
// Данные берутся из зарегистрированных в очереди, учитываются заблокированные более приоритетными очередями данные.
//
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные, которые он будет
// обрабатывать.
// ПолноеИмяОбъекта - Строка - имя объекта, который нужно обработать. Например, РегистрСведений.ШтрихкодыНоменклатуры.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// ВыборкаИзРезультатаЗапроса - выборка значений измерений, которые нужно обработать, имена полей соответствует именам
// измерений регистра. Если по измерению не регистрировалась необходимость обработки,
// то в выборке по этому измерению будет пустое значение.
// ТаблицаЗначений - данные, которые нужно обработать, имена колонок соответствуют именам измерений регистра.
//
Функция ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки(Очередь, ПолноеИмяОбъекта, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ПараметрыОбработчикаОбновления = Неопределено;
ДополнительныеПараметры.Свойство("ПараметрыОбработчикаОбновления", ПараметрыОбработчикаОбновления);
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта,".",Ложь)[1];
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
ПараметрыПостроения = ПараметрыПостроенияВыборки(ДополнительныеПараметры, "ТаблицаИзменений");
ЗаданыПоляУпорядочивания = ЗаданыПоляУпорядочивания(ДополнительныеПараметры);
НеобходимоУпорядочивание = ЗаданыПоляУпорядочивания Или ПараметрыПостроения.ПостраничнаяВыборка;
Запрос = Новый Запрос;
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| &ВыбираемыеПоля
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И &ТекстУсловияПоОтборуНезаблокированных
| И &УсловиеПоДопИсточникамСсылкам
| И &УсловиеПоСтраницам
| И &УсловиеАктуальныеДанные";
Если НеобходимоУпорядочивание Тогда
УстановитьПоляУпорядочиванияНезависимогоРегистраСведений(ПараметрыПостроения);
ТекстЗапроса = ТекстЗапроса + "
|УПОРЯДОЧИТЬ ПО
| &ПорядокВыборки
|";
КонецЕсли;
ФильтрАктуальныхДанных = ОбновлениеИнформационнойБазыСлужебный.ФильтрАктуальныхДанных(ПараметрыОбработчикаОбновления, "ТаблицаИзменений");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
ТекстЗапросаПроверки =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И &УсловиеАктуальныеДанные";
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки, "&УсловиеАктуальныеДанные", ФильтрАктуальныхДанных.Условие);
ТекстЗапросаПроверки = СтрЗаменить(ТекстЗапросаПроверки,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ЗапросПроверки = Новый Запрос;
ЗапросПроверки.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
ЗапросПроверки.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
ЗапросПроверки.Текст = ТекстЗапросаПроверки;
ОбработаныВсеАктуальныеДанные = ЗапросПроверки.Выполнить().Пустой();
УстановитьПараметрыОбработчикаПриВыборкеДанных(ДополнительныеПараметры, ОбработаныВсеАктуальныеДанные, ПараметрыОбработчикаОбновления)
КонецЕсли;
ИзмеренияСОсновнымОтбором = Новый Массив;
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Если Не Измерение.ОсновнойОтбор Тогда
Продолжить;
КонецЕсли;
УстановитьИзмерение(ПараметрыПостроения, Измерение.Имя);
ИзмеренияСОсновнымОтбором.Добавить(Измерение.Имя);
Запрос.УстановитьПараметр("ПустоеЗначениеИзмерения"+ Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЦикла;
ПризнакНепериодический = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический;
Если МетаданныеОбъекта.ПериодичностьРегистраСведений <> ПризнакНепериодический
И МетаданныеОбъекта.ОсновнойОтборПоПериоду Тогда
УстановитьПериод(ПараметрыПостроения);
КонецЕсли;
УстановитьРесурсы(ПараметрыПостроения, МетаданныеОбъекта.Ресурсы);
УстановитьРеквизиты(ПараметрыПостроения, МетаданныеОбъекта.Реквизиты);
ТекстУсловияПоОтборуНезаблокированных = УсловиеОтбораНезаблокированныхИзмерений(ИзмеренияСОсновнымОтбором);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТекстУсловияПоОтборуНезаблокированных", ТекстУсловияПоОтборуНезаблокированных);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТЗаблокированоИзмерения","ВТЗаблокировано" + ИмяОбъекта);
УстановитьРазмерВыборки(ТекстЗапроса, ДополнительныеПараметры);
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц);
ДобавитьПроверкуБлокировкиДополнительныхИсточниковДляНезависимогоРегистра(Очередь,
ТекстЗапроса,
ПолноеИмяОбъекта,
МенеджерВременныхТаблиц,
ДополнительныеПараметры);
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ОчередьСсылкой(Очередь));
Если ФильтрАктуальныхДанных.ЕстьФильтр Тогда
Запрос.УстановитьПараметр("ЗначениеОтбораАктуальныхДанных", ФильтрАктуальныхДанных.Значение);
КонецЕсли;
УстановитьПоляПоСтраницам(Запрос, ПараметрыПостроения);
Если НеобходимоУпорядочивание Тогда
УстановитьПорядокПоСтраницам(Запрос, ПараметрыПостроения);
КонецЕсли;
Возврат ВыбратьДанныеДляОбработки(Запрос, ПараметрыПостроения);
КонецФункции
// Создает временную таблицу значения измерений независимого регистра сведений для обработки.
// Имя таблицы: ВТДляОбработки<ИмяОбъекта>, например ВТДляОбработкиШтрихкодыНоменклатуры.
// Колонки таблицы соответствуют измерениям регистра. Если по измерению не регистрировалась
// необходимость обработки, то в выборке по этому измерению будет пустое значение.
//
// Параметры:
// Очередь - Число - очередь обработки, в которой выполняется текущий обработчик.
// ПолноеИмяОбъекта - Строка - полное имя объекта, для которого выполняется проверка, например Справочник.Номенклатура.
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// Структура - результат формирования временной таблицы:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись. Записей может не быть по
// двум причинам:
// все обработано или все, что нужно обработать, еще заблокировано
// обработчиками с меньшей очередью.
// * ЕстьДанныеДляОбработки - Булево - в очереди есть данные для обработки, т.е. еще не все обработано.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуИзмеренийНезависимогоРегистраСведенийДляОбработки(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта,".",Ложь)[1];
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
Запрос = Новый Запрос;
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 10000
| &ТекстВыборкиИзмерений
|ПОМЕСТИТЬ #ВТДляОбработкиИзмерения
|ИЗ
| #ТаблицаОбъектаИзменения КАК ТаблицаИзменений
|ГДЕ
| ТаблицаИзменений.Узел = &ТекущаяОчередь
| И &ТекстУсловияПоОтборуНезаблокированных
| И &УсловиеПоДопИсточникамСсылкам
|ИНДЕКСИРОВАТЬ ПО
| &ИндексируемыеИзмерения
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ #ВТЗаблокированоИзмерения";
Если Не ДополнительныеПараметры.ВыбиратьПорциями Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ ПЕРВЫЕ 10000", "ВЫБРАТЬ"); // @query-part-1 @query-part-2
КонецЕсли;
ИзмеренияСОсновнымОтбором = Новый Массив;
ОтбираемыеИзмерения = Новый Массив;
ШаблонВыбираемогоИзмерения = "ТаблицаИзменений.%1 КАК %1";
РегистрПериодический =
(МетаданныеОбъекта.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический)
И МетаданныеОбъекта.ОсновнойОтборПоПериоду;
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Если Не Измерение.ОсновнойОтбор Тогда
Продолжить;
КонецЕсли;
ВыбираемоеИзмерение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонВыбираемогоИзмерения,
Измерение.Имя);
ОтбираемыеИзмерения.Добавить(ВыбираемоеИзмерение);
ИзмеренияСОсновнымОтбором.Добавить(Измерение.Имя);
Запрос.УстановитьПараметр("ПустоеЗначениеИзмерения"+ Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЦикла;
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТДляОбработки" + ИмяОбъекта;
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстУсловияПоОтборуНезаблокированных = УсловиеОтбораНезаблокированныхИзмерений(ИзмеренияСОсновнымОтбором);
Если РегистрПериодический Тогда
ИзмеренияСОсновнымОтбором.Добавить("Период");
КонецЕсли;
ТекстВыборкиИзмерений = ПоляДляЗапроса(ИзмеренияСОсновнымОтбором,, "ТаблицаИзменений");
ТекстИндексируемыхИзмерений = УпорядочиванияДляЗапроса(ИзмеренияСОсновнымОтбором);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТекстВыборкиИзмерений", ТекстВыборкиИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИндексируемыеИзмерения", ТекстИндексируемыхИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТекстУсловияПоОтборуНезаблокированных", ТекстУсловияПоОтборуНезаблокированных);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"#ТаблицаОбъектаИзменения", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТЗаблокированоИзмерения","ВТЗаблокировано" + ИмяОбъекта);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ВТДляОбработкиИзмерения",ИмяВременнойТаблицы);
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц);
ДобавитьПроверкуБлокировкиДополнительныхИсточниковДляНезависимогоРегистра(Очередь,
ТекстЗапроса,
ПолноеИмяОбъекта,
МенеджерВременныхТаблиц,
ДополнительныеПараметры);
ТекущаяОчередь = ОчередьСсылкой(Очередь);
Запрос.Текст = ТекстЗапроса;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТекущаяОчередь", ТекущаяОчередь);
РезультатЗапроса = Запрос.ВыполнитьПакет();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице,ЕстьДанныеДляОбработки,ИмяВременнойТаблицы", Ложь, Ложь,"");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса[0].Выгрузить()[0].Количество <> 0;
Если Результат.ЕстьЗаписиВоВременнойТаблице Тогда
Результат.ЕстьДанныеДляОбработки = Истина;
Иначе
Результат.ЕстьДанныеДляОбработки = ЕстьДанныеДляОбработки(Очередь, ПолноеИмяОбъекта);
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет, есть ли еще необработанные данные.
//
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные,
// которые он будет обрабатывать.
// - Неопределено - проверяется, завершена ли обработка в целом;
// - Массив - проверяется, есть данные для обработки в списке очередей.
// ПолноеИмяМетаданныеОбъекта - Строка
// - ОбъектМетаданных - полное имя обрабатываемого объекта или
// его метаданные. Например, "Документ.ПриходныйОрдерНаТовары"
// - Массив - массив полных имен объектов или объектов метаданных,
// в массиве не должно быть независимых регистров сведений.
// Отбор - ЛюбаяСсылка
// - Структура
// - Неопределено
// - Массив - отбор данных для проверки.
// Если передано Неопределено - проверяется по всему типу объекта.
// Если объект - регистр, подчиненный регистратору, то в отборе - ссылка
// на регистратор или массив ссылок.
// Если объект ссылочного типа, то в отборе - или ссылка, или массив ссылок.
// Если объект - независимый регистр сведений, то в отборе - структура со значениями измерений.
// Ключ структуры - имя измерения, значение - значение отбора (можно передать массив значений).
//
// Возвращаемое значение:
// Булево - Истина, если еще не все данные обработаны.
//
Функция ЕстьДанныеДляОбработки(Очередь, ПолноеИмяМетаданныеОбъекта, Отбор = Неопределено) Экспорт
Если ОтложенноеОбновлениеЗавершено() Тогда
Возврат Ложь;
КонецЕсли;
Если ТипЗнч(ПолноеИмяМетаданныеОбъекта) = Тип("Строка") Тогда
ПолныеИменаОбрабатываемыхОбъектов = СтрРазделить(ПолноеИмяМетаданныеОбъекта, ",");
ИначеЕсли ТипЗнч(ПолноеИмяМетаданныеОбъекта) = Тип("Массив") Тогда
ПолныеИменаОбрабатываемыхОбъектов = ПолноеИмяМетаданныеОбъекта;
ИначеЕсли ТипЗнч(ПолноеИмяМетаданныеОбъекта) = Тип("ОбъектМетаданных") Тогда
ПолныеИменаОбрабатываемыхОбъектов = Новый Массив;
ПолныеИменаОбрабатываемыхОбъектов.Добавить(ПолноеИмяМетаданныеОбъекта.ПолноеИмя());
Иначе
ТекстИсключения = НСтр("ru = 'Передан неправильный тип параметра ""%1"" в функцию %2'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ПолноеИмяМетаданныеОбъекта", "ОбновлениеИнформационнойБазы.ЕстьДанныеДляОбработки");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
Запрос = Новый Запрос;
ТекстыЗапроса = Новый Массив;
ТекстыЗапросаРегистров = Новый Массив;
ОтборУстановлен = Ложь;
Для Каждого ОбрабатываемыйТип Из ПолныеИменаОбрабатываемыхОбъектов Цикл
Если ТипЗнч(ОбрабатываемыйТип) = Тип("ОбъектМетаданных") Тогда
МетаданныеОбъекта = ОбрабатываемыйТип;
ПолноеИмяОбъекта = ОбрабатываемыйТип.ПолноеИмя();
Иначе
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ОбрабатываемыйТип);
ПолноеИмяОбъекта = ОбрабатываемыйТип;
КонецЕсли;
ПроверкаРегистра = Ложь;
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта,".",Ложь)[1];
УсловиеОтбораДанных = "ИСТИНА";
УсловиеПроверкиРегистратора = "ИСТИНА";
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ТаблицаИзменений.Ссылка КАК Ссылка
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
| И &УсловиеОтбораДанных
| И ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #ТаблицаОбъекта КАК Таблица
| ГДЕ
| Таблица.Ссылка = ТаблицаИзменений.Ссылка)";
Запрос.УстановитьПараметр("Ссылка", Отбор);
Если Отбор <> Неопределено Тогда
УсловиеОтбораДанных = "ТаблицаИзменений.Ссылка В (&Отбор)";
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеОбъекта)
И МетаданныеОбъекта.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
Если ПолныеИменаОбрабатываемыхОбъектов.Количество() > 1 Тогда
ТекстИсключения = НСтр("ru = 'В массиве имен в параметре ""%1"" в функцию %2 передан независимый регистр сведений.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
"ПолноеИмяМетаданныеОбъекта", "ОбновлениеИнформационнойБазы.ЕстьДанныеДляОбработки");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
ОтборУстановлен = Истина;
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| &ТекстВыборкиИзмерений
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
| И &УсловиеОтбораДанных";
ТекстВыборкиИзмерений = "";
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Если Не Измерение.ОсновнойОтбор Тогда
Продолжить;
КонецЕсли;
ТекстВыборкиИзмерений = ТекстВыборкиИзмерений + "
| ТаблицаИзменений." + Измерение.Имя + " КАК " + Измерение.Имя + ",";
Если Отбор <> Неопределено Тогда
УсловиеОтбораДанных = УсловиеОтбораДанных + "
| И (ТаблицаИзменений." + Измерение.Имя + " В (&ЗначениеОтбора" + Измерение.Имя + ")
| ИЛИ ТаблицаИзменений." + Измерение.Имя + " = &ПустоеЗначение" + Измерение.Имя + ")";
Если Отбор.Свойство(Измерение.Имя) Тогда
Запрос.УстановитьПараметр("ЗначениеОтбора" + Измерение.Имя, Отбор[Измерение.Имя]);
Иначе
Запрос.УстановитьПараметр("ЗначениеОтбора" + Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЕсли;
Запрос.УстановитьПараметр("ПустоеЗначение" + Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЕсли;
КонецЦикла;
Если ПустаяСтрока(ТекстВыборкиИзмерений) Тогда
ТекстВыборкиИзмерений = "*";
Иначе
ТекстВыборкиИзмерений = Лев(ТекстВыборкиИзмерений, СтрДлина(ТекстВыборкиИзмерений) - 1);
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТекстВыборкиИзмерений", ТекстВыборкиИзмерений);
ИначеЕсли ОбщегоНазначения.ЭтоРегистр(МетаданныеОбъекта) Тогда
ПроверкаРегистра = Истина;
ШаблонЗапросаПроверки =
"ИСТИНА В (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| #ИмяТаблицы КАК ПроверяемаяТаблица
|ГДЕ
| ТаблицаИзменений.Регистратор = ПроверяемаяТаблица.Ссылка)";
КоллекцияЗапросов = Новый Массив;
ТипыРегистратора = МетаданныеОбъекта.СтандартныеРеквизиты.Регистратор.Тип;
ТипыРегистратора = ТипыРегистратора.Типы();
Для Каждого ТипРегистратора Из ТипыРегистратора Цикл
МетаданныеРегистратора = Метаданные.НайтиПоТипу(ТипРегистратора);
Если МетаданныеРегистратора = Неопределено Тогда
Продолжить;
КонецЕсли;
ПолноеИмяРегистратора = МетаданныеРегистратора.ПолноеИмя();
ТекстЗапросаПроверки = СтрЗаменить(ШаблонЗапросаПроверки, "#ИмяТаблицы", ПолноеИмяРегистратора);
КоллекцияЗапросов.Добавить(ТекстЗапросаПроверки);
КонецЦикла;
УсловиеПроверкиРегистратора = СтрСоединить(КоллекцияЗапросов, Символы.ПС + "ИЛИ ");
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ТаблицаИзменений.Регистратор КАК Ссылка
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
| И &УсловиеОтбораДанных
| И (&УсловиеПоРегистраторам)";
Если Отбор <> Неопределено Тогда
УсловиеОтбораДанных = "ТаблицаИзменений.Регистратор В (&Отбор)";
КонецЕсли;
Иначе
ТекстИсключения = НСтр("ru = 'Для типа метаданных ""%1"" не поддерживается проверка в функции %2'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
Строка(МетаданныеОбъекта), "ОбновлениеИнформационнойБазы.ЕстьДанныеДляОбработки");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаИзменений", ПолноеИмяОбъекта + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаОбъекта", ПолноеИмяОбъекта);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяОбъекта", ИмяОбъекта);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеОтбораДанных", УсловиеОтбораДанных);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоРегистраторам", УсловиеПроверкиРегистратора);
Если ПроверкаРегистра Тогда
ТекстыЗапросаРегистров.Добавить(ТекстЗапроса);
Иначе
ТекстыЗапроса.Добавить(ТекстЗапроса);
КонецЕсли;
КонецЦикла;
Соединитель = "
|
|ОБЪЕДИНИТЬ ВСЕ
|";
ТекстЗапроса = СтрСоединить(ТекстыЗапроса, Соединитель);
ИтоговыйМассивЗапросов = Новый Массив;
ИтоговыйМассивЗапросов.Добавить(ТекстЗапроса);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИтоговыйМассивЗапросов, ТекстыЗапросаРегистров);
Для Каждого ТекстЗапроса Из ИтоговыйМассивЗапросов Цикл
Если Не ЗначениеЗаполнено(ТекстЗапроса) Тогда
Продолжить;
КонецЕсли;
Если Очередь = Неопределено Тогда
УсловиеОтбораУзла = " ТаблицаИзменений.Узел ССЫЛКА ПланОбмена.ОбновлениеИнформационнойБазы ";
Иначе
УсловиеОтбораУзла = " ТаблицаИзменений.Узел В (&Узлы) ";
Если ТипЗнч(Очередь) = Тип("Массив") Тогда
Запрос.УстановитьПараметр("Узлы", Очередь);
Иначе
Запрос.УстановитьПараметр("Узлы", ОчередьСсылкой(Очередь));
КонецЕсли;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеОтбораУзла", УсловиеОтбораУзла);
Если Не ОтборУстановлен Тогда
Запрос.УстановитьПараметр("Отбор", Отбор);
КонецЕсли;
Запрос.Текст = ТекстЗапроса;
УстановитьОтключениеБезопасногоРежима(Истина);
УстановитьПривилегированныйРежим(Истина);
Если Не Запрос.Выполнить().Пустой() Тогда // @skip-check query-in-loop - для избежания слишком тяжелого запроса.
Возврат Истина;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
УстановитьОтключениеБезопасногоРежима(Ложь);
КонецЦикла;
Возврат Ложь;
КонецФункции
// Проверяет, что все данные обработаны.
//
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные,
// которые он будет обрабатывать.
// - Неопределено - проверяется, завершена ли обработка в целом;
// - Массив - проверяется, есть ли данные для обработки в списке очередей.
// ПолноеИмяМетаданныеОбъекта - Строка
// - ОбъектМетаданных - полное имя обрабатываемого объекта или
// его метаданные. Например, "Документ.ПриходныйОрдерНаТовары"
// - Массив - массив полных имен объектов или объектов метаданных,
// в массиве не должно быть независимых регистров сведений.
// Отбор - ЛюбаяСсылка
// - Структура
// - Неопределено
// - Массив - отбор данных для проверки.
// Если передано Неопределено - проверяется по всему типу объекта.
// Если объект - регистр, подчиненный регистратору, то в отборе - ссылка
// на регистратор или массив ссылок.
// Если объект ссылочного типа, то в отборе - или ссылка, или массив ссылок.
// Если объект - независимый регистр сведений, то в отборе - структура со значениями измерений.
// Ключ структуры - имя измерения, значение - значение отбора (можно передать массив значений).
//
// Возвращаемое значение:
// Булево - Истина, если все данные обработаны.
//
Функция ОбработкаДанныхЗавершена(Очередь, ПолноеИмяМетаданныеОбъекта, Отбор = Неопределено) Экспорт
Возврат Не ЕстьДанныеДляОбработки(Очередь, ПолноеИмяМетаданныеОбъекта, Отбор);
КонецФункции
// Проверяет, есть ли заблокированные меньшими очередями обработки данные.
//
// Параметры:
// Очередь - Число
// - Неопределено - очередь, к которой отнесен обработчик и в которой
// зарегистрированы данные, которые он будет обрабатывать.
// ПолноеИмяМетаданныеОбъекта - Строка
// - ОбъектМетаданных - полное имя обрабатываемого объекта или
// его метаданные. Например, "Документ.ПриходныйОрдерНаТовары"
// - Массив - массив полных имен объектов или объектов метаданных,
// в массиве не должно быть независимых регистров сведений.
//
// Возвращаемое значение:
// Булево - Истина, если данный объект заблокирован для обработки меньшими очередями.
//
Функция ЕстьЗаблокированныеПредыдущимиОчередямиДанные(Очередь, ПолноеИмяМетаданныеОбъекта) Экспорт
Возврат ЕстьДанныеДляОбработки(УзлыМеньшейОчереди(Очередь), ПолноеИмяМетаданныеОбъекта);
КонецФункции
// Проверяет, завершилась ли обработка данных обработчиками, отнесенными на более раннюю очередь.
//
// Параметры:
// Очередь - Число - очередь, к которой отнесен обработчик и в которой зарегистрированы данные,
// которые он будет обрабатывать.
// - Неопределено - проверяется, завершена ли обработка в целом;
// - Массив - проверяется, есть ли данные для обработки в списке очередей.
// Данные - ЛюбаяСсылка
// - РегистрСведенийНаборЗаписей, РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей, РегистрРасчетаНаборЗаписей
// - СправочникОбъект, ДокументОбъект, ПланВидовХарактеристикОбъект, БизнесПроцессОбъект, ЗадачаОбъект
// - ДанныеФормыСтруктура - ссылка на объект, сам объект
// или набор записей, который необходимо проверить.
// Если ДополнительныеПараметры.ЭтоДвижения = Истина, то Данные - это регистратор
// указанного в ДополнительныеПараметры регистра.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки.
// МетаданныеИОтбор - см. ОбновлениеИнформационнойБазы.МетаданныеИОтборПоДанным.
//
// Возвращаемое значение:
// Булево - Истина, если переданный объект обновлен на новую версию и его можно изменять.
//
Функция МожноЧитатьИМенять(Очередь, Данные, ДополнительныеПараметры = Неопределено, МетаданныеИОтбор = Неопределено) Экспорт
Если ОтложенноеОбновлениеЗавершено() Тогда
Возврат Истина;
КонецЕсли;
Если МетаданныеИОтбор = Неопределено Тогда
МетаданныеИОтбор = МетаданныеИОтборПоДанным(Данные, ДополнительныеПараметры);
КонецЕсли;
Если МетаданныеИОтбор.ЭтоНовый Тогда
Возврат Истина;
КонецЕсли;
Если Очередь = Неопределено Тогда
Возврат Не ЕстьДанныеДляОбработки(Неопределено, МетаданныеИОтбор.Метаданные, МетаданныеИОтбор.Отбор);
Иначе
Возврат Не ЕстьДанныеДляОбработки(УзлыМеньшейОчереди(Очередь), МетаданныеИОтбор.Метаданные, МетаданныеИОтбор.Отбор);
КонецЕсли;
КонецФункции
// Создает временную таблицу заблокированных данных.
// Имя таблицы: ВТЗаблокированы<ИмяОбъекта>, например ВТЗаблокированоНоменклатура.
// Колонки таблицы:
// для объектов ссылочного типа
// * Ссылка;
// для регистров, подчиненных регистратору
// * Регистратор;
// для регистров с непосредственной записью
// * колонки, соответствующие измерениям регистра.
//
// Параметры:
// Очередь - Число
// - Неопределено - очередь обработки, в которой выполняется текущий обработчик.
// Если передано Неопределено, то проверяется во всех очередях.
// ПолноеИмяОбъекта - Строка - полное имя объекта, для которого выполняется проверка,
// например Справочник.Номенклатура.
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки
//
// Возвращаемое значение:
// Структура:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ПолноеИмяОбъекта, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта); // ОбъектМетаданныхСправочник, ОбъектМетаданныхДокумент
ИмяИзмеренияДляОтбора = ДополнительныеПараметры.ИмяИзмеренияДляОтбора;
ОтложенноеОбновлениеЗавершеноУспешно = ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеЗавершеноУспешно");
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
Если ОтложенноеОбновлениеЗавершеноУспешно Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| &ПустоеЗначение КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ГДЕ
| ЛОЖЬ";
Запрос.УстановитьПараметр("ПустоеЗначение", МетаданныеОбъекта.СтандартныеРеквизиты.Ссылка.Тип.ПривестиЗначение());
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаИзменений.Ссылка КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
|
|ИНДЕКСИРОВАТЬ ПО
| Ссылка";
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеОбъекта)
И МетаданныеОбъекта.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый
И ВРег(ИмяИзмеренияДляОтбора) = ВРег("Регистратор") Тогда
ИменаИзмерений = Новый Массив;
ПсевдонимыИзмерений = Новый Массив;
Если ОтложенноеОбновлениеЗавершеноУспешно Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| &ТекстВыборкиИзмерений
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ГДЕ
| ЛОЖЬ";
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Если Не Измерение.ОсновнойОтбор Тогда
Продолжить;
КонецЕсли;
ИменаИзмерений.Добавить("&ПустоеЗначениеИзмерения" + Измерение.Имя);
ПсевдонимыИзмерений.Добавить(Измерение.Имя);
Запрос.УстановитьПараметр("ПустоеЗначениеИзмерения" + Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЦикла;
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| &ТекстВыборкиИзмерений
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
|ИНДЕКСИРОВАТЬ ПО
| &ИндексируемыеИзмерения";
Для Каждого Измерение Из МетаданныеОбъекта.Измерения Цикл
Если Не Измерение.ОсновнойОтбор Тогда
Продолжить;
КонецЕсли;
ИменаИзмерений.Добавить("ТаблицаИзменений." + Измерение.Имя);
ПсевдонимыИзмерений.Добавить(Измерение.Имя);
КонецЦикла;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИндексируемыеИзмерения", УпорядочиванияДляЗапроса(ПсевдонимыИзмерений));
КонецЕсли;
ПризнакНепериодический = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический;
Если МетаданныеОбъекта.ПериодичностьРегистраСведений <> ПризнакНепериодический
И МетаданныеОбъекта.ОсновнойОтборПоПериоду Тогда
ИменаИзмерений.Добавить("ТаблицаИзменений.Период");
ПсевдонимыИзмерений.Добавить("Период");
КонецЕсли;
Если ИменаИзмерений.Количество() = 0 Тогда
ТекстВыборкиИзмерений = "*";
Иначе
ТекстВыборкиИзмерений = ПоляДляЗапроса(ИменаИзмерений, ПсевдонимыИзмерений);
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТекстВыборкиИзмерений", ТекстВыборкиИзмерений);
ИначеЕсли ОбщегоНазначения.ЭтоРегистр(МетаданныеОбъекта) Тогда
Если ОтложенноеОбновлениеЗавершеноУспешно Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| &ПустоеЗначение КАК Регистратор
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ГДЕ
| ЛОЖЬ";
Запрос.УстановитьПараметр("ПустоеЗначение", МетаданныеОбъекта.СтандартныеРеквизиты.Регистратор.Тип.ПривестиЗначение());
Иначе
ТекстЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТаблицаИзменений.Регистратор КАК Регистратор
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла
|
|ИНДЕКСИРОВАТЬ ПО
| Регистратор";
КонецЕсли;
Если ВРег(ИмяИзмеренияДляОтбора) <> ВРег("Регистратор") Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "Регистратор", ИмяИзмеренияДляОтбора);
КонецЕсли;
Иначе
ТекстИсключения = НСтр("ru = 'Для этого типа метаданных не поддерживается проверка в функции %1.'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ОбновлениеИнформационнойБазы.СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
Если Не ОтложенноеОбновлениеЗавершеноУспешно Тогда
Если Очередь = Неопределено Тогда
УсловиеОтбораУзла = " ТаблицаИзменений.Узел ССЫЛКА ПланОбмена.ОбновлениеИнформационнойБазы ";
Иначе
УсловиеОтбораУзла = " ТаблицаИзменений.Узел В (&Узлы) ";
Запрос.УстановитьПараметр("Узлы", УзлыМеньшейОчереди(Очередь));
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеОтбораУзла", УсловиеОтбораУзла);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаИзменений", ПолноеИмяОбъекта + ".Изменения");
КонецЕсли;
ИмяОбъекта = СтрРазделить(ПолноеИмяОбъекта, ".")[1];
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТЗаблокировано"+ИмяОбъекта;
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяВременнойТаблицы", ИмяВременнойТаблицы);
Запрос.Текст = ТекстЗапроса;
РезультатЗапроса = Запрос.Выполнить();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице,ИмяВременнойТаблицы", Ложь, "");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса.Выгрузить()[0].Количество <> 0;
Возврат Результат;
КонецФункции
// Создает временную таблицу заблокированных ссылок.
// Имя таблицы: ВТЗаблокировано.
// Колонки таблицы:
// * Ссылка.
//
// Параметры:
// Очередь - Число
// - Неопределено - очередь обработки, в которой выполняется
// текущий обработчик. Если передано Неопределено, то проверяется во всех очередях.
// ПолныеИменаОбъектов - Строка
// - Массив - полные имена объектов, для которых выполняется проверка,
// например Справочник.Номенклатура.
// Могут быть переданы объекты ссылочного типа, или регистры, подчиненные регистратору.
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки
//
// Возвращаемое значение:
// Структура:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияСсылок(Очередь, ПолныеИменаОбъектов, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Если ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеЗавершеноУспешно") Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| НЕОПРЕДЕЛЕНО КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ГДЕ
| ЛОЖЬ";
Иначе
Если ТипЗнч(ПолныеИменаОбъектов) = Тип("Строка") Тогда
ПолныеИменаОбъектовМассив = СтрРазделить(ПолныеИменаОбъектов,",",Ложь);
ИначеЕсли ТипЗнч(ПолныеИменаОбъектов) = Тип("Массив") Тогда
ПолныеИменаОбъектовМассив = ПолныеИменаОбъектов;
Иначе
ПолныеИменаОбъектовМассив = Новый Массив;
ПолныеИменаОбъектовМассив.Добавить(ПолныеИменаОбъектов);
КонецЕсли;
МассивТекстовЗапросов = Новый Массив;
ЕстьРегистры = Ложь;
Для Каждого ОбрабатываемыйТип Из ПолныеИменаОбъектовМассив Цикл
Если ТипЗнч(ОбрабатываемыйТип) = Тип("ОбъектМетаданных") Тогда
МетаданныеОбъекта = ОбрабатываемыйТип;
ПолноеИмяОбъекта = ОбрабатываемыйТип.ПолноеИмя();
Иначе
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ОбрабатываемыйТип);
ПолноеИмяОбъекта = ОбрабатываемыйТип;
КонецЕсли;
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
Если МассивТекстовЗапросов.Количество() = 0 Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаИзменений.Ссылка КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицыПервогоЗапроса
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла";
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаИзменений.Ссылка КАК Ссылка
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла";
КонецЕсли;
ИначеЕсли ОбщегоНазначения.ЭтоРегистр(МетаданныеОбъекта) Тогда
Если МассивТекстовЗапросов.Количество() = 0 Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаИзменений.Регистратор КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицыПервогоЗапроса
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла";
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаИзменений.Регистратор КАК Ссылка
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &УсловиеОтбораУзла";
КонецЕсли;
ЕстьРегистры = Истина;
Иначе
ТекстИсключения = НСтр("ru = 'Для типа метаданных ""%1"" не поддерживается проверка в функции %2'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
Строка(МетаданныеОбъекта), "ОбновлениеИнформационнойБазы.СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияСсылок");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаИзменений", ПолноеИмяОбъекта + ".Изменения");
МассивТекстовЗапросов.Добавить(ТекстЗапроса);
КонецЦикла;
Соединитель = "
|
|ОБЪЕДИНИТЬ ВСЕ
|";
ТекстЗапроса = СтрСоединить(МассивТекстовЗапросов, Соединитель);
Если ЕстьРегистры И МассивТекстовЗапросов.Количество() > 1 Тогда
ШаблонЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВложенныйЗапрос.Ссылка КАК Ссылка
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ИЗ
| #ТекстЗапроса КАК ВложенныйЗапрос
|
|ИНДЕКСИРОВАТЬ ПО
| Ссылка";
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "#ТекстЗапроса", "(" + ТекстЗапроса + ")");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПОМЕСТИТЬ #ИмяВременнойТаблицыПервогоЗапроса", "");
Иначе
ТекстЗапроса = ТекстЗапроса + "
|
|ИНДЕКСИРОВАТЬ ПО
| Ссылка";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяВременнойТаблицыПервогоЗапроса", "#ИмяВременнойТаблицы");
КонецЕсли;
Если Очередь = Неопределено Тогда
УсловиеОтбораУзла = " ТаблицаИзменений.Узел ССЫЛКА ПланОбмена.ОбновлениеИнформационнойБазы ";
Иначе
УсловиеОтбораУзла = " ТаблицаИзменений.Узел В (&Узлы) ";
Запрос.УстановитьПараметр("Узлы", УзлыМеньшейОчереди(Очередь));
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеОтбораУзла", УсловиеОтбораУзла);
КонецЕсли;
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТЗаблокировано";
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяВременнойТаблицы", ИмяВременнойТаблицы);
Запрос.Текст = ТекстЗапроса;
РезультатЗапроса = Запрос.Выполнить();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице, ИмяВременнойТаблицы", Ложь, "");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса.Выгрузить()[0].Количество <> 0;
Возврат Результат;
КонецФункции
// Создает временную таблицу измерений регистров, подчиненных регистраторам, по которым еще есть не обработанные регистраторы.
// Алгоритм вычисления:
// - берутся заблокированные регистраторы;
// - по ним соединяется с основной таблицей регистра;
// - из основной таблицы получаются значения изменений;
// - делается группировка.
// Имя таблицы: ВТЗаблокированы<ИмяОбъекта>, например ВТЗаблокированоТоварыНаСкладах.
// Колонки таблицы соответствуют переданным измерениям.
//
// Параметры:
// Очередь - Число
// - Неопределено - очередь обработки, в которой выполняется
// текущий обработчик. Если передано Неопределено,
// то проверяется во всех очередях.
// ПолноеИмяРегистра - Строка - имя регистра, движения по которому нужно переформировать.
// Например, РегистрНакопления.ТоварыНаСкладах
// Измерения - Строка
// - Массив - имена измерений, по которым нужно проверить блокировку,
// перечисленные через запятую, или массив имен.
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер, в котором будет создана временная таблица.
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки
//
// Возвращаемое значение:
// Структура:
// * ЕстьЗаписиВоВременнойТаблице - Булево - в создаваемой таблице есть хотя бы одна запись.
// * ИмяВременнойТаблицы - Строка - имя созданной временной таблицы.
//
Функция СоздатьВременнуюТаблицуЗначенийЗаблокированныхИзмерений(Очередь, ПолноеИмяРегистра, Измерения, МенеджерВременныхТаблиц, ДополнительныеПараметры = Неопределено) Экспорт
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Если ТипЗнч(Измерения) = Тип("Строка") Тогда
ИзмеренияМассив = СтрРазделить(Измерения, ",", Ложь);
Иначе
ИзмеренияМассив = Измерения;
КонецЕсли;
МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяРегистра);
ИменаИзмерений = Новый Массив;
ПсевдонимыИзмерений = Новый Массив;
Если ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеЗавершеноУспешно") Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| &ЗначенияИзмерений
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ГДЕ
| ЛОЖЬ";
Для Каждого ИзмерениеСтр Из ИзмеренияМассив Цикл
Измерение = МетаданныеОбъекта.Измерения.Найти(ИзмерениеСтр);
ИменаИзмерений.Добавить("&ПустоеЗначениеИзмерения" + Измерение.Имя);
ПсевдонимыИзмерений.Добавить(Измерение.Имя);
Запрос.УстановитьПараметр("ПустоеЗначениеИзмерения" + Измерение.Имя, Измерение.Тип.ПривестиЗначение());
КонецЦикла;
Иначе
ТекстЗапроса =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| &ЗначенияИзмерений
|ПОМЕСТИТЬ #ИмяВременнойТаблицы
|ИЗ
| #ТаблицаИзменений КАК ТаблицаИзменений
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ #ТаблицаРегистра КАК ТаблицаРегистра
| ПО ТаблицаИзменений.Регистратор = ТаблицаРегистра.Регистратор
|ГДЕ
| &УсловиеОтбораУзла
|ИНДЕКСИРОВАТЬ ПО
| &ИндексируемыеИзмерения";
Для Каждого Измерение Из ИзмеренияМассив Цикл
ИменаИзмерений.Добавить("ТаблицаРегистра." + Измерение);
ПсевдонимыИзмерений.Добавить(Измерение);
КонецЦикла;
ТекстИндексируемыхИзмерений = УпорядочиванияДляЗапроса(ПсевдонимыИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИндексируемыеИзмерения", ТекстИндексируемыхИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаИзменений", ПолноеИмяРегистра + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаРегистра", ПолноеИмяРегистра);
Если Очередь = Неопределено Тогда
УсловиеОтбораУзла = " ТаблицаИзменений.Узел ССЫЛКА ПланОбмена.ОбновлениеИнформационнойБазы ";
Иначе
УсловиеОтбораУзла = " ТаблицаИзменений.Узел В (&Узлы) ";
Запрос.УстановитьПараметр("Узлы", УзлыМеньшейОчереди(Очередь));
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеОтбораУзла", УсловиеОтбораУзла);
КонецЕсли;
ИмяОбъекта = СтрРазделить(ПолноеИмяРегистра, ".")[1];
Если ПустаяСтрока(ДополнительныеПараметры.ИмяВременнойТаблицы) Тогда
ИмяВременнойТаблицы = "ВТЗаблокировано" + ИмяОбъекта;
Иначе
ИмяВременнойТаблицы = ДополнительныеПараметры.ИмяВременнойТаблицы;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяВременнойТаблицы", ИмяВременнойТаблицы);
ЗначенияИзмерений = ПоляДляЗапроса(ИменаИзмерений, ПсевдонимыИзмерений);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ЗначенияИзмерений", ЗначенияИзмерений);
Запрос.Текст = ТекстЗапроса;
РезультатЗапроса = Запрос.Выполнить();
Результат = Новый Структура("ЕстьЗаписиВоВременнойТаблице,ИмяВременнойТаблицы", Ложь, "");
Результат.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
Результат.ЕстьЗаписиВоВременнойТаблице = РезультатЗапроса.Выгрузить()[0].Количество <> 0;
Возврат Результат;
КонецФункции
// Функция для проверки объектов при открытии форм и перед записью.
// Может использоваться как функция проверки по умолчанию, если
// достаточно логики - заблокированные объекты зарегистрированы на узлах плана обмена ОбновлениеИнформационнойБазы.
//
// Параметры:
// МетаданныеИОтбор - см. ОбновлениеИнформационнойБазы.МетаданныеИОтборПоДанным.
//
// Возвращаемое значение:
// Булево - Истина, если объект обновлен и доступен для изменения.
//
Функция ДанныеОбновленыНаНовуюВерсиюПрограммы(МетаданныеИОтбор) Экспорт
Возврат МожноЧитатьИМенять(Неопределено, МетаданныеИОтбор.Данные,,МетаданныеИОтбор);
КонецФункции
// Выборка данных через ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Возвращаемое значение:
// Строка - константа "ИзмеренияНезависимогоРегистраСведений".
//
Функция СпособВыборкиИзмеренияНезависимогоРегистраСведений() Экспорт
Возврат "ИзмеренияНезависимогоРегистраСведений";
КонецФункции
// Выборка данных через ВыбратьРегистраторыРегистраДляОбработки().
//
// Возвращаемое значение:
// Строка - константа "РегистраторыРегистра".
//
Функция СпособВыборкиРегистраторыРегистра() Экспорт
Возврат "РегистраторыРегистра";
КонецФункции
// Выборка данных через ВыбратьСсылкиДляОбработки().
//
// Возвращаемое значение:
// Строка - константа "Ссылки".
//
Функция СпособВыборкиСсылки() Экспорт
Возврат "Ссылки";
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Прочие процедуры и функции.
// Проверить необходимость обновления информационной базы при смене версии конфигурации.
//
// Возвращаемое значение:
// Булево - Истина, если требуется обновление.
//
Функция НеобходимоОбновлениеИнформационнойБазы() Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебныйПовтИсп.НеобходимоОбновлениеИнформационнойБазы();
КонецФункции
// Возвращает Истина, если в данный момент выполняется обновление ИБ.
//
// Возвращаемое значение:
// Булево - Истина, если обновление выполняется.
//
Функция ВыполняетсяОбновлениеИнформационнойБазы() Экспорт
Если ОбщегоНазначения.РазделениеВключено()
И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Возврат НеобходимоОбновлениеИнформационнойБазы();
КонецЕсли;
Возврат ПараметрыСеанса.ВыполняетсяОбновлениеИБ;
КонецФункции
// Возвращает признак завершения отложенного обновления.
//
// Параметры:
// ИменаПодсистем - Строка - если передано, будет проверяться результат завершения
// обновления для переданной подсистемы, а не для всей конфигурации.
// - Массив - если требуется проверить завершение обновления сразу нескольких
// подсистем.
//
// Возвращаемое значение:
// Булево - Истина, если обновление завершено.
//
Функция ОтложенноеОбновлениеЗавершено(Знач ИменаПодсистем = Неопределено) Экспорт
Если ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеЗавершеноУспешно") Тогда
ЭтоПодчиненныйУзелРИБ = ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ();
Если Не ЭтоПодчиненныйУзелРИБ Тогда
Возврат Истина;
Иначе
Возврат ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно");
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ИменаПодсистем) Тогда
Возврат Ложь;
КонецЕсли;
Если ТипЗнч(ИменаПодсистем) = Тип("Строка") Тогда
ИменаПодсистем = СтрРазделить(ИменаПодсистем, ",");
КонецЕсли;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Подсистемы", ИменаПодсистем);
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
Запрос.Текст =
"ВЫБРАТЬ
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|ИЗ
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|ГДЕ
| ОбработчикиОбновления.ИмяБиблиотеки В (&Подсистемы)
| И ОбработчикиОбновления.Статус <> &Статус";
Возврат Запрос.Выполнить().Выгрузить().Количество() = 0;
КонецФункции
// Возвращает Истина, если вызов функции выполняется из обработчика обновления.
// Для любого вида обработчика обновления - монопольного, оперативного и отложенного.
//
// Параметры:
// РежимВыполненияОбработчика - Строка - Отложенно, Оперативно, Монопольно или комбинация данных
// вариантов через запятую. Если указано, то проверяется только
// вызов из обработчиков обновления с данным режимом выполнения.
//
// Возвращаемое значение:
// Булево - Истина, если вызов функции выполняется из обработчика обновления.
//
Функция ЭтоВызовИзОбработчикаОбновления(РежимВыполненияОбработчика = "") Экспорт
РежимВыполнения = ПараметрыСеанса.ПараметрыОбработчикаОбновления.РежимВыполнения;
Если Не ЗначениеЗаполнено(РежимВыполнения) Тогда
Возврат Ложь;
КонецЕсли;
Если Не ЗначениеЗаполнено(РежимВыполненияОбработчика) Тогда
Возврат Истина;
КонецЕсли;
Возврат (СтрНайти(РежимВыполненияОбработчика, РежимВыполнения) > 0);
КонецФункции
// Возвращает пустую таблицу обработчиков обновления и первоначального заполнения ИБ.
//
// Возвращаемое значение:
// ТаблицаЗначений - таблица с колонками:
// 1) Для всех типов обработчиков обновления:
//
// * НачальноеЗаполнение - Булево - если Истина, то обработчик должен срабатывать при запуске на "пустой" базе.
// * Версия - Строка - например, "2.1.3.39". Номер версии конфигурации, при переходе
// на которую должна быть выполнена процедура-обработчик обновления.
// Если указана пустая строка, то это обработчик только для начального заполнения
// (должно быть указано свойство НачальноеЗаполнение).
// * Процедура - Строка - полное имя процедуры-обработчика обновления/начального заполнения.
// Например, "ОбновлениеИнформационнойБазыУПП.ЗаполнитьНовыйРеквизит"
// Обязательно должна быть экспортной.
// * РежимВыполнения - Строка - режим выполнения обработчика обновления. Допустимые значения:
// Монопольно, Отложенно, Оперативно. Если значение не заполнено, обработчик
// считается монопольным.
//
// 2) Для обработчиков обновления в модели сервиса:
//
// * ОбщиеДанные - Булево - если Истина, то обработчик должен срабатывать до
// выполнения любых обработчиков, использующих разделенные данные.
// Допустимо указывать только для обработчиков с режимом выполнения Монопольно и Оперативно.
// Если указать значение Истина для обработчика с режимом
// выполнения Отложенно, будет выдано исключение.
// * УправлениеОбработчиками - Булево - если Истина, то обработчик должен иметь параметр типа Структура, в котором
// есть свойство РазделенныеОбработчики - таблица значений со структурой,
// возвращаемой этой функцией.
// При этом колонка Версия игнорируется. В случае необходимости выполнения
// разделенного обработчика в данную таблицу необходимо добавить строку с
// описанием процедуры обработчика.
// Имеет смысл только для обязательных (Версия = *) обработчиков обновления
// с установленным флагом ОбщиеДанные.
//
// 3) Для отложенных обработчиков обновления:
//
// * Комментарий - Строка - описание действий, выполняемых обработчиком обновления.
// * Идентификатор - УникальныйИдентификатор - необходимо заполнять для обработчиков отложенного обновления,
// для остальных заполнение не требуется. Требуется для идентификации
// обработчика в случае его переименования.
//
// * БлокируемыеОбъекты - Строка - необходимо заполнять для обработчиков отложенного обновления,
// для остальных заполнение не требуется. Полные имена объектов через запятую,
// которые следует блокировать от изменения до завершения процедуры обработки данных.
// Если заполнено, то также требуется заполнить и свойство ПроцедураПроверки.
// * НовыеОбъекты - Строка - необходимо заполнять для обработчиков отложенного обновления,
// для остальных заполнение не требуется. Полные имена объектов через запятую,
// которые создаются при работе обработчика обновления.
// * ПроцедураПроверки - Строка - необходимо заполнять для обработчиков отложенного обновления,
// для остальных заполнение не требуется. Имя функции, которая для переданного объекта
// определяет, завершена ли для него процедура обработки данных.
// Если переданный объект обработан, то следует вернуть значение Истина.
// Вызывается из процедуры ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан.
// Параметры, передаваемые в функцию:
// Параметры - см. ОбновлениеИнформационнойБазы.МетаданныеИОтборПоДанным.
//
// 4) Для обработчиков обновления в библиотеках (конфигурации) с параллельным режимом выполнения отложенных обработчиков:
//
// * ПроцедураЗаполненияДанныхОбновления - Строка - указывается процедура, которая регистрирует данные,
// подлежащие обновлению данным обработчиком.
// * ЗапускатьТолькоВГлавномУзле - Булево - только для обработчиков отложенного обновления с режимом выполнения Параллельно.
// Указать Истина, если обработчик обновления должен выполняться только в главном
// узле РИБ.
// * ЗапускатьИВПодчиненномУзлеРИБСФильтрами - Булево - только для обработчиков отложенного обновления с режимом
// выполнения Параллельно.
// Указать Истина, если обработчик обновления должен также выполняться в
// подчиненном узле РИБ с фильтрами.
// * ЧитаемыеОбъекты - Строка - объекты, которые обработчик обновления будет читать при обработке данных.
// * ИзменяемыеОбъекты - Строка - объекты, которые обработчик обновления будет изменять при обработке данных.
// * ПриоритетыВыполнения - ТаблицаЗначений - таблица приоритетов выполнения между отложенными обработчиками,
// изменяющими или читающими одни и те же данные. Подробнее см. в комментарии
// к функции ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика.
// * Многопоточный - Булево - Истина, если обработчик адаптирован для обработки данных в несколько потоков.
// * Порядок - ПеречислениеСсылка.ПорядокОбработчиковОбновления
//
// 5) Для оперативных и монопольных обработчиков начального заполнения:
// * НеВыполнятьПриПереходеСДругойПрограммы - Булево - при переходе с другой программы обработчики начального
// заполнения новых подсистем выполняются автоматически. Если установить
// Истина, такой обработчик не будет выполнен.
//
// 6) Для внутреннего использования:
//
// * ВыполнятьВГруппеОбязательных - Булево - следует указывать, если обработчик требуется
// выполнять в одной группе с обработчиками на версии "*".
// При этом возможно менять порядок выполнения обработчика
// относительно других путем изменения приоритета.
// * Приоритет - Число - для внутреннего использования.
//
// 7) Устарели, используются для обратной совместимости (для новых обработчиков не указывать):
//
// * МонопольныйРежим - Неопределено
// - Булево - если указано Неопределено, то обработчик
// должен безусловно выполняться в монопольном режиме.
// Для обработчиков перехода на конкретную версию (версия <> *):
// Ложь - обработчик не требует монопольного режима для выполнения.
// Истина - обработчик требует монопольного режима для выполнения.
// Для обязательных обработчиков обновления (Версия = "*"):
// Ложь - обработчик не требует монопольного режима.
// Истина - обработчик может требовать монопольного режима для выполнения.
// В такие обработчики передается параметр типа структура
// со свойством МонопольныйРежим (типа Булево).
// При запуске обработчика в монопольном режиме передается
// значение Истина. В этом случае обработчик должен выполнить
// требуемые действия по обновлению. Изменение параметра
// в теле обработчика игнорируется.
// При запуске обработчика в немонопольном режиме передается
// значение Ложь. В этом случае обработчик не должен вносить никакие
// изменения в ИБ.
// Если в результате анализа выясняется, что обработчику требуется
// изменить данные ИБ, следует установить значение параметра в Истина
// и прекратить выполнение обработчика.
// В этом случае оперативное (немонопольное) обновление ИБ будет
// отменено и будет выдана ошибка с требованием выполнить обновление в
// монопольном режиме.
//
Функция НоваяТаблицаОбработчиковОбновления() Экспорт
Обработчики = Новый ТаблицаЗначений;
// Общие свойства.
Обработчики.Колонки.Добавить("НачальноеЗаполнение", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("Версия", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("Процедура", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("РежимВыполнения", Новый ОписаниеТипов("Строка"));
// Для библиотек.
Обработчики.Колонки.Добавить("ВыполнятьВГруппеОбязательных", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(2)));
// Для модели сервиса.
Обработчики.Колонки.Добавить("ОбщиеДанные", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("УправлениеОбработчиками", Новый ОписаниеТипов("Булево"));
// Для отложенных обработчиков обновления.
Обработчики.Колонки.Добавить("Комментарий", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("УникальныйИдентификатор"));
Обработчики.Колонки.Добавить("ПроцедураПроверки", Новый ОписаниеТипов("Строка"));
Обработчики.Колонки.Добавить("БлокируемыеОбъекты", Новый ОписаниеТипов("Строка"));
Обработчики.Колонки.Добавить("НовыеОбъекты", Новый ОписаниеТипов("Строка"));
// Для параллельного режима отложенного обновления.
Обработчики.Колонки.Добавить("ПроцедураЗаполненияДанныхОбновления", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("ОчередьОтложеннойОбработки", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(4)));
Обработчики.Колонки.Добавить("ЗапускатьТолькоВГлавномУзле", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("ЗапускатьИВПодчиненномУзлеРИБСФильтрами", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("ЧитаемыеОбъекты", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("ИзменяемыеОбъекты", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Обработчики.Колонки.Добавить("ПриоритетыВыполнения");
Обработчики.Колонки.Добавить("Многопоточный", Новый ОписаниеТипов("Булево"));
Обработчики.Колонки.Добавить("Порядок", Новый ОписаниеТипов("ПеречислениеСсылка.ПорядокОбработчиковОбновления"));
// Для обработчиков начального заполнения.
Обработчики.Колонки.Добавить("НеВыполнятьПриПереходеСДругойПрограммы", Новый ОписаниеТипов("Булево"));
// Устарело. Обратная совместимость с редакцией "2.2".
Обработчики.Колонки.Добавить("Опциональный");
Обработчики.Колонки.Добавить("МонопольныйРежим");
Возврат Обработчики;
КонецФункции
// Возвращает пустую таблицу приоритетов выполнения между отложенными обработчиками,
// изменяющими или читающими одни и те же данные. Для использования в описании обработчиков обновления.
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * Порядок - Строка - порядок выполнения обработчика относительно указанной процедуры.
// Допустимые варианты: "До", "После", "Любой".
// * Идентификатор - УникальныйИдентификатор - идентификатор процедуры, с которой настраивается взаимосвязь.
// * Процедура - Строка - полное имя процедуры, относительно которой выполняется обработчик.
//
// Пример:
// Приоритет = ПриоритетыВыполненияОбработчика().Добавить();
// Приоритет.Порядок = "До"; // порядок выполнения обработчика относительно процедуры ниже.
// Приоритет.Процедура = "Документ.ЗаказПокупателя.ОбновитьДанныеДляПереходаНаНовуюВерсию";
//
Функция ПриоритетыВыполненияОбработчика() Экспорт
Приоритеты = Новый ТаблицаЗначений;
Приоритеты.Колонки.Добавить("Порядок", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Приоритеты.Колонки.Добавить("Идентификатор");
Приоритеты.Колонки.Добавить("Процедура", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0)));
Возврат Приоритеты;
КонецФункции
// Выполнить обработчики обновления из списка ОбработчикиОбновления
// для библиотеки ИдентификаторБиблиотеки до версии ВерсияМетаданныхИБ.
//
// Параметры:
// ИдентификаторБиблиотеки - Строка - имя конфигурации или идентификатор библиотеки.
// ВерсияМетаданныхИБ - Строка - версия метаданных, до которой необходимо выполнить обновление.
// ОбработчикиОбновления - Соответствие - список обработчиков обновления.
// ХодВыполненияОбработчиков - Структура:
// * ВсегоОбработчиков - Строка - общее количество выполняемых обработчиков.
// * ВыполненоОбработчиков - Булево - количество выполненных обработчиков.
// ОперативноеОбновление - Булево - Истина, если обновление оперативное.
//
// Возвращаемое значение:
// ДеревоЗначений - выполненные обработчики обновления.
//
Функция ВыполнитьИтерациюОбновления(Знач ИдентификаторБиблиотеки, Знач ВерсияМетаданныхИБ,
Знач ОбработчикиОбновления, Знач ХодВыполненияОбработчиков, Знач ОперативноеОбновление = Ложь) Экспорт
ИтерацияОбновления = ОбновлениеИнформационнойБазыСлужебный.ИтерацияОбновления(ИдентификаторБиблиотеки,
ВерсияМетаданныхИБ, ОбработчикиОбновления);
Параметры = Новый Структура;
Параметры.Вставить("ХодВыполненияОбработчиков", ХодВыполненияОбработчиков);
Параметры.Вставить("ОперативноеОбновление", ОперативноеОбновление);
Параметры.Вставить("ВФоне", Ложь);
Возврат ОбновлениеИнформационнойБазыСлужебный.ВыполнитьИтерациюОбновления(ИтерацияОбновления, Параметры);
КонецФункции
// Выполнить неинтерактивное обновление данных ИБ.
// Для вызова через внешнее соединение.
// При вызове метода с подключенными расширениями, модифицирующими роли конфигурации, будет вызвано исключение.
// Важно: Перед вызовом метода необходимо запустить удаление устаревших патчей,
// см. функцию ОбновлениеКонфигурации.ИсправленияИзменены().
//
// Для использования в других библиотеках и конфигурациях.
//
// Параметры:
// ВыполнятьОтложенныеОбработчики - Булево - если Истина, отложенное обновление будет выполнено
// в основном цикле обновления. Только для клиент-серверного режима работы.
//
// Возвращаемое значение:
// Строка - признак выполнения обработчиков обновления:
// "Успешно", "НеТребуется", "ОшибкаУстановкиМонопольногоРежима".
//
Функция ВыполнитьОбновлениеИнформационнойБазы(ВыполнятьОтложенныеОбработчики = Ложь) Экспорт
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
МодульТехнологияСервиса = ОбщегоНазначения.ОбщийМодуль("ТехнологияСервиса");
ВерсияБиблиотекиБТС = МодульТехнологияСервиса.ВерсияБиблиотеки();
ЕстьПередОбновлениемИнформационнойБазы = ОбновлениеИнформационнойБазыСлужебный.ВесВерсии("2.0.0.0") < ОбновлениеИнформационнойБазыСлужебный.ВесВерсии(ВерсияБиблиотекиБТС);
Если ЕстьПередОбновлениемИнформационнойБазы Тогда
Успешно = МодульТехнологияСервиса.ПередОбновлениемИнформационнойБазы(ВыполнятьОтложенныеОбработчики);
Если Успешно Тогда
Возврат "Успешно";
КонецЕсли;
КонецЕсли;
КонецЕсли;
ДатаНачала = ТекущаяДатаСеанса();
Результат = ОбновлениеИнформационнойБазыСлужебныйВызовСервера.ВыполнитьОбновлениеИнформационнойБазы(,,
ВыполнятьОтложенныеОбработчики);
ДатаОкончания = ТекущаяДатаСеанса();
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьВремяВыполненияОбновления(ДатаНачала, ДатаОкончания);
Возврат Результат;
КонецФункции
// Возвращает таблицу с версиями подсистем конфигурации.
// Для пакетной выгрузки/загрузки сведений о версиях подсистем.
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * ИмяПодсистемы - Строка - имя подсистемы.
// * Версия - Строка - версия подсистемы.
//
Функция ВерсииПодсистем() Экспорт
СтандартнаяОбработка = Истина;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
ВерсииПодсистемОбластей = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ВерсииПодсистем(СтандартнаяОбработка);
Если Не СтандартнаяОбработка Тогда
Возврат ВерсииПодсистемОбластей;
КонецЕсли;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВерсииПодсистем.ИмяПодсистемы КАК ИмяПодсистемы,
| ВерсииПодсистем.Версия КАК Версия
|ИЗ
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
// Устанавливает версии всех подсистем.
// Для пакетной выгрузки/загрузки сведений о версиях подсистем.
//
// Параметры:
// ВерсииПодсистем - ТаблицаЗначений:
// * ИмяПодсистемы - Строка - имя подсистемы.
// * Версия - Строка - версия подсистемы.
//
Процедура УстановитьВерсииПодсистем(ВерсииПодсистем) Экспорт
СтандартнаяОбработка = Истина;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриУстановкеВерсийПодсистем(ВерсииПодсистем, СтандартнаяОбработка);
КонецЕсли;
Если Не СтандартнаяОбработка Тогда
Возврат;
КонецЕсли;
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей();
Для Каждого Версия Из ВерсииПодсистем Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ИмяПодсистемы = Версия.ИмяПодсистемы;
НоваяЗапись.Версия = Версия.Версия;
НоваяЗапись.ЭтоОсновнаяКонфигурация = (Версия.ИмяПодсистемы = Метаданные.Имя);
КонецЦикла;
НаборЗаписей.Записать();
КонецПроцедуры
// Получает версию конфигурации или родительской конфигурации (библиотеки),
// которая хранится в информационной базе.
//
// Параметры:
// ИдентификаторБиблиотеки - Строка - имя конфигурации или идентификатор библиотеки.
//
// Возвращаемое значение:
// Строка - версия.
//
// Пример:
// ВерсияКонфигурацииИБ = ОбновлениеИнформационнойБазы.ВерсияИБ(Метаданные.Имя);
//
Функция ВерсияИБ(Знач ИдентификаторБиблиотеки) Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебный.ВерсияИБ(ИдентификаторБиблиотеки);
КонецФункции
// Записывает в информационную базу версию конфигурации или родительской конфигурации (библиотеки).
//
// Параметры:
// ИдентификаторБиблиотеки - Строка - имя конфигурации или родительской конфигурации (библиотеки).
// НомерВерсии - Строка - номер версии.
// ЭтоОсновнаяКонфигурация - Булево - признак, что ИдентификаторБиблиотеки соответствует имени конфигурации.
//
Процедура УстановитьВерсиюИБ(Знач ИдентификаторБиблиотеки, Знач НомерВерсии, Знач ЭтоОсновнаяКонфигурация) Экспорт
ОбновлениеИнформационнойБазыСлужебный.УстановитьВерсиюИБ(ИдентификаторБиблиотеки, НомерВерсии, ЭтоОсновнаяКонфигурация);
КонецПроцедуры
// Выполняет регистрацию новой подсистемы в регистре сведений ВерсииПодсистем.
// Необходима, например, в тех случаях, когда новая подсистема создается на
// основе уже существующих метаданных и не требуется выполнять обработчики начального заполнения.
// Если подсистема уже зарегистрирована, то повторная регистрация не выполняется.
// Вызывать данный метод следует из процедуры ПередОбновлениемИнформационнойБазы общего
// модуля ОбновлениеИнформационнойБазыПереопределяемый.
//
// Параметры:
// ИмяПодсистемы - Строка - имя подсистемы в том виде, в котором оно задано в общем модуле
// ОбновлениеИнформационнойБазыХХХ.
// Например - "СтандартныеПодсистемы".
// НомерВерсии - Строка - полный номер версии, на которую необходимо зарегистрировать подсистему.
// Если не указан, то регистрируется на версию "0.0.0.1". Следует указывать,
// если нужно, чтобы выполнились не все обработчики, а только последние.
//
Процедура ЗарегистрироватьНовуюПодсистему(ИмяПодсистемы, НомерВерсии = "") Экспорт
СтандартнаяОбработка = Истина;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗарегистрироватьНовуюПодсистему(ИмяПодсистемы, НомерВерсии, СтандартнаяОбработка);
КонецЕсли;
Если Не СтандартнаяОбработка Тогда
Возврат;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВерсииПодсистем.ИмяПодсистемы КАК ИмяПодсистемы
|ИЗ
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем";
ПодсистемыКонфигурации = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ИмяПодсистемы");
Если ПодсистемыКонфигурации.Количество() > 0 Тогда
// Это не первый запуск программы
Если ПодсистемыКонфигурации.Найти(ИмяПодсистемы) = Неопределено Тогда
Запись = РегистрыСведений.ВерсииПодсистем.СоздатьМенеджерЗаписи();
Запись.ИмяПодсистемы = ИмяПодсистемы;
Запись.Версия = ?(НомерВерсии = "", "0.0.0.1", НомерВерсии);
Запись.Записать();
КонецЕсли;
КонецЕсли;
Сведения = ОбновлениеИнформационнойБазыСлужебный.СведенияОбОбновленииИнформационнойБазы();
ИндексЭлемента = Сведения.НовыеПодсистемы.Найти(ИмяПодсистемы);
Если ИндексЭлемента <> Неопределено Тогда
Сведения.НовыеПодсистемы.Удалить(ИндексЭлемента);
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьСведенияОбОбновленииИнформационнойБазы(Сведения);
КонецЕсли;
КонецПроцедуры
// Возвращает номер очереди отложенного обработчика обновления по его полному
// имени или уникальному идентификатору.
//
// Параметры:
// ИмяИлиИдентификатор - Строка
// - УникальныйИдентификатор - полное имя отложенного обработчика
// или его идентификатор. Подробнее см. НоваяТаблицаОбработчиковОбновления,
// описание свойств Процедура и Идентификатор.
//
// Возвращаемое значение:
// Число, Неопределено - номер очереди переданного обработчика, если
// обработчик не найден - будет возвращено Неопределено.
//
Функция ОчередьОтложенногоОбработчикаОбновления(ИмяИлиИдентификатор) Экспорт
Результат = ОбновлениеИнформационнойБазыСлужебныйПовтИсп.ОчередьОтложенногоОбработчикаОбновления();
Если ТипЗнч(ИмяИлиИдентификатор) = Тип("УникальныйИдентификатор") Тогда
ОчередьПоИдентификатору = Результат["ПоИдентификатору"];
Возврат ОчередьПоИдентификатору[ИмяИлиИдентификатор];
Иначе
ОчередьПоИмени = Результат["ПоИмени"];
Возврат ОчередьПоИмени[ИмяИлиИдентификатор];
КонецЕсли;
КонецФункции
// Максимальное количество записей в выборке данных для обновления.
//
// Возвращаемое значение:
// Число - константа 10000.
//
Функция МаксимальноеКоличествоЗаписейВВыборке() Экспорт
Возврат 10000;
КонецФункции
// Возвращает таблицу с данными, которые нужно обновить.
// Используется в многопоточных обработчиках обновления.
//
// Параметры:
// Параметры - Структура - тот параметр, который передается в обработчик обновления.
//
// Возвращаемое значение:
// ТаблицаЗначений - для ссылочного объекта с колонками:
// * Ссылка - ЛюбаяСсылка - ссылка на обновляемый объект.
// * Дата - Дата - колонка присутствует только для документов.
//
// ТаблицаЗначений - для регистра состав колонок зависит от состава измерений
// обновляемого объекта.
//
Функция ДанныеДляОбновленияВМногопоточномОбработчике(Параметры) Экспорт
НаборДанных = Параметры.ОбновляемыеДанные.НаборДанных;
Если НаборДанных.Количество() > 0 Тогда
Возврат НаборДанных[0].Данные;
Иначе
Возврат Новый ТаблицаЗначений;
КонецЕсли;
КонецФункции
// Возвращает текущее значение приоритета отложенной обработки данных.
//
// Возвращаемое значение:
// Строка - возможные значения - "ОбработкаДанных" и "РаботаПользователей".
//
Функция ПриоритетОтложеннойОбработки() Экспорт
СведенияОбОбновлении = ОбновлениеИнформационнойБазыСлужебный.СведенияОбОбновленииИнформационнойБазы();
Если СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Свойство("ФорсироватьОбновление") Тогда
Возврат "ОбработкаДанных";
Иначе
Возврат "РаботаПользователей";
КонецЕсли;
КонецФункции
// Позволяет изменить приоритет отложенной обработки данных.
//
// Параметры:
// Приоритет - Строка - значение приоритета. Допустимые значения - "ОбработкаДанных" или "РаботаПользователей".
//
Процедура УстановитьПриоритетОтложеннойОбработки(Приоритет) Экспорт
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
Блокировка.Добавить("Константа.СведенияОбОбновленииИБ");
Блокировка.Заблокировать();
СведенияОбОбновлении = ОбновлениеИнформационнойБазыСлужебный.СведенияОбОбновленииИнформационнойБазы();
Если Приоритет = "ОбработкаДанных" Тогда
СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Вставить("ФорсироватьОбновление");
Иначе
СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Удалить("ФорсироватьОбновление");
КонецЕсли;
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Возвращает количество потоков обновления информационной базы.
//
// Если количество указано в параметре запуска "ЧислоПотоковОбновления", то возвращается оно.
// Иначе, если значение константы КоличествоПотоковОбновленияИнформационнойБазы установлено, то возвращается оно.
// Иначе возвращается значение по умолчанию, см. КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию.
//
// Возвращаемое значение:
// Число - количество потоков.
//
Функция КоличествоПотоковОбновления() Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебный.КоличествоПотоковОбновленияИнформационнойБазы();
КонецФункции
// Позволяет установить количество потоков отложенной обработки данных.
//
// Параметры:
// Количество - Число - число потоков.
//
Процедура УстановитьКоличествоПотоковОбновления(Количество) Экспорт
Константы.КоличествоПотоковОбновленияИнформационнойБазы.Установить(Количество);
КонецПроцедуры
// Возвращает признак разрешения использования многопоточного обновления.
// Многопоточное обновление можно включить в ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек().
//
// Возвращаемое значение:
// Булево - если Истина, многопоточное обновление разрешено. По умолчанию - Ложь (для обратной совместимости).
//
Функция РазрешеноМногопоточноеОбновление() Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебный.РазрешеноМногопоточноеОбновление();
КонецФункции
// Возвращает прогресс обновления областей данных.
//
// Параметры:
// РежимОбновления - Строка - определяет, по какому этапу обновления необходимо получить данные.
// Доступные значения: "Оперативное", "Отложенное".
//
// Возвращаемое значение:
// Структура:
// * Обновлено - Число - количество областей, этап обновления которых завершен.
// * Выполняется - Число - количество областей, по которым обновление выполняется.
// * Ожидают - Число - количество областей, ожидающих начало этапа обновления.
// * Проблемы - Число - количество областей, в процессе обновления которых произошли ошибки.
// * ОбластиСПроблемами - Массив из Число - номера областей, в процессе обновления которых произошли ошибки.
// * ОбластиВыполняется - Массив из Число - номера областей, по которым обновление выполняется.
// * ОбластиОжидает - Массив из Число - номера областей, ожидающих начало этапа обновления.
// * ОбластиОбновлено - Массив из Число - номера областей, этап обновления которых завершен.
//
Функция ПрогрессОбновленияОбластейДанных(РежимОбновления) Экспорт
Если Не ОбщегоНазначения.РазделениеВключено()
Или Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность")
Или Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
Возврат Неопределено;
КонецЕсли;
РежимОбновленияОперативное = "Оперативное";
РежимОбновленияОтложенное = "Отложенное";
Если РежимОбновления = РежимОбновленияОперативное Тогда
РежимыВыполнения = Новый Массив;
РежимыВыполнения.Добавить(Перечисления.РежимыВыполненияОбработчиков.Оперативно);
РежимыВыполнения.Добавить(Перечисления.РежимыВыполненияОбработчиков.Монопольно);
ИначеЕсли РежимОбновления = РежимОбновленияОтложенное Тогда
РежимыВыполнения = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(
Перечисления.РежимыВыполненияОбработчиков.Отложенно);
Иначе
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Некорректное значение параметра ""%1"".
|Доступные значения: ""%2"", ""%3""'"), "РежимОбновления", РежимОбновленияОперативное, РежимОбновленияОтложенное);
КонецЕсли;
ПорядокСостоянияОбновлено = 4;
ПорядокСостоянияОжидает = 3;
ПорядокСостоянияВыполняется = 2;
ПорядокСостоянияОшибка = 1;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("РежимыВыполнения", РежимыВыполнения);
Запрос.УстановитьПараметр("РежимОбновления", РежимОбновления);
Запрос.УстановитьПараметр("РежимОбновленияОперативное", РежимОбновленияОперативное);
Запрос.УстановитьПараметр("РежимОбновленияОтложенное", РежимОбновленияОтложенное);
Запрос.УстановитьПараметр("ПорядокСостоянияОбновлено", ПорядокСостоянияОбновлено);
Запрос.УстановитьПараметр("ПорядокСостоянияВыполняется", ПорядокСостоянияВыполняется);
Запрос.УстановитьПараметр("ПорядокСостоянияОжидает", ПорядокСостоянияОжидает);
Запрос.УстановитьПараметр("ПорядокСостоянияОшибка", ПорядокСостоянияОшибка);
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
ОбластиОбновленныеНаВерсию = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ОбластиОбновленныеНаВерсию(Метаданные.Имя, Метаданные.Версия);
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
Запрос.УстановитьПараметр("ИспользуемыеОбласти", МодульРаботаВМоделиСервиса.ИспользуемыеОбластиДанных().Выгрузить());
Запрос.УстановитьПараметр("ОбновленныеОбласти", ОбластиОбновленныеНаВерсию);
Запрос.Текст =
"ВЫБРАТЬ
| ИспользуемыеОбласти.ОбластьДанных КАК ОбластьДанных
|ПОМЕСТИТЬ ИспользуемыеОбласти
|ИЗ
| &ИспользуемыеОбласти КАК ИспользуемыеОбласти
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ОбновленныеОбласти.ОбластьДанныхВспомогательныеДанные КАК ОбластьДанныхВспомогательныеДанные,
| ОбновленныеОбласти.ВыполненаРегистрацияОтложенныхОбработчиков КАК ВыполненаРегистрацияОтложенныхОбработчиков
|ПОМЕСТИТЬ ОбновленныеОбласти
|ИЗ
| &ОбновленныеОбласти КАК ОбновленныеОбласти
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ИспользуемыеОбласти.ОбластьДанных КАК ОбластьДанных,
| НЕ ОбновленныеОбласти.ОбластьДанныхВспомогательныеДанные ЕСТЬ NULL КАК ОперативноеОбновлениеЗавершено,
| НЕ ОбновленныеОбласти.ОбластьДанныхВспомогательныеДанные ЕСТЬ NULL
| И НЕ ОбновленныеОбласти.ВыполненаРегистрацияОтложенныхОбработчиков КАК ВыполняетсяРегистрацияОтложенныхОбработчиков
|ПОМЕСТИТЬ ОбластиДанных
|ИЗ
| ИспользуемыеОбласти КАК ИспользуемыеОбласти
| ЛЕВОЕ СОЕДИНЕНИЕ ОбновленныеОбласти КАК ОбновленныеОбласти
| ПО (ОбновленныеОбласти.ОбластьДанныхВспомогательныеДанные = ИспользуемыеОбласти.ОбластьДанных)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ОбластиДанных.ОбластьДанных КАК ОбластьДанных,
| МИНИМУМ(ВЫБОР
| КОГДА &РежимОбновления = &РежимОбновленияОперативное
| И ОбластиДанных.ОперативноеОбновлениеЗавершено
| ТОГДА ВЫБОР
| КОГДА ОбластиДанных.ВыполняетсяРегистрацияОтложенныхОбработчиков
| ТОГДА &ПорядокСостоянияВыполняется
| ИНАЧЕ &ПорядокСостоянияОбновлено
| КОНЕЦ
| КОГДА &РежимОбновления = &РежимОбновленияОтложенное
| И НЕ ОбластиДанных.ОперативноеОбновлениеЗавершено
| ТОГДА &ПорядокСостоянияОжидает
| КОГДА &РежимОбновления = &РежимОбновленияОтложенное
| И ЕСТЬNULL(ОбработчикиОбновления.Статус, ЗНАЧЕНИЕ(Перечисление.СтатусыОбработчиковОбновления.Выполнен)) = ЗНАЧЕНИЕ(Перечисление.СтатусыОбработчиковОбновления.Выполнен)
| ТОГДА &ПорядокСостоянияОбновлено
| КОГДА ОбработчикиОбновления.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыОбработчиковОбновления.Выполняется)
| ТОГДА &ПорядокСостоянияВыполняется
| КОГДА ОбработчикиОбновления.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыОбработчиковОбновления.Ошибка)
| ТОГДА &ПорядокСостоянияОшибка
| ИНАЧЕ &ПорядокСостоянияОжидает
| КОНЕЦ) КАК ПорядокСостояния
|ПОМЕСТИТЬ СтатистикаОбновления
|ИЗ
| ОбластиДанных КАК ОбластиДанных
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
| ПО (ОбработчикиОбновления.ОбластьДанныхВспомогательныеДанные = ОбластиДанных.ОбластьДанных)
| И (ОбработчикиОбновления.РежимВыполнения В (&РежимыВыполнения))
|
|СГРУППИРОВАТЬ ПО
| ОбластиДанных.ОбластьДанных
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| СтатистикаОбновления.ПорядокСостояния КАК ПорядокСостояния,
| СтатистикаОбновления.ОбластьДанных КАК ОбластьДанных
|ИЗ
| СтатистикаОбновления КАК СтатистикаОбновления
|
|УПОРЯДОЧИТЬ ПО
| ОбластьДанных
|ИТОГИ
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ОбластьДанных)
|ПО
| ПорядокСостояния";
ПрогрессОбновления = ОбновлениеИнформационнойБазыСлужебный.НовыйПрогрессОбновленияОбластейДанных();
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат ПрогрессОбновления;
КонецЕсли;
ВыборкаПорядокСостояния = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПорядокСостояния.Следующий() Цикл
Если ВыборкаПорядокСостояния.ПорядокСостояния = ПорядокСостоянияОбновлено Тогда
ПрогрессОбновления.Обновлено = ВыборкаПорядокСостояния.ОбластьДанных;
Расшифровка = ПрогрессОбновления.ОбластиОбновлено;
ИначеЕсли ВыборкаПорядокСостояния.ПорядокСостояния = ПорядокСостоянияВыполняется Тогда
ПрогрессОбновления.Выполняется = ВыборкаПорядокСостояния.ОбластьДанных;
Расшифровка = ПрогрессОбновления.ОбластиВыполняется;
ИначеЕсли ВыборкаПорядокСостояния.ПорядокСостояния = ПорядокСостоянияОшибка Тогда
ПрогрессОбновления.Проблемы = ВыборкаПорядокСостояния.ОбластьДанных;
Расшифровка = ПрогрессОбновления.ОбластиСПроблемами;
Иначе
ПрогрессОбновления.Ожидают = ВыборкаПорядокСостояния.ОбластьДанных;
Расшифровка = ПрогрессОбновления.ОбластиОжидает;
КонецЕсли;
ВыборкаОбласти = ВыборкаПорядокСостояния.Выбрать();
Пока ВыборкаОбласти.Следующий() Цикл
Расшифровка.Добавить(ВыборкаОбласти.ОбластьДанных);
КонецЦикла;
КонецЦикла;
Возврат ПрогрессОбновления;
КонецФункции
// Возвращает таблицу обработчиков обновления по указанному отбору.
// В режиме сервиса, если не задан отбор по областям данных,
// возвращаются все обработчики - разделенные и неразделенные.
//
// Параметры:
// Отбор - Структура:
// * РежимыВыполнения - Массив из Строка - доступные значения соответствуют именам значений
// перечисления РежимыВыполненияОбработчиков.
// * Статусы - Массив из Строка - доступные значения соответствуют именам значений
// перечисления СтатусыОбработчиковОбновления.
// * ОбластиДанных - Массив из Число - номера областей, по которым нужно получить обработчики.
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * ИмяОбработчика - Строка
// * РежимВыполнения - Строка - имя соответствующего значения перечисления РежимыВыполненияОбработчиков
// * ИмяБиблиотеки - Строка
// * Версия - Строка
// * Статус - Строка - имя соответствующего значения перечисления СтатусыОбработчиковОбновления
// * ДлительностьОбработки - Число
// * ИнформацияОбОшибке - Строка
// * ОбластьДанных - Число
//
Функция ОбработчикиОбновления(Отбор = Неопределено) Экспорт
Если Отбор = Неопределено Тогда
Отбор = Новый Структура;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
| ОбработчикиОбновления.РежимВыполнения КАК РежимВыполненияСсылка,
| ОбработчикиОбновления.ИмяБиблиотеки КАК ИмяБиблиотеки,
| ОбработчикиОбновления.Версия КАК Версия,
| ОбработчикиОбновления.Статус КАК СтатусСсылка,
| ОбработчикиОбновления.ДлительностьОбработки КАК ДлительностьОбработки,
| ОбработчикиОбновления.ИнформацияОбОшибке КАК ИнформацияОбОшибке,
| ОбработчикиОбновления.ОбластьДанныхВспомогательныеДанные КАК ОбластьДанных
|ИЗ
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|ГДЕ
| &УсловиеОбработчиковОбластей
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ОбработчикиОбновления.ИмяОбработчика,
| ОбработчикиОбновления.РежимВыполнения,
| ОбработчикиОбновления.ИмяБиблиотеки,
| ОбработчикиОбновления.Версия,
| ОбработчикиОбновления.Статус,
| ОбработчикиОбновления.ДлительностьОбработки,
| ОбработчикиОбновления.ИнформацияОбОшибке,
| 0
|ИЗ
| РегистрСведений.ОбработчикиОбновленияОбщихДанных КАК ОбработчикиОбновления
|ГДЕ
| &УсловиеОбработчиковОбщихДанных";
УсловияЗапроса = Новый Массив;
ЕстьФильтрОперативноеОбновление = Ложь;
Если Отбор.Свойство("РежимыВыполнения") Тогда
РежимыВыполнения = Новый Массив;
Для Каждого ИмяЗначения Из Отбор.РежимыВыполнения Цикл
РежимВыполнения = ОбновлениеИнформационнойБазыСлужебный.ЗначениеПеречисленияПоИмени(ИмяЗначения,
Метаданные.Перечисления.РежимыВыполненияОбработчиков);
РежимыВыполнения.Добавить(РежимВыполнения);
Если РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков.Оперативно
Или РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков.Монопольно Тогда
ЕстьФильтрОперативноеОбновление = Истина;
КонецЕсли;
КонецЦикла;
УсловияЗапроса.Добавить("ОбработчикиОбновления.РежимВыполнения В (&РежимыВыполнения)");
Запрос.УстановитьПараметр("РежимыВыполнения", РежимыВыполнения);
КонецЕсли;
ЕстьФильтрВыполняется = Ложь;
Если Отбор.Свойство("Статусы") Тогда
Статусы = Новый Массив;
Для Каждого ИмяЗначения Из Отбор.Статусы Цикл
Статус = ОбновлениеИнформационнойБазыСлужебный.ЗначениеПеречисленияПоИмени(ИмяЗначения,
Метаданные.Перечисления.СтатусыОбработчиковОбновления);
Статусы.Добавить(Статус);
Если Статус = Перечисления.СтатусыОбработчиковОбновления.Выполняется Тогда
ЕстьФильтрВыполняется = Истина;
КонецЕсли;
КонецЦикла;
УсловияЗапроса.Добавить("ОбработчикиОбновления.Статус В (&Статусы)");
Запрос.УстановитьПараметр("Статусы", Статусы);
КонецЕсли;
Если ЗначениеЗаполнено(УсловияЗапроса) Тогда
УсловиеОбработчиковОбщихДанных = СтрСоединить(УсловияЗапроса, Символы.ПС + " И ");
Иначе
УсловиеОбработчиковОбщихДанных = "ИСТИНА";
КонецЕсли;
Если Отбор.Свойство("ОбластиДанных") Тогда
ОбластиДанных = Отбор.ОбластиДанных;
ИначеЕсли ОбщегоНазначения.РазделениеВключено() Тогда
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
ОбластиДанных = МодульРаботаВМоделиСервиса.ИспользуемыеОбластиДанных().Выгрузить().ВыгрузитьКолонку(
"ОбластьДанных");
Иначе
ОбластиДанных = Неопределено;
КонецЕсли;
Если ОбластиДанных <> Неопределено Тогда
УсловияЗапроса.Добавить("ОбработчикиОбновления.ОбластьДанныхВспомогательныеДанные В (&ОбластиДанных)");
Запрос.УстановитьПараметр("ОбластиДанных", ОбластиДанных);
Если Отбор.Свойство("ОбластиДанных") И Отбор.ОбластиДанных.Найти(0) = Неопределено Тогда
УсловиеОбработчиковОбщихДанных = "ЛОЖЬ";
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(УсловияЗапроса) Тогда
УсловиеОбработчиковОбластей = СтрСоединить(УсловияЗапроса, Символы.ПС + " И ");
Иначе
УсловиеОбработчиковОбластей = "ИСТИНА";
КонецЕсли;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеОбработчиковОбластей", УсловиеОбработчиковОбластей);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеОбработчиковОбщихДанных", УсловиеОбработчиковОбщихДанных);
ИнформацияПоОбработчикам = ОбновлениеИнформационнойБазыСлужебный.НоваяТаблицаИнформацииОбОбработчиках();
ИменаРежимовПоЗначению = ОбновлениеИнформационнойБазыСлужебный.ИменаПоЗначениямПеречисления(Метаданные.Перечисления.РежимыВыполненияОбработчиков);
ИменаСтатусовПоЗначению = ОбновлениеИнформационнойБазыСлужебный.ИменаПоЗначениямПеречисления(Метаданные.Перечисления.СтатусыОбработчиковОбновления);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Строка = ИнформацияПоОбработчикам.Добавить();
ЗаполнитьЗначенияСвойств(Строка, Выборка);
Строка.РежимВыполнения = ИменаРежимовПоЗначению[Выборка.РежимВыполненияСсылка];
Строка.Статус = ИменаСтатусовПоЗначению[Выборка.СтатусСсылка];
КонецЦикла;
Если ЕстьФильтрОперативноеОбновление И ЕстьФильтрВыполняется
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
ОбновленныеОбласти = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ОбластиОбновленныеНаВерсию(Метаданные.Имя, Метаданные.Версия);
ОбластиВыполняетсяРегистрация = ОбновленныеОбласти.НайтиСтроки(
Новый Структура("ВыполненаРегистрацияОтложенныхОбработчиков", Ложь));
Для Каждого ЭлементВыполняетсяРегистрация Из ОбластиВыполняетсяРегистрация Цикл
НомерОбласти = ЭлементВыполняетсяРегистрация.ОбластьДанныхВспомогательныеДанные;
Если ОбластиДанных <> Неопределено И ОбластиДанных.Найти(НомерОбласти) = Неопределено Тогда
Продолжить;
КонецЕсли;
Строка = ИнформацияПоОбработчикам.Добавить();
Строка.ИмяОбработчика = НСтр("ru = 'Служебные процедуры регистрации отложенных обработчиков'");
Строка.РежимВыполнения = ИменаРежимовПоЗначению[Перечисления.РежимыВыполненияОбработчиков.Оперативно];
Строка.ИмяБиблиотеки = "БиблиотекаСтандартныхПодсистем";
Строка.Статус = ИменаСтатусовПоЗначению[Перечисления.СтатусыОбработчиковОбновления.Выполняется];
Строка.ОбластьДанных = НомерОбласти;
КонецЦикла;
КонецЕсли;
Возврат ИнформацияПоОбработчикам;
КонецФункции
// Возвращает таблицу обновляемых объектов конфигурации со списком обработчиков,
// которые их обрабатывают на текущую версию.
//
// Возвращаемое значение:
// Соответствие из КлючИЗначение:
// * Ключ - Строка - полное имя объекта.
// * Значение - Массив из Строка - имена выполняемых обработчиков обновления.
//
Функция ОбновляемыеОбъекты() Экспорт
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
Запрос.Текст =
"ВЫБРАТЬ
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
| ОбработчикиОбновления.ИзменяемыеОбъекты КАК ИзменяемыеОбъекты
|ИЗ
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|ГДЕ
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения";
Обработчики = Запрос.Выполнить().Выгрузить();
ОбновляемыеОбъекты = Новый Соответствие;
Для Каждого Обработчик Из Обработчики Цикл
ИзменяемыеОбъектыЧастями = СтрРазделить(Обработчик.ИзменяемыеОбъекты, ",", Ложь);
Для Каждого ИзменяемыйОбъект Из ИзменяемыеОбъектыЧастями Цикл
ИзменяемыйОбъект = СокрЛП(ИзменяемыйОбъект);
Если ОбновляемыеОбъекты[ИзменяемыйОбъект] = Неопределено Тогда
ОбновляемыеОбъекты[ИзменяемыйОбъект] = Новый Массив;
КонецЕсли;
Обработчики = ОбновляемыеОбъекты[ИзменяемыйОбъект]; // Массив
Обработчики.Добавить(Обработчик.ИмяОбработчика);
КонецЦикла;
КонецЦикла;
Возврат ОбновляемыеОбъекты;
КонецФункции
// Добавляет очередной устаревший объект в список объектов, которые
// планируются к удалению в будущих версиях программы.
//
// Параметры:
// Объекты - Соответствие из КлючИЗначение:
// * Ключ - Строка - смотри ниже параметр Объект.
// * Значение - Булево, Соответствие - смотри ниже параметр Уточнение.
//
// Объект - Строка - полное имя объекта метаданных с данными, который следует очистить.
// Либо объект метаданных с основной таблицей, например, "Справочник.УдалитьОчередьЗаданий".
// Либо значение перечисления, например, "Перечисление.ХозяйственныеОперации.УдалитьСписаниеТоваровПереданныхПартнерам".
// Либо точка маршрута, например, "БизнесПроцесс.Задание.ТочкаМаршрута.УдалитьВернутьИсполнителю".
// Либо все точки маршрута, например, "БизнесПроцесс.Задание.Точки".
// Либо поле регистра, входящее в уникальный индекс,
// например, измерение "РегистрСведений._ДемоОтветственныеЛица.Склад".
//
// Уточнение - Булево - когда в параметре Объект указан удаляемый в будущем объект.
// Имя объекта должно начинаться с Удалить.
// По умолчанию Ложь, если указано Истина, то данные объекта будут удалены.
// - ОписаниеТипов, Тип, ПеречислениеСсылка, ТочкаМаршрутаБизнесПроцессаСсылка - когда
// в параметре Объект указано поле тип которого сокращается
// на список указанных ссылочных типов или один тип
// или значение перечисления или значение точки маршрута бизнес-процесса.
//
Процедура ДобавитьОбъектПланируемыйКУдалению(Объекты, Объект, Уточнение = Ложь) Экспорт
Если ТипЗнч(Уточнение) = Тип("Булево") Тогда
Объекты.Вставить(Объект, Уточнение);
Иначе
СокращаемыеТипыИЗначения = Объекты.Получить(Объект);
Если СокращаемыеТипыИЗначения = Неопределено Тогда
СокращаемыеТипыИЗначения = Новый Соответствие;
Объекты.Вставить(Объект, СокращаемыеТипыИЗначения);
КонецЕсли;
Если ТипЗнч(Уточнение) = Тип("ОписаниеТипов") Тогда
Для Каждого Тип Из Уточнение.Типы() Цикл
СокращаемыеТипыИЗначения.Вставить(Тип, Истина);
КонецЦикла;
Иначе
СокращаемыеТипыИЗначения.Вставить(Уточнение, Истина);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
#Область ДляВызоваИзДругихПодсистем
// ИнтернетПоддержкаПользователей.ПолучениеОбновленийПрограммы
// Возвращает статус отложенных обработчиков обновления.
//
// Возвращаемое значение:
// Строка - пустая строка, если все обработчики успешно выполнились.
// "СтатусНеВыполнено" - есть невыполненные обработчики.
// "СтатусОшибка" - все обработчики завершились, но есть хотя бы один с ошибкой.
// "СтатусПриостановлен" - все обработчики завершились, но есть хотя бы один остановленный.
//
Функция СтатусОтложенногоОбновления() Экспорт
Возврат ОбновлениеИнформационнойБазыСлужебный.СтатусНевыполненныхОбработчиков();
КонецФункции
// Конец ИнтернетПоддержкаПользователей.ПолучениеОбновленийПрограммы
#КонецОбласти
////////////////////////////////////////////////////////////////////////////////
// Начальное заполнение элементов.
#Область ЗаполнениеПредопределенныхЭлементов
////////////////////////////////////////////////////////////////////////////////
// Прочие процедуры и функции.
// Зарегистрировать предопределенные элементы для обновления в обработчике обновления.
//
// Параметры:
// Параметры - Структура - служебные параметры обработчика обновления.
// ОбъектМетаданных - ОбъектМетаданных
// - Неопределено - обновляемые объекты
// ДополнительныеПараметры - Структура:
// * РежимОбновления - Строка - определяет вариант регистрация предопределенных элементов для обновления. Варианты:
// Все - будут зарегистрированы все предопределенные элементы;
// НовыеИИзмененные - обновляет только новые и измененные;
// МультиязычныеСтроки - только, если были изменения в мультиязычных реквизитах.
// * ПропускатьПустые - Булево - если Истина, то пустые строки в поставляемых данных исключаются из проверки на изменение.
// Например, объект не будет зарегистрирован, когда в ИБ реквизит заполнен, а в коде пустая строка.
// * СравниватьТабличныеЧасти - Булево - если Ложь, то табличные части игнорируются и не будут сравниваться на различие.
//
Процедура ЗарегистрироватьПредопределенныеЭлементыДляОбновления(Параметры, ОбъектМетаданных = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
ОбновлениеИнформационнойБазыСлужебный.ЗарегистрироватьПредопределенныеЭлементыДляОбновления(Параметры, ОбъектМетаданных, ДополнительныеПараметры);
КонецПроцедуры
// Заполняет предопределенные элементы объекта в обработчике обновления поставляемыми данными.
//
// Параметры:
// Параметры - Структура- служебные параметры обработчика обновления.
// ОбъектМетаданных - ОбъектМетаданных - заполняемый объект.
// НастройкиЗаполнения - см. НастройкиЗаполнения
//
Процедура ЗаполнитьЭлементыНачальнымиДанными(Параметры, ОбъектМетаданных, НастройкиЗаполнения = Неопределено) Экспорт
// Обратная совместимость
Если ТипЗнч(НастройкиЗаполнения) = Тип("Булево") Тогда
ОбновитьМультиязычныеСтроки = НастройкиЗаполнения;
НастройкиЗаполнения = НастройкиЗаполнения();
НастройкиЗаполнения.ОбновитьТолькоМультиязычныеСтроки = ОбновитьМультиязычныеСтроки;
ИначеЕсли НастройкиЗаполнения = Неопределено Тогда
НастройкиЗаполнения = НастройкиЗаполнения();
КонецЕсли;
ОбновлениеИнформационнойБазыСлужебный.ЗаполнитьЭлементыНачальнымиДанными(Параметры, ОбъектМетаданных, НастройкиЗаполнения);
КонецПроцедуры
// Заполнить объект предопределенными данными из кода начального заполнения
//
// Параметры:
// ЗаполняемыйОбъект - СправочникОбъект
// - ПланВидовХарактеристикОбъект - заполняемый объект
// НастройкиЗаполнения - см. НастройкиЗаполнения
//
Процедура ЗаполнитьОбъектНачальнымиДанными(ЗаполняемыйОбъект, НастройкиЗаполнения) Экспорт
ОбновлениеИнформационнойБазыСлужебный.ЗаполнитьОбъектНачальнымиДанными(ЗаполняемыйОбъект, НастройкиЗаполнения);
КонецПроцедуры
// Настройки заполнения предопределенных и поставляемых элементов.
//
// Возвращаемое значение:
// Структура:
// * ОбновитьТолькоМультиязычныеСтроки - Булево - если Истина, то будет обновлены только мультиязычные строки.
// * Реквизиты - Строка - список реквизитов через запятую, которые будут обновлены. Например, "Наименование,Комментарий".
//
Функция НастройкиЗаполнения() Экспорт
Результат = Новый Структура;
Результат.Вставить("ОбновитьТолькоМультиязычныеСтроки", Ложь);
Результат.Вставить("Реквизиты", "");
Возврат Результат;
КонецФункции
#КонецОбласти
#Область УстаревшиеПроцедурыИФункции
// Устарела: больше не требуется, т.к. данные действия выполняются автоматически механизмом обновления.
//
// Удаляет отложенный обработчик из очереди выполняемых обработчиков на новую версию.
// Следует использовать, например, при переводе отложенного обработчика
// на монопольный (оперативный) режим выполнения.
// Для этого необходимо добавить новый разделенный обработчик обновления с режимом выполнения
// "Оперативно" и признаком "ОбщиеДанные = Ложь", после чего разместить в нем вызов данного метода.
//
// Параметры:
// ИмяОбработчика - Строка - полное имя процедуры отложенного обработчика.
//
Процедура УдалитьОтложенныйОбработчикИзОчереди(ИмяОбработчика) Экспорт
Возврат;
КонецПроцедуры
#КонецОбласти
// Записывает в журнал регистрации событие при выполнении обработчика обновления.
// При записи ошибки или предупреждения сохраняет эту информацию в сведениях об обработчике
// обновления для дальнейшей индикации в интерфейсах механизма обновления.
//
// Параметры:
// Комментарий - Строка - текст сообщения, записываемый в журнал регистрации.
// Уровень - УровеньЖурналаРегистрации - уровень важности события.
// Если не указано, то записывается событие с уровнем Ошибка.
// Параметры - Структура - параметры, переданные на вход обработчика обновления.
//
Процедура ЗаписатьСобытиеВЖурналРегистрации(Комментарий, Уровень = Неопределено, Параметры = Неопределено) Экспорт
Если ТипЗнч(Параметры) = Тип("Структура")
И Параметры.Свойство("ИмяОбработчика") Тогда
ИмяОбработчика = Параметры.ИмяОбработчика;
Иначе
ИмяОбработчика = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ИмяОбработчика;
КонецЕсли;
Если Уровень = УровеньЖурналаРегистрации.Ошибка
Или Уровень = Неопределено Тогда
ОбновлениеИнформационнойБазыСлужебный.ДобавитьИнформациюОбОшибкеВОбработчике(ИмяОбработчика);
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьОшибку(Комментарий);
ИначеЕсли Уровень = УровеньЖурналаРегистрации.Предупреждение Тогда
ОбновлениеИнформационнойБазыСлужебный.ДобавитьИнформациюОбОшибкеВОбработчике(ИмяОбработчика);
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьПредупреждение(Комментарий);
Иначе
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьИнформацию(Комментарий);
КонецЕсли;
КонецПроцедуры
// Выполняет перезапуск отложенного обновления в базе, где уже выполнились
// монопольные и оперативные обработчики обновления.
// Может быть применимо для случаев, когда вносились исправления в процедурах
// регистрации или самих обработчиках обновления и нужно запустить отложенное обновление
// с начала.
//
// Выполняет следующие действия:
// - останавливает выполнение регламентного задания по отложенному обновлению.
// - делает повторную регистрацию обновляемых данных:
// - (по умолчанию)для обработчиков которые еще не выполнились на момент перезапуска.
// - для переданных обработчиков обновления из списка зарегистрированных к обновлению
// на текущую версию. Для этого требуется передать в отборе параметр Обработчики.
// - обработчиков подсистем с указанной версии, в т.ч. тех, которые уже выполнены.
// Для этого необходимо передать в отборе параметр Подсистемы, в котором указать имя подсистемы
// и номер версии, с которого требуется отобрать обработчики обновления.
// - включает регламентное задание отложенного обновления.
//
// Параметры:
// Отбор - Структура:
// * Ключ - Строка - имя подсистемы.
// * Значение - Строка - номер версии
// - Массив - имена обработчиков обновления, которые требуется перезапустить.
//
Процедура ПерезапуститьОтложенноеОбновление(Отбор = Неопределено) Экспорт
Если ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(Отбор) = Тип("Структура")
И Отбор.Количество() = 0 Тогда
ВызватьИсключение НСтр("ru = 'В отборе не указан список подсистем, для которых требуется перезапустить отложенные обработчики.'");
КонецЕсли;
// Отключение отложенного обновления.
ОбновлениеИнформационнойБазыСлужебный.ПриВключенииОтложенногоОбновления(Ложь);
Если Не ОбщегоНазначения.РазделениеВключено() Тогда
ОтборЗаданий = Новый Структура;
ОтборЗаданий.Вставить("ИмяМетода", "ОбновлениеИнформационнойБазыСлужебный.ВыполнитьОтложенноеОбновление");
ОтборЗаданий.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(ОтборЗаданий);
Для Каждого ЗаданиеОбновления Из НайденныеЗадания Цикл
Если ЗаданиеОбновления.Состояние = СостояниеФоновогоЗадания.Активно Тогда
ЗаданиеОбновления.Отменить();
КонецЕсли;
КонецЦикла;
КонецЕсли;
Группы = ОбновлениеИнформационнойБазыСлужебный.НовоеОписаниеГруппПотоковОбработчиковОтложенногоОбновления();
ОбновлениеИнформационнойБазыСлужебный.ОтменитьВыполнениеВсехПотоков(Группы);
// Повторная регистрация данных.
ЗапросВременных = Новый Запрос;
ЗапросВременных.Текст =
"ВЫБРАТЬ
| ОбновлениеИнформационнойБазы.Ссылка КАК Ссылка
|ИЗ
| ПланОбмена.ОбновлениеИнформационнойБазы КАК ОбновлениеИнформационнойБазы
|ГДЕ
| ОбновлениеИнформационнойБазы.Временная = ИСТИНА";
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("ПланОбмена.ОбновлениеИнформационнойБазы");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Разделяемый;
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
ВременныеОчереди = ЗапросВременных.Выполнить().Выгрузить();
Для Каждого ВременнаяОчередь Из ВременныеОчереди Цикл
ПланыОбмена.УдалитьРегистрациюИзменений(ВременнаяОчередь.Ссылка);
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
СведенияОБлокируемыхОбъектах = ОбновлениеИнформационнойБазыСлужебный.СведенияОБлокируемыхОбъектах();
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("ПриЗапускеКлиентскогоПриложения", Ложь);
ПараметрыРегистрации.Вставить("ПерезапускОбновления", Истина);
// Список обработчиков, которые не завершены на данный момент.
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("РежимВыполненияОбработчика", Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно);
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
Запрос.Текст =
"ВЫБРАТЬ
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|ИЗ
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|ГДЕ
| ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика = &РежимВыполненияОбработчика
| И ОбработчикиОбновления.Статус <> &Статус";
Если ТипЗнч(Отбор) = Тип("Массив") Тогда
ПараметрыРегистрации.Вставить("РегистрируемыеОбработчики", Отбор);
Для Каждого Обработчик Из Отбор Цикл
СброситьСостояниеОбработчика(Обработчик);
СведенияОбОбработчике = СведенияОБлокируемыхОбъектах.Обработчики[Обработчик];
Если СведенияОбОбработчике <> Неопределено Тогда
СведенияОБлокируемыхОбъектах.Обработчики[Обработчик].Выполнен = Ложь;
КонецЕсли;
КонецЦикла;
НезавершенныеОбработчики = Запрос.Выполнить().Выгрузить();
Для Каждого НезавершенныйОбработчик Из НезавершенныеОбработчики Цикл
СброситьСостояниеОбработчика(НезавершенныйОбработчик.ИмяОбработчика);
СведенияОбОбработчике = СведенияОБлокируемыхОбъектах.Обработчики[Обработчик];
Если СведенияОбОбработчике <> Неопределено Тогда
СведенияОБлокируемыхОбъектах.Обработчики[Обработчик].Выполнен = Ложь;
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(Отбор) = Тип("Структура") Тогда
ИтерацииОбновления = ОбновлениеИнформационнойБазыСлужебный.ИтерацииОбновления();
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
Если Отбор.Свойство(ИтерацияОбновления.Подсистема) Тогда
ИтерацияОбновления.ПредыдущаяВерсия = Отбор[ИтерацияОбновления.Подсистема];
КонецЕсли;
КонецЦикла;
Обработки.ОписаниеОбработчиковОбновления.ЗаполнитьНомерОчереди(ИтерацииОбновления);
ОбновлениеИнформационнойБазыСлужебный.ОбновитьСписокВыполняемыхОбработчиковОбновления(ИтерацииОбновления, Ложь, "Отложенные");
КонецЕсли;
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьСведенияОБлокируемыхОбъектах(СведенияОБлокируемыхОбъектах);
ОбновлениеИнформационнойБазыСлужебный.ЗаполнитьДанныеДляПараллельногоОтложенногоОбновления(ПараметрыРегистрации);
// Повторное получение временных очередей, если они были добавлены.
ВременныеОчереди = ЗапросВременных.Выполнить().Выгрузить();
// Перенос очередей.
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировки = БлокировкаДанных.Добавить("ПланОбмена.ОбновлениеИнформационнойБазы");
ЭлементБлокировки.ИсточникДанных = ВременныеОчереди;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Ссылка", "Ссылка");
НачатьТранзакцию();
Попытка
БлокировкаДанных.Заблокировать();
Для Каждого ВременнаяОчередь Из ВременныеОчереди Цикл
ВременнаяОчередьОбъект = ВременнаяОчередь.Ссылка.ПолучитьОбъект();
Очередь = ВременнаяОчередьОбъект.Очередь;
ОсновнаяОчередь = ОчередьСсылкой(Очередь);
ОсновнаяОчередьОбъект = ОсновнаяОчередь.ПолучитьОбъект();
ВременнаяОчередьОбъект.Наименование = XMLСтрока(Очередь);
ВременнаяОчередьОбъект.Временная = Ложь;
ОсновнаяОчередьОбъект.Наименование = XMLСтрока(Очередь) + " " + НСтр("ru = 'Старая после перезапуска'");
ОсновнаяОчередьОбъект.Временная = Истина;
ВременнаяОчередьОбъект.Записать();
ОсновнаяОчередьОбъект.Записать();
ПланыОбмена.УдалитьРегистрациюИзменений(ОсновнаяОчередь);
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
СведенияОбОбновлении = ОбновлениеИнформационнойБазыСлужебный.СведенияОбОбновленииИнформационнойБазы();
СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно = Неопределено;
СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления = Неопределено;
СведенияОбОбновлении.ТекущаяИтерацияОбновления = 1;
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
Константы.ПорядокОбрабатываемыхДанных.Установить(Перечисления.ПорядокОбработчиковОбновления.Критичный);
Константы.ОтложенноеОбновлениеЗавершеноУспешно.Установить(Ложь);
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Установить(Ложь);
КонецЕсли;
ОбновлениеИнформационнойБазыСлужебный.ПриВключенииОтложенногоОбновления(Истина);
КонецПроцедуры
// Выполняет перезапуск монопольных и оперативных обработчиков обновления в базе, где уже выполнилась
// монопольная (оперативная) часть обновления.
//
// Параметры:
// Отбор - Структура:
// * Ключ - Строка - имя подсистемы.
// * Значение - Строка - номер версии.
//
Процедура ПерезапуститьМонопольноеОбновление(Отбор) Экспорт
ИтерацииОбновления = ОбновлениеИнформационнойБазыСлужебный.ИтерацииОбновления();
ВерсииУстановлены = Ложь;
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
Если Отбор.Свойство(ИтерацияОбновления.Подсистема) Тогда
ИтерацияОбновления.ПредыдущаяВерсия = Отбор[ИтерацияОбновления.Подсистема];
ВерсииУстановлены = Истина;
КонецЕсли;
КонецЦикла;
Если Не ВерсииУстановлены Тогда
Возврат;
КонецЕсли;
Обработки.ОписаниеОбработчиковОбновления.ЗаполнитьНомерОчереди(ИтерацииОбновления);
ОбновлениеИнформационнойБазыСлужебный.ОбновитьСписокВыполняемыхОбработчиковОбновления(ИтерацииОбновления, Ложь, "Монопольные");
ХодВыполненияОбработчиков = Новый Структура;
ХодВыполненияОбработчиков.Вставить("ВсегоОбработчиков", 0);
ХодВыполненияОбработчиков.Вставить("ВыполненоОбработчиков", 0);
Параметры = Новый Структура;
Параметры.Вставить("ХодВыполненияОбработчиков", ХодВыполненияОбработчиков);
Параметры.Вставить("ОперативноеОбновление", Ложь);
Параметры.Вставить("ВФоне", Ложь);
Параметры.Вставить("ОтметитьРегистрациюДанных", Истина);
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
ОбновлениеИнформационнойБазыСлужебный.ВыполнитьИтерациюОбновления(ИтерацияОбновления, Параметры);
КонецЦикла;
КонецПроцедуры
// Регистрирует проблему с данными, выявленную при выполнении обработчика обновления в подсистеме
// КонтрольВеденияУчета.
//
// Параметры:
// ПроблемныйОбъект - ЛюбаяСсылка - объект, в котором обнаружена проблема.
// УточнениеПроблемы - Строка - описание выявленной проблемы.
// Параметры - Структура - параметры, переданные на вход обработчика обновления.
//
Процедура ЗарегистрироватьПроблемуСДанными(ПроблемныйОбъект, УточнениеПроблемы, Параметры = Неопределено) Экспорт
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(Параметры) = Тип("Структура")
И Параметры.Свойство("ИмяОбработчика") Тогда
ИмяОбработчика = Параметры.ИмяОбработчика;
Иначе
ИмяОбработчика = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ИмяОбработчика;
КонецЕсли;
МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
МодульКонтрольВеденияУчетаСлужебный = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчетаСлужебный");
ПараметрыВыполненияПроверки = МодульКонтрольВеденияУчета.ПараметрыВыполненияПроверки("ОбновлениеВерсииИБ", ИмяОбработчика);
ВидПроверки = МодульКонтрольВеденияУчета.ВидПроверки(ПараметрыВыполненияПроверки);
Проверка = МодульКонтрольВеденияУчета.ПроверкаПоИдентификатору("ОбновлениеИнформационнойБазыПроблемаСДанными");
ПараметрыПроверки = МодульКонтрольВеденияУчетаСлужебный.ПодготовитьПараметрыПроверки(Проверка, Неопределено);
Проблема = МодульКонтрольВеденияУчета.ОписаниеПроблемы(ПроблемныйОбъект, ПараметрыПроверки);
Проблема.ВидПроверки = ВидПроверки;
Проблема.УточнениеПроблемы = УточнениеПроблемы;
ШаблонЗаписиВЖурнал = НСтр("ru = 'При выполнении обработчика ""%1"" обнаружена проблема с данными в объекте ""%2"".
|Уточнение проблемы:
|%3'");
ТекстДляЗаписиВЖурнал = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаписиВЖурнал,
ИмяОбработчика, ПроблемныйОбъект, УточнениеПроблемы);
ОбновлениеИнформационнойБазыСлужебный.ЗаписатьПредупреждение(ТекстДляЗаписиВЖурнал);
МодульКонтрольВеденияУчета.ЗаписатьПроблему(Проблема, ПараметрыПроверки);
КонецПроцедуры
// Позволяет включить или отключить отложенное обновление. В коробке управляет флагом Использование
// у регламентного задания ОтложенноеОбновлениеИБ, в в модели сервиса заданием очереди.
//
// Параметры:
// Использование - Булево - Истина, если требуется включить отложенное обновление.
//
Процедура ВключитьОтключитьОтложенноеОбновление(Использование) Экспорт
ОбновлениеИнформационнойБазыСлужебный.ПриВключенииОтложенногоОбновления(Использование);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ДобавитьПроверкуБлокировкиДополнительныхИсточников(Очередь, ТекстЗапроса, ПолноеИмяОбъекта, ПолноеИмяРегистра, МенеджерВременныхТаблиц, ЭтоСозданиеВременнойТаблицы, ДополнительныеПараметры)
Если ДополнительныеПараметры.ДополнительныеИсточникиДанных.Количество() = 0 Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамСсылкам", "ИСТИНА");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамРегистрам", "ИСТИНА");
Иначе
ДополнительныеИсточникиСсылки = Новый Массив;
ДополнительныеИсточникиРегистры = Новый Массив;
Для Каждого КлючЗначение Из ДополнительныеПараметры.ДополнительныеИсточникиДанных Цикл
ИсточникДанных = КлючЗначение.Ключ;
Если СтандартныеПодсистемыСервер.ЭтоТаблицаРегистра(ИсточникДанных) И СтрНайти(ИсточникДанных,".") <> 0 Тогда
ДополнительныеИсточникиРегистры.Добавить(ИсточникДанных);
Иначе
ДополнительныеИсточникиСсылки.Добавить(ИсточникДанных);
КонецЕсли;
КонецЦикла;
#Область ДополнительныеИсточникиСсылки
Если ДополнительныеИсточникиСсылки.Количество() > 0 Тогда
Если ПолноеИмяОбъекта = Неопределено Тогда
ТекстИсключения = НСтр("ru = 'Ошибка вызова функции %ИмяФункции%: не передано имя документа, но переданы дополнительные источники данных.'");
ТекстИсключения = СтрЗаменить(ТекстИсключения, "%ИмяФункции%", "ОбновлениеИнформационнойБазы.ДобавитьПроверкуБлокировкиДополнительныхИсточников");
ВызватьИсключение ТекстИсключения;
КонецЕсли;
МетаданныеДокумента = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
ВременныеТаблицыЗаблокированныхДопИсточников = Новый Соответствие;
РеквизитыШапки = Новый Соответствие;
РеквизитыТЧ = Новый Соответствие;
Для Каждого ИсточникДанных Из ДополнительныеИсточникиСсылки Цикл
СоставИсточникаДанных = СоставСсылочногоИсточникаДанных(ИсточникДанных);
ИмяТЧ = СоставИсточникаДанных.ТабличнаяЧасть;
ИмяРеквизита = СоставИсточникаДанных.Реквизит;
Если ЗначениеЗаполнено(ИмяТЧ) Тогда
ТипыИсточника = МетаданныеДокумента.ТабличныеЧасти[ИмяТЧ].Реквизиты[ИмяРеквизита].Тип.Типы();
Иначе
ТипыИсточника = МетаданныеДокумента.Реквизиты[ИмяРеквизита].Тип.Типы();
КонецЕсли;
Для Каждого ТипИсточника Из ТипыИсточника Цикл
Если ЭтоПримитивныйТип(ТипИсточника) Или ЭтоПеречисление(ТипИсточника) Тогда
Продолжить;
КонецЕсли;
МетаданныеИсточника = Метаданные.НайтиПоТипу(ТипИсточника);
Если ЗначениеЗаполнено(ИмяТЧ) Тогда
МетаданныеРеквизитов = ЗначениеПоКлючу(РеквизитыТЧ, ИмяТЧ);
Реквизиты = ЗначениеПоКлючу(МетаданныеРеквизитов, МетаданныеИсточника);
Реквизиты[ИмяРеквизита] = Истина;
Иначе
Реквизиты = ЗначениеПоКлючу(РеквизитыШапки, МетаданныеИсточника);
Реквизиты[ИмяРеквизита] = Истина;
КонецЕсли;
ИмяВТЗаблокированногоДопИсточника = ВременныеТаблицыЗаблокированныхДопИсточников[МетаданныеИсточника];
Если ИмяВТЗаблокированногоДопИсточника = Неопределено Тогда
ПолноеИмяИсточника = МетаданныеИсточника.ПолноеИмя();
ИмяВТЗаблокированногоДопИсточника = "ВТЗаблокировано" + СтрЗаменить(ПолноеИмяИсточника,".","_");
ВременныеТаблицыЗаблокированныхДопИсточников[МетаданныеИсточника] = ИмяВТЗаблокированногоДопИсточника;
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = ИмяВТЗаблокированногоДопИсточника;
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, // @skip-check query-in-loop - пакетная проверка заблокированных данных.
ПолноеИмяИсточника,
МенеджерВременныхТаблиц,
ДополнительныеПараметрыСозданияВТ);
КонецЕсли;
КонецЦикла;
КонецЦикла;
УсловияПоДопИсточникамСсылкам = Новый Массив;
РазделительУсловийПоДопИсточникамСсылкам =
"
| И ";
Если РеквизитыТЧ.Количество() > 0 Тогда
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапросаВТЗаблокированныхПоТЧ(РеквизитыТЧ,
ПолноеИмяОбъекта,
ПолноеИмяРегистра,
ВременныеТаблицыЗаблокированныхДопИсточников);
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.Выполнить();
УсловияПоДопИсточникамСсылкам.Добавить(ТекстУсловияЗаблокированныхПоТЧ(ПолноеИмяОбъекта, ПолноеИмяРегистра));
ВременныеТаблицыЗаблокированныхДопИсточников["ЗаблокированныеПоТЧ"] = "ЗаблокированныеПоТЧ";
КонецЕсли;
Если РеквизитыШапки.Количество() > 0 Тогда
УсловияЗаблокированныхПоШапке = ТекстУсловияЗаблокированныхПоШапке(РеквизитыШапки,
ПолноеИмяРегистра,
ВременныеТаблицыЗаблокированныхДопИсточников);
УсловияПоДопИсточникамСсылкам.Добавить(УсловияЗаблокированныхПоШапке);
КонецЕсли;
УсловиеПоДопИсточникамСсылкам = СтрСоединить(УсловияПоДопИсточникамСсылкам,
РазделительУсловийПоДопИсточникамСсылкам);
ТекстыЗапроса = Новый Массив;
ТекстыЗапроса.Добавить(ТекстЗапроса);
ДобавитьЗапросыУничтоженияВТ(ТекстыЗапроса, ВременныеТаблицыЗаблокированныхДопИсточников);
ТекстЗапроса = ОбъединитьЗапросыВПакет(ТекстыЗапроса);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамСсылкам", УсловиеПоДопИсточникамСсылкам);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ПолноеИмяДокумента", ПолноеИмяОбъекта);
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамСсылкам", "ИСТИНА");
КонецЕсли;
#КонецОбласти
#Область ДополнительныеИсточникиРегистры
Если ДополнительныеИсточникиРегистры.Количество() > 0 Тогда
УсловиеПоДопИсточникамРегистрам = "ИСТИНА";
ВременныеТаблицыЗаблокированныхДопИсточников = Новый Соответствие;
Для Каждого ИсточникДанных Из ДополнительныеИсточникиРегистры Цикл
МетаданныеИсточника = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ИсточникДанных);
Если ОбщегоНазначения.ЭтоРегистрСведений(МетаданныеИсточника)
И МетаданныеИсточника.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
ТекстИсключения = НСтр("ru = 'Регистр %ИсточникДанных% независимый. Поддерживается проверка только по регистрам, подчиненным регистраторам.'");
ТекстИсключения = СтрЗаменить(ТекстИсключения, "%ИсточникДанных%",ИсточникДанных);
ВызватьИсключение ТекстИсключения;
КонецЕсли;
ИмяВТЗаблокированногоДопИсточника = ВременныеТаблицыЗаблокированныхДопИсточников.Получить(МетаданныеИсточника);
Если ИмяВТЗаблокированногоДопИсточника = Неопределено Тогда
ИмяВТЗаблокированногоДопИсточника = "ВТЗаблокировано" + СтрЗаменить(ИсточникДанных,".","_");
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = ИмяВТЗаблокированногоДопИсточника;
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияДанных(Очередь, ИсточникДанных, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ); // @skip-check query-in-loop - пакетная проверка заблокированных данных.
ВременныеТаблицыЗаблокированныхДопИсточников.Вставить(МетаданныеИсточника, ИмяВТЗаблокированногоДопИсточника);
КонецЕсли;
КонецЦикла;
ТекстыЗапроса = Новый Массив;
ТекстыЗапроса.Добавить(ТекстЗапроса);
ДобавитьЗапросыУничтоженияВТ(ТекстыЗапроса, ВременныеТаблицыЗаблокированныхДопИсточников);
ТекстЗапроса = ОбъединитьЗапросыВПакет(ТекстыЗапроса);
УсловиеПоДопИсточникамРегистрам = ТекстУсловияЗаблокированныхПоРегистрам(ПолноеИмяРегистра,
ВременныеТаблицыЗаблокированныхДопИсточников);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамРегистрам", УсловиеПоДопИсточникамРегистрам);
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамРегистрам", "ИСТИНА");
КонецЕсли;
#КонецОбласти
КонецЕсли;
КонецПроцедуры
Функция ЭтоПримитивныйТип(ПроверяемыйТип)
Если ПроверяемыйТип = Тип("Неопределено")
Или ПроверяемыйТип = Тип("Булево")
Или ПроверяемыйТип = Тип("Строка")
Или ПроверяемыйТип = Тип("Число")
Или ПроверяемыйТип = Тип("Дата")
Или ПроверяемыйТип = Тип("УникальныйИдентификатор") Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Процедура ДобавитьПроверкуБлокировкиДополнительныхИсточниковДляНезависимогоРегистра(Очередь, ТекстЗапроса, ПолноеИмяРегистра, МенеджерВременныхТаблиц, ДополнительныеПараметры)
Если ДополнительныеПараметры.ДополнительныеИсточникиДанных.Количество() = 0 Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТекстЗапросаСоединениеСДопИсточниками", "");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамСсылкам", "ИСТИНА");
Иначе
МетаданныеРегистра = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяРегистра);
УсловияПоДопИсточникамСсылкам = Новый Массив;
ШаблонУсловияПоДопИсточникамСсылкам =
" НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| %1 КАК %1
| ГДЕ
| ТаблицаИзменений.%2 = %1.Ссылка)";
Для Каждого КлючЗначение Из ДополнительныеПараметры.ДополнительныеИсточникиДанных Цикл
ИсточникДанных = КлючЗначение.Ключ;
ТипыИсточника = МетаданныеРегистра.Измерения[ИсточникДанных].Тип.Типы();
МассивОбъектовМетаданных = Новый Массив;
Для Каждого ТипИсточника Из ТипыИсточника Цикл
Если ЭтоПримитивныйТип(ТипИсточника) Или ЭтоПеречисление(ТипИсточника) Тогда
Продолжить;
КонецЕсли;
МассивОбъектовМетаданных.Добавить(Метаданные.НайтиПоТипу(ТипИсточника));
КонецЦикла;
ДополнительныеПараметрыСозданияВТ = ДополнительныеПараметрыВыборкиДанныхДляОбработки();
ИмяВременнойТаблицы = "ВТЗаблокировано" + ИсточникДанных;
ДополнительныеПараметрыСозданияВТ.ИмяВременнойТаблицы = ИмяВременнойТаблицы;
СоздатьВременнуюТаблицуЗаблокированныхДляЧтенияИИзмененияСсылок(Очередь, МассивОбъектовМетаданных, МенеджерВременныхТаблиц, ДополнительныеПараметрыСозданияВТ); // @skip-check query-in-loop - пакетная проверка заблокированных данных.
УсловиеПоДопИсточникамСсылкам = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ШаблонУсловияПоДопИсточникамСсылкам,
ИмяВременнойТаблицы,
ИсточникДанных);
УсловияПоДопИсточникамСсылкам.Добавить(УсловиеПоДопИсточникамСсылкам);
КонецЦикла;
РазделительИ =
"
| И ";
УсловиеПоДопИсточникамСсылкам = СтрСоединить(УсловияПоДопИсточникамСсылкам, РазделительИ);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеПоДопИсточникамСсылкам", УсловиеПоДопИсточникамСсылкам);
КонецЕсли;
КонецПроцедуры
Процедура УстановитьНедостающиеОтборыВНаборе(Набор, МетаданныеНабора, УстанавливаемыеОтборы)
Для Каждого Измерение Из МетаданныеНабора.Измерения Цикл
ЕстьОтборПоИзмерению = Ложь;
Если ТипЗнч(УстанавливаемыеОтборы) = Тип("ТаблицаЗначений") Тогда
ЕстьОтборПоИзмерению = УстанавливаемыеОтборы.Колонки.Найти(Измерение.Имя) <> Неопределено;
Иначе //Отбор
ЕстьОтборПоИзмерению = УстанавливаемыеОтборы[Измерение.Имя].Использование;
КонецЕсли;
Если Не ЕстьОтборПоИзмерению Тогда
ПустоеЗначение = Измерение.Тип.ПривестиЗначение();
Набор.Отбор[Измерение.Имя].Установить(ПустоеЗначение);
КонецЕсли;
КонецЦикла;
Если МетаданныеНабора.ОсновнойОтборПоПериоду Тогда
Если ТипЗнч(УстанавливаемыеОтборы) = Тип("ТаблицаЗначений") Тогда
ЕстьОтборПоИзмерению = УстанавливаемыеОтборы.Колонки.Найти("Период") <> Неопределено;
Иначе //Отбор
ЕстьОтборПоИзмерению = УстанавливаемыеОтборы.Период.Использование;
КонецЕсли;
Если Не ЕстьОтборПоИзмерению Тогда
ПустоеЗначение = '00010101';
Набор.Отбор.Период.Установить(ПустоеЗначение);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Зарегистрировать изменения одного элемента данных, как это было до оптимизации.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Данные - ЛюбаяСсылка
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей.
// ВидДанных - Строка.
// ПолноеИмяОбъекта - Строка.
//
Процедура ЗарегистрироватьИзменения(Параметры, Узел, Данные, ВидДанных, ПолноеИмяОбъекта = "")
ПараметрыРегистрации = НовыеПараметрыРегистрации(Параметры, Узел, ВидДанных, ПолноеИмяОбъекта);
ЗарегистрироватьИзмененияЭлементаДанных(Данные, ПараметрыРегистрации);
ЗавершитьРегистрациюПорцииДанных(ПараметрыРегистрации);
КонецПроцедуры
// Зарегистрировать изменения одной или нескольких ссылок.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Ссылки - ЛюбаяСсылка
// - Массив из ЛюбаяСсылка.
// ВидДанных - Строка.
// ПолноеИмяОбъекта - Строка.
//
Процедура ЗарегистрироватьИзмененияОбъекта(Параметры, Узел, Ссылки, ВидДанных, ПолноеИмяОбъекта = "")
ПараметрыРегистрации = НовыеПараметрыРегистрации(Параметры, Узел, ВидДанных, ПолноеИмяОбъекта);
Для Каждого Ссылка Из МассивЭлементов(Ссылки) Цикл
ЗарегистрироватьИзмененияЭлементаДанных(Ссылка, ПараметрыРегистрации);
КонецЦикла;
ЗавершитьРегистрациюПорцииДанных(ПараметрыРегистрации);
КонецПроцедуры
// Зарегистрировать изменения подчиненного регистра по указанным регистраторам.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Регистраторы - ЛюбаяСсылка
// - Массив из ЛюбаяСсылка.
// ВидДанных - Строка.
// ПолноеИмяОбъекта - Строка.
//
Процедура ЗарегистрироватьИзмененияПодчиненногоРегистра(Параметры, Узел, Регистраторы, ВидДанных, ПолноеИмяОбъекта)
ПараметрыРегистрации = НовыеПараметрыРегистрации(Параметры, Узел, ВидДанных, ПолноеИмяОбъекта);
Для Каждого Регистратор Из МассивЭлементов(Регистраторы) Цикл
Набор = ПолучитьПереиспользуемыйНабор(ПараметрыРегистрации.ПереиспользуемыеНаборы);
Набор.Отбор.Регистратор.Установить(Регистратор);
ЗарегистрироватьИзмененияЭлементаДанных(Набор, ПараметрыРегистрации);
КонецЦикла;
ЗавершитьРегистрациюПорцииДанных(ПараметрыРегистрации);
КонецПроцедуры
// Зарегистрировать изменения независимого регистра по таблице значений,
// где колонки - это измерения, а строки - это регистрируемые записи.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Записи - ТаблицаЗначений.
// ВидДанных - Строка.
// ПолноеИмяОбъекта - Строка.
//
Процедура ЗарегистрироватьИзмененияНезависимогоРегистра(Параметры, Узел, Записи, ВидДанных, ПолноеИмяОбъекта)
ПараметрыРегистрации = НовыеПараметрыРегистрации(Параметры, Узел, ВидДанных, ПолноеИмяОбъекта);
МетаданныеРегистра = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
Для Каждого Запись Из Записи Цикл
Набор = ПолучитьПереиспользуемыйНабор(ПараметрыРегистрации.ПереиспользуемыеНаборы);
УстановитьНедостающиеОтборыВНаборе(Набор, МетаданныеРегистра, Записи);
Для Каждого Колонка Из Записи.Колонки Цикл
Набор.Отбор[Колонка.Имя].Значение = Запись[Колонка.Имя];
Набор.Отбор[Колонка.Имя].Использование = Истина;
КонецЦикла;
ЗарегистрироватьИзмененияЭлементаДанных(Набор, ПараметрыРегистрации);
КонецЦикла;
ЗавершитьРегистрациюПорцииДанных(ПараметрыРегистрации);
КонецПроцедуры
// Зарегистрировать элемент данных в таблице регистрации изменений,
// увеличить счетчик зарегистрированных данных
// и записать данные для обновления в файл рИБ (необходимо в случае РИБ с фильтрами).
//
// Параметры:
// Данные - ЛюбаяСсылка
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей.
// ПараметрыРегистрации - см. НовыеПараметрыРегистрации.
//
Процедура ЗарегистрироватьИзмененияЭлементаДанных(Данные, ПараметрыРегистрации)
Если ПараметрыРегистрации.ДоступнаПакетнаяРегистрация Тогда
ПараметрыРегистрации.ДанныеДляРегистрации.Добавить(Данные);
ЗарегистрироватьПакетДанных(ПараметрыРегистрации, ПараметрыРегистрации.ДанныеДляРегистрации);
Иначе
Попытка
ПланыОбмена.ЗарегистрироватьИзменения(ПараметрыРегистрации.Узел, Данные);
Исключение
ТекстИсключения = НСтр("ru = 'Не удалось зарегистрировать данные для обработки. Возможно, таблицы, по которым
|выполняется регистрация данных, не включены в состав плана обмена ""%1"".
|Для выявления таких ошибок рекомендуется использовать инструмент ""%2"".
|
|%3'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Имя,
"ПроверкаВнедренияБСП",
ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение ТекстИсключения;
КонецПопытки;
ОсвободитьПереиспользуемыеНаборыВПараметрах(ПараметрыРегистрации);
КонецЕсли;
УвеличитьКоличествоЗарегистрированныхДанных(ПараметрыРегистрации.Параметры,
Данные,
ПараметрыРегистрации.ПолноеИмяОбъекта);
Если ПараметрыРегистрации.ЗаписыватьДанныеДляОбновленияВФайл Тогда
ПараметрыРегистрации.МодульОбменДаннымиСервер.ЗаписатьДанныеДляОбновленияВФайл(ПараметрыРегистрации.Параметры,
Данные,
ПараметрыРегистрации.ВидДанных,
ПараметрыРегистрации.ПолноеИмяОбъекта);
КонецЕсли;
КонецПроцедуры
// Зарегистрировать пакет данных, если он уже достаточно большой
// или это нужно сделать принудительно в конце регистрации порции данных.
//
// Параметры:
// ПараметрыРегистрации - см. НовыеПараметрыРегистрации.
// Данные - Массив из ЛюбаяСсылка
// - Массив из РегистрСведенийНаборЗаписей
// - Массив из РегистрНакопленияНаборЗаписей
// - Массив из РегистрБухгалтерииНаборЗаписей
// - Массив из РегистрРасчетаНаборЗаписей.
// Принудительно - Булево - Истина, если нужно зарегистрировать, даже если пакет мал.
// РазмерПакета - Число - если в пакете столько же или больше записей, то он записывается.
//
Процедура ЗарегистрироватьПакетДанных(ПараметрыРегистрации, Данные, Принудительно = Ложь, РазмерПакета = 1000)
Если Данные.Количество() >= РазмерПакета Или Принудительно И Данные.Количество() > 0 Тогда
Попытка
ПланыОбмена.ЗарегистрироватьИзменения(ПараметрыРегистрации.Узел, Данные);
Исключение
ТекстИсключения = НСтр("ru = 'Не удалось зарегистрировать данные для обработки. Возможно, таблицы, по которым
|выполняется регистрация данных, не включены в состав плана обмена ""%1"".
|Для выявления таких ошибок рекомендуется использовать инструмент ""%2"".
|
|%3'");
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Имя,
"ПроверкаВнедренияБСП",
ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение ТекстИсключения;
КонецПопытки;
Данные.Очистить();
ОсвободитьПереиспользуемыеНаборыВПараметрах(ПараметрыРегистрации);
КонецЕсли;
КонецПроцедуры
// Записать оставшуюся порцию данных в конце процесса регистрации, если доступна пакетная регистрация.
//
// Параметры:
// ПараметрыРегистрации - см. НовыеПараметрыРегистрации.
//
Процедура ЗавершитьРегистрациюПорцииДанных(ПараметрыРегистрации)
Если ПараметрыРегистрации.ДоступнаПакетнаяРегистрация Тогда
ЗарегистрироватьПакетДанных(ПараметрыРегистрации, ПараметрыРегистрации.ДанныеДляРегистрации, Истина);
КонецЕсли;
КонецПроцедуры
// Увеличить количество зарегистрированных данных в статистике.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// Данные - ЛюбаяСсылка
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей.
// ПолноеИмяОбъекта - Строка.
//
Процедура УвеличитьКоличествоЗарегистрированныхДанных(Параметры, Данные, ПолноеИмяОбъекта)
Если Параметры.Свойство("ДанныеОбработчика") Тогда
Если Не ЗначениеЗаполнено(ПолноеИмяОбъекта) Тогда
ПолноеИмя = Данные.Метаданные().ПолноеИмя();
Иначе
ПолноеИмя = ПолноеИмяОбъекта;
КонецЕсли;
ДанныеПоОбъекту = Параметры.ДанныеОбработчика[ПолноеИмя];
Если ДанныеПоОбъекту = Неопределено Тогда
ДанныеПоОбъекту = Новый Структура;
ДанныеПоОбъекту.Вставить("Количество", 1);
ДанныеПоОбъекту.Вставить("Очередь", Параметры.Очередь);
Параметры.ДанныеОбработчика.Вставить(ПолноеИмя, ДанныеПоОбъекту);
Иначе
ДанныеПоОбъекту.Количество = ДанныеПоОбъекту.Количество + 1;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Удалить регистрацию изменений одной или нескольких ссылок.
//
// Параметры:
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Ссылки - ЛюбаяСсылка
// - Массив из ЛюбаяСсылка.
//
Процедура УдалитьРегистрациюИзмененийОбъекта(Узел, Ссылки)
ПараметрыУдаления = НовыеПараметрыУдаленияРегистрации(Узел);
Для Каждого Ссылка Из МассивЭлементов(Ссылки) Цикл
УдалитьРегистрациюИзмененийЭлементаДанных(Ссылка, ПараметрыУдаления);
КонецЦикла;
ЗавершитьУдалениеРегистрацииПорцииДанных(ПараметрыУдаления);
КонецПроцедуры
// Удалить регистрацию изменений подчиненного регистра по указанным регистраторам.
//
// Параметры:
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Регистраторы - ЛюбаяСсылка
// - Массив из ЛюбаяСсылка.
// ПолноеИмяОбъекта - Строка.
//
Процедура УдалитьРегистрациюИзмененийПодчиненногоРегистра(Узел, Регистраторы, ПолноеИмяОбъекта)
ПараметрыУдаления = НовыеПараметрыУдаленияРегистрации(Узел, ПолноеИмяОбъекта);
Для Каждого Регистратор Из МассивЭлементов(Регистраторы) Цикл
Набор = ПолучитьПереиспользуемыйНабор(ПараметрыУдаления.ПереиспользуемыеНаборы);
Набор.Отбор.Регистратор.Установить(Регистратор);
ЗаписатьПрогрессВыполненияОбработчика(Набор, Узел); // @skip-check query-in-loop - нет запроса в цикле.
УдалитьРегистрациюИзмененийЭлементаДанных(Набор, ПараметрыУдаления);
КонецЦикла;
ЗавершитьУдалениеРегистрацииПорцииДанных(ПараметрыУдаления);
КонецПроцедуры
// Удалить регистрацию изменений независимого регистра по таблице значений.
//
// Параметры:
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// Записи - ТаблицаЗначений.
// ПолноеИмяОбъекта - Строка.
//
Процедура УдалитьРегистрациюИзмененийНезависимогоРегистра(Узел, Записи, ПолноеИмяОбъекта)
ПараметрыУдаления = НовыеПараметрыУдаленияРегистрации(Узел, ПолноеИмяОбъекта);
МетаданныеРегистра = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
Для Каждого Запись Из Записи Цикл
Набор = ПолучитьПереиспользуемыйНабор(ПараметрыУдаления.ПереиспользуемыеНаборы);
УстановитьНедостающиеОтборыВНаборе(Набор, МетаданныеРегистра, Записи);
Для Каждого Колонка Из Записи.Колонки Цикл
Набор.Отбор[Колонка.Имя].Значение = Запись[Колонка.Имя];
Набор.Отбор[Колонка.Имя].Использование = Истина;
КонецЦикла;
ЗаписатьПрогрессВыполненияОбработчика(Набор, Узел, МетаданныеРегистра); // @skip-check query-in-loop - нет запроса в цикле.
УдалитьРегистрациюИзмененийЭлементаДанных(Набор, ПараметрыУдаления);
КонецЦикла;
ЗавершитьУдалениеРегистрацииПорцииДанных(ПараметрыУдаления);
КонецПроцедуры
// Удалить регистрацию пакета данных, если он уже достаточно большой
// или это нужно сделать принудительно в конце удаления регистрации порции данных.
//
// Параметры:
// ПараметрыУдаления - см. НовыеПараметрыУдаленияРегистрации.
// Данные - Массив из ЛюбаяСсылка
// - Массив из РегистрСведенийНаборЗаписей
// - Массив из РегистрНакопленияНаборЗаписей
// - Массив из РегистрБухгалтерииНаборЗаписей
// - Массив из РегистрРасчетаНаборЗаписей.
// Принудительно - Булево - Истина, если нужно удалить, даже если пакет мал.
// РазмерПакета - Число - если в пакете столько же или больше записей, то он удаляется.
//
Процедура УдалитьРегистрациюИзмененийПакетаДанных(ПараметрыУдаления, Данные, Принудительно = Ложь, РазмерПакета = 1000)
Если Данные.Количество() >= РазмерПакета Или Принудительно И Данные.Количество() > 0 Тогда
ПланыОбмена.УдалитьРегистрациюИзменений(ПараметрыУдаления.Узел, Данные);
Данные.Очистить();
ОсвободитьПереиспользуемыеНаборыВПараметрах(ПараметрыУдаления);
КонецЕсли;
КонецПроцедуры
// Удалить регистрацию элемента данных в таблице регистрации изменений.
//
// Параметры:
// Данные - ЛюбаяСсылка
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей
// - РегистрРасчетаНаборЗаписей.
// ПараметрыУдаления - см. НовыеПараметрыУдаленияРегистрации.
//
Процедура УдалитьРегистрациюИзмененийЭлементаДанных(Данные, ПараметрыУдаления)
Если ПараметрыУдаления.ДоступнаПакетнаяРегистрация Тогда
ПараметрыУдаления.ДанныеДляУдаления.Добавить(Данные);
УдалитьРегистрациюИзмененийПакетаДанных(ПараметрыУдаления, ПараметрыУдаления.ДанныеДляУдаления);
Иначе
ПланыОбмена.УдалитьРегистрациюИзменений(ПараметрыУдаления.Узел, Данные);
ОсвободитьПереиспользуемыеНаборыВПараметрах(ПараметрыУдаления);
КонецЕсли;
КонецПроцедуры
// Удалить оставшуюся порцию данных в конце процесса удаления регистрации, если доступна пакетная регистрация.
//
// Параметры:
// ПараметрыУдаления - см. НовыеПараметрыУдаленияРегистрации.
//
Процедура ЗавершитьУдалениеРегистрацииПорцииДанных(ПараметрыУдаления)
Если ПараметрыУдаления.ДоступнаПакетнаяРегистрация Тогда
УдалитьРегистрациюИзмененийПакетаДанных(ПараметрыУдаления, ПараметрыУдаления.ДанныеДляУдаления, Истина);
КонецЕсли;
КонецПроцедуры
// Необходимо ли записывать данные для обновления в файл при использовании РИБ с фильтрами.
//
// Возвращаемое значение:
// Булево - Истина - необходимо записывать данные в файл для РИБ.
//
Функция ЗаписыватьДанныеДляОбновленияВФайл(Параметры)
Возврат ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными")
И СтандартныеПодсистемыПовтИсп.ИспользуетсяРИБ("СФильтром")
И Не Параметры.ПовторнаяРегистрация
И Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ();
КонецФункции
// Получить общий модуль ОбменДаннымиСервер, если он доступен.
//
// Возвращаемое значение:
// ОбщийМодуль.
//
Функция МодульОбменДаннымиСервер(ЗаписыватьДанныеДляОбновленияВФайл)
Возврат ?(ЗаписыватьДанныеДляОбновленияВФайл, ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер"), Неопределено);
КонецФункции
// Вернуть массив элементов, даже если передан один элемент.
//
// Параметры:
// Элементы - Массив
// - Произвольный.
//
// Возвращаемое значение:
// Массив.
//
Функция МассивЭлементов(Элементы)
Если ТипЗнч(Элементы) <> Тип("Массив") Тогда
МассивЭлементов = Новый Массив;
МассивЭлементов.Добавить(Элементы);
Иначе
МассивЭлементов = Элементы;
КонецЕсли;
Возврат МассивЭлементов;
КонецФункции
// Структура с контекстом регистрации данных на плане обмена.
//
// Параметры:
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// ВидДанных - Строка.
// ПолноеИмяОбъекта - Строка.
//
// Возвращаемое значение:
// Структура:
// * Параметры - см. ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке.
// * Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// * ВидДанных - Строка.
// * ПолноеИмяОбъекта - Строка.
// * ДанныеДляРегистрации - Массив.
// * МенеджерОбъекта - ДокументМенеджер
// - СправочникМенеджер
// - ПланВидовХарактеристикМенеджер
// - ПланСчетовМенеджер
// - ПланыВидовРасчетаМенеджер
// - БизнесПроцессМенеджер
// - ЗадачаМенеджер
// - РегистрСведенийМенеджер
// - РегистрНакопленияМенеджер
// - РегистрБухгалтерииМенеджер
// - РегистрРасчетаМенеджер.
// * ДоступнаПакетнаяРегистрация - Булево.
// * ЗаписыватьДанныеДляОбновленияВФайл - Булево.
// * МодульОбменДаннымиСервер - ОбщийМодуль.
//
Функция НовыеПараметрыРегистрации(Параметры, Узел, ВидДанных, ПолноеИмяОбъекта)
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Параметры", Параметры);
ПараметрыРегистрации.Вставить("Узел", Узел);
ПараметрыРегистрации.Вставить("ВидДанных", ВидДанных);
ПараметрыРегистрации.Вставить("ПолноеИмяОбъекта", ПолноеИмяОбъекта);
ПараметрыРегистрации.Вставить("ДанныеДляРегистрации", Новый Массив);
ПараметрыРегистрации.Вставить("ДоступнаПакетнаяРегистрация", Истина);
ПараметрыРегистрации.Вставить("ЗаписыватьДанныеДляОбновленияВФайл", ЗаписыватьДанныеДляОбновленияВФайл(Параметры));
ПараметрыРегистрации.Вставить("МодульОбменДаннымиСервер",
МодульОбменДаннымиСервер(ПараметрыРегистрации.ЗаписыватьДанныеДляОбновленияВФайл));
МенеджерОбъекта = Неопределено;
Если ЗначениеЗаполнено(ПолноеИмяОбъекта) Тогда
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмяОбъекта);
Если ОбщегоНазначения.ЭтоРегистр(ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта)) Тогда
ПараметрыРегистрации.Вставить("ПереиспользуемыеНаборы", НовыеПереиспользуемыеНаборы(МенеджерОбъекта));
КонецЕсли;
КонецЕсли;
ПараметрыРегистрации.Вставить("МенеджерОбъекта", МенеджерОбъекта);
Возврат ПараметрыРегистрации;
КонецФункции
// Структура с контекстом удаления регистрации данных с плана обмена.
//
// Параметры:
// Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// ПолноеИмяОбъекта - Строка.
//
// Возвращаемое значение:
// Структура:
// * Узел - ПланОбменаСсылка.ОбновлениеИнформационнойБазы.
// * ПолноеИмяОбъекта - Строка.
// * ДанныеДляУдаления - Массив.
// * МенеджерОбъекта - ДокументМенеджер
// - СправочникМенеджер
// - ПланВидовХарактеристикМенеджер
// - ПланСчетовМенеджер
// - ПланыВидовРасчетаМенеджер
// - БизнесПроцессМенеджер
// - ЗадачаМенеджер
// - РегистрСведенийМенеджер
// - РегистрНакопленияМенеджер
// - РегистрБухгалтерииМенеджер
// - РегистрРасчетаМенеджер.
// * ДоступнаПакетнаяРегистрация - Булево.
//
Функция НовыеПараметрыУдаленияРегистрации(Узел, ПолноеИмяОбъекта = "")
ПараметрыУдаления = Новый Структура;
ПараметрыУдаления.Вставить("Узел", Узел);
ПараметрыУдаления.Вставить("ПолноеИмяОбъекта", ПолноеИмяОбъекта);
ПараметрыУдаления.Вставить("ДанныеДляУдаления", Новый Массив);
ПараметрыУдаления.Вставить("ДоступнаПакетнаяРегистрация", Истина);
МенеджерОбъекта = Неопределено;
Если ЗначениеЗаполнено(ПолноеИмяОбъекта) Тогда
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмяОбъекта);
Если ОбщегоНазначения.ЭтоРегистр(ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта)) Тогда
ПараметрыУдаления.Вставить("ПереиспользуемыеНаборы", НовыеПереиспользуемыеНаборы(МенеджерОбъекта));
КонецЕсли;
КонецЕсли;
ПараметрыУдаления.Вставить("МенеджерОбъекта", МенеджерОбъекта);
Возврат ПараметрыУдаления;
КонецФункции
// Новая коллекция переиспользуемых наборов.
//
// Параметры:
// Менеджер - РегистрСведенийМенеджер
// - РегистрНакопленияМенеджер
// - РегистрРасчетаМенеджер
// - РегистрБухгалтерииМенеджер - менеджер для создания наборов.
// Размер - Число
//
// Возвращаемое значение:
// Структура:
// * Наборы - Массив - переиспользуемые наборы.
// * Создано - Число - количество созданных наборов.
// * Выдано - Число - количество выданных наборов.
//
Функция НовыеПереиспользуемыеНаборы(Менеджер, Размер = 1000)
ПереиспользуемыеОбъекты = Новый Структура;
ПереиспользуемыеОбъекты.Вставить("Менеджер", Менеджер);
ПереиспользуемыеОбъекты.Вставить("Наборы", Новый Массив(Размер));
ПереиспользуемыеОбъекты.Вставить("Создано", 0);
ПереиспользуемыеОбъекты.Вставить("Выдано", 0);
Возврат ПереиспользуемыеОбъекты;
КонецФункции
// Получить ранее созданный переиспользуемый набор или создать новый и получить его.
//
// Параметры:
// ПереиспользуемыеНаборы - см. НовыеПереиспользуемыеНаборы.
//
// Возвращаемое значение:
// - РегистрСведенийНаборЗаписей
// - РегистрНакопленияНаборЗаписей
// - РегистрРасчетаНаборЗаписей
// - РегистрБухгалтерииНаборЗаписей - готовый к работе набор.
//
Функция ПолучитьПереиспользуемыйНабор(ПереиспользуемыеНаборы)
Если ПереиспользуемыеНаборы.Создано = ПереиспользуемыеНаборы.Выдано Тогда
НовыйНабор = ПереиспользуемыеНаборы.Менеджер.СоздатьНаборЗаписей();
Если ПереиспользуемыеНаборы.Создано > ПереиспользуемыеНаборы.Наборы.ВГраница() Тогда
ПереиспользуемыеНаборы.Наборы.Добавить(НовыйНабор);
Иначе
ПереиспользуемыеНаборы.Наборы[ПереиспользуемыеНаборы.Создано] = НовыйНабор;
КонецЕсли;
ПереиспользуемыеНаборы.Создано = ПереиспользуемыеНаборы.Создано + 1;
КонецЕсли;
ВозвращаемыйНабор = ПереиспользуемыеНаборы.Наборы[ПереиспользуемыеНаборы.Выдано];
ПереиспользуемыеНаборы.Выдано = ПереиспользуемыеНаборы.Выдано + 1;
Возврат ВозвращаемыйНабор;
КонецФункции
// Освободить ранее занятые переиспользуемые наборы.
//
// Параметры:
// ПереиспользуемыеНаборы - см. НовыеПереиспользуемыеНаборы.
//
Процедура ОсвободитьПереиспользуемыеНаборы(ПереиспользуемыеНаборы)
ПереиспользуемыеНаборы.Выдано = 0;
КонецПроцедуры
// Освободить ранее занятые переиспользуемые наборы на основе параметров.
//
// Параметры:
// Параметры - см. НовыеПараметрыРегистрации
// - см. НовыеПараметрыУдаленияРегистрации.
//
Процедура ОсвободитьПереиспользуемыеНаборыВПараметрах(Параметры)
Если Параметры.Свойство("ПереиспользуемыеНаборы") Тогда
ОсвободитьПереиспользуемыеНаборы(Параметры.ПереиспользуемыеНаборы);
КонецЕсли;
КонецПроцедуры
Функция УзлыМеньшейОчереди(Очередь)
Возврат ПланыОбмена.ОбновлениеИнформационнойБазы.УзлыМеньшейОчереди(Очередь);
КонецФункции
Функция ОчередьСсылкой(Очередь, Временная = Ложь)
Возврат ПланыОбмена.ОбновлениеИнформационнойБазы.УзелПоОчереди(Очередь, Временная);
КонецФункции
// Контекст построения выборки при помощи таких функций, как:
// - ВыбратьРегистраторыРегистраДляОбработки();
// - ВыбратьСсылкиДляОбработки();
// - ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки();
//
// Параметры:
// ДополнительныеПараметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки
// ИмяТаблицы - Строка - имя таблицы из которой выбираются данные.
//
// Возвращаемое значение:
// Структура:
// * ДополнительныеПараметры - Структура - копия ссылки входного параметра для процедур механизма.
// * ПостраничнаяВыборка - Булево - Истина, если выборка выполняется по страницам.
// * ИмяТаблицы - Строка - имя таблицы из которой выбираются данные.
// * ПоляВыборки - Массив - поля, которые подставляются в список выборки запроса.
// * ПоляУпорядочивания - Массив - поля, которые подставляются в раздел упорядочивания запроса.
// * ИспользуемыеПоляУпорядочивания - Соответствие - кеш полей, которые уже использованы для упорядочивания.
// * Псевдонимы - Массив - псевдонимы имен выбираемых полей, подставляемых в запрос выборки.
// * Направления - Массив - направления упорядочивания (УБЫВ, ВОЗР).
//
Функция ПараметрыПостроенияВыборки(ДополнительныеПараметры, ИмяТаблицы = Неопределено)
ПроверитьПараметрыВыборки(ДополнительныеПараметры);
ПараметрыПостроения = Новый Структура;
ПараметрыПостроения.Вставить("ДополнительныеПараметры", ДополнительныеПараметры);
ПараметрыПостроения.Вставить("ПостраничнаяВыборка", ЭтоПостраничнаяВыборка(ДополнительныеПараметры));
ПараметрыПостроения.Вставить("ИмяТаблицы", ИмяТаблицы);
ПараметрыПостроения.Вставить("ПоляВыборки", Новый Массив);
ПараметрыПостроения.Вставить("ПоляУпорядочивания", Новый Массив);
ПараметрыПостроения.Вставить("ИспользуемыеПоляУпорядочивания", Новый Соответствие);
ПараметрыПостроения.Вставить("Псевдонимы", Новый Массив);
ПараметрыПостроения.Вставить("Направления", Новый Массив);
Возврат ПараметрыПостроения;
КонецФункции
// Установить поля упорядочивания в ВыбратьСсылкиДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
// ЭтоДокумент - Булево - Истина, если обрабатываются ссылки документа.
//
Процедура УстановитьПоляУпорядочиванияСсылок(ПараметрыПостроения, ЭтоДокумент)
ПоляВыборки = ПараметрыПостроения.ПоляВыборки;
ПоляУпорядочивания = ПараметрыПостроения.ПоляУпорядочивания;
ПостраничнаяВыборка = ПараметрыПостроения.ПостраничнаяВыборка;
Если ЭтоДокумент Тогда
Если ПостраничнаяВыборка Тогда
ПоляВыборки.Добавить("ТаблицаОбъекта.Дата");
КонецЕсли;
ПоляУпорядочивания.Добавить("ТаблицаОбъекта.Дата");
КонецЕсли;
ПоляВыборки.Добавить("ТаблицаИзменений.Ссылка");
Если ПостраничнаяВыборка Тогда
ПоляУпорядочивания.Добавить("ТаблицаИзменений.Ссылка");
КонецЕсли;
КонецПроцедуры
// Установить поля упорядочивания для регистра в ВыбратьРегистраторыРегистраДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
Процедура УстановитьПоляУпорядочиванияРегистра(ПараметрыПостроения)
ПоляВыборки = ПараметрыПостроения.ПоляВыборки;
Псевдонимы = ПараметрыПостроения.Псевдонимы;
ПоляУпорядочивания = ПараметрыПостроения.ПоляУпорядочивания;
ИмяИзмеренияДляОтбора = ПараметрыПостроения.ДополнительныеПараметры.ИмяИзмеренияДляОтбора;
ПолеРегистратора = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("ТаблицаРегистраИзменения.%1",
ИмяИзмеренияДляОтбора);
ПоляВыборки.Добавить(ПолеРегистратора);
Псевдонимы.Добавить(ИмяИзмеренияДляОтбора);
Если ПараметрыПостроения.ПостраничнаяВыборка Тогда
ПоляУпорядочивания.Добавить(ПолеРегистратора);
Иначе
Если ВРег(ИмяИзмеренияДляОтбора) = ВРег("Регистратор") Тогда
ПоляВыборки.Добавить("МАКСИМУМ(ЕСТЬNULL(ТаблицаРегистра.Период, ДАТАВРЕМЯ(3000, 1, 1)))");
Псевдонимы.Добавить("Период");
ПоляУпорядочивания.Добавить("МАКСИМУМ(ЕСТЬNULL(ТаблицаРегистра.Период, ДАТАВРЕМЯ(3000, 1, 1)))");
Иначе
ПолеДаты = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.Дата", ПолеРегистратора);
ПоляВыборки.Добавить(ПолеДаты);
Псевдонимы.Добавить("Период");
ПоляУпорядочивания.Добавить(ПолеДаты);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Установить поля упорядочивания для документа в ВыбратьРегистраторыРегистраДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
Процедура УстановитьПоляУпорядочиванияРегистраПоДокументу(ПараметрыПостроения)
ПоляВыборки = ПараметрыПостроения.ПоляВыборки;
Псевдонимы = ПараметрыПостроения.Псевдонимы;
ПоляУпорядочивания = ПараметрыПостроения.ПоляУпорядочивания;
ПоляУпорядочивания.Добавить("ТаблицаДокумента.Дата");
ИмяИзмеренияДляОтбора = ПараметрыПостроения.ДополнительныеПараметры.ИмяИзмеренияДляОтбора;
ПолеРегистратора = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("ТаблицаРегистраИзменения.%1",
ИмяИзмеренияДляОтбора);
Если ПараметрыПостроения.ПостраничнаяВыборка Тогда
ПоляВыборки.Добавить("ТаблицаДокумента.Дата");
Псевдонимы.Добавить("Дата");
ПоляУпорядочивания.Добавить(ПолеРегистратора);
КонецЕсли;
ПоляВыборки.Добавить(ПолеРегистратора);
Псевдонимы.Добавить(ИмяИзмеренияДляОтбора);
КонецПроцедуры
// Установить поля упорядочивания для документа в ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
Процедура УстановитьПоляУпорядочиванияНезависимогоРегистраСведений(ПараметрыПостроения)
Разделители = " " + Символы.Таб + Символы.ПС;
ПоляУпорядочивания = ПараметрыПостроения.ДополнительныеПараметры.ПоляУпорядочивания;
Для ИндексПоля = 0 По ПоляУпорядочивания.ВГраница() Цикл
Поле = ПоляУпорядочивания[ИндексПоля];
Состав = СтрРазделить(Поле, Разделители, Ложь);
ИмяПоля = Состав[0];
ПараметрыПостроения.ПоляВыборки.Добавить(ИмяПоля);
ПараметрыПостроения.ИспользуемыеПоляУпорядочивания[ИмяПоля] = Истина;
Если Состав.Количество() > 1 Тогда
ПараметрыПостроения.Направления.Добавить(Состав[1]);
Иначе
ПараметрыПостроения.Направления.Добавить(?(ИндексПоля = 0, "УБЫВ", ""));
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Учесть измерение в параметрах формирования запроса в ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
// ИмяИзмерения - Строка - имя обрабатываемого измерения.
//
Процедура УстановитьИзмерение(ПараметрыПостроения, ИмяИзмерения)
Если ПараметрыПостроения.ИспользуемыеПоляУпорядочивания[ИмяИзмерения] = Неопределено Тогда
ПараметрыПостроения.ПоляВыборки.Добавить(ИмяИзмерения);
ЗаданыПоляУпорядочивания = ЗаданыПоляУпорядочивания(ПараметрыПостроения.ДополнительныеПараметры);
Если ЗаданыПоляУпорядочивания Или ПараметрыПостроения.ПостраничнаяВыборка Тогда
ПараметрыПостроения.Направления.Добавить("");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Учесть период в параметрах формирования запроса в ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
Процедура УстановитьПериод(ПараметрыПостроения)
ПараметрыПостроения.ПоляВыборки.Вставить(0, "Период");
ПараметрыПостроения.Направления.Вставить(0, "");
КонецПроцедуры
// Учесть ресурсы в параметрах формирования запроса в ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
// Ресурсы - КоллекцияОбъектовМетаданных
//
Процедура УстановитьРесурсы(ПараметрыПостроения, Ресурсы)
Если ПараметрыПостроения.ПоляВыборки.Количество() = 0 Тогда
Для Каждого Ресурс Из Ресурсы Цикл
Если ПараметрыПостроения.ИспользуемыеПоляУпорядочивания[Ресурс.Имя] = Неопределено Тогда
ПараметрыПостроения.ПоляВыборки.Добавить(Ресурс.Имя);
ПараметрыПостроения.Направления.Добавить("");
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Учесть реквизиты в параметрах формирования запроса в ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки().
//
// Параметры:
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
// Реквизиты - КоллекцияОбъектовМетаданных
//
Процедура УстановитьРеквизиты(ПараметрыПостроения, Реквизиты)
Если ПараметрыПостроения.ПоляВыборки.Количество() = 0 Тогда
Для Каждого Реквизит Из Реквизиты Цикл
Если ПараметрыПостроения.ИспользуемыеПоляУпорядочивания[Реквизит.Имя] = Неопределено Тогда
ПараметрыПостроения.ПоляВыборки.Добавить(Реквизит.Имя);
ПараметрыПостроения.Направления.Добавить("");
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Выбрать данные в следующих функциях с учетом постраничной выборки:
// - ВыбратьРегистраторыРегистраДляОбработки();
// - ВыбратьСсылкиДляОбработки();
// - ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки();
//
// Параметры:
// Запрос - Запрос - запрос выборки данных.
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
// Возвращаемое значение:
// ВыборкаИзРезультатаЗапроса - в случае обычной выборки.
// ТаблицаЗначений - в случае постраничной выборки.
//
Функция ВыбратьДанныеДляОбработки(Запрос, ПараметрыПостроения)
Если ПараметрыПостроения.ПостраничнаяВыборка Тогда
Возврат ВыбратьДанныеПостранично(Запрос, ПараметрыПостроения);
Иначе
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоСтраницам", "ИСТИНА");
Возврат Запрос.Выполнить().Выбрать();
КонецЕсли;
КонецФункции
// Получить таблицу значений с данными для обработки с учетом постраничной выборки.
//
// Параметры:
// Запрос - Запрос - запрос выборки данных.
// ПараметрыПостроения - см. ПараметрыПостроенияВыборки
//
// Возвращаемое значение:
// ТаблицаЗначений - данные для обработчика обновления (многопоточного).
//
Функция ВыбратьДанныеПостранично(Запрос, ПараметрыПостроения)
ПоляВыборки = ПараметрыПостроения.ПоляВыборки;
Параметры = ПараметрыПостроения.ДополнительныеПараметры;
ТаблицаИзменений = ПараметрыПостроения.ИмяТаблицы;
Направления = ПараметрыПостроения.Направления;
ПоследняяВыбраннаяЗапись = Параметры.ПоследняяВыбраннаяЗапись;
ПерваяЗапись = Параметры.ПерваяЗапись;
ПоследняяЗапись = Параметры.ПоследняяЗапись;
ВыбратьПервые = ПоследняяВыбраннаяЗапись = Неопределено
И ПерваяЗапись = Неопределено
И ПоследняяЗапись = Неопределено;
Если ВыбратьПервые Тогда
ИзменитьМаксимумВыборки(Запрос.Текст, МаксимальноеКоличествоЗаписейВВыборке(), Параметры.МаксимумВыборки);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоСтраницам", "ИСТИНА");
Результат = Запрос.Выполнить().Выгрузить();
Иначе
ВыбратьДиапазон = ПерваяЗапись <> Неопределено И ПоследняяЗапись <> Неопределено;
БазовыйТекстЗапроса = Запрос.Текст;
Если ВыбратьДиапазон Тогда
Условия = УсловияДляДиапазонаСтраницы(ПоляВыборки, Параметры, Направления);
Иначе
Условия = УсловияДляСледующейСтраницы(ПоляВыборки, Параметры, Направления);
КонецЕсли;
Если Параметры.ОптимизироватьВыборкуПоСтраницам Тогда
Результат = Неопределено;
ИндексПоследнегоУсловия = Условия.Количество() - 1;
ОтложитьУничтожениеВременныхТаблиц = Условия.Количество() > 1;
Если ОтложитьУничтожениеВременныхТаблиц Тогда
ТекстЗапросаУничтоженияВременныхТаблиц = ВырезатьУничтожениеВременныхТаблиц(БазовыйТекстЗапроса);
КонецЕсли;
Для Индекс = 0 По ИндексПоследнегоУсловия Цикл
Если Результат = Неопределено Тогда
Количество = Параметры.МаксимумВыборки;
Иначе
Количество = Параметры.МаксимумВыборки - Результат.Количество();
КонецЕсли;
Запрос.Текст = Строка(БазовыйТекстЗапроса);
ИзменитьМаксимумВыборки(Запрос.Текст, МаксимальноеКоличествоЗаписейВВыборке(), Количество);
УстановитьУсловияВыборкиПоСтраницам(Запрос, Условия, ТаблицаИзменений, Параметры, Истина, Индекс);
Если ОтложитьУничтожениеВременныхТаблиц И Индекс = ИндексПоследнегоУсловия Тогда
Запрос.Текст = Запрос.Текст + ТекстЗапросаУничтоженияВременныхТаблиц;
КонецЕсли;
Выгрузка = Запрос.Выполнить().Выгрузить(); // @skip-check query-in-loop - оптимизированная выборка данных.
Если Результат = Неопределено Тогда
Результат = Выгрузка;
Иначе
Для Каждого СтрокаВыгрузки Из Выгрузка Цикл
СтрокаРезультата = Результат.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаРезультата, СтрокаВыгрузки);
КонецЦикла;
КонецЕсли;
Если Результат.Количество() = Параметры.МаксимумВыборки Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
ИзменитьМаксимумВыборки(Запрос.Текст, МаксимальноеКоличествоЗаписейВВыборке(), Параметры.МаксимумВыборки);
УстановитьУсловияВыборкиПоСтраницам(Запрос, Условия, ТаблицаИзменений, Параметры, Истина);
Результат = Запрос.Выполнить().Выгрузить();
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Удалить из пакета запросов запросы удаления временных таблиц и вернуть их, как результат этой функции.
//
// Параметры:
// ТекстЗапроса - Строка - изменяемый текст запроса.
//
// Возвращаемое значение:
// Строка - фрагмент текста запроса с удалением временных таблиц.
//
Функция ВырезатьУничтожениеВременныхТаблиц(ТекстЗапроса)
ЗапросыУничтожения = Новый Массив;
ПозицияУничтожить = СтрНайти(ТекстЗапроса, "УНИЧТОЖИТЬ");
Пока ПозицияУничтожить > 0 Цикл
ПозицияРазделителя = СтрНайти(ТекстЗапроса, ";",, ПозицияУничтожить);
Если ПозицияРазделителя > 0 Тогда
ЗапросУничтожения = Сред(ТекстЗапроса, ПозицияУничтожить, ПозицияРазделителя - ПозицияУничтожить + 1);
Иначе
ЗапросУничтожения = Сред(ТекстЗапроса, ПозицияУничтожить);
КонецЕсли;
Если ЗапросыУничтожения.Количество() = 0 Тогда
ЗапросыУничтожения.Добавить(Символы.ПС);
КонецЕсли;
ЗапросыУничтожения.Добавить(ЗапросУничтожения);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ЗапросУничтожения, "");
ПозицияУничтожить = СтрНайти(ТекстЗапроса, "УНИЧТОЖИТЬ");
КонецЦикла;
Возврат СтрСоединить(ЗапросыУничтожения, Символы.ПС);
КонецФункции
// Добавить в запрос условия, ограничивающие выборку по страницам.
//
// Постраничная выборка работает в двух режимах:
// - выборка сверху - записи большие указанной (аналогично динамическому списку);
// - выборка диапазона - записи между двумя указанными записями включительно.
//
// Параметры:
// Запрос - Запрос - запрос выборки данных.
// Условия - см. НовыеУсловияПостраничнойВыборки
// Таблица - Строка - имя таблицы из которой выполняется выборка.
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки
// Первые - Булево - Истина, если это первые условия в запросе.
// НомерУсловия - Число - номер обрабатываемого условия.
//
Процедура УстановитьУсловияВыборкиПоСтраницам(Запрос, Условия, Таблица, Параметры, Первые, НомерУсловия = Неопределено)
ПерваяЗапись = Параметры.ПерваяЗапись;
ПоследняяЗапись = Параметры.ПоследняяЗапись;
ВыбратьДиапазон = ПерваяЗапись <> Неопределено
И ПоследняяЗапись <> Неопределено;
Если Не ВыбратьДиапазон Тогда
ПерваяЗапись = Параметры.ПоследняяВыбраннаяЗапись;
КонецЕсли;
Колонки = Условия.Колонки;
КоличествоКолонок = Колонки.Количество();
УсловияИ = Новый Массив;
УсловияИли = Новый Массив;
ЕстьУсловияИли = (НомерУсловия = Неопределено);
ЕстьТаблица = Не ПустаяСтрока(Таблица);
ШаблонУсловияИ = ?(ЕстьТаблица, Таблица + ".%1 %2 &%3", "%1 %2 &%3");
ШаблонУсловияИли = "(%1)";
РазделительУсловийИ =
"
| И ";
РазделительУсловийИли =
"
| ) ИЛИ (
| ";
Если ЕстьУсловияИли Тогда
ИндексНачала = 0;
ИндексОкончания = Условия.Количество() - 1;
Иначе
ИндексНачала = НомерУсловия;
ИндексОкончания = НомерУсловия;
КонецЕсли;
Для ИндексСтроки = ИндексНачала По ИндексОкончания Цикл
УсловияИ.Очистить();
Для ИндексКолонки = 0 По КоличествоКолонок - 1 Цикл
Оператор = Условия[ИндексСтроки][ИндексКолонки];
ИндексПоля = ?(ВыбратьДиапазон, Цел(ИндексКолонки / 2), ИндексКолонки) + 2;
Если Не ПустаяСтрока(Оператор) Тогда
Колонка = Колонки[ИндексКолонки];
ИмяПоляПолное = Колонка.Заголовок;
ИмяПараметра = Колонка.Имя + "Значение";
ИмяПоля = ИмяКолонкиДляЗапроса(ИмяПоляПолное);
Условие = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияИ, ИмяПоля, Оператор, ИмяПараметра);
УсловияИ.Добавить(Условие);
Если ЭтоИмяКолонкиКонцаДиапазона(ИмяПоляПолное) Тогда
ЗначениеПараметра = ПоследняяЗапись[ИндексПоля].Значение;
Иначе
ЗначениеПараметра = ПерваяЗапись[ИндексПоля].Значение;
КонецЕсли;
Запрос.УстановитьПараметр(ИмяПараметра, ЗначениеПараметра);
КонецЕсли;
КонецЦикла;
ТекстУсловий = СтрСоединить(УсловияИ, РазделительУсловийИ);
Если ЕстьУсловияИли Тогда
УсловияИли.Добавить(ТекстУсловий);
КонецЕсли;
КонецЦикла;
Если ЕстьУсловияИли Тогда
ТекстУсловийИли = СтрСоединить(УсловияИли, РазделительУсловийИли);
ТекстУсловий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияИли, ТекстУсловийИли);
КонецЕсли;
Если Не Первые Тогда
ТекстУсловий = " И " + ТекстУсловий;
КонецЕсли;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоСтраницам", ТекстУсловий);
КонецПроцедуры
// Получить условия для выборки записей большие указанной (аналогично динамическому списку).
//
// Параметры:
// ПоляВыборки - Массив - выбираемые запросом поля.
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки.
// Направления - Массив - направления упорядочивания (ВОЗР, УБЫВ) в количестве равном количеству ПоляВыборки.
// - Неопределено - порядок не указывается (всегда ВОЗР).
//
// Возвращаемое значение:
// см. НовыеУсловияПостраничнойВыборки
//
Функция УсловияДляСледующейСтраницы(ПоляВыборки, Параметры, Направления)
ВсеУсловия = НовыеУсловияПостраничнойВыборки(ПоляВыборки);
КоличествоПолей = ПоляВыборки.Количество();
Пока КоличествоПолей > 0 Цикл
НовыеУсловия = ВсеУсловия.Добавить();
Для НомерУсловия = 1 По КоличествоПолей Цикл
ИмяКолонкиПоля = ПоляВыборки[НомерУсловия - 1];
Если НомерУсловия < КоличествоПолей Тогда
Оператор = "=";
Иначе
Оператор = ОператорБольше(Направления[НомерУсловия - 1]);
КонецЕсли;
НовыеУсловия[ИмяКолонкиИзПоляВыборки(ИмяКолонкиПоля)] = Оператор;
КонецЦикла;
КоличествоПолей = КоличествоПолей - 1;
КонецЦикла;
Возврат ВсеУсловия;
КонецФункции
// Получить условия для выборки записей между двумя указанными записями включительно.
//
// Параметры:
// ПоляВыборки - Массив - выбираемые запросом поля.
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыОтметкиОбработки.
// Направления - Массив - направления упорядочивания (ВОЗР, УБЫВ) в количестве равном количеству ПоляВыборки.
// - Неопределено - порядок не указывается (всегда ВОЗР).
//
// Возвращаемое значение:
// см. НовыеУсловияПостраничнойВыборки
//
Функция УсловияДляДиапазонаСтраницы(ПоляВыборки, Параметры, Направления)
ВсеУсловия = НовыеУсловияПостраничнойВыборки(ПоляВыборки, Истина);
ПерваяЗапись = Параметры.ПерваяЗапись;
ПоследняяЗапись = Параметры.ПоследняяЗапись;
КоличествоПолей = ПоляВыборки.Количество();
ВсегоПолей = ПоляВыборки.Количество();
ПозицияВставки = 0;
Пока КоличествоПолей > 0 Цикл
ТекущиеПоляРавны = ЗаписиРавны(ПерваяЗапись, ПоследняяЗапись, КоличествоПолей);
Если ТекущиеПоляРавны И КоличествоПолей <> ВсегоПолей Тогда
Прервать;
КонецЕсли;
ПервыеУсловия = ВсеУсловия.Вставить(ПозицияВставки);
ПозицияВставки = ПозицияВставки + 1;
ПредыдущиеПоляРавны = ЗаписиРавны(ПерваяЗапись, ПоследняяЗапись, КоличествоПолей - 1);
Если Не ПредыдущиеПоляРавны Тогда
ПоследниеУсловия = ВсеУсловия.Вставить(ПозицияВставки);
КонецЕсли;
Для НомерУсловия = 1 По КоличествоПолей Цикл
ИмяКолонкиПоля = ИмяКолонкиИзПоляВыборки(ПоляВыборки[НомерУсловия - 1]);
ИмяКолонкиПоляПоДиапазону = ИмяКолонкиДиапазона(ИмяКолонкиПоля);
Если НомерУсловия < КоличествоПолей Или ТекущиеПоляРавны И КоличествоПолей = ВсегоПолей Тогда
ОператорПервый = "=";
ОператорПоследний = "=";
Иначе
Направление = Направления[НомерУсловия - 1];
Если КоличествоПолей = ВсегоПолей Тогда
ОператорПервый = ОператорБольшеИлиРавно(Направление);
ОператорПоследний = ОператорМеньшеИлиРавно(Направление);
Иначе
ОператорПервый = ОператорБольше(Направление);
ОператорПоследний = ОператорМеньше(Направление);
КонецЕсли;
// Ограничение по диапазону
Если ПредыдущиеПоляРавны Тогда
ПервыеУсловия[ИмяКолонкиПоляПоДиапазону] = ОператорПоследний;
КонецЕсли;
КонецЕсли;
// Выборка по первой записи
ПервыеУсловия[ИмяКолонкиПоля] = ОператорПервый;
// Выборка по последней записи
Если Не ПредыдущиеПоляРавны Тогда
ПоследниеУсловия[ИмяКолонкиПоляПоДиапазону] = ОператорПоследний;
КонецЕсли;
КонецЦикла;
КоличествоПолей = КоличествоПолей - 1;
КонецЦикла;
Возврат ВсеУсловия;
КонецФункции
// Возвращает результат сравнения двух записей.
//
// Параметры:
// ПерваяЗапись - СписокЗначений из Строка
// ПоследняяЗапись - СписокЗначений из Строка
// КоличествоПолей - Число - количество прикладных полей в ключе записи.
//
// Возвращаемое значение:
// Булево - Истина, если записи равны.
//
Функция ЗаписиРавны(ПерваяЗапись, ПоследняяЗапись, КоличествоПолей)
Для Индекс = 2 По КоличествоПолей + 2 - 1 Цикл
Если ПерваяЗапись[Индекс].Значение <> ПоследняяЗапись[Индекс].Значение Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
// Возвращает таблицу значений с условиями постраничной выборки.
//
// Параметры:
// ПоляВыборки - Массив - выбираемые запросом поля.
// ДляДиапазона - Булево - Истина, если таблица будет использоваться для ограничения по диапазону.
// В этом случае, добавляются дополнительные колонки для нижнего условия диапазона.
//
// Возвращаемое значение:
// ТаблицаЗначений - колонки таблицы описывают поля запроса, где в заголовке хранится полное имя поля.
// Имена колонок формируются динамические из имен полей выборки запроса.
// Каждая строка описывает условия для одного запроса выбирающего порции данных для страницы
// или группы условий при выборке через ИЛИ. В ячейках таблицы хранятся условия
// ("=", ">", "<", ">=", "<=")..
//
Функция НовыеУсловияПостраничнойВыборки(ПоляВыборки, ДляДиапазона = Ложь)
Условия = Новый ТаблицаЗначений;
Колонки = Условия.Колонки;
Для Каждого ПолеВыборки Из ПоляВыборки Цикл
Имя = ИмяКолонкиИзПоляВыборки(ПолеВыборки);
Колонки.Добавить(Имя,, ПолеВыборки);
Если ДляДиапазона Тогда
Колонки.Добавить(ИмяКолонкиДиапазона(Имя),, ПолеВыборки);
КонецЕсли;
КонецЦикла;
Возврат Условия;
КонецФункции
// Возвращает имя колонки для условия по нижней границе диапазона постраничной выборки.
//
// Параметры:
// ИмяПоля - Строка - имя поля.
//
// Возвращаемое значение:
// Строка - имя поля для условия по нижней границе диапазона.
//
Функция ИмяКолонкиДиапазона(ИмяПоля)
Возврат ИмяПоля + ПостфиксКонцаДиапазона();
КонецФункции
// Возвращает имя, например, для колонки таблицы значений, полученное из полного имени поля запроса.
//
// Параметры:
// Имя - Строка - полное имя поля запроса (возможно, разделенное точкой).
//
// Возвращаемое значение:
// Строка - имя поля.
//
Функция ИмяКолонкиИзПоляВыборки(Имя)
ЗаменяемыеСимволы = ".,() ";
ИмяКолонки = Строка(Имя);
Для Индекс = 1 По СтрДлина(ЗаменяемыеСимволы) Цикл
Символ = Сред(ЗаменяемыеСимволы, Индекс, 1);
ИмяКолонки = СтрЗаменить(ИмяКолонки, Символ, "_");
КонецЦикла;
Возврат ИмяКолонки;
КонецФункции
// Имя поля, полученное из колонки таблицы условий постраничной выборки, см. НовыеУсловияПостраничнойВыборки.
//
// Параметры:
// ИмяПоля - Строка - имя поля.
//
// Возвращаемое значение:
// Строка - имя поля без служебных символов.
//
Функция ИмяКолонкиДляЗапроса(ИмяПоля)
Если ЭтоИмяКолонкиКонцаДиапазона(ИмяПоля) Тогда
Возврат Лев(ИмяПоля, СтрДлина(ИмяПоля) - СтрДлина(ПостфиксКонцаДиапазона()));
Иначе
Возврат ИмяПоля;
КонецЕсли;
КонецФункции
// Определяет, описывает ли колонка конец диапазона постраничной выборки.
//
// Параметры:
// ИмяПоля - Строка - имя поля.
//
// Возвращаемое значение:
// Булево - Истина, если это поле описывает конец диапазона постраничной выборки.
//
Функция ЭтоИмяКолонкиКонцаДиапазона(ИмяПоля)
Возврат СтрЗаканчиваетсяНа(ИмяПоля, ПостфиксКонцаДиапазона());
КонецФункции
Функция ПостфиксКонцаДиапазона()
Возврат "_" + "КонецДиапазона";
КонецФункции
// Проверка корректности заполнения параметров выборки данных.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
Процедура ПроверитьПараметрыВыборки(Параметры)
Если Не Параметры.ВыбиратьПорциями И ЭтоПостраничнаяВыборка(Параметры) Тогда
ВызватьИсключение НСтр("ru = 'Многопоточный обработчик обновления обязан выбирать данные порциями.'");
КонецЕсли;
КонецПроцедуры
// Формирует фрагмент текста запроса с выбираемыми полями.
//
// Параметры:
// ИменаПолей - Массив - имена полей в виде массива.
// Псевдонимы - Массив - псевдонимы в виде массива с тем же количеством элементов, что и в ИменаПолей.
// - Неопределено - в этом случае, псевдонимы равны именам полей.
// ИмяТаблицы - Строка - имя таблицы в которой расположены поля.
// если указана пустая строка, то имя таблицы не подставляется.
// Дополнительные - Булево - Истина, если это не первые поля в выборке и перед ними нужна ",".
//
// Возвращаемое значение:
// Строка - фрагмент текста запроса с выбираемыми полями.
//
Функция ПоляДляЗапроса(ИменаПолей, Псевдонимы = Неопределено, ИмяТаблицы = "", Дополнительные = Ложь)
КоличествоПолей = ИменаПолей.Количество();
Если КоличествоПолей = 0 Тогда
Возврат "";
КонецЕсли;
ЕстьПсевдонимы = Псевдонимы <> Неопределено И Псевдонимы.Количество() = КоличествоПолей;
ПолноеИмяТаблицы = ?(ПустаяСтрока(ИмяТаблицы), "", ИмяТаблицы + ".");
ИспользуемыеПсевдонимы = Новый Соответствие;
Поля = Новый Массив;
Для Индекс = 0 По КоличествоПолей - 1 Цикл
ИмяПоля = ИменаПолей[Индекс];
Если ЕстьПсевдонимы Тогда
Псевдоним = Псевдонимы[Индекс];
Иначе
Состав = СтрРазделить(ИмяПоля, ".");
Псевдоним = Состав[Состав.Количество() - 1];
ИспользуемыйПсевдоним = ИспользуемыеПсевдонимы[Псевдоним];
Если ИспользуемыйПсевдоним = Неопределено Тогда
ИспользуемыеПсевдонимы[Псевдоним] = 1;
Иначе
ИспользуемыеПсевдонимы[Псевдоним] = ИспользуемыеПсевдонимы[Псевдоним] + 1;
Псевдоним = Псевдоним + Формат(ИспользуемыеПсевдонимы[Псевдоним], "ЧГ=0");
КонецЕсли;
КонецЕсли;
Если ОбщегоНазначенияКлиентСервер.ИмяСоответствуетТребованиямИменованияСвойств(Псевдоним) Тогда
Псевдоним = " КАК " + Псевдоним;
Иначе
Псевдоним = "";
КонецЕсли;
Имя = ПолноеИмяТаблицы + ИмяПоля + Псевдоним;
Поля.Добавить(Имя);
КонецЦикла;
Разделитель = ",
| ";
Возврат ?(Дополнительные, Разделитель, "") + СтрСоединить(Поля, Разделитель);
КонецФункции
// Формирует фрагмент текста запроса с указанным порядком.
//
// Параметры:
// ИменаПолей - Массив - имена полей в виде массива.
// Направления - Массив - направления упорядочивания (ВОЗР, УБЫВ) в количестве равном количеству ИменаПолей.
// - Неопределено - порядок не указывается (всегда ВОЗР).
// ИмяТаблицы - Строка - имя таблицы в которой расположены поля.
// если указана пустая строка, то имя таблицы не подставляется.
// Дополнительные - Булево - Истина, если это не первые поля в выборке и перед ними нужна ",".
//
// Возвращаемое значение:
// Строка - фрагмент текста запроса для упорядочивания.
//
Функция УпорядочиванияДляЗапроса(ИменаПолей, Направления = Неопределено, ИмяТаблицы = "", Дополнительные = Ложь)
КоличествоПолей = ИменаПолей.Количество();
Если КоличествоПолей = 0 Тогда
Возврат "";
КонецЕсли;
ПолноеИмяТаблицы = ?(ПустаяСтрока(ИмяТаблицы), "", ИмяТаблицы + ".");
ЕстьНаправления = Направления <> Неопределено И Направления.Количество() = КоличествоПолей;
Упорядочивание = Новый Массив;
Для Индекс = 0 По КоличествоПолей - 1 Цикл
ИмяПоля = ИменаПолей[Индекс];
Если ЕстьНаправления Тогда
ТекущееНаправление = Направления[Индекс];
Направление = ?(ПустаяСтрока(ТекущееНаправление), "", " " + ТекущееНаправление);
Иначе
Направление = "";
КонецЕсли;
Порядок = ПолноеИмяТаблицы + ИмяПоля + Направление;
Упорядочивание.Добавить(Порядок);
КонецЦикла;
Разделитель = ",
| ";
Возврат ?(Дополнительные, Разделитель, "") + СтрСоединить(Упорядочивание, Разделитель);
КонецФункции
// Установить размер выборки запроса, получающего данные для обновления.
//
// Параметры:
// ТекстЗапроса - Строка - текст модифицируемого запроса.
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
Процедура УстановитьРазмерВыборки(ТекстЗапроса, Параметры)
РазмерВыборки = ?(Параметры.ВыбиратьПорциями, Параметры.МаксимумВыборки, Неопределено);
ИзменитьМаксимумВыборки(ТекстЗапроса, 10000, РазмерВыборки);
КонецПроцедуры
// Установить размер выборки запроса (ПЕРВЫЕ N).
//
// Параметры:
// ТекстЗапроса - Строка - текст изменяемого запроса.
// ТекущееКоличество - Число - количество, установленное в текущем тексте запроса.
// НовоеКоличество - Число - новое значение для "ПЕРВЫЕ N".
// - Неопределено - выбрать все (без ПЕРВЫЕ N).
//
Процедура ИзменитьМаксимумВыборки(ТекстЗапроса, ТекущееКоличество, НовоеКоличество)
ТекстПоиска = "ПЕРВЫЕ " + Формат(ТекущееКоличество, "ЧН=0; ЧГ=0"); // @query-part
Если НовоеКоличество = Неопределено Тогда
ТекстЗамены = "";
Иначе
ТекстЗамены = "ПЕРВЫЕ " + Формат(НовоеКоличество, "ЧН=0; ЧГ=0"); // @query-part
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ТекстПоиска, ТекстЗамены);
КонецПроцедуры
// Установить поля выборки с учетом многопоточных обработчиков обновления.
//
// Параметры:
// Запрос - Запрос - модифицируемый запрос.
// ИменаПолей - Массив - имена полей для выборки.
// Псевдонимы - Массив - псевдонимы выбираемых полей.
// ИмяТаблицы - Строка - имя таблицы в которой расположены поля.
// если указана пустая строка, то имя таблицы не подставляется.
//
Процедура УстановитьПоляПоСтраницам(Запрос, ПараметрыПостроения)
ВыбираемыеПоля = ПоляДляЗапроса(ПараметрыПостроения.ПоляВыборки,
ПараметрыПостроения.Псевдонимы,
ПараметрыПостроения.ИмяТаблицы);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ВыбираемыеПоля", ВыбираемыеПоля);
КонецПроцедуры
// Установить порядок выборки с учетом многопоточных обработчиков обновления.
//
// Параметры:
// Запрос - Запрос - модифицируемый запрос.
// ИменаПолей - Массив - имена полей для выборки.
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
// ИмяТаблицы - Строка - имя таблицы в которой расположены поля.
// если указана пустая строка, то имя таблицы не подставляется.
// Направления - Массив - направления упорядочивания (ВОЗР, УБЫВ) в количестве равном количеству ИменаПолей.
// - Неопределено - порядок не указывается (всегда ВОЗР).
//
Процедура УстановитьПорядокПоСтраницам(Запрос, ПараметрыПостроения)
ПоляВыборки = ПараметрыПостроения.ПоляВыборки;
ИмяТаблицы = ПараметрыПостроения.ИмяТаблицы;
Направления = ПараметрыПостроения.Направления;
Если Направления.Количество() = 0 Тогда
Направления.Добавить("УБЫВ");
Если ПараметрыПостроения.ПостраничнаяВыборка Тогда
Для Индекс = 1 По ПоляВыборки.Количество() - 1 Цикл
Направления.Добавить("");
КонецЦикла;
КонецЕсли;
КонецЕсли;
ПорядокВыборки = УпорядочиванияДляЗапроса(ПоляВыборки, Направления, ИмяТаблицы);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ПорядокВыборки", ПорядокВыборки);
КонецПроцедуры
// Позволяет определить постраничная ли это выборка.
//
// Параметры:
// Параметры - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляОбработки.
//
// Возвращаемое значение:
// Булево - Истина, если выборка многопоточная.
//
Функция ЭтоПостраничнаяВыборка(Параметры)
Возврат Параметры.Свойство("СпособВыборки") И Параметры.ВыбиратьПорциями;
КонецФункции
// Возвращает, выполняется ли упорядочивание по возрастанию.
//
// Параметры:
// Направление - Строка - проверяемое направление упорядочивания.
//
// Возвращаемое значение:
// Булево - Истина, если упорядочивание по возрастанию, иначе Ложь.
//
Функция УпорядочиваниеПоВозрастанию(Направление)
Если Направление = Неопределено Тогда
Возврат Истина;
Иначе
ПорядокВРег = ВРег(Направление);
// НеПереводить: "УБЫВ".
Возврат НЕ (ПорядокВРег = "УБЫВ" Или ПорядокВРег = "DESC");
КонецЕсли;
КонецФункции
// Возвращает оператор ">" для страничной выборки, с учетом порядка упорядочивания.
//
// Параметры:
// Направление - Строка - проверяемое направление упорядочивания.
//
// Возвращаемое значение:
// Строка - оператор ">", если Порядок = "ВОЗР", иначе "<".
//
Функция ОператорБольше(Направление)
Возврат ?(УпорядочиваниеПоВозрастанию(Направление), ">", "<");
КонецФункции
// Возвращает оператор "<" для страничной выборки, с учетом порядка упорядочивания.
//
// Параметры:
// Направление - Строка - проверяемое направление упорядочивания.
//
// Возвращаемое значение:
// Строка - оператор "<", если Порядок = "ВОЗР", иначе ">".
//
Функция ОператорМеньше(Направление)
Возврат ?(УпорядочиваниеПоВозрастанию(Направление), "<", ">");
КонецФункции
// Возвращает оператор ">=" для страничной выборки, с учетом порядка упорядочивания.
//
// Параметры:
// Направление - Строка - проверяемое направление упорядочивания.
//
// Возвращаемое значение:
// Строка - оператор ">=", если Порядок = "ВОЗР", иначе "<=".
//
Функция ОператорБольшеИлиРавно(Направление)
Возврат ?(УпорядочиваниеПоВозрастанию(Направление), ">=", "<=");
КонецФункции
// Возвращает оператор "<=" для страничной выборки, с учетом порядка упорядочивания.
//
// Параметры:
// Направление - Строка - проверяемое направление упорядочивания.
//
// Возвращаемое значение:
// Строка - оператор "<=", если Порядок = "ВОЗР", иначе ">=".
//
Функция ОператорМеньшеИлиРавно(Направление)
Возврат ?(УпорядочиваниеПоВозрастанию(Направление), "<=", ">=");
КонецФункции
// Возвращает имя объекта метаданных из его полного имени.
//
// Параметры:
// ПолноеИмя - Строка - полное имя объекта метаданных.
//
// Возвращаемое значение:
// Строка - имя объекта метаданных (после точки).
//
Функция ИмяОбъектаМетаданных(ПолноеИмя)
Позиция = СтрНайти(ПолноеИмя, ".", НаправлениеПоиска.СКонца);
Если Позиция > 0 Тогда
Возврат Сред(ПолноеИмя, Позиция + 1);
Иначе
Возврат ПолноеИмя;
КонецЕсли;
КонецФункции
// Возвращает признак наличия полей упорядочивания.
//
// Параметры:
//
Функция ЗаданыПоляУпорядочивания(ДополнительныеПараметры)
Возврат ДополнительныеПараметры.ПоляУпорядочивания.Количество() > 0;
КонецФункции
// Возвращает вид источника данных, см. ДополнительныеПараметрыВыборкиДанныхДляОбработки п. 1 и п. 2.
//
// Параметры:
// ДополнительныеИсточникиДанных - см. ДополнительныеПараметрыВыборкиДанныхДляОбработки
//
// Возвращаемое значение:
// Булево - Истина, если это простой набор источников, как в п.1, Ложь - если это иерархия соответствий,
// как в п. 2.
//
Функция ЭтоПростойИсточникДанных(ДополнительныеИсточникиДанных)
ПростойИсточник = Ложь;
СложныйИсточник = Ложь;
ТипСоответствие = Тип("Соответствие");
Для Каждого КлючИЗначение Из ДополнительныеИсточникиДанных Цикл
Если ТипЗнч(КлючИЗначение.Значение) = ТипСоответствие Тогда
СложныйИсточник = Истина;
Иначе
ПростойИсточник = Истина;
КонецЕсли;
КонецЦикла;
Если ПростойИсточник И СложныйИсточник Тогда
Ошибка = НСтр("ru = 'Источник данных задан неверно (см. %1).'");
Ошибка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Ошибка, "ДополнительныеПараметрыВыборкиДанныхДляОбработки()");
ВызватьИсключение Ошибка;
Иначе
Возврат ПростойИсточник;
КонецЕсли;
КонецФункции
Функция ЭтоПеречисление(ПроверяемыйТип)
Возврат Перечисления.ТипВсеСсылки().СодержитТип(ПроверяемыйТип);
КонецФункции
// Добавить в список запросов запросы, уничтожающие указанные временные таблицы.
//
// Параметры:
// Запросы - Массив - массив, в который добавляются тексты запросов.
// ВременныеТаблицы - Соответствие
//
Процедура ДобавитьЗапросыУничтоженияВТ(Запросы, ВременныеТаблицы)
ШаблонЗапроса =
"УНИЧТОЖИТЬ
| %1";
Для Каждого ВременнаяТаблица Из ВременныеТаблицы Цикл
ТекстЗапроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗапроса, ВременнаяТаблица.Значение);
Запросы.Добавить(ТекстЗапроса);
КонецЦикла;
КонецПроцедуры
// Получить значение коллекции по ключу, а если ключ не найден, создать для ключа значение указанного типа.
//
// Параметры:
// Коллекция - Соответствие
// - Структура - коллекция в которой ищется значение.
// Ключ - Произвольный - ключ по которому ищется значение.
// Тип - Строка - тип создаваемого значения.
//
// Возвращаемое значение:
// Соответствие
//
Функция ЗначениеПоКлючу(Коллекция, Ключ, Тип = "Соответствие")
Значение = Коллекция[Ключ];
Если Значение = Неопределено Тогда
Значение = Новый(Тип);
Коллекция[Ключ] = Значение;
КонецЕсли;
Возврат Значение;
КонецФункции
// Объединить указанные тексты запросов в пакет.
//
// Параметры:
// Запросы - Массив - тексты запросов, которые нужно объединить.
// РазделительЗапросов - Строка
// - Неопределено - текст разделителя запросов (по умолчанию, как у конструктора).
//
// Возвращаемое значение:
// Строка - запросы, объединенные в пакет.
//
Функция ОбъединитьЗапросыВПакет(Запросы, РазделительЗапросов = Неопределено)
Если РазделительЗапросов = Неопределено Тогда
Разделитель =
"
|;
|
|";
Иначе
Разделитель = РазделительЗапросов;
КонецЕсли;
Возврат СтрСоединить(Запросы, Разделитель);
КонецФункции
// Получить источник данных в виде структуры с полями ТабличнаяЧасть и Реквизит.
//
// Параметры:
// Источник - Строка - источник данных (путь к реквизиту шапки или табличной части объекта).
//
// Возвращаемое значение:
// Структура:
// * ТабличнаяЧасть - Строка - имя табличной части (Неопределено, если источник - реквизит шапки).
// * Реквизит - Строка - имя реквизита.
//
Функция СоставСсылочногоИсточникаДанных(Источник)
Состав = СтрРазделить(Источник, ".");
Описание = Новый Структура("ТабличнаяЧасть, Реквизит");
Если Состав.Количество() > 1 Тогда
Описание.ТабличнаяЧасть = СокрЛП(Состав[0]);
Описание.Реквизит = СокрЛП(Состав[1]);
Иначе
Описание.Реквизит = СокрЛП(Состав[0]);
КонецЕсли;
Возврат Описание;
КонецФункции
// Текст запроса создания временной таблицы со ссылками, заблокированными по реквизитам табличных частей.
//
// Параметры:
// РеквизитыТЧ - Соответствие из КлючИЗначение:
// * Ключ - Строка - имя табличной части источника данных.
// * Значение - Соответствие из КлючИЗначение:
// ** Ключ - ОбъектМетаданных - объект метаданных, соответствующий типу источника данных.
// ** Значение - Соответствие из КлючИЗначение:
// *** Ключ - Строка - имя реквизита табличной части источника данных.
// *** Значение - Булево - Истина, как значение по умолчанию (не нужно, т.к. по сути - это множество).
// ПолноеИмяОбъекта - Строка - полное имя обновляемого ссылочного объекта метаданных.
// ПолноеИмяРегистра - Строка - полное имя обновляемого объекта метаданных регистра.
// ВременныеТаблицы - Соответствие из КлючИЗначение:
// * Ключ - ОбъектМетаданных - для которого создана временная таблица.
// * Значение - Строка - имя временной таблицы.
//
// Возвращаемое значение:
// Строка - текст запроса.
//
Функция ТекстЗапросаВТЗаблокированныхПоТЧ(РеквизитыТЧ, ПолноеИмяОбъекта, ПолноеИмяРегистра, ВременныеТаблицы)
ШаблонЗапроса =
"ВЫБРАТЬ
| &Реквизит КАК Ссылка
|ПОМЕСТИТЬ ЗаблокированныеПоТЧ
|ИЗ
| &ТаблицаИзменений КАК ТаблицаИзменений
|ГДЕ
| &Условие
|ИНДЕКСИРОВАТЬ ПО
| Ссылка";
ШаблонУсловия =
"ИСТИНА В " + "(" + "
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #Таблица КАК ТЧДокументаПолноеИмяОбъекта
| ГДЕ
| &УсловиеПоПолюТаблицы
| И (&ТекстУсловийПоЗаблокированным)" + ")";
ШаблонУсловияПоЗаблокированным =
"ИСТИНА В " + "(" + "
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #Таблица КАК ВТЗаблокированоТаблица
| ГДЕ
| &УсловиеПоЗаблокированным" + ")";
ШаблонУсловияПоРеквизиту = "ТЧДокумента%1.%2 = %3.Ссылка"; // @query-part
РазделительУсловий =
"
| ИЛИ ";
РазделительУсловийПоЗаблокированным =
"
| ИЛИ ";
РазделительУсловийПоРеквизитам =
"
| ИЛИ ";
Если ПолноеИмяРегистра <> Неопределено Тогда
ПолеТаблицы = "Регистратор";
Таблица = ПолноеИмяРегистра;
Иначе
ПолеТаблицы = "Ссылка";
Таблица = ПолноеИмяОбъекта;
КонецЕсли;
Условия = Новый Массив;
Для Каждого ОписаниеТабличнойЧасти Из РеквизитыТЧ Цикл
ТабличнаяЧасть = ОписаниеТабличнойЧасти.Ключ;
МетаданныеРеквизитов = ОписаниеТабличнойЧасти.Значение;
УсловияПоЗаблокированным = Новый Массив;
Для Каждого ОписаниеМетаданных Из МетаданныеРеквизитов Цикл
МетаданныеИсточника = ОписаниеМетаданных.Ключ;
Реквизиты = ОписаниеМетаданных.Значение;
ТаблицаЗаблокированных = ВременныеТаблицы[МетаданныеИсточника];
УсловияПоРеквизитам = Новый Массив;
Для Каждого ОписаниеРеквизита Из Реквизиты Цикл
Реквизит = ОписаниеРеквизита.Ключ;
УсловиеПоРеквизиту = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияПоРеквизиту,
ТабличнаяЧасть,
Реквизит,
ТаблицаЗаблокированных);
УсловияПоРеквизитам.Добавить(УсловиеПоРеквизиту);
КонецЦикла;
ТекстУсловийПоРеквизитам = СтрСоединить(УсловияПоРеквизитам, РазделительУсловийПоРеквизитам);
УсловиеПоЗаблокированным = СтрЗаменить(ШаблонУсловияПоЗаблокированным, "#Таблица", ТаблицаЗаблокированных);
УсловиеПоЗаблокированным = СтрЗаменить(УсловиеПоЗаблокированным, "ВТЗаблокированоТаблица", ТаблицаЗаблокированных);
УсловиеПоЗаблокированным = СтрЗаменить(УсловиеПоЗаблокированным, "&УсловиеПоЗаблокированным", ТекстУсловийПоРеквизитам);
УсловияПоЗаблокированным.Добавить(УсловиеПоЗаблокированным);
КонецЦикла;
ТекстУсловийПоЗаблокированным = СтрСоединить(УсловияПоЗаблокированным, РазделительУсловийПоЗаблокированным);
Условие = СтрЗаменить(ШаблонУсловия, "#Таблица", ПолноеИмяОбъекта + "." + ТабличнаяЧасть);
Условие = СтрЗаменить(Условие, "ТЧДокументаПолноеИмяОбъекта", "ТЧДокумента" + ТабличнаяЧасть);
Условие = СтрЗаменить(Условие, "&УсловиеПоПолюТаблицы", "ТаблицаИзменений." + ПолеТаблицы + " = ТЧДокумента"+ ТабличнаяЧасть + ".Ссылка");
Условие = СтрЗаменить(Условие, "&ТекстУсловийПоЗаблокированным", ТекстУсловийПоЗаблокированным);
Условия.Добавить(Условие);
КонецЦикла;
ТекстУсловий = СтрСоединить(Условия, РазделительУсловий);
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&Реквизит", ПолеТаблицы);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТаблицаИзменений", Таблица + ".Изменения");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Условие", ТекстУсловий);
Возврат ТекстЗапроса;
КонецФункции
// Текст условия запроса для исключения из обновления данных, заблокированных по регистру.
//
// Параметры:
// ПолноеИмяРегистра - Строка - полное имя обновляемого объекта метаданных регистра.
// ВременныеТаблицы - Соответствие из КлючИЗначение:
// * Ключ - ОбъектМетаданных - для которого создана временная таблица.
// * Значение - Строка - имя временной таблицы.
//
// Возвращаемое значение:
// Строка - текст запроса.
//
Функция ТекстУсловияЗаблокированныхПоРегистрам(ПолноеИмяРегистра, ВременныеТаблицы)
ШаблонУсловия =
"НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| %1 КАК %1
| ГДЕ
| %2 = %1.Регистратор)";
РазделительУсловий =
"
| И ";
Поле = ?(ПолноеИмяРегистра <> Неопределено, "ТаблицаРегистраИзменения.Регистратор", "ТаблицаОбъекта.Ссылка");
Условия = Новый Массив;
Для Каждого ОписаниеВременнойТаблицы Из ВременныеТаблицы Цикл
ВременнаяТаблица = ОписаниеВременнойТаблицы.Значение;
Условие = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловия, ВременнаяТаблица, Поле);
Условия.Добавить(Условие);
КонецЦикла;
Возврат СтрСоединить(Условия, РазделительУсловий);
КонецФункции
// Текст условия запроса для исключения из обновления данных, заблокированных по реквизитам табличных частей.
//
// Параметры:
// ПолноеИмяОбъекта - Строка - полное имя обновляемого ссылочного объекта метаданных.
// ПолноеИмяРегистра - Строка - полное имя обновляемого объекта метаданных регистра.
//
// Возвращаемое значение:
// Строка - текст запроса.
//
Функция ТекстУсловияЗаблокированныхПоТЧ(ПолноеИмяОбъекта, ПолноеИмяРегистра)
Поле = ?(ПолноеИмяРегистра <> Неопределено, "ТаблицаРегистраИзменения.Регистратор", "ТаблицаИзменений.Ссылка");
ШаблонУсловия =
"НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ЗаблокированныеПоТЧ КАК ЗаблокированныеПоТЧ
| ГДЕ
| %1 = ЗаблокированныеПоТЧ.Ссылка)";
Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловия, Поле);
КонецФункции
// Текст условия запроса для исключения из обновления данных, заблокированных по реквизитам шапки объекта.
//
// Параметры:
// РеквизитыШапки - Соответствие из КлючИЗначение:
// * Ключ - ОбъектМетаданных - объект метаданных, соответствующий типу источника данных.
// * Значение - Соответствие из КлючИЗначение:
// ** Ключ - Строка - имя реквизита табличной части источника данных.
// ** Значение - Булево - Истина, как значение по умолчанию (не нужно, т.к. по сути - это множество).
// ПолноеИмяРегистра - Строка - полное имя обновляемого объекта метаданных регистра.
// ВременныеТаблицы - Соответствие из КлючИЗначение:
// * Ключ - ОбъектМетаданных - для которого создана временная таблица.
// * Значение - Строка - имя временной таблицы.
//
// Возвращаемое значение:
// Строка - текст запроса.
//
Функция ТекстУсловияЗаблокированныхПоШапке(РеквизитыШапки, ПолноеИмяРегистра, ВременныеТаблицы)
ШаблонУсловия =
"НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| %1 КАК %1
| ГДЕ
| %2)";
ШаблонУсловияПоРеквизиту = "%1.%2 = %3.Ссылка";
РазделительУсловий =
"
| И ";
РазделительУсловийПоРеквизитам =
"
| ИЛИ ";
Таблица = ?(ПолноеИмяРегистра <> Неопределено, "ТаблицаДокумента", "ТаблицаОбъекта");
Условия = Новый Массив;
Для Каждого ОписаниеМетаданных Из РеквизитыШапки Цикл
МетаданныеИсточника = ОписаниеМетаданных.Ключ;
ТаблицаЗаблокированных = ВременныеТаблицы[МетаданныеИсточника];
Реквизиты = ОписаниеМетаданных.Значение;
УсловияПоРеквизитам = Новый Массив;
Для Каждого ОписаниеРеквизита Из Реквизиты Цикл
Реквизит = ОписаниеРеквизита.Ключ;
УсловиеПоРеквизиту = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияПоРеквизиту,
Таблица,
Реквизит,
ТаблицаЗаблокированных);
УсловияПоРеквизитам.Добавить(УсловиеПоРеквизиту);
КонецЦикла;
ТекстУсловийПоРеквизитам = СтрСоединить(УсловияПоРеквизитам, РазделительУсловийПоРеквизитам);
Условие = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловия,
ТаблицаЗаблокированных,
ТекстУсловийПоРеквизитам);
Условия.Добавить(Условие);
КонецЦикла;
Возврат СтрСоединить(Условия, РазделительУсловий);
КонецФункции
// Формирует условие для отбора только не заблокированных комбинаций измерений.
//
// Параметры:
// Измерения - Массив - имена измерений, по которым нужно сделать отбор.
//
// Возвращаемое значение:
// Строка - текст условия отбора.
//
Функция УсловиеОтбораНезаблокированныхИзмерений(Измерения)
УсловияНаИзмерения = Новый Массив;
ШаблонУсловияНаИзмерение =
"(ТаблицаИзменений.%1 = ВТЗаблокированоИзмерения.%1
| ИЛИ ТаблицаИзменений.%1 = &ПустоеЗначениеИзмерения%1
| ИЛИ ВТЗаблокированоИзмерения.%1 = &ПустоеЗначениеИзмерения%1)";
ШаблонУсловияПоОтборуНезаблокированных =
" НЕ ИСТИНА В (
| ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| #ВТЗаблокированоИзмерения КАК ВТЗаблокированоИзмерения
| ГДЕ
| %1)";
РазделительИ =
"
| И ";
Для Каждого Измерение Из Измерения Цикл
Условие = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияНаИзмерение, Измерение);
УсловияНаИзмерения.Добавить(Условие);
КонецЦикла;
УсловияПоВсемИзмерениям = СтрСоединить(УсловияНаИзмерения, РазделительИ);
Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияПоОтборуНезаблокированных,
УсловияПоВсемИзмерениям);
КонецФункции
Функция ОбъектРегистрируетсяНаПланеОбмена(Данные)
ТипОбъекта = ТипЗнч(Данные);
Кеш = ОбновлениеИнформационнойБазыСлужебныйПовтИсп.КешПроверкиЗарегистрированныхОбъектов();
ВходитВСостав = Кеш.Получить(ТипОбъекта);
Если ВходитВСостав <> Неопределено Тогда
Возврат ВходитВСостав;
КонецЕсли;
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипОбъекта);
Если ОбъектМетаданных = Неопределено Тогда
Кеш.Вставить(ТипОбъекта, Ложь);
Возврат Ложь;
КонецЕсли;
СоставПланаОбмена = Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Состав;
ВходитВСостав = СоставПланаОбмена.Содержит(ОбъектМетаданных);
Кеш.Вставить(ТипОбъекта, ВходитВСостав);
Возврат ВходитВСостав;
КонецФункции
Процедура СброситьСостояниеОбработчика(Обработчик)
ОбработчикОбновления = РегистрыСведений.ОбработчикиОбновления.СоздатьМенеджерЗаписи();
ОбработчикОбновления.ИмяОбработчика = Обработчик;
ОбработчикОбновления.Прочитать();
ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.НеВыполнялся;
ОбработчикОбновления.ДлительностьОбработки = 0;
ОбработчикОбновления.ЧислоПопыток = 0;
ОбработчикОбновления.СтатистикаВыполнения = Новый ХранилищеЗначения(Новый Соответствие);
ОбработчикОбновления.ИнформацияОбОшибке = "";
ОбработчикОбновления.ОбработкаПорцииЗавершена = Истина;
ОбработчикОбновления.Записать();
КонецПроцедуры
Процедура ЗаписатьПрогрессВыполненияОбработчика(Данные, Узел, МетаданныеОбъекта = Неопределено)
ОбъектовОбработано = 0;
Если (ТипЗнч(Данные) = Тип("Массив")
Или ТипЗнч(Данные) = Тип("ТаблицаЗначений")) Тогда
ОбъектовОбработано = Данные.Количество();
Иначе
Если МетаданныеОбъекта = Неопределено Тогда
ТипЗначенияОбъекта = ТипЗнч(Данные);
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗначенияОбъекта);
КонецЕсли;
Если ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
ПолноеИмя = МетаданныеОбъекта.ПолноеИмя();
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Узел", Узел);
Запрос.УстановитьПараметр("Ссылка", Данные.Ссылка);
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| &ИмяТаблицыИзменений КАК ТаблицаИзменения
|ГДЕ
| ТаблицаИзменения.Узел = &Узел
| И ТаблицаИзменения.Ссылка = &Ссылка";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыИзменений", ПолноеИмя + ".Изменения"); // @query-part
Если Не Запрос.Выполнить().Пустой() Тогда
ОбъектовОбработано = 1;
КонецЕсли;
Иначе
Если Данные.Количество() = 0 Тогда
ОбъектовОбработано = 1;
Иначе
ОбъектовОбработано = Данные.Количество();
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ОбъектовОбработано = 0 Тогда
Возврат;
КонецЕсли;
ПараметрыОбработчикаОбновления = ПараметрыСеанса.ПараметрыОбработчикаОбновления;
ТекущаяДата = ТекущаяДатаСеанса();
ИнтервалЧас = НачалоЧаса(ТекущаяДата);
МенеджерЗаписи = РегистрыСведений.ПрогрессОбновления.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИмяОбработчика = ПараметрыОбработчикаОбновления.ИмяОбработчика;
МенеджерЗаписи.КлючЗаписи = ПараметрыОбработчикаОбновления.КлючЗаписиПрогрессаОбновления;
МенеджерЗаписи.ИнтервалЧас = ИнтервалЧас;
МенеджерЗаписи.Прочитать();
Если Не МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.ИмяОбработчика = ПараметрыОбработчикаОбновления.ИмяОбработчика;
МенеджерЗаписи.КлючЗаписи = ПараметрыОбработчикаОбновления.КлючЗаписиПрогрессаОбновления;
МенеджерЗаписи.ИнтервалЧас = ИнтервалЧас;
МенеджерЗаписи.ОбъектовОбработано = ОбъектовОбработано;
Иначе
МенеджерЗаписи.ОбъектовОбработано = МенеджерЗаписи.ОбъектовОбработано + ОбъектовОбработано;
КонецЕсли;
МенеджерЗаписи.Записать();
КонецПроцедуры
Процедура УстановитьПараметрыОбработчикаПриВыборкеДанных(ДополнительныеПараметры, ОбработаныВсеАктуальныеДанные, ПараметрыОбработчикаОбновления, ПолноеИмяДокумента = Неопределено)
Если ПараметрыОбработчикаОбновления = Неопределено Тогда
ПараметрыОбработчика = ПараметрыСеанса.ПараметрыОбработчикаОбновления;
Иначе
ПараметрыОбработчика = ПараметрыОбработчикаОбновления;
КонецЕсли;
ПараметрыОбработчика = Новый Структура(ПараметрыОбработчика);
Если ПолноеИмяДокумента = Неопределено Тогда
ПараметрыОбработчика.ОбработаныАктуальныеДанные = ОбработаныВсеАктуальныеДанные;
Иначе
Если ПараметрыОбработчика.ОбработанныеТаблицыРегистраторов = Неопределено Тогда
ОбработанныеТаблицы = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ПолноеИмяДокумента);
Иначе
ОбработанныеТаблицы = Новый Массив(ПараметрыОбработчика.ОбработанныеТаблицыРегистраторов);
ОбработанныеТаблицы.Добавить(ПолноеИмяДокумента);
КонецЕсли;
ОбработанныеТаблицы = Новый ФиксированныйМассив(ОбработанныеТаблицы);
ПараметрыОбработчика.ОбработанныеТаблицыРегистраторов = ОбработанныеТаблицы;
КонецЕсли;
Если ПараметрыОбработчикаОбновления = Неопределено Тогда
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(ПараметрыОбработчика);
Иначе
ДополнительныеПараметры.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(ПараметрыОбработчика);
КонецЕсли;
КонецПроцедуры
#КонецОбласти