При настройке обмена данными между конфигурациями (например, между «Бухгалтерия предприятия 2.0» и «Управление торговлей 10.3») часто возникает задача защитить определенные документы в базе-приемнике от перезаписи. Типичный сценарий: если документу в базе-приемнике присвоена категория (например, «Не редактировать»), его данные не должны обновляться при повторных выгрузках из базы-источника. Рассмотрим, в каких обработчиках Конвертации данных следует выполнять проверку, как составить оптимальный запрос и как правильно раскрасить такие документы в форме списка.
Разберем последовательность работы механизмов загрузки в «Конвертации данных 2.0»:
СсылкаНаОбъект (или Объект.Ссылка) доступна ссылка на существующий документ.Если мы установим флаг Отказ = Истина; в обработчике «После загрузки», запись текущего объекта будет корректно пропущена, при этом загрузка остальных объектов из пакета обмена продолжится без прерывания транзакции.
Проанализируем структуру регистра сведений КатегорииОбъектов. В типовых конфигурациях на обычных формах составной кластерный индекс СУБД строится по измерениям в порядке их следования: сначала Объект, затем Категория.
Если в запросе указать условие только по объекту, СУБД выполнит сканирование диапазона (Index Scan / Seek по первому полю) среди всех категорий, привязанных к объекту. Если же мы сразу укажем и конкретную категорию, запрос выполнит точечный поиск по полному ключу индекса (Exact Match Seek), что обеспечивает максимальное быстродействие.
Посмотрим на реализацию проверки в обработчике «После загрузки» нужного ПКО:
Если ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| 1
|ИЗ
| РегистрСведений.КатегорииОбъектов КАК КатегорииОбъектов
|ГДЕ
| КатегорииОбъектов.Объект = &Объект
| И КатегорииОбъектов.Категория = &Категория";
Запрос.УстановитьПараметр("Объект", СсылкаНаОбъект);
Запрос.УстановитьПараметр("Категория", Параметры.КатегорияНеРедактировать);
Если НЕ Запрос.Выполнить().Пустой() Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
Обратите внимание: ссылку на саму категорию «Не редактировать» рекомендуется один раз получить в глобальном обработчике правил «После загрузки правил обмена» и поместить в структуру Параметры, чтобы избежать постоянного поиска категории по наименованию в теле цикла загрузки документов.
Также вместо полного отказа от записи через Отказ = Истина; можно программно взвести флаг НеЗамещать = Истина;, если требуется оставить объект в базе нетронутым стандартными механизмами конвертации.
Выясним причину, почему нельзя выполнять запросы к базе данных в обработчике ПриВыводеСтроки. Это событие вызывается для каждой отдельной строки, что приводит к множественным одиночным запросам к СУБД и критическому падению производительности при прокрутке списка.
В обычном приложении для оформления списков правильно использовать обработчик ПриПолученииДанных табличного поля. Он принимает сразу массив оформлений для всех видимых на экране строк, что позволяет обработать данные одним пакетным запросом.
Разберем по шагам реализацию раскраски строк:
ОформленияСтрок и собираем массив ссылок документов.КатегорииОбъектов с условием В (&МассивСсылок).ОформленияСтрок и устанавливаем цвет фона или текста для тех строк, документы которых присутствуют в выборке.Посмотрим на пример кода в модуле формы списка:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
МассивСсылок = Новый Массив;
Для Каждого Оформление Из ОформленияСтрок Цикл
МассивСсылок.Добавить(Оформление.ДанныеСтроки.Ссылка);
КонецЦикла;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КатегорииОбъектов.Объект КАК Объект
|ИЗ
| РегистрСведений.КатегорииОбъектов КАК КатегорииОбъектов
|ГДЕ
| КатегорииОбъектов.Объект В(&МассивСсылок)
| И КатегорииОбъектов.Категория = &Категория";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Запрос.УстановитьПараметр("Категория", Справочники.КатегорииОбъектов.НайтиПоНаименованию("Не редактировать"));
Выборка = Запрос.Выполнить().Выбрать();
СоответствиеОбъектов = Новый Соответствие;
Пока Выборка.Следующий() Цикл
СоответствиеОбъектов.Вставить(Выборка.Объект, Истина);
КонецЦикла;
Для Каждого Оформление Из ОформленияСтрок Цикл
Если СоответствиеОбъектов[Оформление.ДанныеСтроки.Ссылка] <> Неопределено Тогда
Оформление.ЦветФона = WebЦвета.СветлоСерый;
Оформление.ЦветТекста = WebЦвета.ТемноКрасный;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Такой подход обеспечивает высокую скорость отрисовки формы списка при прокрутке и гарантирует надежную защиту помеченных документов от перезаписи при регулярных обменах.