Загрузка данных
/////////////////////////////////////////////////////////////////////////////
// Расширение общего модуля менеджера обмена (БП 3.0.191, формат 1.22)
//
// Назначение: несколько документов "Реализация товаров и услуг" с видом
// операции "Передача на комиссию", пришедших из УТ за один сеанс обмена,
// загружаются в БП как ОДИН документ.
//
// Механика: первый документ группы грузится штатно. У второго и последующих
// в ПОД подменяются ключевые свойства (Ссылка/Дата/Номер) на значения первого,
// поэтому штатная идентификация находит уже записанный документ и обновляет
// его. Табличная часть при этом не замещается, а дополняется.
//
// Перехват идёт через экспортный диспетчер ВыполнитьПроцедуруМодуляМенеджера,
// сами обработчики ПОД/ПКО в модуле не экспортные.
////////////////////////////////////////////////////////////////////////////////
#Область НастройкиОтбора
// ИНН комиссионера, передачи к которому нужно сворачивать.
// Если комиссионеров несколько — заменить на список.
Функция КМ_ИННКомиссионера()
Возврат "9714053621"; // ООО "РВБ" (Wildberries)
КонецФункции
#КонецОбласти
#Область Перехваты
&Перед("ВыполнитьПроцедуруМодуляМенеджера")
Процедура КМ_Перед_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры)
Если ИмяПроцедуры <> "ПКО_Документ_РеализацияТоваровУслуг_ПередЗаписьюПолученныхДанных" Тогда
Возврат;
КонецЕсли;
// ДанныеИБ = Неопределено означает, что документа в базе ещё нет:
// это первый документ группы, накапливать нечего.
Если Параметры.ДанныеИБ = Неопределено Тогда
Возврат;
КонецЕсли;
// Запоминаем строки, которые сейчас лежат в базе, — типовой обработчик
// ниже по стеку их затрёт строками нового документа.
Хранилище = КМ_Хранилище(Параметры.КомпонентыОбмена);
Хранилище.Вставить("НакопленныеТовары", Параметры.ДанныеИБ.Товары.Выгрузить());
КонецПроцедуры
&После("ВыполнитьПроцедуруМодуляМенеджера")
Процедура КМ_После_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры)
Если ИмяПроцедуры = "ПОД_Документ_РеализацияТоваровУслуг_ПриОбработке" Тогда
КМ_ПодменитьКлючевыеСвойства(Параметры.ОбъектОбработки, Параметры.КомпонентыОбмена);
ИначеЕсли ИмяПроцедуры = "ПКО_Документ_РеализацияТоваровУслуг_ПередЗаписьюПолученныхДанных" Тогда
КМ_ОбъединитьТовары(Параметры.ДанныеИБ, Параметры.КомпонентыОбмена);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ПодменаКлючевыхСвойств
Процедура КМ_ПодменитьКлючевыеСвойства(ДанныеXDTO, КомпонентыОбмена)
// Загрузка объекта как значения чужого свойства — трогать нельзя
// (аналог типовой ЭтоЗагрузкаКлючевыхСвойств).
Если ДанныеXDTO.Количество() = 1 Тогда
Возврат;
КонецЕсли;
Если Не КМ_ЭтоСворачиваемаяПередача(ДанныеXDTO) Тогда
Возврат;
КонецЕсли;
КлючГруппы = КМ_КлючГруппы(ДанныеXDTO);
Если Не ЗначениеЗаполнено(КлючГруппы) Тогда
Возврат;
КонецЕсли;
Хранилище = КМ_Хранилище(КомпонентыОбмена);
Лидер = Хранилище.Лидеры.Получить(КлючГруппы);
Если Лидер = Неопределено Тогда
// Первый документ группы. Грузится штатно, запоминаем его ключевые свойства.
Лидер = Новый Структура("Ссылка, Дата, Номер",
ДанныеXDTO.КлючевыеСвойства.Ссылка,
ДанныеXDTO.КлючевыеСвойства.Дата,
ДанныеXDTO.КлючевыеСвойства.Номер);
// Корневая Ссылка — именно её берёт СтруктураОбъектаXDTOВДанныеИБ
// как ОригинальныйУИДСтрокой. Это ключевая подмена.
КорневаяСсылка = Неопределено;
Если ДанныеXDTO.Свойство("Ссылка", КорневаяСсылка) Тогда
Лидер.Вставить("КорневаяСсылка", КорневаяСсылка);
КонецЕсли;
Хранилище.Лидеры.Вставить(КлючГруппы, Лидер);
Возврат;
КонецЕсли;
// Второй и последующие: выдаём себя за лидера.
//
// ГЛАВНОЕ — подменить УИД. Идентификация по полям поиска (Дата, Номер)
// здесь НЕ поможет: СсылкаОбъектаПоСвойствамОбъектаXDTO добавляет в запрос
// условие "ПубличныеИдентификаторы.Ссылка is null", то есть намеренно
// исключает уже сопоставленные объекты. Документ-лидер получает публичный
// идентификатор сразу при записи и становится невидим для этого поиска.
//
// С подменённым УИД срабатывает первая ветка идентификации —
// по публичному идентификатору, — и находит документ лидера.
Если Лидер.Свойство("КорневаяСсылка") И ДанныеXDTO.Свойство("Ссылка") Тогда
ДанныеXDTO.Ссылка = Лидер.КорневаяСсылка;
КонецЕсли;
// Ключевые свойства подменяем для консистентности шапки
// (номер и дата документа берутся отсюда через ПКС).
ДанныеXDTO.КлючевыеСвойства.Ссылка = Лидер.Ссылка;
ДанныеXDTO.КлючевыеСвойства.Дата = Лидер.Дата;
ДанныеXDTO.КлючевыеСвойства.Номер = Лидер.Номер;
КонецПроцедуры
Функция КМ_ЭтоСворачиваемаяПередача(ДанныеXDTO)
Если Не ДанныеXDTO.Свойство("ВидОперации")
Или ДанныеXDTO.ВидОперации = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Если ДанныеXDTO.ВидОперации.Значение <> "ПередачаНаКомиссию" Тогда
Возврат Ложь;
КонецЕсли;
Если Не ДанныеXDTO.Свойство("Контрагент")
Или ДанныеXDTO.Контрагент = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
ИНН = "";
ДанныеXDTO.Контрагент.Свойство("ИНН", ИНН);
Возврат СокрЛП(ИНН) = КМ_ИННКомиссионера();
КонецФункции
// Ключ группировки: день + договор. Организация и контрагент уже
// зафиксированы отбором выше.
Функция КМ_КлючГруппы(ДанныеXDTO)
Если Не ДанныеXDTO.КлючевыеСвойства.Свойство("Дата") Тогда
Возврат "";
КонецЕсли;
ИдентификаторДоговора = "";
Если ДанныеXDTO.Свойство("ДанныеВзаиморасчетов")
И ДанныеXDTO.ДанныеВзаиморасчетов <> Неопределено
И ДанныеXDTO.ДанныеВзаиморасчетов.Свойство("Договор")
И ДанныеXDTO.ДанныеВзаиморасчетов.Договор <> Неопределено Тогда
СсылкаДоговора = Неопределено;
ДанныеXDTO.ДанныеВзаиморасчетов.Договор.Свойство("Ссылка", СсылкаДоговора);
Если СсылкаДоговора <> Неопределено Тогда
ИдентификаторДоговора = Строка(СсылкаДоговора);
КонецЕсли;
КонецЕсли;
Возврат Формат(НачалоДня(ДанныеXDTO.КлючевыеСвойства.Дата), "ДФ=yyyyMMdd")
+ "|" + ИдентификаторДоговора;
КонецФункции
#КонецОбласти
#Область ОбъединениеТабличнойЧасти
Процедура КМ_ОбъединитьТовары(ДанныеИБ, КомпонентыОбмена)
Если ДанныеИБ = Неопределено Тогда
Возврат;
КонецЕсли;
Хранилище = КМ_Хранилище(КомпонентыОбмена);
Накопленные = Неопределено;
Хранилище.Свойство("НакопленныеТовары", Накопленные);
Если Накопленные = Неопределено Или Накопленные.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// На этот момент типовой обработчик уже заместил ТЧ строками нового
// документа. Кладём обратно накопленные, следом дописываем новые.
НовыеСтроки = ДанныеИБ.Товары.Выгрузить();
ДанныеИБ.Товары.Загрузить(Накопленные);
Для Каждого СтрокаНовая Из НовыеСтроки Цикл
ЗаполнитьЗначенияСвойств(ДанныеИБ.Товары.Добавить(), СтрокаНовая);
КонецЦикла;
Хранилище.Вставить("НакопленныеТовары", Неопределено);
// Сумма шапки была перенесена из полученных данных и относится
// только к последнему документу — пересчитываем.
ДанныеИБ.СуммаДокумента = ДанныеИБ.Товары.Итог("Сумма");
КонецПроцедуры
#КонецОбласти
#Область Служебные
// Хранилище состояния на время одного сеанса обмена.
// ПараметрыКонвертации живут ровно столько, сколько нужно.
Функция КМ_Хранилище(КомпонентыОбмена)
ПараметрыКонвертации = КомпонентыОбмена.ПараметрыКонвертации;
Хранилище = Неопределено;
Если Не ПараметрыКонвертации.Свойство("КМ_СводныеПередачи", Хранилище)
Или Хранилище = Неопределено Тогда
Хранилище = Новый Структура;
Хранилище.Вставить("Лидеры", Новый Соответствие);
Хранилище.Вставить("НакопленныеТовары", Неопределено);
ПараметрыКонвертации.Вставить("КМ_СводныеПередачи", Хранилище);
КонецЕсли;
Возврат Хранилище;
КонецФункции
#КонецОбласти
////////////////////////////////////////////////////////////////////////////////
// ПОЧЕМУ ПОДМЕНЫ НОМЕРА НЕДОСТАТОЧНО
//
// ВариантИдентификации = "СначалаПоУникальномуИдентификаторуПотомПоПолямПоиска",
// ПоляПоиска = "Дата,Номер". Кажется, что достаточно подменить номер и дату —
// но поиск по полям в СсылкаОбъектаПоСвойствамОбъектаXDTO строит запрос с
// условием "ПубличныеИдентификаторы.Ссылка is null" и отбрасывает объекты,
// уже сопоставленные с этим узлом. Документ-лидер получает публичный
// идентификатор при записи, поэтому по номеру он больше не находится,
// и создаётся дубль с тем же номером.
//
// Работает только подмена корневой ДанныеXDTO.Ссылка (УИД).
//
// ПЕРЕД ЗАПУСКОМ
//
// Точка останова в КМ_ПодменитьКлючевыеСвойства: убедиться, что корневое
// свойство "Ссылка" существует и что присваивание целиком (а не через
// .Значение) проходит. Если в структуре его нет, а УИД лежит только в
// КлючевыеСвойства — сообщить, логику подмены надо будет строить иначе.
////////////////////////////////////////////////////////////////////////////////