Как реализовать выборочное снятие объектов с регистрации при обмене данными в 1С

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

При организации обмена данными между конфигурациями 1С разработчики часто сталкиваются со стандартным механизмом квитирования (подтверждения получения данных). Штатно платформа 1С работает с «пакетами» или «сообщениями». Когда источник получает подтверждение, что сообщение №123 принято, он удаляет регистрацию для всех объектов, входивших в это сообщение. Однако в сложных бизнес-процессах возникает ситуация, когда часть объектов из пакета загружена успешно, а часть — отклонена приемником по логическим условиям (например, документ нельзя проводить в закрытом периоде или не заполнены обязательные реквизиты, специфичные для базы-приемника). В таких случаях нам необходимо «оставить» регистрацию для ошибочных объектов в источнике, чтобы пользователь мог исправить их и отправить повторно.

В этой статье мы подробно разберем, как обойти ограничение «пакетного» подтверждения и реализовать детальный контроль регистрации на уровне каждого отдельного объекта.

Анализ стандартного механизма и его ограничений

Прежде всего, проанализируем, как работает метод ПланыОбмена.УдалитьРегистрациюИзменений(). Когда мы вызываем этот метод с указанием номера сообщения, платформа находит все записи в таблицах регистрации изменений (для всех объектов, входящих в план обмена), у которых номер сообщения меньше или равен указанному. Эти записи физически удаляются из таблиц регистрации.

Проблема заключается в том, что платформа не предоставляет штатной возможности сказать: «Удали регистрацию для всех объектов сообщения №123, кроме вот этого справочника и этого документа». Поэтому нам придется реализовывать программную надстройку.

Вариант 1: Метод «Очистка и повторная регистрация»

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

Рассмотрим алгоритм действий в базе-источнике при обработке ответа:

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

Посмотрим на пример кода, реализующий эту логику:


// Процедура обработки подтверждения в источнике
Процедура ОбработатьПодтверждениеПриема(УзелИнформационнойБазы, НомерСообщения, СписокОшибок)
    
    НачатьТранзакцию();
    Попытка
        // 1. Очищаем регистрацию по номеру сообщения (стандартный механизм)
        ПланыОбмена.УдалитьРегистрациюИзменений(УзелИнформационнойБазы, НомерСообщения);
        
        // 2. Возвращаем регистрацию для объектов, которые не загрузились в приемнике
        Для Каждого ЭлементСписка Из СписокОшибок Цикл
            // Предположим, в списке у нас ссылки на объекты
            Если ЭлементСписка.Ссылка.Пустая() Тогда
                Продолжить;
            КонецЕсли;
            
            ПланыОбмена.ЗарегистрироватьИзменения(УзелИнформационнойБазы, ЭлементСписка.Ссылка);
        КонецЦикла;
        
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ЗаписатьЛогСобытий("Ошибка при выборочном снятии с регистрации: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Важный нюанс: метод ЗарегистрироватьИзменения для конкретной ссылки работает значительно медленнее, чем массовое удаление по номеру сообщения. Если список ошибок огромен, это может вызвать задержки. Однако в штатной ситуации количество ошибок обычно невелико относительно общего объема данных.

Вариант 2: Использование промежуточного буфера (Регистр сведений)

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

Разберем, как это работает:

  1. При получении ответа от приемника объекты с ошибками не просто перерегистрируются, а записываются в этот регистр сведений вместе с текстом ошибки и датой возникновения.
  2. У объекта в таблице регистрации изменений в источнике сохраняется запись (или создается новая).
  3. Пользователь в специальном интерфейсе (АРМ администратора обмена) видит список всех «проблемных» объектов.
  4. Пока запись в ОчередьОшибокОбмена существует и не помечена как «Исправлена», система может либо продолжать попытки выгрузки, либо приостановить их до вмешательства человека.

Для регистров сведений, где нет ссылки, в таком буфере необходимо хранить ключи записей. Проанализируем ситуацию: если структура регистра сведений изменится, десериализация ключа может не сработать. Поэтому рекомендуем хранить ключи в виде структуры ИмяПоля - Значение, упакованной в ХранилищеЗначения или JSON.

Вариант 3: Фильтрация через подписки на события

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

Рассмотрим использование события ПриОтправкеДанныхПодчиненному (в РИБ) или соответствующих перехватов в БСП. Если мы знаем, что объект «проблемный» (например, он есть в нашем регистре ошибок), мы можем программно установить параметр ОтправкаЭлемента в значение ОтправкаЭлементаДанных.Игнорировать.

Таким образом, объект остается зарегистрированным на узле, но не попадает в файл обмена до тех пор, пока не будут выполнены условия успешной загрузки. Это избавляет нас от постоянных попыток передать «битые» данные, которые все равно будут отвергнуты.

Работа с удалением объектов

Отдельный вопрос — как быть с удалением объектов? Если в источнике объект удален, в приемник уходит УдалениеОбъекта. Если приемник отказывается «удалять» (например, из-за ссылочной целостности), в источнике восстановить объект невозможно (он уже удален физически). В этой ситуации единственно верный путь — логировать критическую ошибку в источнике для администратора, так как автоматическое решение здесь отсутствует.

Рекомендации по реализации интерфейса

Для того чтобы система была удобной для пользователя, выполнение «задач» по исправлению данных должно быть прозрачным. Рассмотрим ключевые элементы интерфейса:

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

← На главную