При настройке или восстановлении синхронизации данных между конфигурациями «Управление торговлей» (начиная с версии 11.4) и «Бухгалтерия предприятия» (версии 3.0) специалисты часто сталкиваются со сложными ошибками валидации пакетов обмена. Одна из самых распространенных и труднодиагностируемых проблем — сбой на этапе проверки XDTO со следующим текстом:
Ошибка проверки данных XDTO: Структура объекта '/Товары/Строка[1]/ДанныеНоменклатуры/Упаковка' не соответствует типу... Не установлено значение одного из следующих свойств: ЕдиницаИзмерения
В этой статье мы подробно проанализируем, почему возникает данная ошибка, разберем внутреннюю архитектуру хранения упаковок и единиц измерения в 1С, а также рассмотрим практические способы исправления данных для восстановления стабильного обмена.
Синхронизация между современными конфигурациями 1С построена на использовании универсального формата обмена EnterpriseData. Этот формат жестко регламентирует структуру XML-файлов, передаваемых между базами. Валидация данных происходит с помощью встроенных механизмов платформы перед непосредственной отправкой пакета.
Когда в «Управлении торговлей» инициируется выгрузка документов (например, ПриобретениеТоваровУслуг или РеализацияТоваровУслуг), система обращается к табличной части «Товары». Для каждой строки модуль обмена пытается собрать сведения о номенклатуре и используемой упаковке (единице измерения).
Если в схеме XDTO свойство ЕдиницаИзмерения внутри структуры Упаковка определено как обязательное, а алгоритм сопоставления в 1С не смог получить значение этого реквизита из базы данных (вернув пустое значение или Неопределено), метод платформы ОбъектXDTO.Проверить() возвращает ошибку и полностью блокирует отправку всего пакета обмена.
Чтобы понять, из-за чего в XML-пакет выгружается пустое значение единицы измерения, проанализируем структуру хранения этих данных в конфигурации «Управление торговлей 11». В системе задействованы три ключевых справочника:
УпаковкиНоменклатуры) — подчиненный справочник, который хранит как индивидуальные упаковки, так и базовые единицы измерения.Справочник УпаковкиЕдиницыИзмерения подчинен справочнику НаборыУпаковок. При этом архитектура системы делит все записи на два типа по их владельцу:
Номенклатура или индивидуальный набор упаковок для этого товара.НаборыУпаковок под названием БазовыеЕдиницыИзмерения. Именно этот предопределенный элемент должен быть указан в качестве владельца!Суть проблемы: Если перенос номенклатуры выполнялся программно (например, с помощью внешней обработки после восстановления базы из копии или при получении данных через электронный документооборот), разработчики часто допускают ошибку. Они создают базовую единицу измерения для каждого товара отдельно и назначают ее владельцем сам элемент справочника Номенклатура. При попытке синхронизации стандартные правила обмена не находят ожидаемую связь с предопределенным элементом БазовыеЕдиницыИзмерения, из-за чего свойство ЕдиницаИзмерения в выгружаемом файле остается незаполненным.
Рассмотрим подробнее варианты решения этой проблемы — от быстрого группового изменения реквизитов до программного скрипта.
Для исправления ошибочно заполненных владельцев единиц измерения в базе «1С:Управление торговлей» напишем внешнюю обработку. С помощью запроса мы выберем все единицы измерения, у которых владельцем ошибочно установлена номенклатура, и заменим владельца на предопределенный элемент БазовыеЕдиницыИзмерения.
Создадим новую обработку и вставим в модуль следующий код:
Процедура ИсправитьВладельцевЕдиницИзмерения() Экспорт
// Шаг 1. Находим некорректно заполненные элементы
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка,
| Упаковки.Владелец КАК ТекущийВладелец
|ИЗ
| Справочник.УпаковкиЕдиницыИзмерения КАК Упаковки
|ГДЕ
| НЕ Упаковки.Владелец = ЗНАЧЕНИЕ(Справочник.НаборыУпаковок.БазовыеЕдиницыИзмерения)
| И Упаковки.ПометкаУдаления = ЛОЖЬ";
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Некорректных единиц измерения не обнаружено.");
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
КоличествоИзменено = 0;
// Шаг 2. Обходим выборку и исправляем владельца
Пока Выборка.Следующий() Цикл
// Проверяем тип владельца. Если это Номенклатура - исправляем
Если ТипЗнч(Выборка.ТекущийВладелец) = Тип("СправочникСсылка.Номенклатура") Тогда
ОбъектУпаковки = Выборка.Ссылка.ПолучитьОбъект();
ОбъектУпаковки.Владелец = Справочники.НаборыУпаковок.БазовыеЕдиницыИзмерения;
// Отключаем бизнес-логику и проверки при записи
ОбъектУпаковки.ОбменДанными.Загрузка = Истина;
Попытка
ОбъектУпаковки.Записать();
КоличествоИзменено = КоличествоИзменено + 1;
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
НСтр("ru = 'Ошибка записи объекта: '") + Выборка.Ссылка + " - " + ОписаниеОшибки()
);
КонецПопытки;
КонецЕсли;
КонецЦикла;
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
Шаблон("Успешно исправлено объектов: %1", КоличествоИзменено)
);
КонецПроцедуры
Этот код безопасно находит только те элементы, владельцем которых ошибочно выступает номенклатура, и перезаписывает их с указанием системного владельца БазовыеЕдиницыИзмерения. Использование флага ОбменДанными.Загрузка = Истина позволяет избежать блокировок при записи со стороны стандартных подписок на события конфигурации.
Если у вас нет возможности или прав для запуска внешней обработки с кодом, исправление можно выполнить с помощью стандартного инструмента «Групповое изменение реквизитов».
Однако при обычной попытке изменить реквизит Владелец в справочнике Упаковки и единицы измерения платформа не покажет системный элемент Базовые единицы измерения в списке выбора. Чтобы обойти это ограничение интерфейса, выполним следующие шаги:
Владелец Ссылка На Номенклатуру (чтобы не затронуть корректные индивидуальные упаковки других товаров).Наборы упаковок. Выбираем предопределенный элемент Базовые единицы измерения.Проанализируем ситуацию, когда нам необходимо в дальнейшем программно создавать номенклатуру и единицы измерения (например, при интеграции со сторонними сервисами или маркетплейсами), чтобы не допустить повторения этой ошибки.
Правильный алгоритм программного создания единицы измерения для новой карточки товара должен выглядеть следующим образом:
// Функция создает или находит базовую единицу измерения
Функция ПолучитьБазовуюЕдиницуИзмерения(КодОКЕИ, НаименованиеЕдиницы)
// Проверяем наличие предопределенного набора
БазовыйНабор = Справочники.НаборыУпаковок.БазовыеЕдиницыИзмерения;
// Ищем уже существующую единицу измерения по наименованию и владельцу
ЕдиницаСсылка = Справочники.УпаковкиЕдиницыИзмерения.НайтиПоНаименованию(
НаименованиеЕдиницы,
Истина, // Поиск по полному соответствию
, // Родитель не заполняется
БазовыйНабор // Владельцем должен быть базовый набор!
);
Если ЕдиницаСсылка.Пустая() Тогда
// Создаем новую базовую единицу измерения
НоваяЕдиница = Справочники.УпаковкиЕдиницыИзмерения.СоздатьЭлемент();
НоваяЕдиница.Наименование = НаименованиеЕдиницы;
НоваяЕдиница.Владелец = БазовыйНабор; // Указываем правильного владельца
НоваяЕдиница.Числитель = 1;
НоваяЕдиница.Знаменатель = 1;
НоваяЕдиница.БезУчетаУпаковок = Истина;
// Если есть связь с классификатором ОКЕИ
Классификатор = Справочники.КлассификаторЕдиницИзмерения.НайтиПоКоду(КодОКЕИ);
Если Не Классификатор.Пустая() Тогда
НоваяЕдиница.ЕдиницаИзмерения = Классификатор;
КонецЕсли;
НоваяЕдиница.Записать();
Возврат НоваяЕдиница.Ссылка;
КонецЕсли;
Возврат ЕдиницаСсылка;
КонецФункции
При таком подходе все новые единицы измерения будут создаваться с корректной привязкой к системным классификаторам, и последующая выгрузка документов через EnterpriseData пройдет без замечаний.
После того как владельцы единиц измерения исправлены одним из описанных выше способов, необходимо подготовить документы к повторной отправке:
Приобретение товаров и услуг), и зарегистрируем их к обмену принудительно, если регистрация была снята.Проанализировав журнал регистрации после завершения обмена, мы увидим, что валидация XDTO-пакета прошла успешно, и все документы были успешно проведены в базе «1С:Бухгалтерия предприятия».