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

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

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

1. Тщательная настройка правил поиска объектов (ПКО)

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

  1. Уникальные поля поиска: Мы должны убедиться, что в правилах конвертации объектов (ПКО) для справочника Контрагенты и для реквизита Владелец (или Контрагент) в справочнике ДоговорыКонтрагентов настроены корректные и уникальные поля поиска. Наиболее надежными полями для поиска контрагентов традиционно являются ИНН и КПП (если контрагент является юридическим лицом или ИП). Если ИНН и КПП недостаточно (например, для физических лиц или когда КПП не используется), мы можем добавить Наименование, но с осторожностью, так как наименование может меняться. Важно, чтобы комбинация полей поиска обеспечивала максимальную уникальность.

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

  2. Флажок «Продолжить поиск по полям поиска, если по идентификатору объект приемник не найден»: Убедитесь, что в ПКО для контрагента установлен флажок Продолжить поиск по полям поиска, если по идентификатору объект приемник не найден. Этот флажок критически важен. Он позволяет системе использовать заданные реквизиты (ИНН, КПП) для поиска объекта, если первоначальный поиск по уникальному идентификатору (GUID) не дал результата. Без этого флага система может сразу перейти к созданию нового объекта, если GUID не совпал, даже если в базе-приемнике уже есть контрагент с таким же ИНН и КПП.

  3. Флажок «Не замещать существующие объекты»: Также обратите внимание на флажок Не замещать существующие объекты в приемнике при загрузке, а только создавать новые и заполнять их. Если он установлен, система будет создавать дубликаты вместо обновления существующих контрагентов, что усугубит проблему. В большинстве случаев при обмене данными этот флажок должен быть снят, чтобы обеспечить обновление, а не дублирование. Мы хотим, чтобы при совпадении по полям поиска существующий контрагент обновлялся, а не создавался новый.

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

2. Обеспечение корректного порядка обработки объектов

Хотя коллеги на форуме могут утверждать, что для КД порядок обработки объектов часто считается второстепенным, в данном сценарии проблема ясно указывает на то, что объект ДоговорКонтрагента пытается найти своего Владельца (Контрагента) до того, как этот контрагент был полноценно загружен и идентифицирован в базе-приемнике. Это классический случай зависимости. Мы должны обеспечить, чтобы объекты, являющиеся владельцами (родителями), были обработаны раньше своих подчиненных (дочерних) объектов.

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

  2. Порядок создания в базе-приемнике: Даже если выгрузка настроена корректно, сам процесс загрузки может быть оптимизирован. Некоторые обработки загрузки данных или ручные настройки позволяют управлять порядком создания объектов. Если мы используем собственную обработку для загрузки, мы можем сначала загрузить всех контрагентов, записать их, а затем уже приступить к загрузке договоров, привязывая их к уже созданным контрагентам.

3. Использование обработчиков событий в ПКО для точного контроля

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

  1. Обработчик ПриЗагрузке для ДоговоровКонтрагентов: В этом обработчике для ПКО, отвечающего за конвертацию ДоговоровКонтрагентов, мы можем добавить код, который будет явно искать контрагента по заданным полям (ИНН, Наименование) перед тем, как система попытается автоматически создать или найти «заглушку». Это позволяет нам перехватить стандартную логику поиска КД и применить свою.

    Пример логики:

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

    Этот код проверяет, назначен ли владельцу договора корректный контрагент по ИНН и КПП. Если контрагент найден, договор привязывается к нему, и мы устанавливаем Отказ = Истина, чтобы стандартная логика КД не вмешивалась. Если не найден, мы можем решить, что делать дальше: создать, пропустить или записать ошибку. Обратите внимание, что переменная Отказ в обработчиках событий позволяет предотвратить дальнейшую стандартную обработку данного свойства.

  2. Обработчик ПослеЗагрузки для Контрагентов: В этом обработчике мы можем реализовать логику, которая при обнаружении «заглушки» (неполного контрагента, который мог быть создан ранее из-за ошибки в порядке или поиске) будет пытаться найти полноценного контрагента и перепривязать к нему все зависимые объекты (договоры, документы), а «заглушку» пометить на удаление. Это более сложный сценарий, требующий внимательной разработки, чтобы избежать потери данных. Мы рекомендуем использовать этот метод как пост-коррекцию, если проблема возникла, а не как основное средство предотвращения.

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

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

4. Единообразие правил конвертации

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

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

5. Отключение автоматического создания контрагентов (применимо к специфическим сценариям)

В некоторых специфических сценариях, например, при работе с 1С-ЭДО, обработками загрузки из внешних источников или другими интеграциями, может быть включена настройка Создавать контрагентов автоматически. Если такая настройка активно используется, она может способствовать созданию дубликатов и «заглушек», особенно если ее логика конфликтует с вашей настройкой КД. Мы должны контролировать эту настройку и при необходимости отключать ее на время обмена или адаптировать под нее правила КД. Внимательно изучите все фоновые процессы и настройки в базе-приемнике, которые могут влиять на создание новых элементов справочника Контрагенты.

6. Коррекция уже возникших проблем

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

  1. «Поиск и удаление дублей»: В 1С существуют стандартные обработки для поиска и удаления дублирующихся элементов справочников. Мы можем использовать ее для поиска «заглушечных» контрагентов (например, по неполным реквизитам, отсутствию определенных данных, или по отличию от эталонного контрагента с полным набором реквизитов) и замены их ссылок на корректных. Эта обработка позволяет объединять дубликаты, перенося все ссылки на один, «правильный», элемент. Для эффективного использования данной обработки мы можем настроить критерии поиска дублей (например, поиск по совпадающему ИНН, но различному Наименованию или другим признакам «заглушки»).

  2. «Групповое изменение реквизитов»: Если большое количество договоров привязано к неверным контрагентам, мы можем использовать обработку Групповое изменение реквизитов (обычно находится в меню «Все функции» или «Администрирование и сервис»). С ее помощью мы можем массово заменить ссылки на неправильных контрагентов на правильных контрагентов во всех необходимых документах и справочниках. Для этого:

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

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

  3. «Корректировка долга»: Если ошибка затронула взаиморасчеты (например, долг числится на договоре, привязанном к «заглушке», или на самом «заглушечном» контрагенте), документ Корректировка долга может быть использован для переноса задолженности с одного договора или контрагента на другой. Это бухгалтерский инструмент, который поможет привести в порядок данные взаиморасчетов после исправления ссылок на объекты. Мы используем его для переноса сальдо по взаиморасчетам с некорректного объекта на корректный, чтобы финансовые данные оставались целостными.

Тщательная настройка правил обмена, особенно в части идентификации и поиска существующих объектов, является ключом к успешному переносу данных без возникновения дубликатов и «заглушек». Мы всегда должны помнить о последовательности обработки данных и использовать программные средства для контроля сложных зависимостей. Регулярное тестирование правил обмена на тестовой базе данных поможет выявить потенциальные проблемы до их появления в рабочей среде.

← На главную