Загрузка данных


////////////////////////////////////////////////////////////////////////////
// Расширение общего модуля менеджера обмена (БП 3.0.191, формат 1.22)
//
// Назначение: несколько документов "Реализация товаров и услуг" с видом
// операции "Передача на комиссию", пришедших из УТ за один сеанс обмена,
// загружаются в БП как ОДИН документ.
//
// Механика: первый документ группы грузится штатно. У второго и последующих
// в ПОД подменяются ключевые свойства (Ссылка/Дата/Номер) на значения первого,
// поэтому штатная идентификация находит уже записанный документ и обновляет
// его. Табличная часть при этом не замещается, а дополняется.
//
// Перехват идёт через экспортный диспетчер ВыполнитьПроцедуруМодуляМенеджера,
// сами обработчики ПОД/ПКО в модуле не экспортные.
////////////////////////////////////////////////////////////////////////////////

#Область НастройкиОтбора

// ИНН комиссионера, передачи к которому нужно сворачивать.
// Если комиссионеров несколько — заменить на список.
Функция КМ_ИННКомиссионера()
	Возврат "9714053621"; // ООО "РВБ" (Wildberries)
КонецФункции

#КонецОбласти

#Область Перехваты

&Перед("ВыполнитьПроцедуруМодуляМенеджера")
Процедура КМ_Перед_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры)

	Если ИмяПроцедуры <> "ПКО_Документ_РеализацияТоваровУслуг_ПередЗаписьюПолученныхДанных" Тогда
		Возврат;
	КонецЕсли;

	// ДанныеИБ = Неопределено означает, что документа в базе ещё нет:
	// это первый документ группы, накапливать нечего.
	Если Параметры.ДанныеИБ = Неопределено Тогда
		Возврат;
	КонецЕсли;

	// Запоминаем строки, которые сейчас лежат в базе, — типовой обработчик
	// ниже по стеку их затрёт строками нового документа.
	Хранилище = КМ_Хранилище(Параметры.КомпонентыОбмена);
	Хранилище.Вставить("НакопленныеТовары", Параметры.ДанныеИБ.Товары.Выгрузить());

КонецПроцедуры

&После("ВыполнитьПроцедуруМодуляМенеджера")
Процедура КМ_После_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры)

	Если ИмяПроцедуры = "ПОД_Документ_РеализацияТоваровУслуг_ПриОбработке" Тогда

		КМ_ПодменитьКлючевыеСвойства(Параметры.ОбъектОбработки, Параметры.КомпонентыОбмена);

	ИначеЕсли ИмяПроцедуры = "ПКО_Документ_РеализацияТоваровУслуг_ПередЗаписьюПолученныхДанных" Тогда

		КМ_ОбъединитьТовары(Параметры.ДанныеИБ, Параметры.КомпонентыОбмена);

	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#Область ПодменаКлючевыхСвойств

Процедура КМ_ПодменитьКлючевыеСвойства(ДанныеXDTO, КомпонентыОбмена)

	// Загрузка объекта как значения чужого свойства — трогать нельзя
	// (аналог типовой ЭтоЗагрузкаКлючевыхСвойств).
	Если ДанныеXDTO.Количество() = 1 Тогда
		Возврат;
	КонецЕсли;

	Если Не КМ_ЭтоСворачиваемаяПередача(ДанныеXDTO) Тогда
		Возврат;
	КонецЕсли;

	КлючГруппы = КМ_КлючГруппы(ДанныеXDTO);
	Если Не ЗначениеЗаполнено(КлючГруппы) Тогда
		Возврат;
	КонецЕсли;

	Хранилище = КМ_Хранилище(КомпонентыОбмена);
	Лидер = Хранилище.Лидеры.Получить(КлючГруппы);

	Если Лидер = Неопределено Тогда
		// Первый документ группы. Грузится штатно, запоминаем его ключевые свойства.
		Лидер = Новый Структура("Ссылка, Дата, Номер",
			ДанныеXDTO.КлючевыеСвойства.Ссылка,
			ДанныеXDTO.КлючевыеСвойства.Дата,
			ДанныеXDTO.КлючевыеСвойства.Номер);
		Хранилище.Лидеры.Вставить(КлючГруппы, Лидер);
		Возврат;
	КонецЕсли;

	// Второй и последующие: выдаём себя за лидера, чтобы штатная идентификация
	// (СначалаПоУникальномуИдентификаторуПотомПоПолямПоиска) нашла его документ.
	ДанныеXDTO.КлючевыеСвойства.Ссылка = Лидер.Ссылка;
	ДанныеXDTO.КлючевыеСвойства.Дата   = Лидер.Дата;
	ДанныеXDTO.КлючевыеСвойства.Номер  = Лидер.Номер;

	// Если в вашей версии Ссылка продублирована в корне структуры —
	// раскомментировать (проверить на точке останова, см. комментарий в конце файла).
	// Если ДанныеXDTO.Свойство("Ссылка") Тогда
	//     ДанныеXDTO.Ссылка = Лидер.Ссылка;
	// КонецЕсли;

КонецПроцедуры

Функция КМ_ЭтоСворачиваемаяПередача(ДанныеXDTO)

	Если Не ДанныеXDTO.Свойство("ВидОперации")
		Или ДанныеXDTO.ВидОперации = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ДанныеXDTO.ВидОперации.Значение <> "ПередачаНаКомиссию" Тогда
		Возврат Ложь;
	КонецЕсли;

	Если Не ДанныеXDTO.Свойство("Контрагент")
		Или ДанныеXDTO.Контрагент = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	ИНН = "";
	ДанныеXDTO.Контрагент.Свойство("ИНН", ИНН);

	Возврат СокрЛП(ИНН) = КМ_ИННКомиссионера();

КонецФункции

// Ключ группировки: день + договор. Организация и контрагент уже
// зафиксированы отбором выше.
Функция КМ_КлючГруппы(ДанныеXDTO)

	Если Не ДанныеXDTO.КлючевыеСвойства.Свойство("Дата") Тогда
		Возврат "";
	КонецЕсли;

	ИдентификаторДоговора = "";
	Если ДанныеXDTO.Свойство("ДанныеВзаиморасчетов")
		И ДанныеXDTO.ДанныеВзаиморасчетов <> Неопределено
		И ДанныеXDTO.ДанныеВзаиморасчетов.Свойство("Договор")
		И ДанныеXDTO.ДанныеВзаиморасчетов.Договор <> Неопределено Тогда

		СсылкаДоговора = Неопределено;
		ДанныеXDTO.ДанныеВзаиморасчетов.Договор.Свойство("Ссылка", СсылкаДоговора);
		Если СсылкаДоговора <> Неопределено Тогда
			ИдентификаторДоговора = Строка(СсылкаДоговора);
		КонецЕсли;
	КонецЕсли;

	Возврат Формат(НачалоДня(ДанныеXDTO.КлючевыеСвойства.Дата), "ДФ=yyyyMMdd")
		+ "|" + ИдентификаторДоговора;

КонецФункции

#КонецОбласти

#Область ОбъединениеТабличнойЧасти

Процедура КМ_ОбъединитьТовары(ДанныеИБ, КомпонентыОбмена)

	Если ДанныеИБ = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Хранилище = КМ_Хранилище(КомпонентыОбмена);
	Накопленные = Неопределено;
	Хранилище.Свойство("НакопленныеТовары", Накопленные);

	Если Накопленные = Неопределено Или Накопленные.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	// На этот момент типовой обработчик уже заместил ТЧ строками нового
	// документа. Кладём обратно накопленные, следом дописываем новые.
	НовыеСтроки = ДанныеИБ.Товары.Выгрузить();

	ДанныеИБ.Товары.Загрузить(Накопленные);
	Для Каждого СтрокаНовая Из НовыеСтроки Цикл
		ЗаполнитьЗначенияСвойств(ДанныеИБ.Товары.Добавить(), СтрокаНовая);
	КонецЦикла;

	Хранилище.Вставить("НакопленныеТовары", Неопределено);

	// Сумма шапки была перенесена из полученных данных и относится
	// только к последнему документу — пересчитываем.
	ДанныеИБ.СуммаДокумента = ДанныеИБ.Товары.Итог("Сумма");

КонецПроцедуры

#КонецОбласти

#Область Служебные

// Хранилище состояния на время одного сеанса обмена.
// ПараметрыКонвертации живут ровно столько, сколько нужно.
Функция КМ_Хранилище(КомпонентыОбмена)

	ПараметрыКонвертации = КомпонентыОбмена.ПараметрыКонвертации;

	Хранилище = Неопределено;
	Если Не ПараметрыКонвертации.Свойство("КМ_СводныеПередачи", Хранилище)
		Или Хранилище = Неопределено Тогда

		Хранилище = Новый Структура;
		Хранилище.Вставить("Лидеры", Новый Соответствие);
		Хранилище.Вставить("НакопленныеТовары", Неопределено);
		ПараметрыКонвертации.Вставить("КМ_СводныеПередачи", Хранилище);
	КонецЕсли;

	Возврат Хранилище;

КонецФункции

#КонецОбласти

////////////////////////////////////////////////////////////////////////////////
// ПЕРЕД ПЕРВЫМ ЗАПУСКОМ
//
// Поставить точку останова в КМ_ПодменитьКлючевыеСвойства и посмотреть
// фактическую структуру ДанныеXDTO. Проверить два места:
//
//   1. ДанныеXDTO.КлючевыеСвойства.Ссылка — что это: строка UID или
//      структура со свойством "Значение". От этого зависит присваивание.
//   2. Есть ли Ссылка продублированной в корне ДанныеXDTO. Если да —
//      раскомментировать соответствующий блок.
//
// Это единственное, что стоит уточнить в отладчике: остальное из типового
// кода читается однозначно.
////////////////////////////////////////////////////////////////////////////////