Как запретить перезапись документов в базе-приемнике при синхронизации данных 1С

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

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

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

Вариант 1. Простая настройка правил конвертации (КД 2.0)

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

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

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

Важное ограничение: этот метод слишком радикален. Если в источнике в документ внесут важные исправления (например, изменят сумму), а в приемнике документ еще никто не трогал, изменения все равно не придут. Поэтому рассмотрим более гибкие подходы.

Вариант 2. Использование признака ручной правки (Флаг «Грязный Гари»)

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

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

Проанализируем процесс автоматизации установки этого флага. Нам потребуется создать Подписку на событие ПередЗаписью для всех необходимых типов документов. В обработчике подписки пропишем следующую логику:


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

Теперь каждый раз, когда пользователь нажимает «Провести» или «Записать» в базе-приемнике, документ будет получать невидимую метку о том, что он отредактирован локально.

Вариант 3. Настройка обработчика «ПриЗагрузке» в Конвертации данных

Теперь перейдем к самому главному — настройке правил обмена, чтобы они учитывали наш флаг. В «Конвертации данных 2.0» для нужного ПКО выберем вкладку «Обработчики событий» и найдем событие ПриЗагрузке. Именно здесь решается судьба объекта перед его записью в базу.

Рассмотрим пример кода, который нужно вставить в этот обработчик:


// Параметр ОбъектНайден указывает, что документ уже существует в базе
// Параметр НеЗамещатьОбъект при установке в Истина отменяет обновление реквизитов

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

Этот код гарантирует: если документ найден и у него стоит признак ручной правки, загрузка данных из источника для этого конкретного объекта будет пропущена. Система просто «пройдет мимо», сохранив все локальные изменения бухгалтера.

Вариант 4. Использование штатного версионирования объектов

Выясним еще один интересный способ, который не требует создания лишних флагов. В современных версиях «1С:Бухгалтерия 3.0» встроен механизм «История изменений» (версионирование). Мы можем проверить, кто был автором последней версии документа.

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

В обработчике ПриЗагрузке код будет выглядеть примерно так:


Если ОбъектНайден Тогда
    ПоследнийАвтор = РегистрыСведений.ВерсииОбъектов.Выбрать(
        Новый Структура("Объект", НайденныйОбъект), "ДатаВерсии УБЫВ"
    );
    Если ПоследнийАвтор.Следующий() Тогда
        Если ПоследнийАвтор.Автор <> Справочники.Пользователи.НайтиПоНаименованию("РоботСинхронизации") Тогда
            НеЗамещатьОбъект = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

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

Тонкости и подводные камни

При реализации подобных механизмов стоит учитывать несколько важных моментов:

  1. Групповое изменение реквизитов: Если администратор воспользуется обработкой «Групповое изменение реквизитов», свойство ОбменДанными.Загрузка может быть установлено в Истина в зависимости от настроек обработки. В этом случае подписка на событие не сработает, и флаг «Изменено в приемнике» не проставится.
  2. Частичное обновление: Иногда нужно запретить изменение только определенных полей (например, счета учета), но разрешить обновление сумм. В этом случае в КД 2.0 следует использовать ПКС (Правила Конвертации Свойств) и флаг «Не замещать значение свойства у существующих объектов» для конкретных реквизитов.
  3. Удаление объектов: Помните, что если документ будет помечен на удаление в источнике, информация об этом все равно придет в приемник. Если вы используете НеЗамещатьОбъект = Истина, пометка на удаление также не будет установлена, что может привести к расхождению данных.

Таким образом, мы рассмотрели комплексный подход к защите данных в базе-приемнике. Наиболее надежным и производительным решением является использование Дополнительных сведений в связке с обработчиком ПриЗагрузке и параметром НеЗамещатьОбъект. Это позволяет гибко управлять процессом синхронизации и гарантирует сохранность ручного труда пользователей.

← На главную