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

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

При интеграции 1С с внешними системами (например, используя универсальный Python-коннектор к 1С, корпоративным порталом, сайтом или BI-системой) часто возникает задача инкрементальной выгрузки данных. Нам не нужно выгружать весь справочник сотрудников каждый раз — это долго и создает лишнюю нагрузку. Нам необходимо получить только тех сотрудников, данные которых изменились после определенной даты. Рассмотрим подробно, как решить эту задачу, используя стандартный интерфейс OData в платформе 1С:Предприятие, и проанализируем различные подходы к реализации.

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

При первом знакомстве с платформой и интерфейсом OData разработчики часто сталкиваются с тем, что в стандартной структуре справочников (например, Справочник.Сотрудники) отсутствует реквизит, отвечающий за дату и время последней записи элемента. Платформа 1С не хранит эту информацию в самой таблице справочника по умолчанию.

Если мы обратимся к сущности через OData, например, по адресу /Catalog_Сотрудники, мы получим набор полей, определенных в конфигураторе (проанализировать которые поможет генератор структуры метаданных объекта), плюс системные поля, такие как Ref_Key (уникальный идентификатор GUID), DataVersion (версия данных, но не дата) и DeletionMark. Построить фильтр вида «дай мне всех, кто изменился после 01.01.2024» без дополнительных доработок невозможно.

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

Способ 1. Использование подсистемы «Версионирование объектов» (БСП)

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

В старых версиях БСП это регистр ВерсииОбъектов, в более новых, использующих механизмы платформы 8.3.11+, это может быть механизм ИсторияДанных. Рассмотрим вариант с регистром сведений, так как он чаще доступен для прямой публикации в OData.

Как это работает:

  1. Вам необходимо опубликовать регистр сведений ВерсииОбъектов (или аналогичный) в составе OData-интерфейса.
  2. Внешняя система выполняет GET-запрос к сущности этого регистра.
  3. Фильтрация производится по полю, содержащему дату версии.

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

Недостатки метода:

Тем не менее, если вам нужно просто узнать факт изменения и получить список ссылок (GUID) для последующего запроса актуальных данных, этот метод применим.

Способ 2. Добавление реквизита «Дата изменения» через Расширение (Рекомендуемый)

Наиболее эффективным и простым для внешней системы способом является добавление явного поля, по которому можно делать фильтрацию. Чтобы не снимать основную конфигурацию с поддержки, мы воспользуемся механизмом Расширений.

Рассмотрим алгоритм реализации:

Шаг 1. Создание расширения

Создадим новое расширение конфигурации. В него добавим заимствованный справочник Сотрудники.

Шаг 2. Добавление реквизита

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

Шаг 3. Заполнение даты при записи

Нам нужно гарантировать, что при любом изменении сотрудника (интерактивном или программном) в это поле будет попадать текущая метка времени. Для этого лучше всего использовать Подписку на событие.

  1. В расширении создаем подписку на событие ПередЗаписью для справочника Сотрудники.
  2. Создаем общий модуль (или используем модуль объекта расширения), где прописываем логику.

Пример кода в модуле подписки:


Процедура УстановитьДатуИзмененияСотрудника(Источник, Отказ) Экспорт
	// Устанавливаем текущую дату сеанса (или дату сервера)
	Источник.ДатаПоследнегоИзменения = ТекущаяДатаСеанса();
КонецПроцедуры

Шаг 4. Первичное заполнение

После применения расширения поле у всех существующих сотрудников будет пустым. Чтобы механизм заработал сразу для всех, необходимо написать простую обработку, которая пробежит по всем сотрудникам и заполнит это поле текущей датой или датой создания, если она известна. Это разовая операция.

Результат для OData:

Теперь сущность Catalog_Сотрудники содержит поле ДатаПоследнегоИзменения. Внешняя система может выполнять эффективные запросы вида:

GET /Catalog_Сотрудники?$filter=ДатаПоследнегоИзменения gt datetime'2023-10-25T12:00:00'

Это самый быстрый и надежный способ выборки изменений.

Способ 3. Использование Планов обмена

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

Как это реализовать:

  1. Создание Плана обмена: В дереве метаданных создаем новый План обмена, например, ИнтеграцияССайтом.
  2. Состав: В состав плана включаем справочник Сотрудники. Оставляем авторегистрацию включенной.
  3. Узлы: В режиме Предприятия создаем узел для нашей внешней системы.

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

Получение данных через OData:

Интерфейс OData предоставляет доступ к таблицам изменений. Для получения списка измененных объектов используется специальный виртуальный ресурс.

Мы можем обратиться к ресурсу изменений плана обмена, указав GUID узла-получателя. В ответ система вернет список сущностей, которые были зарегистрированы для этого узла.

Преимущество этого метода в том, что вам не нужно хранить дату последнего опроса на стороне внешней системы. Вы просто запрашиваете «всё новое». После получения данных, внешняя система должна подтвердить прием сообщения (удалить регистрацию изменений), чтобы в следующий раз получить только новые дельты.

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

Почему не подходит Журнал регистрации?

В обсуждении часто упоминается Журнал регистрации (ЖР). Важно понимать, что стандартный интерфейс OData не предоставляет доступа к данным Журнала регистрации. ЖР — это, по сути, лог-файл (или отдельные таблицы), который лежит отдельно от бизнес-данных.

Чтобы получить данные из ЖР по HTTP, вам придется писать собственный HTTP-сервис внутри конфигурации 1С, который будет программно читать журнал методами встроенного языка и сериализовать результат в JSON. Это возможно, но это уже не «коробочное» решение OData.

Идентификация объектов

При любом выбранном способе (кроме HTTP-сервисов, где вы сами формируете ответ), для однозначной идентификации сотрудников следует использовать поле Ref_Key. Это уникальный идентификатор (GUID), который никогда не меняется (в отличие от Кода или Табельного номера, которые теоретически могут быть исправлены пользователем).

Подведем итог:

← На главную