Введение
В типовой конфигурации Управление автотранспортом Проф, редакция 2.2 (УАТ) поддерживается обмен с Бухгалтерией 3.0 (БП) через универсальный формат EnterpriseData. Однако уже после первого обмена, ожидая увидеть документы поступления товаров, оформленные в БП, был неприятно удивлен - их не оказалось. Модель ведения складского учета в УАТ предполагает, что документы поступления товаров и услуг должны быть оформлены в УАТ и обменом попасть в БП. С одной стороны это правильно, где возникают первичные документы, там они и должны быть оформлены, но реалии другие и зачастую первичные документы вводятся в БП, которые уже после должны попасть в УАТ.
Анализ проблемы
В подсистеме обмена данными стандартных подсистем есть служебный регистр сведений Настройки обмена данными XDTO, в котором для узла обмена сохраняется информация о том, какие метаданные может отправлять и получать корреспондент, заглянув в него в базе БП, увидим, что получение отключено:
Обмен в формате EnterpriseData в самой 1С построен на общий модулях, центральным из который является МенеджерОбменаЧерезУниверсальныйФормат, опередящий по сути правила обмена (описывает структуры обмена и обработчики). В этом модуле есть экспортная процедура ЗаполнитьПравилаОбработкиДанных, которая и определяет, какие данные отправлять и получать, на основании этой функции и происходит заполнение описанного выше служебного регистра сведений. Общий ее вид такой:
Процедура ЗаполнитьПравилаОбработкиДанных(НаправлениеОбмена, ПравилаОбработкиДанных) Экспорт
Если НаправлениеОбмена = "Отправка" Тогда
ДобавитьПОД_Документ_АвансовыйОтчет_Отправка(ПравилаОбработкиДанных);
ДобавитьПОД_Документ_ВыдачаРасходныхМатериалов_Отправка(ПравилаОбработкиДанных);
// и т.д.
ИначеЕсли НаправлениеОбмена = "Получение" Тогда
ДобавитьПОД_Документ_АвансовыйОтчет_Получение(ПравилаОбработкиДанных);
ДобавитьПОД_Документ_ЗаказКлиентаВЗаказНаТС_Получение(ПравилаОбработкиДанных);
// и т.д.
КонецЕсли;
КонецПроцедуры
Ожидаемо в ветке "Получение" не было описания правил обработки данных для Поступления товаров и услуг. Это и надо будет решить.
Дописываем правила
Можно было бы воспользоваться конвертацией данных 3, но конкретно в данной задаче это только займет время, которое можно потратить эффективней. Учитывая, что правила отправки документа Поступления товаров и услуг есть, то по сути нам надо повторить все те же самые процедуры, но на случай получения. Дописывать все будем в расширении, в которое добавим общий модуль МенеджерОбменаЧерезУниверсальныйФормат. Начнем с процедуры ЗаполнитьПравилаОбработкиДанных, добавляем в нее процедуру, которая после работы основной процедуры, добавить наше правило:
&После("ЗаполнитьПравилаОбработкиДанных")
Процедура лок_ЗаполнитьПравилаОбработкиДанных(НаправлениеОбмена, ПравилаОбработкиДанных) Экспорт
Если НаправлениеОбмена = "Получение" Тогда
лок_ДобавитьПОД_Документ_ПоступлениеТоваровУслуг_Получение(ПравилаОбработкиДанных);
КонецЕсли;
КонецПроцедуры
Основа процедуры лок_ДобавитьПОД_Документ_ПоступлениеТоваровУслуг_Получение взята из этого же общего модуля, но для получения другого документа, которая в общем типична:
Процедура лок_ДобавитьПОД_Документ_ПоступлениеТоваровУслуг_Получение(ПравилаОбработкиДанных)
ПравилоОбработки = ПравилаОбработкиДанных.Добавить();
ПравилоОбработки.Имя = "Документ_ПоступлениеТоваровУслуг_Получение";
ПравилоОбработки.ОбъектВыборкиФормат = "Документ.ПоступлениеТоваровУслуг";
ПравилоОбработки.ПриОбработке = "лок_ПОД_Документ_ПоступлениеТоваровУслуг_Получение_ПриОбработке";
ПравилоОбработки.ИспользуемыеПКО.Добавить("Документ_ПоступлениеТоваровУслуг_Получение");
КонецПроцедуры
Процедура достаточно понятная, в ней определяем имя нашего правила, указываем для какого объекта работают правила в названии метаданных для корреспондента, то есть так как называется документ в БП. Указываем процедуру для обработчика при получении данных, в нашем случае в этой процедуре ничего особенного происходить не будет, опять же копируем подобную процедуру и меняем в ней параметры на наши:
Процедура лок_ПОД_Документ_ПоступлениеТоваровУслуг_Получение_ПриОбработке(ДанныеИБ, ИспользованиеПКО, КомпонентыОбмена)
Если Не КомпонентыОбмена.ПараметрыКонвертации.ЗапрещенныеКПолучению.Найти("ПоступлениеТоваровУслуг", "Имя") = Неопределено Тогда
ИспользованиеПКО.Документ_ПоступлениеТоваровУслуг_Получение = Ложь;
Возврат;
КонецЕсли;
КонецПроцедуры
Следующим этапом заполняем правила конвертации, которые заполняются экспортной процедурой ЗаполнитьПравилаКонвертацииОбъектов, она очень похожа на ЗаполнитьПравилаОбработкиДанных и имеет по сути тот же вид, наше ее расширение выглядит так:
&После("ЗаполнитьПравилаКонвертацииОбъектов")
Процедура лок_ЗаполнитьПравилаКонвертацииОбъектов(НаправлениеОбмена, ПравилаКонвертации) Экспорт
Если НаправлениеОбмена = "Получение" Тогда
лок_ДобавитьПКО_Документ_ПоступлениеТоваровУслуг_Получение(ПравилаКонвертации);
КонецЕсли;
КонецПроцедуры
Опять же добавленная процедура лок_ДобавитьПКО_Документ_ПоступлениеТоваровУслуг_Получение особо не отличается от процедуры отправки ДобавитьПКО_Документ_ПоступлениеТоваровУслуг_Отправка присутствующей в модуле, поэтому берем ее за основу и получаем:
Процедура лок_ДобавитьПКО_Документ_ПоступлениеТоваровУслуг_Получение(ПравилаКонвертации)
ПравилоКонвертации = ОбменДаннымиXDTOСервер.ИнициализироватьПравилоКонвертацииОбъекта(ПравилаКонвертации);
ПравилоКонвертации.ИмяПКО = "Документ_ПоступлениеТоваровУслуг_Получение";
ПравилоКонвертации.ОбъектДанных = Метаданные.Документы.уатПоступлениеТоваровУслуг;
ПравилоКонвертации.ОбъектФормата = "Документ.ПоступлениеТоваровУслуг";
ПравилоКонвертации.ПравилоДляГруппыСправочника = Ложь;
ПравилоКонвертации.ВариантИдентификации = "ПоУникальномуИдентификатору";
ПравилоКонвертации.ПриКонвертацииДанныхXDTO = "лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПриКонвертацииДанныхXDTO";
ПравилоКонвертации.ПередЗаписьюПолученныхДанных = "лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПередЗаписьюПолученныхДанных";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ВалютаДокумента";
НоваяСтрока.СвойствоФормата = "Валюта";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Валюты";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Дата";
НоваяСтрока.СвойствоФормата = "Дата";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ДатаВходящегоДокумента";
НоваяСтрока.СвойствоФормата = "ДатаВходящегоДокумента";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Контрагент";
НоваяСтрока.СвойствоФормата = "Контрагент";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Контрагенты_Получение";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "КратностьВзаиморасчетов";
НоваяСтрока.СвойствоФормата = "КратностьВзаиморасчетов";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "КурсВзаиморасчетов";
НоваяСтрока.СвойствоФормата = "КурсВзаиморасчетов";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Номер";
НоваяСтрока.СвойствоФормата = "Номер";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "НомерВходящегоДокумента";
НоваяСтрока.СвойствоФормата = "НомерВходящегоДокумента";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Организация";
НоваяСтрока.СвойствоФормата = "Организация";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Организации_Получение";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Ответственный";
НоваяСтрока.СвойствоФормата = "Ответственный";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Пользователи_Получение";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Подразделение";
НоваяСтрока.СвойствоФормата = "Подразделение";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Подразделения_Получение";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Склад";
НоваяСтрока.СвойствоФормата = "Склад";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Склады_Получение";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СуммаВключаетНДС";
НоваяСтрока.СвойствоФормата = "СуммаВключаетНДС";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СуммаДокумента";
НоваяСтрока.СвойствоФормата = "Сумма";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ВалютаДокумента";
НоваяСтрока.СвойствоФормата = "ВалютаВзаиморасчетов";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Валюты";
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Комментарий";
НоваяСтрока.СвойствоФормата = "Комментарий";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
ПравилоКонвертации.СвойстваТабличныхЧастей.Вставить("ДополнительныеРеквизиты", ОбменДаннымиXDTOСервер.ИнициализироватьТаблицуСвойствДляПравилаКонвертации());
СвойстваТЧ = ПравилоКонвертации.СвойстваТабличныхЧастей.ДополнительныеРеквизиты;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ЗначениеСвойства";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Свойство";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_ДополнительныеРеквизиты";
ПравилоКонвертации.СвойстваТабличныхЧастей.Вставить("Товары", ОбменДаннымиXDTOСервер.ИнициализироватьТаблицуСвойствДляПравилаКонвертации());
СвойстваТЧ = ПравилоКонвертации.СвойстваТабличныхЧастей.Товары;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ЕдиницаИзмерения";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_ЕдиницыИзмерения_Получение";
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Количество";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Номенклатура";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Номенклатура_Получение";
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СтавкаНДС";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "СтавкиНДС";
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Сумма";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СуммаНДС";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Цена";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
ПравилоКонвертации.СвойстваТабличныхЧастей.Вставить("Услуги", ОбменДаннымиXDTOСервер.ИнициализироватьТаблицуСвойствДляПравилаКонвертации());
СвойстваТЧ = ПравилоКонвертации.СвойстваТабличныхЧастей.Услуги;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Количество";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Номенклатура";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Номенклатура_Получение";
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Содержание";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СтавкаНДС";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока.ПравилоКонвертацииСвойства = "СтавкиНДС";
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Сумма";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "СуммаНДС";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
НоваяСтрока = СвойстваТЧ.Добавить();
НоваяСтрока.СвойствоКонфигурации = "Цена";
НоваяСтрока.ИспользуетсяАлгоритмКонвертации = Истина;
КонецПроцедуры
Только внимательное следим, какое свойство формата (типа данных из пакета XDTO EnterpriseData) мы будем использовать и в какой реквизит нашего документа он будет конвертироваться, например:
//...
НоваяСтрока = ПравилоКонвертации.Свойства.Добавить();
НоваяСтрока.СвойствоКонфигурации = "ВалютаДокумента";
НоваяСтрока.СвойствоФормата = "Валюта";
НоваяСтрока.ПравилоКонвертацииСвойства = "Справочник_Валюты";
//...
В данном примере свойство формата (входящий данных) Валюта будет конвертироваться в реквизит ВалютаДокумента документа уатПоступлениеТоваровУслуг. Так же дополнительно указываются процедуры при конвертации объекта и перед записью объекта. Особенностью процедур конвертации является дополнительное преобразование табличных полей, пример процедура конвертации для табличной части Товары:
Процедура-обработчик перед записью полностью типовая, в данном случае так же ее наличие диктуется обработкой дополнительный свойств и реквизитов, а так же особенностью ведения единиц измерений для товара, когда для номенклатуры необходимо указывать не только базовую единицу, но и единицу хранения остатков, которой нет в БП, поэтому перед записью документа УАТ делает проверку для всех номенклатур из документа на наличие единицы хранения остатков и если ее нет, то генерирует на основе базовой единицы измерения.
Последним этапом необходимо переопределить процедуру ВыполнитьПроцедуруМодуляМенеджера, с помощью данной процедуры происходит вызов всех объявленных обработчиков, в том числе и объявленные нами ПриОбработке, ПриКонвертацииДанныхXDTO, ПередЗаписьюПолученныхДанных:
&После("ВыполнитьПроцедуруМодуляМенеджера")
Процедура лок_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры) Экспорт
Если ИмяПроцедуры = "лок_ПОД_Документ_ПоступлениеТоваровУслуг_Получение_ПриОбработке" Тогда
лок_ПОД_Документ_ПоступлениеТоваровУслуг_Получение_ПриОбработке(
Параметры.ОбъектОбработки, Параметры.ИспользованиеПКО, Параметры.КомпонентыОбмена);
ИначеЕсли ИмяПроцедуры = "лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПриКонвертацииДанныхXDTO" Тогда
лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПриКонвертацииДанныхXDTO(
Параметры.ДанныеXDTO, Параметры.ПолученныеДанные, Параметры.КомпонентыОбмена);
ИначеЕсли ИмяПроцедуры = "лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПередЗаписьюПолученныхДанных" Тогда
лок_ПКО_Документ_ПоступлениеТоваровУслуг_Получение_ПередЗаписьюПолученныхДанных(
Параметры.ПолученныеДанные, Параметры.ДанныеИБ, Параметры.КонвертацияСвойств, Параметры.КомпонентыОбмена);
КонецЕсли;
КонецПроцедуры
Последний штрих, особенность УАТ, из метаданных плана обмена СинхронизацияДанныхЧерезУниверсальныйФормат, в расширение надо добавить макет ПравилаОтправкиПолученияДанных, который описывает фильтры для управлением отправки/получения данных над механизмом обмена данными. В этот макет необходимо добавить запись, что мы теперь умеем получить документ Поступление товаров и услуг.
На этом все. Запускаем расширение и проверяем перенос документ Поступление товаров и услуг. Документ перенесется, но не проведется из-за незаполненного договора контрагента, который в УАТ обязателен для заполнения, но при этом в формате обмена его нет. Решение опять же либо дописать обмен, но уже с двух сторон, если нужен реальный договор, либо отключить необходимость договора, переопределив ОбработкуПроверкиЗаполнения, либо генерировать произвольный общий договор. В моем случае важен только приход товара, поэтому в процедуре-обработчике ПередЗаписьюПолученныхДанных генерируется договор с предопределенным названием если такой не найден для контрагента и этот договор подставляется в документ.
Итог
Доработка правил не составила особого труда, понадобилось только определить точки входа в модуле МенеджерОбменаЧерезУниверсальныйФормат, их три:
- ЗаполнитьПравилаОбработкиДанных
- Добавили процедуру обработки данных при получении документа,
- Определили процедуру-обработчик события ПриОбработке
- ЗаполнитьПравилаКонвертацииОбъектов
- Добавили процедуру правила конвертации объекта
- Определили процедуру-обработчик события ПриКонвертацииДанныхXDTO
- Определили процедуру-обработчик события ПередЗаписьюПолученныхДанных
- ВыполнитьПроцедуруМодуляМенеджера
и по аналогии с имеющимися процедурами для получения данных в модуле, дописать необходимые и дозаполнить макет ПравилаОтправкиПолученияДанных, добавив туда строку, опять же, по аналогии с имеющимися. К публикации приложено расширение, которое в точности повторяет описанное с учетом создания обобщенного договора для контрагента.
Тестирование проводилось на платформе версии 8.3.13.1809, 1С: Бухгалтерия предприятия 3.0.102.11 и Управление автотранспортом ПРОФ 2.2.18.1.