При работе с внешними системами через протокол OData в 1С программисты часто сталкиваются с необходимостью получить не только основные данные регистра (например, остатки), но и дополнительные реквизиты измерений. Типичная ситуация: мы запрашиваем остатки из регистра ТоварыНаСкладах и хотим сразу увидеть Артикул номенклатуры. Однако попытка указать в запросе поле вида Номенклатура_Артикул приводит к ошибке: «Сегмент пути не найден». Разберем подробно, почему так происходит и как правильно организовать получение данных.
Проанализируем ситуацию. В языке запросов 1С мы привыкли обращаться к реквизитам через точку: Номенклатура.Артикул. Однако стандарт OData, реализованный в платформе 1С, работает иначе. Когда вы обращаетесь к виртуальной таблице остатков регистра накопления, платформа формирует плоский список полей. Поле Номенклатура_Key содержит уникальный идентификатор (GUID) ссылки, а поле Номенклатура____Presentation — строковое представление.
Попытка просто дописать название реквизита через подчеркивание (Номенклатура_Артикул) не сработает, так как в метаданных этой конкретной сущности (таблицы остатков) такого поля не существует. Система OData не выполняет автоматическое соединение таблиц «на лету» только по имени поля в параметре $select. Для изучения структуры доступных сущностей и анализа передаваемых данных подойдёт обработка для анализа структуры OData и содержимого таблиц.
Рассмотрим основной механизм OData для получения данных связанных объектов — параметр $expand. Он позволяет «развернуть» навигационное свойство и включить данные связанного объекта в основной ответ сервера. Для безошибочного построения подобных URL-обращений с параметрами выборки подойдёт генератор запросов к стандартному интерфейсу OData.
Выясним, как изменить ваш ТекстЗапроса, чтобы получить артикул:
// Формируем текст запроса с использованием $expand
ТекстЗапроса = "/БАЗА/odata/standard.odata/AccumulationRegister_ТоварыНаСкладах/Balance(Period=datetime'"
+ DateTime + "')?"
+ "$select=Номенклатура,ВНаличииBalance" // Выбираем объект Номенклатура целиком
+ "&$expand=Номенклатура" // Разворачиваем объект Номенклатура
+ "&$format=json;odata=nometadata";
При использовании $expand сервер вернет структуру, где внутри каждого элемента остатков будет вложенный объект Номенклатура, содержащий все свои реквизиты, включая Артикул. Важный нюанс: этот метод работает только в том случае, если в метаданных OData поле Номенклатура определено как NavigationProperty. В некоторых версиях платформы для виртуальных таблиц остатков это может быть ограничено.
Если механизм $expand недоступен или работает слишком медленно, проанализируем альтернативный подход. Мы можем сначала получить список остатков с идентификаторами номенклатуры, а затем запросить данные из справочника Номенклатура отдельно.
Разберем этот процесс по шагам:
Номенклатура_Key (GUID).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.
Если номенклатуры много, выполнение отдельного HTTP-запроса на каждый товар будет крайне неэффективным. Посмотрим на профессиональное решение — использование механизма $batch. Это позволяет отправить один POST-запрос, содержащий внутри себя множество команд GET.
Проанализируем структуру такого взаимодействия:
Ref_Key.Чтобы больше не гадать, почему то или иное поле недоступно, выполним проверку метаданных вашей базы. Введите в браузере адрес:
http://ххх.ххх.ххх.х/БАЗА/odata/standard.odata/$metadata
В открывшемся XML-документе найдите раздел EntityType для вашего регистра (например, AccumulationRegister_ТоварыНаСкладах_Balance). Посмотрите, как описано измерение Номенклатура:
Property с типом Edm.Guid, то вы можете получить только GUID.NavigationProperty, то вы имеете право использовать $expand для перехода к реквизитам справочника.Посмотрим на ваш исходный код обработки ответа. Вы используете ПрочитатьJSON(ЧтениеJSON, Истина), что возвращает объект типа Соответствие. Помните, что в Соответствие нельзя обращаться к полям через точку (например, Данные.Номенклатура_Key). Используйте квадратные скобки: Данные["Номенклатура_Key"].
Если вы решили использовать второй запрос для получения артикулов, рекомендуем загрузить результаты в Таблицу Значений или Соответствие, где ключом будет выступать GUID номенклатуры. Это позволит мгновенно находить артикул при переборе строк остатков.
Пример эффективного сопоставления:
// Допустим, Артикулы — это Соответствие, где Ключ - GUID, Значение - Артикул
Для Каждого СтрокаОстатков Из МассивРезультатов Цикл
ТекущийGUID = СтрокаОстатков["Номенклатура_Key"];
ТекущийАртикул = Артикулы[ТекущийGUID];
Если ТекущийАртикул <> Неопределено Тогда
// Обрабатываем данные
КонецЕсли;
КонецЦикла;
Подведем итог нашему разбору. Прямое обращение к реквизитам через точку в стиле 1С-запросов (Номенклатура_Артикул) в OData не поддерживается. Для решения вашей задачи мы рекомендуем:
$filter.Эти методы позволят вам корректно сверять данные между КА и Розницей, даже если ссылки «битые», используя Артикул как дополнительный идентификатор для поиска. Для точечной миграции объектов между базами без прямой синхронизации по ссылкам может использоваться обработка для переноса данных между похожими конфигурациями 1С.