Интеграция с 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 Ответить
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот