При разработке и настройке правил обмена в конфигурации «Конвертация данных 3.0» (КД 3.0) через универсальный формат EnterpriseData разработчики часто сталкиваются с ситуацией, когда в документе ПоступлениеНаРасчетныйСчет с видом операции «Поступления от продаж по платежным картам и банковским кредитам» в базе-источнике заполнен реквизит ДоговорКонтрагента (в шапке или в табличной части РасшифровкаПлатежа), однако в схеме XDTO формата EnterpriseData соответствующее свойство для данного документа отсутствует.
Разберем детально, почему возникает эта проблема, какие особенности структуры XDTO мешают использовать стандартный механизм дополнительных реквизитов и какими способами можно корректно передать или восстановить договор контрагента в базе-приемнике.
Проанализируем структуру пакета XDTO. В типовых версиях формата EnterpriseData объект Документ.ПБДСПоПлатежнымКартам (Поступление безналичных денежных средств по платежным картам) не имеет базового типа Object из пространства имен ExchangeMessage. Вследствие этого у данного типа XDTO отсутствует стандартное свойство AdditionalInfo (Дополнительная информация), которое обычно применяется для передачи произвольных структур данных.
Попытка выполнить принудительную вставку в обработчике выгрузки:
ДанныеXDTO.Вставить("AdditionalInfo", Строка(ДанныеИБ.ДоговорКонтрагента.УникальныйИдентификатор()));
без изменения схемы XDTO приводит к тому, что свойство либо игнорируется сериализатором, либо вызывает ошибку валидации сообщения обмена. Рассмотрим основные пути решения этой задачи без нарушения типовой логики и структуры метаданных.
В типовых правилах конфигураций на базе БСП (например, «1С:Бухгалтерия предприятия») логика заполнения договора эквайринга вынесена в обработчик ПередЗаписьюПолученныхДанных. Если в документе участвует один основной договор эквайринга с банком, его можно найти или создать автоматически при загрузке.
Посмотрим на пример типового алгоритма заполнения табличной части:
ДоговорЭквайринга = ДоговорЭквайринга(ПолученныеДанные.Организация, ПолученныеДанные.Контрагент);
Для Каждого Расшифровка Из ПолученныеДанные.РасшифровкаПлатежа Цикл
Если НЕ ЗначениеЗаполнено(Расшифровка.ДоговорКонтрагента) Тогда
Расшифровка.ДоговорКонтрагента = ДоговорЭквайринга;
КонецЕсли;
КонецЦикла;
Функция поиска и создания договора эквайринга на стороне приемника строится по следующей схеме:
Функция ДоговорЭквайринга(Организация, Контрагент)
Если НЕ ЗначениеЗаполнено(Организация) ИЛИ НЕ ЗначениеЗаполнено(Контрагент) Тогда
Возврат Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
КонецЕсли;
НаименованиеЭлементаДляОбменаПоУмолчанию = НСтр("ru='Договор эквайринга'");
ВидДоговора = Перечисления.ВидыДоговоровКонтрагентов.Прочее;
ПараметрыДоговора = Новый Структура;
ПараметрыДоговора.Вставить("Наименование", НаименованиеЭлементаДляОбменаПоУмолчанию);
ПараметрыДоговора.Вставить("Организация", Организация);
ПараметрыДоговора.Вставить("Владелец", Контрагент);
ПараметрыДоговора.Вставить("ВалютаВзаиморасчетов", ОбщегоНазначенияБПВызовСервераПовтИсп.ПолучитьВалютуРегламентированногоУчета());
ПараметрыДоговора.Вставить("ВидДоговора", ВидДоговора);
Договор = ДоговорСПараметрамиПоУмолчанию(ПараметрыДоговора);
Возврат Договор.Ссылка;
КонецФункции
Этот вариант является наиболее простым и надежным, если взаиморасчеты с банком-эквайрером ведутся в рамках единого договора «Прочее».
Если в базе-источнике заведено несколько договоров эквайринга с одним банком, мы можем идентифицировать договор через сопутствующие реквизиты, передаваемые в формате: банковский счет и эквайринговый терминал.
Документ.ПБДСПоПлатежнымКартам передаются реквизиты счета и терминала эквайринга.ЭквайринговыеТерминалы или ДоговорыЭквайринга каждый терминал жестко привязан к конкретному договору взаиморасчетов.ПередЗаписьюПолученныхДанных производим поиск договора по связке Контрагент + Организация + Терминал/Счет, что исключает ошибки при наличии нескольких договоров.Если требуется передать строго конкретный договор из базы-источника без изменения пакета XDTO, применим технику инкапсуляции данных в свободные текстовые поля формата (например, НазначениеПлатежа или Комментарий).
ПриОтправкеДанных):
Помещаем в текстовое поле специальный служебный маркер с уникальным идентификатором или кодом договора:
Если ЗначениеЗаполнено(ДанныеИБ.ДоговорКонтрагента) Тогда
GUIDДоговора = Строка(ДанныеИБ.ДоговорКонтрагента.УникальныйИдентификатор());
ДанныеXDTO.НазначениеПлатежа = "[ContractGUID:" + GUIDДоговора + "]" + ДанныеXDTO.НазначениеПлатежа;
КонецЕсли;
ПриКонвертацииДанныхXDTO):
Считываем маркер из строки, извлекаем идентификатор и очищаем технический префикс:
Маркер = "[ContractGUID:";
ПозицияМаркера = СтрНайти(ДанныеXDTO.НазначениеПлатежа, Маркер);
Если ПозицияМаркера > 0 Тогда
КонецМаркера = СтрНайти(ДанныеXDTO.НазначениеПлатежа, "]", , ПозицияМаркера);
ДлинаМаркера = СтрДлина(Маркер);
ИдентификаторДоговора = Сред(ДанныеXDTO.НазначениеПлатежа, ПозицияМаркера + ДлинаМаркера, КонецМаркера - ПозицияМаркера - ДлинаМаркера);
// Сохраняем во временную структуру для записи
ПолученныеДанные.ДополнительныеСвойства.Вставить("ИдентификаторДоговора", ИдентификаторДоговора);
// Очищаем реквизит до исходного вида
ДанныеXDTO.НазначениеПлатежа = Сред(ДанныеXDTO.НазначениеПлатежа, КонецМаркера + 1);
КонецЕсли;
ПередЗаписьюПолученныхДанных:
По сохраненному УникальныйИдентификатор находим ссылку в справочнике ДоговорыКонтрагентов (или через регистр СоответствияОбъектовИнформационныхБаз) и присваиваем ее строкам табличной части РасшифровкаПлатежа.
Если архитектура проекта требует передачи данных через строгие типы, вносить изменения напрямую в типовой пакет EnterpriseData не рекомендуется, так как это усложняет обновление конфигурации. В современных версиях БСП для добавления реквизитов рекомендуется подключать собственное расширение формата обмена с отдельным пространством имен (URI), расширяющим базовые типы схемы без снятия типовой конфигурации с поддержки.