Как в OData сделать отбор документов по ИНН организации (фильтрация по вложенным полям)?

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

При интеграции 1С с внешними системами (сайтами, мобильными приложениями, личными кабинетами) часто используется стандартный интерфейс OData. Это удобный механизм, который генерируется платформой автоматически ("из коробки"). Однако разработчики часто сталкиваются с неочевидными ограничениями при попытке выполнить сложные отборы.

Одной из самых распространенных задач является фильтрация списка документов по реквизиту связанного справочника. Например, нам нужно получить список документов ВозвратТоваровПоставщику, но отобрать их не по ссылке на организацию, а по ее ИНН. Давайте разберем подробно, почему прямой запрос не сработает, и как правильно решить эту задачу.

Суть проблемы: почему не работает простой фильтр?

В языке запросов 1С мы привыкли к тому, что можем обращаться к реквизитам через точку. Мы пишем:


ГДЕ Документ.Организация.ИНН = &НужныйИНН

Переходя на OData, мы интуитивно пытаемся перенести эту логику в URL запроса, ожидая, что конструкция вида Organization/INN или Organization.INN в параметре $filter сработает. Пример такого запроса мог бы выглядеть так:


http://host/base/odata/standard.odata/Document_ВозвратТоваровПоставщику?$filter=Organization/INN eq '7777777777'

Однако, выполнив такой запрос, мы получим ошибку. Дело в том, что стандартная реализация протокола OData в платформе 1С:Предприятие не поддерживает фильтрацию по навигационным свойствам (Navigation Properties) в том виде, в котором это делают полноценные SQL-серверы.

Платформа не умеет "на лету" строить сложные JOIN-соединения для стандартного интерфейса OData при фильтрации. Поэтому попытка обратиться к вложенному полю (свойству ссылочного объекта) внутри $filter обречена на неудачу.

Решение задачи: Метод двух запросов

Поскольку мы не можем отфильтровать документы по ИНН напрямую, нам необходимо действовать, опираясь на уникальные идентификаторы (GUID), которые в терминологии OData 1С называются Ref_Key.

Давайте проанализируем алгоритм, который является стандартом для решения подобных задач в экосистеме 1С OData. Мы разобьем задачу на два простых и быстрых шага.

Шаг 1. Получение ключа организации по ИНН

Сначала нам нужно найти саму организацию. Справочники в OData прекрасно фильтруются по своим собственным реквизитам (примитивным типам, таким как Строка). ИНН — это строковый реквизит справочника Организации.

Сформируем запрос к справочнику организаций. Нам не нужно получать все поля, достаточно только поля Ref_Key (уникальный идентификатор).

URL запроса будет выглядеть следующим образом:


GET http://АдресСервера/ИмяБазы/odata/standard.odata/Catalog_Организации?$select=Ref_Key&$filter=ИНН eq '7777777777'&$format=json

В этом запросе:

  1. Catalog_Организации — обращаемся к сущности справочника.
  2. $select=Ref_Key — просим вернуть только GUID, чтобы не тратить трафик на остальные данные.
  3. $filter=ИНН eq '7777777777' — устанавливаем отбор по нужному нам значению ИНН.

В ответ сервер вернет JSON, из которого мы должны извлечь значение Ref_Key. Допустим, мы получили значение: guid'a1b2c3d4-e5f6-...'.

Шаг 2. Получение документов с отбором по ссылке

Теперь, когда у нас есть конкретный идентификатор организации, мы можем запросить список документов. В самом документе поле Организация_Key (или просто ссылка на организацию) присутствует как поле, по которому можно делать отбор.

Формируем второй запрос:


GET http://АдресСервера/ИмяБазы/odata/standard.odata/Document_ВозвратТоваровПоставщику?$select=Ref_Key,Number,Date,СуммаДокумента&$filter=Posted eq true and Organization_Key eq guid'a1b2c3d4-e5f6-...'

Обратите внимание на детали:

  1. Organization_Key — имя поля в OData, хранящего ссылку на организацию (имя может отличаться в зависимости от конфигурации, иногда это просто имя реквизита, например Организация).
  2. guid'...' — обязательный литерал, указывающий, что мы передаем уникальный идентификатор.

Преимущества такого подхода:

Как вывести ИНН в списке документов (Select и Expand)

Часто возникает сопутствующий вопрос: "Хорошо, с фильтром разобрались. А как мне в списке документов сразу увидеть ИНН организации, чтобы не делать лишних запросов?"

Если вы попробуете просто добавить поле в $select, например $select=Organization/INN, это может не сработать без использования механизма разыменования (раскрытия) ссылок.

Для того чтобы включить данные связанной сущности в ответ, в OData используется параметр $expand.

Давайте рассмотрим пример запроса, который вернет документы и сразу подтянет ИНН организации:


GET http://АдресСервера/ИмяБазы/odata/standard.odata/Document_ВозвратТоваровПоставщику?$expand=Организация&$select=Ref_Key,Number,Date,Организация/ИНН

Разберем, что здесь происходит:

  1. $expand=Организация — мы сообщаем серверу, что хотим "раскрыть" ссылочное поле Организация. Сервер понимает, что нужно заглянуть внутрь этой ссылки.
  2. $select=...,Организация/ИНН — теперь, когда поле раскрыто, мы можем указать путь к конкретному реквизиту (ИНН) через слэш.

Важно понимать разницу:

Альтернативный вариант: HTTP-сервис

Если специфика вашей задачи категорически запрещает делать два запроса (например, критичные требования к latency или очень сложная логика "ИЛИ", где нужно искать по ИНН организации ИЛИ по КПП контрагента), стандартный OData вам не подойдет.

В этом случае единственным правильным решением будет создание собственного HTTP-сервиса внутри конфигурации 1С.

В HTTP-сервисе вы сможете:

  1. Написать произвольный запрос на языке 1С: ВЫБРАТЬ ... ИЗ ... ГДЕ Организация.ИНН = &ИНН.
  2. Обработать входящие параметры любым удобным способом.
  3. Вернуть JSON именно той структуры, которая нужна клиенту.

Однако, для большинства интеграционных задач метод "двух запросов" через стандартный OData остается наиболее предпочтительным, так как не требует доработки конфигурации ("no-code" решение на стороне 1С).

Итоги

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

  1. Не пытайтесь использовать вложенные поля (через точку или слэш) в параметре $filter стандартного OData 1С.
  2. Используйте двухшаговую схему: сначала запросите Ref_Key справочника по понятному реквизиту (ИНН, Код, Наименование), затем используйте полученный GUID для фильтрации основного списка документов.
  3. Если нужно вывести данные связанного объекта в результат, используйте связку $expand (для сущности) и $select (для полей).
← На главную