Как исправить ошибку при переносе справочников, если обработка изменила данные в рабочей базе 1С, и восстановить их без потери дневной работы?

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

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

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

Выясняем причины: почему обработка выгрузки изменила данные в рабочей базе?

Для многих технических специалистов кажется парадоксом, что процедура чтения и экспорта данных приводит к перезаписи объектов в источнике. Проанализируем основные технические причины, по которым это происходит в среде 1С:

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

Методология восстановления: реставрация справочника без потери дневных данных

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

Рассмотрим два основных способа решения этой задачи.

Способ 1. Программное восстановление реквизитов по GUID из копии

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

  1. Разверните ночной бэкап базы данных на тестовом сервере или локальном компьютере.
  2. Напишите и запустите в рабочей базе обработку, которая через COM-соединение подключится к развернутой копии, сопоставит контрагентов по уникальному идентификатору (GUID) и восстановит поврежденные реквизиты.

Ниже представлен пример программного кода для такой обработки:


Процедура ВосстановитьКонтрагентовИзКопии()
    
    // 1. Инициализируем COM-соединение с резервной копией базы
    ПараметрыПодключения = "Srvr=""MyServer"";Ref=""Backup_Base"";Usr=""Admin"";Pwd=""Password"";";
    Connector = Новый COMОбъект("V83.COMConnector");
    
    Попытка
        БазаКопия = Connector.Connect(ПараметрыПодключения);
    Исключение
        Предупреждение("Не удалось подключиться к копии базы: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // 2. Выбираем всех контрагентов из текущей рабочей базы
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Контрагенты.Ссылка КАК Ссылка,
        |	Контрагенты.Представление КАК Представление
        |ИЗ
        |	Справочник.Контрагенты КАК Контрагенты
        |ГДЕ
        |	НЕ Контрагенты.ЭтоГруппа";
        
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    КоличествоВосстановленных = 0;
    
    Пока Выборка.Следующий() Цикл
        
        // Получаем GUID текущего контрагента в рабочей базе
        ТекущийУИД = Выборка.Ссылка.УникальныйИдентификатор();
        СтрокаУИД = Строка(ТекущийУИД);
        
        // Создаем аналогичный GUID в контексте базы-копии
        КопияУИД = БазаКопия.NewObject("УникальныйИдентификатор", СтрокаУИД);
        СсылкаКопия = БазаКопия.Справочники.Contragents.GetRef(КопияУИД); // Обратите внимание на имя метаданных в копии
        
        // Проверяем, существует ли объект в копии базы
        Если БазаКопия.ValueIsFilled(СсылкаКопия) Тогда
            
            // Получаем объект для редактирования в рабочей базе
            ОбъектРабочий = Выборка.Ссылка.ПолучитьОбъект();
            Изменено = Ложь;
            
            // Построчно сравниваем и восстанавливаем реквизиты
            Если ОбъектРабочий.Наименование <> СсылкаКопия.Description Тогда
                ОбъектРабочий.Наименование = СсылкаКопия.Description;
                Изменено = Истина;
            КонецЕсли;
            
            Если ОбъектРабочий.НаименованиеПолное <> СсылкаКопия.НаименованиеПолное Тогда
                ОбъектРабочий.НаименованиеПолное = СсылкаКопия.НаименованиеПолное;
                Изменено = Истина;
            КонецЕсли;
            
            Если ОбъектРабочий.ИНН <> СсылкаКопия.ИНН Тогда
                ОбъектРабочий.ИНН = СсылкаКопия.ИНН;
                Изменено = Истина;
            КонецЕсли;
            
            Если ОбъектРабочий.КПП <> СсылкаКопия.КПП Тогда
                ОбъектРабочий.КПП = СсылкаКопия.КПП;
                Изменено = Истина;
            КонецЕсли;
            
            // Если реквизиты отличались, перезаписываем объект
            Если Изменено Тогда
                Попытка
                    // Важно: отключаем обработчики и регистрацию изменений для обмена
                    ОбъектРабочий.ОбменДанными.Загрузка = Истина;
                    ОбъектРабочий.Записать();
                    КоличествоВосстановленных = КоличествоВосстановленных + 1;
                Исключение
                    Сообщить("Не удалось записать контрагента: " + ОбъектРабочий.Наименование + ". Ошибка: " + ОписаниеОшибки());
                КонецПопытки;
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
    Сообщить("Обработка завершена. Восстановлено контрагентов: " + КоличествоВосстановленных);

КонецПроцедуры

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

Способ 2. Восстановление через стандартную обработку «Выгрузка и загрузка данных XML»

Если конфигурации базы-бэкапа и рабочей базы абсолютно идентичны, можно обойтись без написания кода, применив штатный инструмент 1С — обработку ВыгрузкаЗагрузкаДанныхXML.epf (ее можно найти на диске ИТС или в каталогах шаблонов).

Проанализируем этот сценарий детально:

  1. Разверните резервную копию базы данных.
  2. Запустите в базе-копии обработку ВыгрузкаЗагрузкаДанныхXML.epf. На вкладке «Выгрузка» отметьте галочкой справочник «Контрагенты» (а также, при необходимости, подчиненные справочники «Договоры контрагентов» и «Банковские счета»). Сделайте выгрузку в XML-файл.
  3. Важный шаг предосторожности: Чтобы не перезаписать новых контрагентов, которых пользователи создали вручную за сегодняшний рабочий день, откройте в рабочей базе Журнал регистрации. Настройте отбор по метаданным справочника «Контрагенты» и событию «Добавление» за текущую дату. Выпишите ИНН или коды этих новых контрагентов. При загрузке XML-файла они не пострадают (так как в бэкапе их не было), но их необходимо держать на контроле.
  4. Запустите обработку в рабочей базе на вкладке «Загрузка» и выберите полученный XML-файл. Поскольку выгрузка и загрузка XML сопоставляет объекты строго по GUID, поврежденные элементы перезапишутся исходными реквизитами, а созданные за день новые контрагенты останутся нетронутыми. Все ссылки в документах, созданных за текущий день, корректно сохранятся.

Что делать с обменами в РИБ (распределенных базах)?

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

Сценарий А. Обмены были вовремя остановлены (пакеты не дошли до филиалов)

Если администраторы оперативно заблокировали каналы обмена и ошибочные данные не успели загрузиться в базы филиалов, порядок действий следующий:

  1. Выполните восстановление справочника контрагентов в центральной базе одним из способов, описанных выше.
  2. Откройте обработку «Регистрация изменений для обмена данными» в ЦБ.
  3. Найдите узел нужного обмена, выберите справочник «Контрагенты» (а также «Договоры контрагентов») и полностью отмените регистрацию изменений для этих объектов. Это удалит «испорченные» версии объектов из очереди отправки.
  4. После этого запустите процедуру восстановления данных в ЦБ. При записи объектов с установленным флагом ОбменДанными.Загрузка = Истина регистрация изменений для обмена не произойдет автоматически.
  5. При необходимости зарегистрируйте измененных контрагентов заново и запустите обмен в штатном режиме. В филиалы уйдут корректные данные.

Сценарий Б. Обмены прошли, и филиалы получили испорченные данные

Если обмены отработали и некорректные реквизиты контрагентов уже записались в базы филиалов, ситуация сложнее, но полностью поправима:

  1. Проведите процедуру полного восстановления справочника контрагентов в центральной базе.
  2. Откройте в ЦБ обработку «Регистрация изменений для обмена данными».
  3. Выберите узел обмена с филиалами, нажмите правой кнопкой мыши на справочник «Контрагенты» и выберите команду «Зарегистрировать изменения» -> «Зарегистрировать все элементы справочника». Повторите процедуру для подчиненных справочников (договоры, счета), если они тоже пострадали.
  4. Инициируйте принудительную выгрузку данных из ЦБ. Центральная база отправит во все периферийные узлы эталонные, восстановленные версии объектов. При приеме пакета в филиалах старые испорченные данные перезапишутся правильными по GUID.

Советы на будущее: как избежать подобных инцидентов?

Чтобы обезопасить рабочие базы от деструктивного воздействия внешних обработок, придерживайтесь простых правил разработки и администрирования:

← На главную