Использовать типовые правила обмена в КД2

Версия для печатиPDF-версия

Платформа:

Конфигурация:

В общем вопрос такой возник. Хочу попробовать использовать типовые правила обмена, доработать слегка их в КД 2 и использовать в обработке обмена XML. Проблема в том, что там используются регистры, которые встроены в саму типовую конфигурацию, а в КД2 их нет. Например ВыгрузитьРегистр. Думаю над вопросом: либо отказаться от "ВыгрузитьРегистр" на что-либо другое, либо сделать его как алгоритм в КД2 (перенести из кода), либо как-то заставить обмен обратиться к модулю конфигурации. Пока не знаю, что из этого возможно сделать, буду пробовать, но может у кого есть идеи

Что-то непонятно что значит "там используются регистры, которые встроены в саму типовую конфигурацию, а в КД2 их нет"? Может речь не о регистрах, а о процедурах/методах?

Да, это процедуры. Просто опечатался, потому что называется "ВыгрузитьРегистр"
 

Самое простое, наверное, перенести эти процедуры в обработку выгрузки XML.

А как к ним обратиться тогда? Раньше такого не делал

Выгружать планируете обработкой УниверсальныйОбменДаннымиXML?

Да. Попробовал сделать обмен через типовую синхронизацию данных, но что-то пошло не так. Так что наверное через УниверсальныйОбмен.

Еще сейчас смотрю процедуру ВыгрузитьПоПравилу, которая есть в коде этой обработки
 

ВыгрузитьПоПравилу - мощная штука.

Скопируйте нужные процедуры из модуля объекта обработки ОбменДаннымиXML в модуль объекта обработки УниверсальныйОбменДаннымиXML. Может и так заработает.

Да, тоже думал пойти таким способом. Главное разобраться, что скопировать надо
 

Методом научного тыка.

Теоретически можно скопировать все экспортные процедуры и функции. Только чтоб дублей не появилось.

Да часть переменных и процедур есть и там и там. Визуально глянул - вроде одинаковые.

Хотя правильнее было бы правила изменять.

Решил воспользоваться "ВыгрузитьПоПравилам". Посмотрю, что из этого выйдет
 

В общем пока отказался от выгрузки регистров, просто закомментировал данную строку (в старом варианте правил, сделанных предыдущим программистом было так же). Вроде выгрузилось, только ругается в конце

Ошибка в обработчике события ПослеВыгрузкиДанных (конвертация)
    Обработчик             =  ПослеВыгрузкиДанных (конвертация)
    ОписаниеОшибки         =  Ошибка компиляции при вычислении выражения или выполнении фрагмента кода: {(8,31)}: Переменная не определена (УзелДляОбмена)
    ПозицияМодуля          =  ВнешняяОбработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(12668)
    КодСообщения           =  63

А при попытке загрузить пишет:

Ошибка при загрузке данных: {Обработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(6065)}: Индекс находится за границами массива

И грузит 0 объектов. Вот и думаю... вроде ничего особого не менял, чтобы прям ругалось.
 

Посмотрите обработчики событий у самой конвертации. Там в типовых правилах много лабуды написано. Что-то можно удалять спокойно (в частности обращения к переменной УзелДляОбмена), а что-то придётся переделывать.

Нашел, где находит ошибку

Попытка
            
            Если ФлагРежимОтладкиОбработчиков Тогда
                
                Если Не ПустаяСтрока(Конвертация.ПослеВыгрузкиДанных) Тогда
                    
                    Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПослеВыгрузкиДанных"));
                    
                КонецЕсли;
                
            Иначе
                
                Выполнить(Конвертация.ПослеВыгрузкиДанных);
                
            КонецЕсли;

        Исключение
            ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(63, ОписаниеОшибки(), Нстр("ru = 'ПослеВыгрузкиДанных (конвертация)'"));
        КонецПопытки;

В момент ошибки в Конвертация.ПослеВыгрузкиДанных находятся данные:

// Регистрируем объекты, созданные в этом сеансе обмена так, чтобы они относились к текущему сообщению обмена
Если Параметры.ТаблицаВыгружаемыхОтветственныхЛиц.Количество() > 0 И Параметры.ПравилаОтправкиСправочников <> "НеСинхронизировать" Тогда
    Выполнить(Алгоритмы.ВыгрузитьОтветственныхЛиц);
КонецЕсли;

Если Параметры.СписокОбъектовСозданныхВТекущемСеансеОбмена.Количество() <> 0 Тогда
    
    ПланыОбмена.ВыбратьИзменения(УзелДляОбмена.Ссылка, ЗаписьСообщения.НомерСообщения,
        Параметры.СписокОбъектовСозданныхВТекущемСеансеОбмена);
        
КонецЕсли;

Вот и думаю, что делать... Так то показывает, что объекты ВЫГРУЗИЛИСЬ. Но при загрузке не дает.
 

В КД откройте саму конвертацию (не правила!) и очистите все обработчики событий. Попробуйте без них выгрузку-загрузку произвести.

Пока только ту, на которую ругается, удалил и пробую. Точнее закомментил. Может пригодится еще
 

Выгрузилось что-то, но только часть. При загрузке в один момент выкидывает с ошибкой:

Ошибка при загрузке данных: {Обработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(1274)}: Ошибка в обработчике события ПоследовательностьПолейПоиска
    ИмяПКО                 =  
    ТипОбъекта             =  Договор контрагента
    Обработчик             =  Последовательность полей поиска
    ОписаниеОшибки         =  Значение не является значением объектного типа (Получить)
    ПозицияМодуля          =  (6)
    КодСообщения           =  73

Думаю теперь, как определить где смотреть ошибку в правилах...

Нашел. Ругается здесь

Запрос = Новый Запрос;
Для Каждого СвойствоПоиска Из СвойстваПоиска Цикл
    Запрос.УстановитьПараметр(СвойствоПоиска.Ключ, СвойствоПоиска.Значение);
КонецЦикла;
 
Если Не ПараметрыОбъекта.Получить("ЗначениеСвойстваИспользуетсяПриОбменеДанными") = Неопределено Тогда
и далее код... либо по реквизитам договора, либо по реквизитам и свойствам
 

А в ПараметрыОбъекта что-нибудь передаётся? Посмотрите в конвертации свойств.

Добавьте перед "Если Не ПараметрыОбъекта.Получить" проверку типа или заполненности ПараметрыОбъекта:

Если ТипЗнч(ПараметрыОбъекта) = Тип("Соответствие") Тогда ...

Вроде что-то вышло. Пока только выгрузка РКО сбоит, но остальное нормально грузится.
 

Теперь другая проблема. Нужно в документах поступления, в зависимости от значения в поле Ставка НДС заполнить реквизит Вид Поступления.

Делаю обработку, в ней код:

Для Каждого Строка Из Объект.Товары Цикл
        Если Строка.СтавкаНДС.Ставка = 12 Тогда
            Строка.НДСВидПоступления = Справочники.ВидыПоступления.НайтиПоНаименованию("Товары, приобретенные с НДС");
        Иначе
            Строка.НДСВидПоступления = Справочники.ВидыПоступления.НайтиПоНаименованию("Без НДС");    
        КонецЕсли;        
    КонецЦикла;

Работет. Пробую сделать такое же в ПКО в обработчике после записи - ничего... вот вообще не знаю, что делать. Неужто там, как в обработке надо добавить пункт "объект.Записать()"?
 

Должно работать без "Объект.Записать()".

Ошибок не выдаёт?

Это полный текст обработчика? Может не доходит до этого фрагмента?

Выполнить(Алгоритмы.ОбработатьЗаписьДокументаПослеЗагрузки);
Выполнить(Алгоритмы.ЗаполнитьВалютуДокумента);

Если РежимЗагрузкиДанныхВИнформационнуюБазу() Тогда
    Объект.СуммаДокумента = УчетНДСИАкциза.ПолучитьСуммуДокументаСНДС(Объект);
    
    // Определение переменных, используемых в алгоритмах
    МетаданныеДокумента = Объект.Метаданные();
    
    Попытка
        
        ОрганизацияЯвляетсяПлательщикомКПН =  ПроцедурыНалоговогоУчета.ПолучитьПризнакПлательщикаНалогаНаПрибыль(Объект.Организация, Объект.Дата);

        Если Не ОрганизацияЯвляетсяПлательщикомКПН Тогда
            Объект.УчитыватьКПН = Ложь;
        Иначе
            Объект.УчитыватьКПН = Истина;
        КонецЕсли;    
        
        Если НЕ Объект.УчитыватьКПН Тогда
            Объект.ВидУчетаНУ = Справочники.ВидыУчетаНУ.НеОтражаетсяВНУ;
        Иначе
            Объект.ВидУчетаНУ = Справочники.ВидыУчетаНУ.НУ;
        КонецЕсли;
        
    Исключение
    КонецПопытки;
    
    // Заполняет счета учетов документа
    СчетаУчета = УправлениеВзаиморасчетамиСервер.ПолучитьСчетаРасчетовСКонтрагентом(Объект.Организация, Объект.Контрагент, Объект.ДоговорКонтрагента);
    Объект.СчетУчетаРасчетовСКонтрагентом = СчетаУчета.СчетРасчетов;
    Объект.СчетУчетаРасчетовПоАвансам     = СчетаУчета.СчетАвансов;
    
    // Заполняет счета учета табличной части "Товары"
    Документы.ПоступлениеТоваровУслуг.ЗаполнитьСчетаУчетаВТабличнойЧасти(Объект, "Товары");
    // Заполняет счета учета табличной части "Услуги"
    Документы.ПоступлениеТоваровУслуг.ЗаполнитьСчетаУчетаВТабличнойЧасти(Объект, "Услуги");
    
    Попытка
        // Заполняет реквизиты налогового учета табличной части "Товары"
        Для Каждого СтрокаТЧ Из Объект.Товары Цикл
            Документы.ПоступлениеТоваровУслуг.ЗаполнитьРеквизитыНалоговогоУчета(Объект, СтрокаТЧ, "Товары");
        КонецЦикла;
        
        // Заполняет реквизиты налогового учета табличной части "Услуги"
        Для Каждого СтрокаТЧ Из Объект.Услуги Цикл
            Документы.ПоступлениеТоваровУслуг.ЗаполнитьРеквизитыНалоговогоУчета(Объект, СтрокаТЧ, "Услуги");
        КонецЦикла;
    Исключение
    Конецпопытки;
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
        |    ВЫБОР
        |        КОГДА ВидыПоступления.Наименование = ""Без НДС""
        |            ТОГДА ВидыПоступления.Ссылка
        |    КОНЕЦ КАК Поле1
        |ПОМЕСТИТЬ ВТ_1
        |ИЗ
        |    Справочник.ВидыПоступления КАК ВидыПоступления
        |ГДЕ
        |    ВидыПоступления.Наименование = ""Без НДС""
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ВЫБОР
        |        КОГДА ВидыПоступления.Наименование = ""Товары, приобретенные с НДС""
        |            ТОГДА ВидыПоступления.Ссылка
        |    КОНЕЦ КАК Поле2
        |ПОМЕСТИТЬ ВТ_2
        |ИЗ
        |    Справочник.ВидыПоступления КАК ВидыПоступления
        |ГДЕ
        |    ВидыПоступления.Наименование = ""Товары, приобретенные с НДС""
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ВТ_1.Поле1 КАК НДС,
        |    ВТ_2.Поле2 КАК БЕЗНДС
        |ИЗ
        |    ВТ_1 КАК ВТ_1,
        |    ВТ_2 КАК ВТ_2
        |";
    Результат = Запрос.Выполнить().Выбрать();
    Результат.Следующий();
    
    Для Каждого Строка Из Объект.Товары Цикл
        Если Строка.СтавкаНДС.Ставка = 12 Тогда
            Строка.НДСВидПоступления = Результат.НДС;
        Иначе
            Строка.НДСВидПоступления = Результат.БЕЗНДС;    
        КонецЕсли;        
    КонецЦикла;
    Объект.НомерВходящегоДокумента = "Привет";
    
КонецЕсли;

Вот полный код. Обмен выполняется через синхронизацию данных, а не через универсальный обмен XML
 

Нашел в чем был затык... Надо было править правила корреспондента, они отвечают за загрузку. Подправил - и загрузилось. Теперь следующий этап - в документе реализации заполнить субконто, которое хранится в характеристике...
 

С запросом, конечно, намудрили... Чем НайтиПоНаименованию() не устраивает? И 2 цикла обхода ТЧ Товары - это нехорошо.

По идее, правила выгрузки в первой базе и правила корреспондента во второй базе должны быть идентичны. Редактируете правила для первой базы, сохраняете, загружаете в первую базу. Потом копируете их, переименовываете в CorrespondentExchangeRules.xml и загружаете во вторую базу.

А в чём сложность с получением субконто?

 

Да ни в чем, почти сразу сделал. Теперь только надо понять, почему ставки НДС дублятся

А с запросом мудрил потому, что не выгружалось и я просто уже перешел на самые абсурдные варианты решения)

 

Посмотрите поля поиска.

Да, нашел. Там почему-то стояла синхронизация по внутреннему идентификатору. А так как в Бухгалтерии начали работать раньше, чем в Аптеке - естественно, что там давно и прочно сидела своя ставка. А потом из аптеки новые документы стали пихать свою ставку
 

В типовых правилах практически везде синхронизация по внутреннему идентификатору. В общем-то это нормально, но надо добавлять и синхронизацию по полям поиска.