Как правильно использовать «Отказ = Истина» в Конвертации данных 2.0 и не запутаться в булевой логике?

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

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

В этой статье мы подробно разберем типичную ошибку при работе со сложными отрицаниями, изучим законы алгебры логики применительно к коду 1С, рассмотрим правильные и лаконичные варианты написания условий, а также обсудим неочевидные подводные камни использования механизма Отказ = Истина, влияющие на производительность и корректность обмена.

В чем заключается суть проблемы? Выясняем причину

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

  1. Являются покупателями (Источник.ВидКонтрагента = Перечисления.ВидыКонтрагентов.Покупатель).
  2. Являются юридическими лицами (Источник.ФормаСобственности = Перечисления.ФормыСобственности.ЮридическоеЛицо).

Для всех остальных контрагентов выгрузка должна быть отменена. Первоначально разработчик написал в обработчике ПКО следующий код:


Если НЕ Источник.ВидКонтрагента = Перечисления.ВидыКонтрагентов.Покупатель И НЕ Источник.ФормаСобственности = Перечисления.ФормыСобственности.ЮридическоеЛицо Тогда
    Отказ = Истина;
КонецЕсли;

На первый взгляд код кажется логичным: «Если не покупатель и не юрлицо — отказываем в выгрузке». Однако при запуске обмена система начинает выгружать абсолютно всех контрагентов, полностью игнорируя это условие. Почему так происходит? Давайте проанализируем ситуацию.

Разбор логической ошибки: законы Де Моргана на практике

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

Пусть:

Нам подходят только те контрагенты, у которых одновременно выполняются оба условия: А И B. Следовательно, отказ должен срабатывать во всех остальных случаях, то есть когда истинно отрицание этого выражения: НЕ (А И B).

Согласно закону Де Моргана, отрицание конъюнкции (операции «И») эквивалентно дизъюнкции (операции «ИЛИ») отрицаний:

НЕ (А И B) = НЕ А ИЛИ НЕ B

Посмотрим, что написал разработчик в исходном коде: НЕ А И НЕ B. В булевой алгебре это выражение эквивалентно отрицанию дизъюнкции: НЕ (А ИЛИ B).

Давайте разберем, как это работало на практике для разных контрагентов:

  1. Контрагент — Юрлицо и Поставщик.
    • Условие А (Покупатель) = Ложь. Соответственно, НЕ А = Истина.
    • Условие B (Юрлицо) = Истина. Соответственно, НЕ B = Ложь.
    • Вычисляем общее условие: Истина И Ложь. Результат вычисления — Ложь.
    • Итог: Условие в блоке Если не выполняется, программа проходит мимо, и объект выгружается, хотя он является поставщиком!
  2. Контрагент — ИП и Покупатель.
    • Условие А (Покупатель) = Истина. Соответственно, НЕ А = Ложь.
    • Условие B (Юрлицо) = Ложь. Соответственно, НЕ B = Истина.
    • Вычисляем общее условие: Ложь И Истина. Результат вычисления — Ложь.
    • Итог: Условие в блоке Если снова не выполняется, и объект выгружается, хотя он не является юрлицом!

Таким образом, отказ срабатывал только тогда, когда контрагент одновременно не являлся ни покупателем, ни юридическим лицом (например, ИП-Поставщик). Во всех остальных случаях код пропускал объекты на выгрузку.

Как написать этот код правильно и лаконично?

Рассмотрим несколько вариантов решения этой задачи, начиная от простых и заканчивая наиболее профессиональными и изящными с точки зрения стандартов разработки 1С.

Вариант 1. Использование полной конструкции ветвления

Этот вариант интуитивно понятен и именно к нему в итоге пришел автор темы на форуме:


Если Источник.ВидКонтрагента = Перечисления.ВидыКонтрагентов.Покупатель 
   И Источник.ФормаСобственности = Перечисления.ФормыСобственности.ЮридическоеЛицо Тогда
    Отказ = Ложь; // Если удовлетворяет обоим условиям — выгружаем
Иначе
    Отказ = Истина; // В противном случае — отказываем
КонецЕсли;

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

Вариант 2. Прямое отрицание с использованием скобок

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


Отказ = НЕ (Источник.ВидКонтрагента = Перечисления.ВидыКонтрагентов.Покупатель 
            И Источник.ФормаСобственности = Перечисления.ФормыСобственности.ЮридическоеЛицо);

Этот код читается очень легко: «Отказ равен Истине, если НЕ выполняется условие, что контрагент является покупателем и одновременно юридическим лицом».

Вариант 3. Использование оператора «ИЛИ» и неравенств

Если мы раскроем скобки по правилам алгебры логики, то получим следующее выражение, использующее операторы неравенства <>:


Отказ = (Источник.ВидКонтрагента <> Перечисления.ВидыКонтрагентов.Покупатель) 
        ИЛИ (Источник.ФормаСобственности <> Перечисления.ФормыСобственности.ЮридическоеЛицо);

Здесь отказ сработает, если контрагент не является покупателем ИЛИ если он не является юридическим лицом. Это математически точное и лаконичное решение задачи.

Важные подводные камни использования «Отказ = Истина» в КД 2.0

Настройка логических условий в обработчике — это лишь половина дела. При работе с Конвертацией данных 2.0 крайне важно понимать, как именно платформа обрабатывает директиву Отказ = Истина под капотом. Рассмотрим два критически важных нюанса.

А. Проблема выгрузки объектов «по ссылке»

Даже если вы напишете идеальное и безошибочное условие отбора в ПКО контрагентов, некоторые «нежелательные» контрагенты все равно могут быть выгружены в файл обмена!

Это происходит в тех случаях, когда на отсекаемого контрагента ссылается другой выгружаемый объект — например, документ «Реализация товаров и услуг» или договор контрагента. Если в ПКО для контрагентов включен режим выгрузки по умолчанию («Выгружать при необходимости»), КД 2.0 проигнорирует ваш отказ в ПКО, чтобы не нарушать ссылочную целостность выгружаемого документа. Платформа создаст объект-ссылку в файле обмена, заполнив его ключевыми полями (например, УИД, Код или ИНН/КПП).

Как решить эту проблему?

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

Б. Проблемы с производительностью обмена

Фильтрация через Отказ = Истина в обработчике ПКО происходит в оперативной памяти на этапе обхода выборки данных. Проанализируем следующую ситуацию:

Допустим, в вашей базе-источнике содержится 500 000 контрагентов, а нужных вам покупателей-юрлиц — всего 5 000. Если вы используете стандартную выгрузку по правилам, КД 2.0 сделает запрос ко всей таблице контрагентов, прочитает все 500 000 записей, для каждой из них инициализирует интерпретатор кода 1С, выполнит ваше условие в обработчике и в 495 000 случаях установит отказ.

Это приведет к колоссальным потерям процессорного времени и перерасходу оперативной памяти на сервере.

Как оптимизировать этот процесс?

Резюме

Для создания надежных и быстрых правил обмена в КД 2.0 всегда соблюдайте следующие правила:

← На главную