Как исправить ошибку расхождения сумм в табличной части Платежного поручения при синхронизации БП 3.0 и УНФ 1.6?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет IT и автоматизация бизнеса
← На главную

При настройке стандартной синхронизации данных между конфигурациями 1С:Бухгалтерия предприятия 3.0 (БП) и 1С:Управление нашей фирмой 1.6/3.0 (УНФ) пользователи часто сталкиваются с неприятным поведением системы. Документ ПлатежноеПоручение, созданный в БП, успешно мигрирует в УНФ, однако при его проведении или проверке заполнения программа выдает предупреждение: «Сумма документа не соответствует сумме разнесенных платежей в табличной части». При этом визуально на форме документа всё выглядит корректно: присутствует одна строка с заполненной суммой, которая в точности совпадает с суммой в шапке документа.

В этой статье мы подробно разберем причины возникновения данной коллизии, заглянем во внутреннюю архитектуру конфигурации УНФ и рассмотрим три практических способа решения этой проблемы без снятия типовых конфигураций с поддержки («с замка»).

Выясняем причину: почему возникает предупреждение?

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

Разработчики 1С в конфигурации УНФ применили механизм «эмуляции» табличной части на форме документа ПлатежноеПоручение для удобства пользователя. Рассмотрим подробнее, как это устроено:

  1. В базе данных (СУБД) документ имеет физическую табличную часть РасшифровкаПлатежа. Именно в ней хранятся аналитика платежа (договор, статья ДДС, заказ) и конкретные суммы распределения.
  2. Если пользователь открывает документ на форме в интерактивном режиме, а табличная часть РасшифровкаПлатежа в базе данных абсолютно пуста, срабатывает программный код формы (например, в процедуре ПриСозданииНаСервере). Он визуально эмулирует одну строку, подставляя туда сумму из шапки документа и базовую аналитику. Пользователь уверен, что строка существует.
  3. При ручном сохранении или проведении документа эта визуальная строка физически записывается в СУБД, и документ становится «полноценным».
  4. Ситуация кардинально меняется при синхронизации данных. Документ загружается из БП программно. Стандартные правила обмена (в формате EnterpriseData) переносят только реквизиты шапки, поскольку в БП у платежного поручения нет аналогичной детальной табличной части расшифровки.
  5. В момент записи документа при обмене данными устанавливается признак ОбменДанными.Загрузка = Истина. Код интерактивных форм при этом не выполняется. Документ записывается в базу данных с заполненной шапкой, но с абсолютно пустой табличной частью РасшифровкаПлатежа.

В дальнейшем при проведении документа или принудительной проверке заполнения срабатывает код в модуле объекта (в обработчике события ОбработкаПроверкиЗаполнения):


СуммаПлатежа = РасшифровкаПлатежа.Итог("СуммаПлатежа");
Если СуммаПлатежа <> СуммаДокумента Тогда
    // Генерируется предупреждение о несоответствии сумм...
КонецЕсли;

Поскольку физически в табличной части ноль строк, метод Итог("СуммаПлатежа") возвращает 0. Программа сравнивает 0 с реальной суммой документа (например, 1800) и выдает предупреждение об ошибке, регистрируя его в журнале регистрации обмена.

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

Решение 1. Использование расширения конфигурации (Рекомендуемый способ)

Поскольку наши конфигурации находятся «на замке» и мы не хотим лишать их возможности автоматического обновления, идеальным инструментом для решения проблемы будет создание небольшого расширения в базе УНФ.

Мы перехватим событие ПередЗаписью документа ПлатежноеПоручение на уровне объектного модуля. Если запись инициирована процессом обмена данными, мы принудительно создадим строку в табличной части и заполним ее данными из шапки.

Выполним следующие шаги:

  1. Откроем конфигуратор УНФ и перейдем в меню Конфигурация — Расширения конфигурации.
  2. Добавим новое расширение (например, с именем ФиксЗагрузкиПлатежныхПоручений) с назначением «Адаптация».
  3. В дереве объектов расширения добавим документ ПлатежноеПоручение и заимствуем его модуль объекта.
  4. В заимствованном модуле объекта создадим обработчик события ПередЗаписью с аннотацией &Перед или &После.

Рассмотрим пример кода, который необходимо поместить в модуль расширения:


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

Этот способ полностью решает проблему: при загрузке документа из БП табличная часть заполнится автоматически одной строкой с правильной суммой, встроенная проверка сопоставления сумм УНФ отработает без ошибок, и предупреждение в мониторе обмена больше не появится.

Решение 2. Корректировка логики загрузки через EnterpriseData

Если обмен настроен по современному протоколу EnterpriseData, логика обработки входящих XDTO-пакетов описывается в общем модуле менеджера обмена. Мы также можем модифицировать её с помощью расширения.

Рассмотрим, как переопределить обработку загрузки объектов программно:

  1. В расширении заимствуем общий модуль менеджера обмена (например, МенеджерОбменаЧерезУниверсальныйФормат).
  2. Находим процедуру, отвечающую за сопоставление и заполнение свойств документа ПлатежноеПоручение (обычно это обработчики загрузки XDTO-объектов).
  3. Дописываем алгоритм пост-обработки, который принудительно анализирует структуру загруженного документа и инициализирует коллекцию РасшифровкаПлатежа на этапе конвертации данных, до момента непосредственной записи объекта в базу.

Преимущество этого метода в том, что данные готовятся еще на этапе разбора XML/XDTO-пакета, однако этот метод более трудоемок в реализации и требует детального знания внутренней структуры формата EnterpriseData конкретной версии.

Решение 3. Написание внешней обработки для исправления уже загруженных документов

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

Давайте разберем по шагам логику внешней обработки, которая найдет все «проблемные» документы за указанный период времени и автоматически исправит их структуру:


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

Этот код выбирает все платежные поручения за период, проверяет их табличные части на пустоту и программно их заполняет, устанавливая свойство ОбменДанными.Загрузка = Истина, чтобы избежать блокировок из-за других проверок контроля заполнения.

Резюме и практические рекомендации

Мы выяснили, что ложные предупреждения при синхронизации БП и УНФ возникают из-за различия в логике экранных форм и физического хранения табличных частей в СУБД.

Для надежного решения этой проблемы рекомендуем применить Вариант 1 (Создание расширения конфигурации с обработчиком ПередЗаписью). Это позволит вам:

← На главную