Как работает платформа
Если открыть форму записи регистра и поменять значение измерения, то физически запись с старыми значениями удалится, и появится новая - с новыми измерениями. При этом в таблице изменений зарегистрируются две записи со старыми и новыми значениями измерения. В этой таблице будут колонки, соответствующие измерениям регистра с установленной галкой основной отбор, в которых и будут хранится значения измерений. Следует заметить, что в этой таблице нет других колонок, например признака удаления.
Если далее выбирать изменения для узла, то по каждой записи таблицы изменений будет получаться НаборЗаписей с установленными отборами, соответствующими значениям колонок таблицы изменений. Этот набор записей уже будет заполнен текущими существующими записями регистра, соответствующими отбору.
МетаданныеРегистра1 = Метаданные.РегистрыСведений.РегистрСведений1;
Выборка = ПланыОбмена.ВыбратьИзменения(Узел, НомерОтправляемогоСообщения, МетаданныеРегистра1);
Пока Выборка.Следующий() Цикл
Объект = Выборка.Получить();
// Объектом будет НаборЗаписей, с установленными отборами по значениям таблицы изменений и уже отобранными записями
...
КонецЦикла;
Как работает обработка УниверсальныйОбменДаннымиXML из БСП
Если просто настроить передачу регистра в правиле КД2, то передаваться будут только существующие в источнике записи, а из приемника старые записи удаляться не будут.
Это происходит потому, что набор записей полученный из выборки изменений, обходится по записям и каждая запись передается далее в правило конвертации. Таким образом в отправку попадают только новые записи, т.к. только они присутствуют в наборе.
Фрагмент модуля объекта обработки, где происходит обход набора записей из выборки изменений.
Если ВыгружаетсяРегистр Тогда
Для Каждого СтрокаРегистра Из ОбъектДляПравилВыгрузки Цикл
ВыгрузкаОбъектаВыборки(СтрокаРегистра, ТекущаяСтрокаПравилаВыгрузки, , ИсходящиеДанные);
КонецЦикла;
...
Здесь `ОбъектДляПравилВыгрузки` как раз тот самый набор записей полученный из `Выборка.Получить()`
Попытка обойти это использованием произвольного алгоритма в правиле выгрузки вместо стандартной выборки оказалось не успешной, т.к. при этом не присваивается номер сообщения.
Реализация
Из кода обработки обмена видно, что при "стандартной выборке" в ПВД все равно выполняется событие ПередОбработкой.
Передать из него в ПКО какие-то данные нельзя, Исходящие и ВходящиеДанные затираются.
После выполнения ПередОбработкой, если это регистр, происходит итерирование переменной ОбъектДляПравилВыгрузки, содержащей набор записей из выборки изменений.
Т.к. обработчики выполняются прямо в контексте обработки, а не изолированно, то хак выглядит в подмене этой переменной на массив структур. Понять, что запись удалена можно по тому, что набор записей пустой. Данный подход не сработает, если не у всех измерений регистра стоит галка "Основной отбор", т.к. тогда непонятно какие записи удалены.
(!) Переменная ОбъектДляПравилВыгрузки не упоминается в справке КД2, и может быть изменена в будущих версиях.
Используем полученные из анализа кода обработки знания для написания правил ПВД и ПКО регистра.
Правило выгрузки обычное, "Стандартная выборка". Только задаем обработчик "ПередОбработкой", где анализируем, была ли удалена запись.
// Недокументированные возможности обработки обмена
// ОбъектДляПравилВыгрузки - это набор записей регистра сведений полученный из выборки изменений узла.
// Он потом итератором обходится и выгружается по правилу конвертации
ЗаписьУдалена = (ОбъектДляПравилВыгрузки.Количество() = 0);
Если ЗаписьУдалена Тогда
Запись = Новый Структура;
Запись.Вставить("Измерение1", ОбъектДляПравилВыгрузки.Отбор.Измерение1.Значение);
Запись.Вставить("Измерение2", ОбъектДляПравилВыгрузки.Отбор.Измерение2.Значение);
Запись.Вставить("Измерение3", ОбъектДляПравилВыгрузки.Отбор.Измерение3.Значение);
Запись.Вставить("Ресурс1", ""); // Значение неизвестно и не важно
Запись.Вставить("ЗаписьУдалена", ЗаписьУдалена); // Признак удаления
Записи = Новый Массив;
Записи.Добавить(Запись);
ОбъектДляПравилВыгрузки = Записи; // Подмена
КонецЕсли;
Соответственно в ПКО приходит либо ЗаписьРегистра, если запись существует и обрабатывается как обычно. Или приходит структура, тогда это удаление.
Правило ПКО обычное, сопоставлены поля один в один.
Только дополнительно создаем поле "ЗаписьУдалена" для передачи в приемник в качестве параметра ("передавать в параметр").
Определяем его значение в обработчике ПКС "ПередВыгрузкой"
ЗаписьУдалена = Неопределено;
Если ТипЗнч(Источник) = Тип("Структура") И Источник.Свойство("ЗаписьУдалена", ЗаписьУдалена) Тогда
Значение = ЗаписьУдалена;
Иначе
Значение = Ложь;
КонецЕсли;
В общем случае, наверное, достаточно, что мы получили структуру, и это уже признак того, что запись удалена. Но как так сложилось.
Далее в приемнике нужно удалить запись, если установлен параметр "ЗаписьУдалена" и отменить запись.
Обработчик ПКО "ПослеЗагрузки"
Если ПараметрыОбъекта <> Неопределено
И ПараметрыОбъекта["ЗаписьУдалена"] <> Неопределено И ПараметрыОбъекта["ЗаписьУдалена"] Тогда
Запись = РегистрыСведений.РегистрСведений1.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(Запись, Объект);
Запись.Удалить();
Отказ = Истина;
КонецЕсли;
Этого достаточно для передачи удаленных записей регистра.
Дополнительно проводил эксперименты, снимал галку основной отбор у измерений и смотрел на состав индекса и возможность отбора в наборе записей. Индекс не изменился, в него также входили все измерения регистра. И отбор в наборе записей также работал и для измерений без основного отбора. Наверное, подробнее об этой галке написано в какой-нибудь книге от 1С.