Как зарегистрировать в плане обмена удаленную строку подчиненного регистра сведений?

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

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

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

Причина возникновения проблемы

Рассмотрим механику работы платформы. Для подчиненного регистра сведений ключом регистрации изменений в плане обмена всегда выступает ссылка на документ-регистратор. Когда мы считываем изменения из плана обмена, мы получаем ссылку на документ. При попытке прочитать записи регистра по этому регистратору, мы увидим только те строки, которые актуальны на данный момент. Удаленные строки физически отсутствуют в базе данных, и платформа не хранит информацию о них в стандартной таблице изменений плана обмена.

Решение 1: Изменение архитектуры на независимый регистр

Это наиболее радикальный, но действенный способ, который применил автор темы. Если бизнес-логика позволяет, мы можем перевести регистр в статус независимого. В этом случае для каждой строки будет создаваться отдельная запись регистрации изменений по её ключевым измерениям.

Рассмотрим алгоритм действий при этом подходе:

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

Таким образом, план обмена будет фиксировать удаление старых записей и появление новых. Однако у этого метода есть существенный минус: теряется жесткая ссылочная целостность, обеспечиваемая платформой на уровне СУБД для подчиненных объектов.

Решение 2: Полная замена набора данных на стороне приемника

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

Логика взаимодействия в этом случае выглядит так:

  1. План обмена фиксирует изменение регистратора.
  2. При выгрузке 1С формирует пакет данных, содержащий все текущие строки регистра по этому регистратору.
  3. Сторона приемника (сайт) получает этот пакет и полностью замещает у себя все старые записи по данному заказу/объекту новыми данными.

Это избавляет нас от необходимости отслеживать, что именно было удалено. Если строки нет в новом пакете — значит, её больше нет. Этот подход наиболее надежен, так как он самовосстанавливающийся (даже если произошел сбой, следующая полная выгрузка синхронизирует состояние).

Решение 3: Использование обработчика «ПередЗаписью» и технического лога

Если нам критично передать именно событие «Удалена строка со статусом Отменено», и мы не можем менять тип регистра на независимый, воспользуемся программным перехватом данных. Разберем, как реализовать сравнение наборов записей.

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

Пример кода для вычисления удаленных строк:


Процедура ПередЗаписью(Отказ, Замещение)
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Считываем текущее состояние из БД до записи
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ * ИЗ РегистрСведений.НашРегистр ГДЕ Регистратор = &Регистратор";
    Запрос.УстановитьПараметр("Регистратор", ЭтотОбъект.Отбор.Регистратор.Значение);
    
    СтарыйНабор = Запрос.Выполнить().Выгрузить();
    
    // Сравниваем со строками в текущем наборе (ЭтотОбъект)
    Для Каждого СтрокаИзБД Из СтарыйНабор Цикл
        // Ищем строку из базы в записываемом наборе по ключевым измерениям
        СтруктураПоиска = Новый Структура("Номенклатура, Склад"); // Ваши измерения
        ЗаполнитьЗначенияСвойств(СтруктураПоиска, СтрокаИзБД);
        
        Если ЭтотОбъект.НайтиСтроки(СтруктураПоиска).Количество() = 0 Тогда
            // Строка удалена! Регистрируем этот факт в техническом независимом регистре
            РегистрацияУдалений.ЗафиксироватьУдаление(СтрокаИзБД);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

В данном примере мы создаем вспомогательный независимый регистр (например, ОчередьВыгрузкиНаСайт), в который записываем ключ удаленной строки. План обмена в этом случае настраивается именно на этот технический регистр.

Решение 4: Механизм «История данных» (для платформы 8.3.11 и выше)

Выясним, как современные возможности платформы упрощают эту задачу. Если для регистра включено использование механизма История данных, 1С автоматически сохраняет версии наборов записей. Мы можем программно обратиться к истории и получить различие между текущей и предыдущей версией документа.

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

Важные рекомендации по идентификации строк

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

Чтобы обмен работал стабильно, рекомендуется:

Это позволит точно понимать, была ли строка удалена и добавлена новая, или же просто изменились её параметры (цена, количество). Без такого идентификатора удаление строки "Товар А" и добавление строки "Товар Б" для сайта может выглядеть неоднозначно, если вы пытаетесь отследить именно "позицию в заказе".

Резюме

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

← На главную