Как при обмене не загружать договор в проводки, если не перенесен его владелец (контрагент)?

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

При настройке обменов данными между базами 1С с использованием конфигурации «Конвертация данных» часто возникает потребность жестко контролировать ссылочную целостность. Рассмотрим классическую ситуацию: в правилах обмена указано не создавать контрагента, если он не найден в базе-приемнике. При этом мы ожидаем, что и подчиненные договоры без владельцев создаваться не будут. Однако на практике объекты всё равно загружаются, а в оборотно-сальдовых ведомостях появляются «битые ссылки» вида <Объект не найден>. Проанализируем эту ситуацию и разберем по шагам, почему так происходит и как правильно решить проблему.

Выясним причину: почему не работает Отказ = Истина?

Первое интуитивное решение, которое приходит на ум разработчику — зайти в Правило конвертации объектов (ПКО) справочника «Договоры контрагентов» и в обработчике После загрузки прописать проверку заполненности владельца. Если он пуст, устанавливаем Отказ = Истина.

Но здесь мы сталкиваемся с первой особенностью платформы 1С. В базе-приемнике поле владельца на самом деле не пустое. Узел XML приносит уникальный идентификатор (GUID) владельца. Ссылка создается, функция ЗначениеЗаполнено() для нее вернет Истина, просто самого объекта еще нет в базе — это так называемая «битая ссылка».

Чтобы отловить битую ссылку, мы можем использовать метод ПолучитьОбъект(). Посмотрим на пример кода для проверки:


Попытка
    Об = Объект.Владелец.ПолучитьОбъект();
    Если Об = Неопределено Тогда
        Отказ = Истина;
    КонецЕсли;
Исключение
    Отказ = Истина;
КонецПопытки;

Код успешно определяет, что владелец не загружен, переменная Отказ принимает значение Истина, однако договор всё равно появляется в базе. Мистика? Нет, архитектурная особенность.

Специфика загрузки субконто и регистров бухгалтерии

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

Когда система обмена формирует набор записей регистра бухгалтерии, она обязана сохранить структуру документа. Установка Отказ = Истина в ПКО Договора отменяет лишь полноценную запись самого элемента справочника со всеми его реквизитами. Но платформа уже прочитала GUID договора из XML-файла и подставила эту «ссылку-пустышку» в колонку субконто табличной части движений. В итоге элемент справочника не записывается, но в проводках документа прочно оседает битая ссылка.

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

Решение 1: Отсекаем на стороне источника (Перед выгрузкой)

Самый идеологически верный и надежный подход в Конвертации данных 2.1 — не выгружать то, что не должно быть загружено. Асинхронные обмены 1С изначально спроектированы так, что битые ссылки считаются нормой (ожидается, что недостающий контрагент прилетит в следующем пакете обмена). Если наша бизнес-логика строго запрещает договоры без контрагентов в проводках, фильтрацию нужно делать еще при выгрузке.

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


// Проверяем владельца субконто, если это Договор
Если ТипЗнч(Источник) = Тип("СправочникСсылка.ДоговорыКонтрагентов") Тогда
    Если Не ЗначениеЗаполнено(Источник.Владелец) Тогда
        // Отменяем выгрузку этого значения в XML
        Значение = Неопределено; 
    КонецЕсли;
КонецЕсли;

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

Решение 2: Очистка в движениях документа (После загрузки)

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

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

Посмотрим на пример реализации такого обработчика:


// Перебираем движения по регистру бухгалтерии
НаборЗаписей = Объект.Движения.Хозрасчетный;
ЕстьИзменения = Ложь;

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

// Если нашли и очистили битые ссылки, перезаписываем набор
Если ЕстьИзменения Тогда
    НаборЗаписей.Записать();
КонецЕсли;

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

Что насчет настройки «НЕ создавать новый объект»?

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

Используйте описанные выше решения с программным контролем в обработчиках Перед выгрузкой (ПКО источника) или После загрузки (в документе-приемнике), чтобы гарантированно избавиться от некорректных субконто в вашей базе.

← На главную