Как получить реквизиты связанных справочников через OData в 1С: решение проблемы с обращением через точку

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

При работе с внешними системами через протокол OData в 1С программисты часто сталкиваются с необходимостью получить не только основные данные регистра (например, остатки), но и дополнительные реквизиты измерений. Типичная ситуация: мы запрашиваем остатки из регистра ТоварыНаСкладах и хотим сразу увидеть Артикул номенклатуры. Однако попытка указать в запросе поле вида Номенклатура_Артикул приводит к ошибке: «Сегмент пути не найден». Разберем подробно, почему так происходит и как правильно организовать получение данных.

Почему возникает ошибка «Сегмент пути не найден»

Проанализируем ситуацию. В языке запросов 1С мы привыкли обращаться к реквизитам через точку: Номенклатура.Артикул. Однако стандарт OData, реализованный в платформе 1С, работает иначе. Когда вы обращаетесь к виртуальной таблице остатков регистра накопления, платформа формирует плоский список полей. Поле Номенклатура_Key содержит уникальный идентификатор (GUID) ссылки, а поле Номенклатура____Presentation — строковое представление.

Попытка просто дописать название реквизита через подчеркивание (Номенклатура_Артикул) не сработает, так как в метаданных этой конкретной сущности (таблицы остатков) такого поля не существует. Система OData не выполняет автоматическое соединение таблиц «на лету» только по имени поля в параметре $select. Для изучения структуры доступных сущностей и анализа передаваемых данных подойдёт обработка для анализа структуры OData и содержимого таблиц.

Способ 1. Использование параметра $expand для получения реквизитов

Рассмотрим основной механизм OData для получения данных связанных объектов — параметр $expand. Он позволяет «развернуть» навигационное свойство и включить данные связанного объекта в основной ответ сервера. Для безошибочного построения подобных URL-обращений с параметрами выборки подойдёт генератор запросов к стандартному интерфейсу OData.

Выясним, как изменить ваш ТекстЗапроса, чтобы получить артикул:


// Формируем текст запроса с использованием $expand
ТекстЗапроса = "/БАЗА/odata/standard.odata/AccumulationRegister_ТоварыНаСкладах/Balance(Period=datetime'" 
    + DateTime + "')?" 
    + "$select=Номенклатура,ВНаличииBalance" // Выбираем объект Номенклатура целиком
    + "&$expand=Номенклатура" // Разворачиваем объект Номенклатура
    + "&$format=json;odata=nometadata";

При использовании $expand сервер вернет структуру, где внутри каждого элемента остатков будет вложенный объект Номенклатура, содержащий все свои реквизиты, включая Артикул. Важный нюанс: этот метод работает только в том случае, если в метаданных OData поле Номенклатура определено как NavigationProperty. В некоторых версиях платформы для виртуальных таблиц остатков это может быть ограничено.

Способ 2. Получение данных в два этапа (через GUID)

Если механизм $expand недоступен или работает слишком медленно, проанализируем альтернативный подход. Мы можем сначала получить список остатков с идентификаторами номенклатуры, а затем запросить данные из справочника Номенклатура отдельно.

Разберем этот процесс по шагам:

  1. Выполняем запрос к регистру и получаем Номенклатура_Key (GUID).
  2. Собираем все уникальные GUID в массив или строку.
  3. Делаем второй запрос к Catalog_Номенклатура с фильтром по полученным идентификаторам.

Пример запроса к справочнику для получения артикулов по конкретным ссылкам:


// Запрос к справочнику с фильтром по нескольким GUID
ТекстЗапросаСправочник = "/БАЗА/odata/standard.odata/Catalog_Номенклатура?"
    + "$filter=Ref_Key eq guid'7a8f4016-e580-11df-a18a-959bba206076' or Ref_Key eq guid'7a8f4018-e580-11df-a18a-959bba206076'"
    + "&$select=Ref_Key,Артикул"
    + "&$format=json";

Затем в коде 1С мы можем сопоставить данные по ключу Ref_Key. Это надежный способ, который гарантированно работает во всех версиях платформы, поддерживающих OData.

Способ 3. Пакетные запросы ($batch)

Если номенклатуры много, выполнение отдельного HTTP-запроса на каждый товар будет крайне неэффективным. Посмотрим на профессиональное решение — использование механизма $batch. Это позволяет отправить один POST-запрос, содержащий внутри себя множество команд GET.

Проанализируем структуру такого взаимодействия:

Как проверить доступные поля через $metadata

Чтобы больше не гадать, почему то или иное поле недоступно, выполним проверку метаданных вашей базы. Введите в браузере адрес:

http://ххх.ххх.ххх.х/БАЗА/odata/standard.odata/$metadata

В открывшемся XML-документе найдите раздел EntityType для вашего регистра (например, AccumulationRegister_ТоварыНаСкладах_Balance). Посмотрите, как описано измерение Номенклатура:

  1. Если это Property с типом Edm.Guid, то вы можете получить только GUID.
  2. Если это NavigationProperty, то вы имеете право использовать $expand для перехода к реквизитам справочника.

Рекомендации по обработке ответа в 1С

Посмотрим на ваш исходный код обработки ответа. Вы используете ПрочитатьJSON(ЧтениеJSON, Истина), что возвращает объект типа Соответствие. Помните, что в Соответствие нельзя обращаться к полям через точку (например, Данные.Номенклатура_Key). Используйте квадратные скобки: Данные["Номенклатура_Key"].

Если вы решили использовать второй запрос для получения артикулов, рекомендуем загрузить результаты в Таблицу Значений или Соответствие, где ключом будет выступать GUID номенклатуры. Это позволит мгновенно находить артикул при переборе строк остатков.

Пример эффективного сопоставления:


// Допустим, Артикулы — это Соответствие, где Ключ - GUID, Значение - Артикул
Для Каждого СтрокаОстатков Из МассивРезультатов Цикл
    ТекущийGUID = СтрокаОстатков["Номенклатура_Key"];
    ТекущийАртикул = Артикулы[ТекущийGUID];
    Если ТекущийАртикул <> Неопределено Тогда
        // Обрабатываем данные
    КонецЕсли;
КонецЦикла;

Итоги

Подведем итог нашему разбору. Прямое обращение к реквизитам через точку в стиле 1С-запросов (Номенклатура_Артикул) в OData не поддерживается. Для решения вашей задачи мы рекомендуем:

  1. Проверить возможность использования $expand=Номенклатура в одном запросе с остатками.
  2. Если это невозможно, использовать дополнительный запрос к справочнику Номенклатура, передавая список нужных GUID в параметре $filter.
  3. Всегда анализировать $metadata, чтобы точно знать структуру доступных сущностей и их связей.

Эти методы позволят вам корректно сверять данные между КА и Розницей, даже если ссылки «битые», используя Артикул как дополнительный идентификатор для поиска. Для точечной миграции объектов между базами без прямой синхронизации по ссылкам может использоваться обработка для переноса данных между похожими конфигурациями 1С.

← На главную