Интеграция с 1с:ДО 2.1 и постоянное обновление организации вместе с внутренним документом (договором)

1. triviumfan 93 17.10.18 22:25 Сейчас в теме
Доброго вечера, коллеги.

Проблема, собственно, в названии темы.
Имеется УТ 11.3 и ДО 2.1.
Настроен обмен УТ->ДО договорами.

С чего все началось... пользователи стали жаловаться, что невозможно внести изменения в справочник "Организации" в ДО - "Данные были изменены или удалены другим пользователем".
Смотрю ЖР. Оказывается, что WS-соединение почти каждые 3 секунды перезаписывает организацию!
В правилах интеграции ничего криминального нет, они почти те, что в типовой методичке приведены.

Далее смотрю регистр "Очередь сообщений в 1С:Документооборот".
Оказывается, там аж 2500 записей об ошибках.
Типичные из них:
{ОбщийМодуль.ИнтеграцияС1СДокументооборот.Модуль(390)}: Ошибка при записи внутреннего документа:¶Регистрационный номер не уникален!¶

{ОбщийМодуль.ИнтеграцияС1СДокументооборотОбмен.Модуль(346)}: Ошибка при вызове метода контекста (execute): При вызове веб-сервиса произошла ошибка. Ошибка вызова операции сервиса:  {http://www.1c.ru/dm}:DMService:execute(): При вызове веб-сервиса произошла ошибка. Неизвестная ошибка. Ошибка работы с Интернет:   Превышено время ожидания: Ошибка работы с Интернет:   Превышено время ожидания

{ОбщийМодуль.ИнтеграцияС1СДокументооборот.Модуль(390)}: Ошибка при изменении внутреннего документа:¶Не удалось заблокировать запись. Действие (изменение, удаление или блокировка записи) не выполнено.¶Ошибка блокировки объекта. Объект уже заблокирован:¶пользователь: Администратор, сеанс: 294, начат: 03.09.2018 в 10:30:31, приложение: WS-соединение¶


Судя по регламентному заданию "Интеграция с 1С:Документооборотом - Выполнить обмен данными" то этот регистр должен чиститься после каждого успешного обмена. Что будет если просто его очистить? Изменения не перетекут в ДО?

А теперь самое интересное!
Залезаю в отладку (ДО) и вижу, такое (см. скриншот "Стек вызовов").
Оказывается, при любом раскладе в ОбработкаЗапросовXDTO.НайтиСоздатьОрганизацию() будет перезаписана организация! Будь она найдена по внутреннему id или ключам поиска (наименование, инн/кпп):
Полное описание функции

Почему именно НайтиСоздатьОрганизацию()? Смотрим выше:
// Заполняет реквизит объекта информационной базы из свойства объекта XDTO
//
// Параметры:
//   Узел - ПланОбменаСсылка.ИнтегрированныеСистемы - узел интегрированной системы
//   Реквизит - Произвольный - реквизит объекта, подлежащий заполнению
//   ОбъектXDTO - ОбъектXDTO - объект, свойство которого соответствует заполняемому реквизиту
//   ИмяСвойстваXDTO - Строка - имя свойства, значение которого переносится в реквизит
// 
Процедура ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Реквизит, ОбъектXDTO, ИмяСвойстваXDTO) Экспорт 
	
	Если ОбъектXDTO.Установлено(ИмяСвойстваXDTO) Тогда  
		ЗначениеСвойстваXDTO = ОбъектXDTO[ИмяСвойстваXDTO];
		Если ТипЗнч(ЗначениеСвойстваXDTO) = Тип("ОбъектXDTO") Тогда  
			Тип = ЗначениеСвойстваXDTO.objectId.type;
			ID  = ЗначениеСвойстваXDTO.objectId.id;
			Если Не ЗначениеЗаполнено(ID) И Не ЗначениеЗаполнено(Тип) И ЗначениеСвойстваXDTO.Установлено("ExternalObject") Тогда 
				НовоеЗначение = НайтиСоздатьВнешнийОбъект(Узел, ЗначениеСвойстваXDTO);
			Иначе
				НовоеЗначение = ПолучитьСсылкуПоObjectID(ЗначениеСвойстваXDTO.objectId);
			КонецЕсли;
		Иначе
			НовоеЗначение = ЗначениеСвойстваXDTO;
		КонецЕсли;
		
		Если Реквизит <> НовоеЗначение Тогда
			Реквизит = НовоеЗначение;
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры
Показать

Также прикладываю файл обмена. Стоит отметить, что данные IbjectID пустые (в отличие от того же самого внутреннего документа), а данных организации в РС "СвязиОбъектовИнтегрированныхСистем" нет, там лишь соответствия договоров. Видимо свойства договора все-же должны искаться по ключам. Но почему каждый раз перезаписываясь?!
Спасибо всем, кто откликнется.
Прикрепленные файлы:
По теме из базы знаний
Вознаграждение за ответ
Показать полностью
Найденные решения
5. triviumfan 93 18.10.18 17:43 Сейчас в теме +1 $m
Все-таки исправил проблему.
Решение:
// Заполняет объект Документооборота по данным объекта XDTO
//
// Параметры:
//   Узел - ПланОбменаСсылка.ИнтегрированныеСистемы - узел интегрированной системы
//   Организация - СправочникОбъект.Организации - заполняемый объект
//   ОбъектXDTO - ОбъектXDTO типа DMOrganization - источник данных заполнения
//
Процедура ЗаполнитьДанныеОрганизации(Узел, Организация, ОбъектXDTO) Экспорт 
	
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Наименование, ОбъектXDTO, "name");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ИНН, ОбъектXDTO, "inn");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.КПП, ОбъектXDTO, "kpp");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.КодПоОКПО, ОбъектXDTO, "okpo");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Префикс, ОбъектXDTO, "prefix");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ПлательщикНДС, ОбъектXDTO, "VATpayer");
	
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.НаименованиеПолное, ОбъектXDTO, "fullName");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Комментарий, ОбъектXDTO, "comment");
	
	Если ОбъектXDTO.Установлено("legalPrivatePerson") Тогда 
		ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ЮрФизЛицо, ОбъектXDTO, "legalPrivatePerson");
	Иначе
		//++
		//Организация.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;
		Если Не ЗначениеЗаполнено(Организация.ЮрФизЛицо) Тогда
			Организация.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;	
		КонецЕсли;
		//-- 
	КонецЕсли;
	
КонецПроцедуры
Показать

Не нужно каждый раз перезаполнять "ЮрФизЛицо", а свойства "legalPrivatePerson" у меня нет.
Остальные ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. Eyerie 18.10.18 14:25 Сейчас в теме
Была похожая проблема, некогда было разбираться, просто закомментировала код перезаписи организации, т.к. у нас дополнительно к интеграции настроен обмен.
3. triviumfan 93 18.10.18 16:40 Сейчас в теме
(2) У нас тоже, эта проблема и связана именно с обменом. Похоже, что отсюда выползает и ещё одна проблема - ЖР - он слишком быстрыми темпами "полнеет", и не удивительно, при таком то количестве перезаписей.
4. triviumfan 93 18.10.18 17:10 Сейчас в теме
Больше всего раздражает этот момент:
ЗаполнитьДанныеОрганизации(Узел, ОбъектДО, ОбъектXDTO);
    Если ОбъектДО.Модифицированность() Тогда
        ОбъектДО.Записать();
    КонецЕсли;

Ну так он же всегда модифицирован будет!
Перезаполняем СправочникОбъект и проверяем модифицированность!

СправочникОбъект.<Имя справочника> (CatalogObject.<Имя справочника>)
Модифицированность (Modified)
Синтаксис:

Модифицированность()
Возвращаемое значение:

Тип: Булево.
Истина - объект изменен; Ложь - в противном случае.
Описание:

Определяет, был ли изменен объект после считывания из базы данных.

Доступность:

Сервер, толстый клиент, внешнее соединение, мобильное приложение(сервер).
Примечание:

Метод не позволяет определить, был ли изменен объект другими пользователями.
Пример:

Если Объект.Модифицированность() Тогда
Объект.Записать();
КонецЕсли;
Показать


Кажется, это писали рукож#пы.
5. triviumfan 93 18.10.18 17:43 Сейчас в теме +1 $m
Все-таки исправил проблему.
Решение:
// Заполняет объект Документооборота по данным объекта XDTO
//
// Параметры:
//   Узел - ПланОбменаСсылка.ИнтегрированныеСистемы - узел интегрированной системы
//   Организация - СправочникОбъект.Организации - заполняемый объект
//   ОбъектXDTO - ОбъектXDTO типа DMOrganization - источник данных заполнения
//
Процедура ЗаполнитьДанныеОрганизации(Узел, Организация, ОбъектXDTO) Экспорт 
	
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Наименование, ОбъектXDTO, "name");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ИНН, ОбъектXDTO, "inn");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.КПП, ОбъектXDTO, "kpp");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.КодПоОКПО, ОбъектXDTO, "okpo");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Префикс, ОбъектXDTO, "prefix");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ПлательщикНДС, ОбъектXDTO, "VATpayer");
	
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.НаименованиеПолное, ОбъектXDTO, "fullName");
	ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.Комментарий, ОбъектXDTO, "comment");
	
	Если ОбъектXDTO.Установлено("legalPrivatePerson") Тогда 
		ОбработкаЗапросовXDTO.ЗаполнитьРеквизитИзСвойстваXDTO(Узел, Организация.ЮрФизЛицо, ОбъектXDTO, "legalPrivatePerson");
	Иначе
		//++
		//Организация.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;
		Если Не ЗначениеЗаполнено(Организация.ЮрФизЛицо) Тогда
			Организация.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;	
		КонецЕсли;
		//-- 
	КонецЕсли;
	
КонецПроцедуры
Показать

Не нужно каждый раз перезаполнять "ЮрФизЛицо", а свойства "legalPrivatePerson" у меня нет.
6. triviumfan 93 18.10.18 21:59 Сейчас в теме
Осталось разобраться, почему копятся записи в РС "ОчередьСообщенийВ1СДокументооборот".
При этом есть и вовсе записи с пустыми XML
<?xml version="1.0" encoding="UTF-8"?>
<Message/>

А основная ошибка - "превышено время ожидания".

Может кто ткнет, где можно почитать про технические особенности подсистемы "Интеграция1СДокументооборотом"?
7. triviumfan 93 18.10.18 23:38 Сейчас в теме
Написал обработку, в которой изменил алгоритм отправки данных, чтобы после каждого запроса удалялось сообщение в очереди.
Далее нашёл те, при которых происходила ошибка, удалил их и снова продолжил обмен.
Тем самым все сообщения были отправлены.
// Прочитывает данные из очереди на отправку и отправляет их в Документооборот.
//
Процедура ОтправитьДанные()
	
	Попытка
		
		ИдентификаторСообщения = Неопределено;
		МоментВремени = Неопределено;
		
		Запрос = Новый Запрос(
			"ВЫБРАТЬ
			|	ОчередьСообщенийВ1СДокументооборот.МоментВремени КАК МоментВремени,
			|	ОчередьСообщенийВ1СДокументооборот.Данные КАК Данные,
			|	ОчередьСообщенийВ1СДокументооборот.Идентификатор КАК Идентификатор
			|ИЗ
			|	РегистрСведений.ОчередьСообщенийВ1СДокументооборот КАК ОчередьСообщенийВ1СДокументооборот
			|
			|УПОРЯДОЧИТЬ ПО
			|	МоментВремени");
		
		Результат = Запрос.Выполнить();
		
		Если Результат.Пустой() Тогда
			Возврат;
		КонецЕсли; 
		
		Прокси = ИнтеграцияС1СДокументооборотПовтИсп.ПолучитьПрокси();
		
		Запрос = ИнтеграцияС1СДокументооборот.СоздатьОбъект(Прокси, "DMPutChangesRequest");
		ОбщийРазмерСообщений = 0;
		ПредельныйРазмерСообщений = 
			ИнтеграцияС1СДокументооборотВызовСервера.МаксимальныйРазмерПередаваемогоФайла();
		
		Выборка = Результат.Выбрать();
		
		Пока Выборка.Следующий() Цикл
			
			ИдентификаторСообщения = Выборка.Идентификатор;
			МоментВремени = Выборка.МоментВремени;
			
			ДвоичныеДанные = Выборка.Данные.Получить();
			
			//ОбщийРазмерСообщений = ОбщийРазмерСообщений + ДвоичныеДанные.Размер();
			
			//Если ОбщийРазмерСообщений > ПредельныйРазмерСообщений
			//	И Запрос.objects.Количество() > 0 Тогда
			//	
			//	Результат = Прокси.execute(Запрос);
			//	ИнтеграцияС1СДокументооборот.ПроверитьВозвратВебСервиса(Прокси, Результат);
			//	
			//	Запрос = ИнтеграцияС1СДокументооборот.СоздатьОбъект(Прокси, "DMPutChangesRequest");
			//	ОбщийРазмерСообщений = 0;
			//	
			//КонецЕсли;
			
			ИмяФайлаСообщенияОбмена = ПолучитьИмяВременногоФайла("xml");
			ДвоичныеДанные.Записать(ИмяФайлаСообщенияОбмена);
			
			ЧтениеXML = Новый ЧтениеXML;
			ЧтениеXML.ОткрытьФайл(ИмяФайлаСообщенияОбмена);
			ЧтениеXML.Прочитать();
			ЧтениеXML.Прочитать();
			
			Пока ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Цикл
				// Выполняется последовательное чтение одного объекта за другим
				ТипXDTO = Прокси.ФабрикаXDTO.Тип("http://www.1c.ru/dm", ЧтениеXML.Имя);
				ОбъектXDTO = Прокси.ФабрикаXDTO.ПрочитатьXML(ЧтениеXML, ТипXDTO);
				Запрос.objects.Добавить(ОбъектXDTO);
			КонецЦикла;
			
			ЧтениеXML = Неопределено;
			#Если Сервер Тогда
				УдалитьФайлы(ИмяФайлаСообщенияОбмена);
			#КонецЕсли
			
			Если Запрос.objects.Количество() > 0 Тогда
				Результат = Прокси.execute(Запрос);
				ИнтеграцияС1СДокументооборот.ПроверитьВозвратВебСервиса(Прокси, Результат);
			КонецЕсли;
			
			МенеджерЗаписи = РегистрыСведений.ОчередьСообщенийВ1СДокументооборот.СоздатьМенеджерЗаписи();
			ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
			МенеджерЗаписи.Удалить();
			
		КонецЦикла; 
		
		//Если Запрос.objects.Количество() > 0 Тогда
		//	Результат = Прокси.execute(Запрос);
		//	ИнтеграцияС1СДокументооборот.ПроверитьВозвратВебСервиса(Прокси, Результат);
		//КонецЕсли;
		
		//Выборка.Сбросить();
		//
		//Пока Выборка.Следующий() Цикл
		//	
		//	МенеджерЗаписи = РегистрыСведений.ОчередьСообщенийВ1СДокументооборот.СоздатьМенеджерЗаписи();
		//	ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
		//	МенеджерЗаписи.Удалить();
		//	
		//КонецЦикла;
		
	Исключение
		
		Инфо = ОписаниеОшибки();
		
		ЗаписьЖурналаРегистрации(
			НСтр("ru = 'Интеграция с 1С:Документооборотом.Отправка данных'",
				ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()),
			УровеньЖурналаРегистрации.Ошибка,
			Метаданные.РегистрыСведений.ОчередьСообщенийВ1СДокументооборот,
			Строка(ИдентификаторСообщения),
			Запрос.Тип().Имя + Символы.ПС + Инфо);
			
		Если ИдентификаторСообщения <> Неопределено Тогда
			МенеджерЗаписи = РегистрыСведений.ОчередьСообщенийВ1СДокументооборот.СоздатьМенеджерЗаписи();
			МенеджерЗаписи.МоментВремени = МоментВремени;
			МенеджерЗаписи.Идентификатор = ИдентификаторСообщения;
			МенеджерЗаписи.Прочитать();
			МенеджерЗаписи.КоличествоПопытокОтправки = МенеджерЗаписи.КоличествоПопытокОтправки + 1;
			МенеджерЗаписи.ТекстСообщенияОбОшибке = Инфо;
			МенеджерЗаписи.Записать();
		КонецЕсли;
		
	КонецПопытки; 
	
КонецПроцедуры
Показать

Изначально они копились в одном файле, пока не достигнув максимального размера, указанного в константе. Все же не стоило очищать стек только после отправки абсолютно всех данных. Или, возможно, уменьшение максимального размер пакета как-то помогло решить проблему. Стоит 10 мб.
safm; user809597; Dunda; +3 Ответить
Оставьте свое сообщение
Вакансии
1С аналитик
Москва
зарплата от 210 000 руб.
Полный день

Руководитель направления 1С
Москва
зарплата от 350 000 руб.
Полный день

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)