При реализации выборочной синхронизации данных между конфигурациями 1С (например, между «1С:Управление нашей фирмой» и «1С:Бухгалтерия предприятия») разработчики часто используют ручной признак — специальный флаг (чекбокс) вроде ВыгружатьВБУ или ОтражатьВРеглУчете. Схема проста: если флаг установлен, документ регистрируется к обмену и уходит в базу-приемник. Но что происходит, когда пользователь снимает этот флаг с уже выгруженного документа?
В базе-источнике документ остается проведенным и активным, однако в базе-приемнике он «зависает» в своем первоначальном состоянии. Более того, повторные манипуляции пользователей могут приводить к появлению дублей документов. Выясним причину этой проблемы и разберем по шагам технические способы её решения.
В исходной ситуации автора темы бухгалтеры обнаружили две расходные накладные по одному заказу в базе «1С:Бухгалтерия предприятия» (БП), хотя в «1С:Управление нашей фирмой» (УНФ) все выглядело корректно. Проанализируем ситуацию: почему при снятии флага выгрузки и повторных действиях пользователя в БП создается копия, а не обновляется существующий документ?
Такое поведение связано с архитектурными особенностями правил конвертации данных (ПКО) и правил регистрации объектов (ПРО):
Новый УникальныйИдентификатор()). При каждой повторной выгрузке генерируются новые идентификаторы, что и приводит к лавинообразному созданию дублей в базе БП.Для предотвращения дублирования идентификаторы документов-приемников всегда должны формироваться детерминировано (например, на основании GUID исходного документа с добавлением фиксированного префикса или суффикса).
Рассмотрим подробнее самый гибкий и контролируемый вариант решения проблемы — отслеживание изменения флага выгрузки в коде базы-источника с последующей принудительной регистрацией специального виртуального объекта платформы — УдалениеОбъекта.
Наша задача — поймать момент, когда транзакция записи еще не завершена, сравнить старое значение флага (из базы данных) с новым значением (которое записывает пользователь) и принять решение о регистрации.
Для этого мы можем использовать подписку на событие ПередЗаписью для нужного типа документа. Посмотрим на пример кода:
Процедура ПередЗаписьюДокументаДляРегистрацииУдаления(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Проверяем, что это не новый документ, так как для нового документа предыдущего состояния в БД нет
Если Источник.ОбменДанными.Загрузка Или Источник.ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Получаем текущее состояние флага из базы данных до записи объекта
СтароеЗначениеБУ = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Источник.Ссылка, "БУ");
НовоеЗначениеБУ = Источник.БУ;
// Нас интересует ситуация, когда флаг БУ был Истина (ранее выгружался), а стал Ложь (сняли выгрузку)
Если СтароеЗначениеБУ И НЕ НовоеЗначениеБУ Тогда
// Получаем узел плана обмена, для которого нужно зарегистрировать изменения
УзелОбмена = НайтиУзелПланаОбменаДляРегламентированногоУчета();
Если ЗначениеЗаполнено(УзелОбмена) Тогда
// Создаем виртуальный объект удаления на основании ссылки текущего документа
ОбъектУдаления = Новый УдалениеОбъекта(Источник.Ссылка);
// Регистрируем удаление на узле плана обмена
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, ОбъектУдаления);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: Создание конструкции Новый УдалениеОбъекта(Источник.Ссылка) никак не влияет на состояние самого документа в базе-источнике. Документ в УНФ остается проведенным и доступным для пользователей. Однако платформа регистрирует на узле обмена команду удаления. При следующей сессии выгрузки в XML-файл обмена запишется только этот GUID с тегом удаления, и база БП корректно пометит на удаление связанный документ.
Если обмен построен на современных стандартах Библиотеки стандартных подсистем (БСП) и технологии EnterpriseData, разберем, как решить задачу без изменения программного кода конфигурации.
В составе БСП есть мощный инструмент — Правила регистрации объектов (ПРО), которые настраиваются в специализированной конфигурации «Конвертация данных 3» (или «Конвертация данных 2.1»). Настроим автоматическую регистрацию удаления при изменении реквизитов.
Проанализируем шаги настройки ПРО для нашего документа:
БУ Равно Истина.При включении этой настройки БСП автоматически берет на себя всю рутину: во время записи любого документа система сама проверяет, изменилось ли выполнение условий отбора. Если документ перестал соответствовать правилу (флаг сняли), система автоматически сформирует запись УдалениеОбъекта в таблице изменений плана обмена.
Рассмотрим альтернативный сценарий, когда мы не хотим перегружать базу-источник дополнительными проверками в момент записи документа (ведь запись выполняется пользователями постоянно, а обмен происходит по расписанию). Мы можем перенести логику на момент непосредственной выгрузки пакета данных.
Для этого используется обработчик ПриОтправкеДанныхПодчиненному (или ПриОтправкеДанныхАдресату в зависимости от типа обмена) в модуле менеджера плана обмена. Проанализируем код этого обработчика:
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза)
// Проверяем, что отправляемый элемент — это наш документ
Если ТипЗнч(ЭлементДанных) = Тип("ДокументСсылка.РасходнаяНакладная") Тогда
// Быстро считываем значение флага БУ напрямую из базы данных
ЗначениеБУ = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЭлементДанных, "БУ");
// Если флаг снят, но документ зарегистрирован к обмену
Если НЕ ЗначениеБУ Тогда
// Подменяем выгрузку самого документа на команду удаления
ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
При использовании этого подхода платформа автоматически сформирует в результирующем XML-файле узел удаления вместо полной структуры документа. Это элегантное решение, работающее непосредственно в момент генерации пакета выгрузки.
Безопасно ли отправлять команду удаления для проведенных документов? Нам не нужно переживать, что база-приемник безвозвратно удалит важную информацию. Стандартные механизмы БСП в БП 3.0 обрабатывают входящую команду УдалениеОбъекта по строгому и безопасному алгоритму:
ПометкаУдаления = Истина).Это полностью решает проблему бухгалтеров. Документ перестает делать движения по счетам учета и исключается из оборотов, но остается видимым в списке помеченных на удаление объектов для возможности проведения ручного анализа или последующего удаления через стандартную обработку «Удаление помеченных объектов».