Как получить остатки из регистра накопления через REST-запрос с фильтром из другой базы 1С

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

При настройке интеграции между двумя базами 1С часто возникает задача получения данных из одной системы на основании условий, хранящихся в другой. Типичный пример: нам нужно получить остатки по РегиструНакопления в «Базе-Приемнике», но список номенклатуры или складов для отбора хранится в «Базе-Источнике» (например, в РегистреСведений). В этой статье мы разберем, как реализовать такое взаимодействие максимально эффективно, избегая лишних сетевых вызовов.

Анализ проблемы: почему стандартный OData может не подойти

Стандартный интерфейс OData, который 1С предоставляет «из коробки», очень удобен для простых операций, но имеет существенные архитектурные ограничения. Рассмотрим ситуацию: у вас есть фильтр в первой базе, и вы хотите применить его ко второй базе. Если использовать чистый OData, вам придется выполнить как минимум два действия:

  1. Прочитать данные отбора из первой базы.
  2. Сформировать сложную строку запроса с оператором $filter и отправить её во вторую базу.

Проблема заключается в том, что интерфейс OData в 1С является «плоским». Он работает напрямую с таблицами и не умеет выполнять сложные JOIN или вложенные запросы к сущностям, которые не связаны на уровне метаданных. Более того, если ваш фильтр содержит сотни или тысячи элементов, строка URL запроса может превысить допустимые лимиты, что приведет к ошибке. Именно поэтому для решения задачи «за один запрос» профессиональное сообщество рекомендует переходить от стандартного OData к кастомным HTTP-сервисам.

Решение 1: Использование собственного HTTP-сервиса

Разберем наиболее правильный и производительный способ решения задачи. Вместо того чтобы пытаться заставить стандартный механизм OData делать то, для чего он не предназначен, мы создадим собственный HTTP-сервис в той базе, из которой нужно получить остатки.

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

Рассмотрим пример кода для серверной части HTTP-сервиса. Предположим, мы передаем массив ссылок номенклатуры в формате JSON, по которым нужно получить остатки.


Функция ПолучитьОстатки(Запрос)
    
    // Читаем тело запроса, где лежит наш JSON с фильтрами
    ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
    СтруктураПараметров = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    // Формируем стандартный запрос 1С
    ЗапросКБД = Новый Запрос;
    ЗапросКБД.Текст = 
        "ВЫБРАТЬ
        |   ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
        |   ТоварыНаСкладахОстатки.В НаличииОстаток КАК Остаток
        |ИЗ
        |   РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Номенклатура В (&МассивНоменклатуры)) КАК ТоварыНаСкладахОстатки";
    
    ЗапросКБД.УстановитьПараметр("Период", ТекущаяДата());
    ЗапросКБД.УстановитьПараметр("МассивНоменклатуры", СтруктураПараметров.СписокНоменклатуры);
    
    РезультатЗапроса = ЗапросКБД.Выполнить().Выгрузить();
    
    // Сериализуем результат обратно в JSON
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, РезультатЗапроса);
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
    Возврат Ответ;
    
КонецФункции

Проблема сопоставления объектов (GUID)

Проанализируем важный технический нюанс, с которым сталкиваются разработчики при передаче фильтров между разными базами. Если вы передаете GUID (Уникальный идентификатор) объекта из одной базы в другую, вы должны быть уверены, что объекты синхронизированы.

Выясним причину, почему фильтр может не сработать: Если в «Базе 1» товар «Кирпич» имеет один УникальныйИдентификатор, а в «Базе 2» тот же «Кирпич» создан вручную и имеет другой GUID, то поиск по ссылке в запросе вернет пустой результат. В таких случаях мы рекомендуем:

  1. Передавать в фильтре не ссылки, а уникальные бизнес-ключи: Артикул, Код или ИНН/КПП.
  2. Внутри кода HTTP-сервиса сначала находить ссылки по этим кодам и только потом передавать их в параметры виртуальной таблицы.
  3. Использовать механизмы синхронизации данных (например, через КД 3.0), чтобы гарантировать идентичность GUID.

Решение 2: Функции и действия OData (Actions/Functions)

Если вы не хотите создавать полноценный HTTP-сервис, в современных версиях платформы 1С существует «компромиссный» вариант. Вы можете опубликовать экспортную процедуру или функцию модуля менеджера как Действие (Action) или Функцию (Function) интерфейса OData.

Это позволяет вызвать конкретный алгоритм на языке 1С через стандартный REST-интерфейс. Рассмотрим, как это работает:

Этот метод объединяет простоту настройки OData и гибкость программного кода 1С. Однако создание отдельного HTTP-сервиса все равно остается более гибким решением, так как позволяет полностью контролировать структуру заголовков, формат ответа и обработку ошибок.

Оптимизация производительности при работе с регистрами

Рассмотрим подробнее, как повысить скорость получения остатков. При использовании стандартного OData платформа часто сначала выбирает данные, а затем накладывает фильтр. В случае с большими регистрами накопления это может привести к серьезным задержкам.

Используя собственный HTTP-сервис, мы можем применить следующие оптимизации:

  1. Использование индексированных временных таблиц: Если список фильтрации очень большой, его лучше сначала поместить во временную таблицу с индексом, а затем соединить с виртуальной таблицей остатков.
  2. Минимизация состава полей: Получайте только те данные, которые действительно нужны (например, только количество без лишних реквизитов номенклатуры).
  3. Кэширование: Если данные об остатках не меняются каждую секунду, результат запроса можно кэшировать на стороне сервиса, чтобы не нагружать СУБД повторными вызовами.

Резюме по реализации

Для решения задачи получения остатков с фильтром из другой базы за один вызов, мы рекомендуем следующий алгоритм действий:

  1. В базе-приемнике (где лежат остатки) создайте новый HTTP-сервис.
  2. Добавьте в него шаблон URL и метод POST.
  3. В обработчике метода опишите логику чтения JSON с параметрами отбора.
  4. Выполните классический Запрос к виртуальной таблице остатков с использованием полученных параметров.
  5. Верните результат в виде компактного JSON-массива.

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

← На главную