Каталог решений - Веб-сервисы, что они и как их применить в реальных условиях

Веб-сервисы, что они и как их применить в реальных условиях

Веб-сервисы, что они и как их применить в реальных условиях

В наличии

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

Категория:

Описание

Веб-сервисы, что они и как их применить в реальных условиях.

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

Ну пожалуй начнем немного с теории и того, как было раньше.

Была 1 центральная база (далее ЦБ) и был 1 интернет магазин (далее ИМ), и нам, как и всем смертным было необходимо выгружать туда остатки, цены и прочий хлам.

Ну пожалуй следует начать с того, как мы выгружали номенклатуру и ее описание, изначально мы просто раз в какой то период – выгружали файлик xml на ftp, этот период выбирал кто угодно, сайт его автоматом подхватывал и обновлял. Но, так как мы легких путей не ищем, было принято решение добавить в номенклатуру реквизит ДатаИзменения, и тогда выгружалась только та номенклатура, которая была изменена начиная с указанного периода.

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

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

Далее открыли другие партнерские ИМ и с ними тоже надо было как то и что то делать.

В тот момент я уже поднатаскался в веб сервисах 1С и технологии соап в целом, и мы РЕШИЛИСЬ!

Ну во первых у нас возник вопрос – как выгрузить остатки, он решился довольно таки быстро, на стороне сайта подняли соап сервер и я к нему подключаясь через 1С слал строку, но строку не простую, а великолепную :).

Код этой злобной функции приведен ниже.

Однако, мы пока еще немного зайдем в глубь, и так, цель выгрузок для ИМ1 и ИМ2 – была разной, т.е. для ИМ1 выгружались все остатки по складам, а в случае ИМ2 – остатки нужны были в целом, без разбиения по складам.

Поэтому, для того что бы не плодить кучу функций, был добавлен параметр Номер, если Номер = 0, то это выгрузка была для ИМ1, если Номер = 1, то для ИМ2.

И та

//Выгрузка регламентная остатков, эта процедура вызывалась регламентом раз в сутки и отправляла данные в ИМ.
Процедура ВыгрузкаОстатковДляИнтернетМагазина() Экспорт
//Тут мы определяем цикл, т.е. функция выполняется столько раз, сколько ИМ магазинов у нас есть.
    Для Номер = 0 По 1 Цикл    
        Запрос = Новый Запрос;
        Если Номер = 0 Тогда
            Запрос.Текст =
            "ВЫБРАТЬ
            |    Склады.Ссылка
            |ИЗ
            |    Справочник.Склады КАК Склады
            |ГДЕ
            |    Склады.СтатусСклада = ЗНАЧЕНИЕ(Перечисление.СтатусСклада.Розничный)"
;
            Результат = Запрос.Выполнить();
            
            ВыборкаДетальныеЗаписи = Результат.Выбрать();
//Определяем переменную, которую будет отправлять на сервер
            хмл = "";
//Для случая ИМ1 мы выполняем отдельный запрос и отправку для каждого склада
            Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
                Попытка
//Пытаемся получить хмл строку для данного склада
                    хмл = ПолучитьХМЛ(ВыборкаДетальныеЗаписи.Ссылка, Номер);
                    Если хмл = Неопределено Тогда
                        
                    Иначе
//Если все успешно, то получаем структуру подключения, куда передаем номер ИМ и имя функции.
                        СтруктураДанных = ПолучитьСоединение("Prod_1c",Номер);
//Получили строку, теперь надо отправить данные по SOAP, тут передается три параметра на сервер
//1 – сама строка хмл
//2 – код склада
//3 – тип остатков, если это начальные остатки, то он равен «0», если это оборот – то «1»                        
                        Ответ = СтруктураДанных.ВСПрокси. Prod_1c(ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[0], хмл),
                        ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[1], СокрЛП(ВыборкаДетальныеЗаписи.Ссылка.Код)),
                        ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[2], "0"));
//Тут стоить понимать, что посылая данные, мы получаем и ответ, ответ может быть разным, для нас в одних случаях ответ должен быть «Success» или «Error», в других случаях, мы просто возвращали количество строк в таблице. Т.е. я например выгрузил 1000 строк в хмл, сайт отпарсил и отвечает мне, если ответ != 1000, то это считалось ошибкой, хотя не всегда, например был новый товар, которого в ИМ еще нету, или не должно быть, тогда это просто записывается в журнал и дальше просматривается в ручную.                        
                        Если Ответ = "Success" Тогда
                            //ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Информация, ,ВыборкаДетальныеЗаписи.Ссылка , Ответ);        
                        Иначе
                            ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Ошибка, ,ВыборкаДетальныеЗаписи.Ссылка , Ответ);
                        КонецЕсли;
                    КонецЕсли;
                Исключение
                    ТекстОшибки = ОписаниеОшибки();
                    ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Ошибка, ,ВыборкаДетальныеЗаписи.Ссылка , ТекстОшибки);        
                КонецПопытки;
                хмл = "";
            КонецЦикла;
            
        ИначеЕсли Номер = 1 Тогда
//В этом случае, цикла по складам не было, мы просто выгружаем остатки
            хмл = "";
            Попытка
                хмл = ПолучитьХМЛ("", Номер);
                Если хмл = Неопределено Тогда
                    
                Иначе
                    СтруктураДанных = ПолучитьСоединение("Prod_1c",Номер);
                    
                    Ответ = СтруктураДанных.ВСПрокси. Prod_1c(ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[0], хмл),
                    ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[1], ""),
                    ФабрикаXDTO.Создать(СтруктураДанных.ТипыXDTO[2], "0"));
                    
                    Если Ответ = "Success" Тогда
                        //ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Информация, ,ВыборкаДетальныеЗаписи.Ссылка , Ответ);        
                    Иначе
                        ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Ошибка, ,"ИМ" , Ответ);
                    КонецЕсли;
                КонецЕсли;
            Исключение
                ТекстОшибки = ОписаниеОшибки();
                ЗаписьЖурналаРегистрации("Отправка остатков со склада, кол. символов = " + СтрДлина(хмл), УровеньЖурналаРегистрации.Ошибка, ,"ИМ", ТекстОшибки);        
            КонецПопытки;
            хмл = "";
        КонецЕсли;
        
    КонецЦикла;
КонецПроцедуры

//Собственно сама функция для получения хмл
Функция ПолучитьХМЛ(Склад,Номер)    
//тут для каждого случая, мы создаем свою таблицу
    Если Номер = 0 Тогда
        Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ
        |    ТоварыНаСкладахОстатки.Номенклатура.Код КАК nom_id,
        |    ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры.Наименование КАК size_name,
        |    ТоварыНаСкладахОстатки.КоличествоОстаток КАК count
        |ИЗ
        |    РегистрНакопления.ТоварыНаСкладах.Остатки(
        |            ,
        |            Склад = &Склад
        |                И Номенклатура.ВидНоменклатуры = &ВидНоменклатуры) КАК ТоварыНаСкладахОстатки"
);
        Запрос.УстановитьПараметр("Склад", Склад);
        Запрос.УстановитьПараметр("ВидНоменклатуры", Справочники.ВидыНоменклатуры.НайтиПоКоду("000000001"));
    ИначеЕсли Номер = 1 Тогда
        Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ
        |    ТоварыНаСкладахОстатки.Номенклатура.Код КАК nom_id,
        |    ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры.Наименование КАК size_name,
        |    ТоварыНаСкладахОстатки.КоличествоОстаток КАК count
        |ИЗ
        |    РегистрНакопления.ТоварыНаСкладах.Остатки(
        |            ,
        |            Склад.родитель = &Склад
        |                И (Склад.СтатусСклада = ЗНАЧЕНИЕ(Перечисление.СтатусСклада.Розничный)
        |                    ИЛИ Склад.СтатусСклада = ЗНАЧЕНИЕ(Перечисление.СтатусСклада.Склад))) КАК ТоварыНаСкладахОстатки"
);
        Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоКоду("00001"));
        
    КонецЕсли;
    Результат = Запрос.Выполнить().Выгрузить();
    Если Результат.Количество() = 0 Тогда
        Возврат Неопределено;
    КонецЕсли;
//Тут обратите внимание, я не создаю файл хмл,  я не занимаюсь собственной наработкой для создания хмл структуры, я использую сериализатор 1С
    ДеревоВОбъектеXDTO = СериализаторXDTO.ЗаписатьXDTO(Результат);
    МойXML = Новый ЗаписьXML;
    МойXML.УстановитьСтроку();
    
    ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь);
    ФабрикаXDTO.ЗаписатьXML(МойXML, ДеревоВОбъектеXDTO);
    
    xml = МойXML.Закрыть();
//Вот и все, теперь в xml находится хмл структура, в виде строки, которую я и возвращаю в первую функцию, и передаю потом на сервер сайта ИМ.
//А вот очень интересная функция, УбратьЛишнее, она чистит хмл структуру созданную 1С, убирая оттуда не нужные данные и символы, таким образом мы сжимаем файл в 3 – 5 раз, а на парсинг это никак не влияет.
    xml = УбратьЛишнее(xml);
    
    Возврат xml
    
КонецФункции

//Чистка хмл на лишний мусор
//А вот и сама функция
Функция УбратьЛишнее(xml)
    xml = СтрЗаменить(xml,"xsi:type=""xs:decimal""", "");
    xml = СтрЗаменить(xml,"xsi:type=""xs:string""", "");
    xml = СтрЗаменить(xml,"xsi:type=""xs:boolean""", "");
    xml = СтрЗаменить(xml,"xsi:type=""xs:dateTime""", "");
    xml = СтрЗаменить(xml,"T00:00:00", "");
    xml = СтрЗаменить(xml,"0001-01-01", "");
    xml = СтрЗаменить(xml,"<Value ", "<Vl");
    xml = СтрЗаменить(xml,"", "");
    xml = СтрЗаменить(xml,"false", "0");
    xml = СтрЗаменить(xml,"true", "1");
    xml = СтрЗаменить(xml,"xsi:type=""Null""", "");  
//Для красоты 1С рисует структуру при помощи табуляции, это удобно читать, то для парсинга – это мусор, поэтому мы убираем все лишние табуляции, что позволяет сократить объем данных в 2 раза
    xml = СтрЗаменить(xml,"    ","");
    Возврат xml
КонецФункции

//Куда же без функции подключения к соап серверу?
//Сюда мы передаем имя операции, которую нам надо вернуть в структуре и номер ИМ
Функция ПолучитьСоединение(Имя, НомерСоединения)
    СтруктураДанных = Новый Структура;
    Если НомерСоединения = 0 Тогда
        Пользователь = " Пользователь 1";
        Пароль = " Пароль 1";
        Адрес = "http:// 127.0.0.1/sync";
        URIПространстваИменСервиса = "URI";
        ИмяСервиса = " ИмяСервиса ";
        ИмяТочкиПодключения = " ИмяСервиса Soap";
    ИначеЕсли НомерСоединения = 1 Тогда
        Пользователь = " Пользователь 2";
        Пароль = " Пароль 2";
        Адрес = "http:// 127.0.0.1:12345/product";
        URIПространстваИменСервиса = "URI";
        ИмяСервиса = " ИмяСервиса ";
        ИмяТочкиПодключения = " ИмяСервиса Soap";
    ИначеЕсли НомерСоединения = 2 Тогда
        Пользователь = " Пользователь 3";
        Пароль = " Пароль 3";
        //Адрес = "http://127.0.0.1/IM/ws/SendUsers.1cws?wsdl";
        URIПространстваИменСервиса = "URI";
        ИмяСервиса = " ИмяСервиса ";
        ИмяТочкиПодключения = " ИмяСервиса Soap";
    КонецЕсли;
    
    ВСОпределение = Новый WSОпределения(Адрес, Пользователь, Пароль);
    
    ВСПрокси = Новый WSПрокси(ВСОпределение, URIПространстваИменСервиса, ИмяСервиса, ИмяТочкиПодключения) ;
    ВСПрокси.Пользователь = Пользователь;
    ВСПрокси.Пароль       = Пароль;
    ВСервис     = ВСОпределение.Сервисы.Получить(0);
    ВТочкаВхода = ВСервис.ТочкиПодключения.Получить(0);
    ВОперация     = ПоискФункции(ВТочкаВхода.Интерфейс.Операции, Имя);        
    
    ТипыXDTO = Новый Массив;
    Для Каждого Параметр Из ВОперация.Параметры Цикл
        _ТипXDTO = ФабрикаXDTO.Тип(Параметр.Тип.URIПространстваИмен, Параметр.Тип.Имя);
        ТипыXDTO.Добавить(_ТипXDTO);
    КонецЦикла;
    // ТипыXDTO – это массив параметров, в нашем случае он будет равен 3. Я специально не привязываюсь к имени параметров, так как тогда, нужно будет под каждую операцию писать свою функцию, а мне влом.
    СтруктураДанных.Вставить("ВСОпределение", ВСОпределение);
    СтруктураДанных.Вставить("ВСПрокси", ВСПрокси);
    СтруктураДанных.Вставить("ВСервис", ВСервис);
    СтруктураДанных.Вставить("ВТочкаВхода", ВТочкаВхода);
    СтруктураДанных.Вставить("ВОперация", ВОперация);
    СтруктураДанных.Вставить("ТипыXDTO", ТипыXDTO);
    
    Возврат СтруктураДанных;

//Тут по сути ничего менять не надо, кроме данных авторизации
КонецФункции

//Найдем нужную функцию
//Ну тут все просто, после того как вы получили коллекцию операций, мы ищем нужную нам операцию и возвращаем ее. Сделана для экономии пространства
Функция ПоискФункции(Операции, Имя)
    Для Каждого Операция ИЗ Операции Цикл
        Если Операция.Имя = Имя Тогда
            Возврат Операция
        КонецЕсли;
    КонецЦикла;
КонецФункции

 

В итоге – на сайт придет строка такого формата:

Изначально идет описание колонок ТЗ, где указывается имя колонки, длина символов (максимальная), тип данных и др.

Далее – последовательно идут теги row, это строка таблицы, и теги Vl, их порядок соответствует порядку колонок в заголовке. Если бы мы не сделали сжатие, то данных там было бы на порядок больше, но они были бы бесполезны.

 

<ValueTable xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <column>
        <Name>nom_id>
        <ValueType>
        <Type>Null>
        <Type>xs:decimal>
        <NumberQualifiers>
        <Digits>11>
        <FractionDigits>0>
        <AllowedSign>Nonnegative>
        >
        >
        <Title>nom_id>
        <Width>11>
    >
    <column>
        <Name>size_name>
        <ValueType>
        <Type>xs:string>
        <Type>Null>
        <StringQualifiers>
        <Length>100>
        <AllowedLength>Variable>
        >
        >
        <Title>size_name>
        <Width>100>
    >
    <column>
        <Name>count>
        <ValueType>
        <Type>Null>
        <Type>xs:decimal>
        <NumberQualifiers>
        <Digits>38>
        <FractionDigits>0>
        <AllowedSign>Any>
        >
        >
        <Title>count>
        <Width>38>
    >
    <row>
        <Vl>95761>
        <Vl>40>
        <Vl>2>
    >
    <row>
        <Vl>95761>
        <Vl>41>
        <Vl>1>
    >
    <row>
        <Vl>95761>
        <Vl>42>
        <Vl>1>
    >
    <row>
        <Vl>95761>
        <Vl>44>
        <Vl>2>
    >
    <row>
        <Vl>95762>
        <Vl>40>
        <Vl>1>
    >
>
 
Часть xml тегов съел сайт, но тут главное суть :).

Теперь можно передавать данные на сайт, минуя всякие там фтп, файлы и прочую лабуду. Для пущей безопасности – у нас обмен данными идет внутри тунеля, так что просто так, со стороны, туда ничего не отправишь. Скорость обмена – выше всех похвал, таблица на 10 000 строк передается около 30 секунд, это с учетом времени запроса, формирования хмл, создания подключения, отправки данных, парсинг данных на стороне ИМ и получение ответа от сайта.

 

Ну как? Интересно? А может пойдем еще дальше? Мы же программисты 1С, а не веба? А может веб программист не хочет этого делать, такое тоже бывает, но вот у вас, допустим, есть франчайзы, и у вас общая дисконтная система, ну бывает же такое? Бывает. А база у них – своя, а вот дисконтов хочется видеть у себя, или вот вы сделали документ перемещения на них, а теперь надо что бы он попал в их базу, бывает? А для того что бы он выгрузился к ним в базу, нужно что бы у них была вся номенклатура? Ну без этого никак, а вдруг они сделают загрузят документ у себя, через файлик, а потом что то изменят, и начинается сверка, а там полная лажа. Тоже бывает.

 

И так, давайте поставим сами себе задачу – СДЕЛАТЬ ВСЕ КРАСИВО.

Ну вначале давайте определимся с тем, что есть красиво?

В нашем случае, это есть последовательная передача данных с базы в базу, логично?

И так, если мы хотим выгрузить документ перемещения в базу франчайзи, нам надо быть уверенными в том, что как минимум у них стоит 1С и включен сервер. Проверили? Ок. Следующая задача – убедиться что у них есть вся номенклатура, логично? А как мы можем быть в этом уверенными?

 

Тут стоит отметить, что я специально исключаю вредительство, т.е. если мы раз им выгрузили номенлатуру, то она никуда потом не девается :).

 

Но, давайте посмотрим на то, как и что делается в нашей базе.

Изначально, до создания документа – создается номенклатура, хотя надо предусмотреть вариант, когда создался документ, потом мы создали номенклатуру, а потом ее добавили в тот документ :). Но те кто с этим работает постоянно, знают как выкрутиться из этой ситуации.

 

И так, рисуется определенный алгоритм, а именно, вначале мы создаем номенклатуру, потом документ.

 

Тут приходит осознание того, что если эту же последовательность действий перенести на другую базу, то там тоже должно быть все красиво.

 

И так, выходом в моем случае – было создание регистра сведений Синхронизация, с вот такими вот полями:

Объект – это составной тип данных, в нашем случае указываем в нем Номенклатуру, ДокументПеремещения

ДатаДобавления — Дата

ДатаПопытки — Дата

ОписаниеОшибки — Строка

НомерСайта – число, хотите делайте строкой, дело ваше.

 

Тут все очень просто, это регистр сведений без подчинения, непериодический.

 

Далее, мы делаем подписку на события документа перемещения и номенклатуры.

Подписка работает в случае записи.

В подписке вот такой код:

 

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

 

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

 

И так, теперь в случае создания/изменения номенклатуры или документа, он попадет в этот регистр.

При чем в той же последовательности.

И так, вроде все идет хорошо, теперь же что то надо делать с этим регистром?

А делаем мы вот что, создаем регламент, у меня периодичность стоит 5 минут.

 

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

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

 

Давайте отработаем ситуацию, когда у нас в очереди 2 Номенлатуры и 1 Документ с ними.

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

 

Тут можно долго мудрить, у меня например в случае ошибки приходит сообщение, и запись помечается – как запись ошибочная и она не долбится постоянно в базу приемник, пока я не сниму эту метку.

Так же для выравнивания партионного учета, у нас есть специальный пользователь – если он проводит документ, то в регистр ничего не записывается.

На стороне базы приемника – есть система логов, которая логирует, когда и какой документ изменился и что в нем поменяли.

 

Тут можно думать долго и нудно, и каждый найдет свой путь просвещения.

 

Однако, на такой нотке было бы закончить совсем не весело, по этому я осмелюсь напомнить о вот таком куске кода:

ДеревоВОбъектеXDTO = СериализаторXDTO.ЗаписатьXDTO(Результат);
МойXML = Новый ЗаписьXML;
МойXML.УстановитьСтроку();
        
ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь);
ФабрикаXDTO.ЗаписатьXML(МойXML, ДеревоВОбъектеXDTO);
        
хмл = МойXML.Закрыть();
хмл = СтрЗаменить(хмл,"    ","");
 

 

Помните? Ну тот, который создает сам хмл структуру и она потом уходит на сайт. А давайте посмотрим, что можно придумать, если эта структура уходит в другую базу 1С?

ЧтениеXMLДанных = Новый ЧтениеXML;
ЧтениеXMLДанных.УстановитьСтроку(хмл);
ТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXMLДанных);
ЧтениеXMLДанных.Закрыть(); 

А вот эта операция вернет вам таблицу значений, т.е. больше ничего парсить не надо, вы сериализовали таблицу товаров документа, передали в базу приемник и там же – десериализовали. И дальше работаете с обычной ТЗ.

Однако! Обратите внимание, что я вырезаль только табуляцию, так как остальные параметры нужны 1С для десериализации!

Правда если вы синхронизацию с базами делаете не через GUID, то в этом случае, я например, сериализую таблицу, но вместо ссылки на номенклатуру передаю код, в базе приемнике – я добавляю к ТЗ колонку Номенклатура, заполняю ее по коду, и просто загружаю в ТЗ документа, так как название колонок в таблицах совпадают.

 

Надеюсь это кому то помогло!

Тему о поднятии веб сервисов – я не рассматриваю, так как она уже достаточно разжевана и в моих и в других статьях.

Если есть вопросы – добро пожаловать в комментарии.

Очень приветствуется злобная критика. Я еще учусь 🙂

has been added to your cart:
Оформление заказа