Как в 1С:ERP связать документы «Отчет переработчика» и «Отчет давальцу» по данным партнера

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

В системе 1С:ERP часто возникает задача сопоставления «зеркальных» документов, когда одна организация выступает переработчиком, а другая — давальцем. Основная сложность заключается в том, что связь между ними часто не является прямой, а строится на основе реквизитов Номер по данным партнера и Дата по данным партнера. Эти поля являются текстовыми и заполняются вручную, что вносит определенный хаос: номера могут содержать префиксы, лидирующие нули или разделители.

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

Постановка задачи и анализ реквизитов

Рассмотрим ситуацию: нам необходимо сопоставить документ ОтчетПереработчика с документом ОтчетДавальцу. Условия связи следующие:

  1. Дата: Должны совпадать месяцы и годы документов (используются поля ДатаПоДаннымПартнера у переработчика и стандартная Дата у давальца).
  2. Номер: Числовое значение номера по данным партнера должно совпадать с номером документа давальца (по последним 6 знакам).
  3. Номенклатура: Дополнительная проверка по совпадению позиций в табличных частях.

Проанализируем технические сложности. Реквизит НомерПоДаннымПартнера имеет длину 30 символов, в то время как стандартный номер документа — 11 символов. Поиск по подстроке в условии соединения запроса — это ресурсоемкая операция, которая может привести к серьезному замедлению работы базы данных (Full Table Scan на уровне SQL-сервера).

Решение через запрос: использование функций работы с датами

Для начала разберем, как реализовать связь по датам непосредственно в запросе. Самый надежный способ — привести обе даты к началу месяца. Рассмотрим пример кода, который формирует временную таблицу:


ВЫБРАТЬ
    ОтчетПереработчика.Ссылка КАК ОтчетПереработчика,
    ОтчетПереработчика.НомерПоДаннымПартнера КАК НомерПартнера,
    НАЧАЛОПЕРИОДА(ОтчетПереработчика.ДатаПоДаннымПартнера, МЕСЯЦ) КАК МесяцПартнера,
    ОтчетПереработчикаМатериалы.Номенклатура КАК Материал,
    СУММА(ОтчетПереработчикаМатериалы.Количество) КАК Количество
ПОМЕСТИТЬ ВТ_ОтчетыПереработчика
ИЗ
    Документ.ОтчетПереработчика.Материалы КАК ОтчетПереработчикаМатериалы
ГДЕ
    ОтчетПереработчикаМатериалы.Ссылка.Проведен
    И ОтчетПереработчикаМатериалы.Ссылка.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
    ОтчетПереработчика.Ссылка,
    ОтчетПереработчика.НомерПоДаннымПартнера,
    НАЧАЛОПЕРИОДА(ОтчетПереработчика.ДатаПоДаннымПартнера, МЕСЯЦ),
    ОтчетПереработчикаМатериалы.Номенклатура;

Проанализируем этот фрагмент. Мы используем функцию НАЧАЛОПЕРИОДА, чтобы подготовить данные для связи. Теперь, при соединении с таблицей ОтчетДавальцу, мы сможем просто сравнить полученные «начала месяцев».

Проблема сопоставления номеров

Как отмечалось в обсуждении, номера могут выглядеть как «УП0z-000050», «z-50» или просто «50». Если мы будем использовать ПОДСТРОКА в условии ЛЕВОЕ СОЕДИНЕНИЕ, СУБД не сможет использовать индексы.

Существует два подхода к решению этой проблемы:

Вариант 1. «Чистый» запрос с использованием ПОДСТРОКА

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


ИЗ
    ВТ_ОтчетыПереработчика КАК Т1
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ОтчетДавальцу КАК Т2
    ПО НАЧАЛОПЕРИОДА(Т2.Дата, МЕСЯЦ) = Т1.МесяцПартнера
    И Т2.Проведен
    И ПОДСТРОКА(Т1.НомерПартнера, 25, 6) = ПОДСТРОКА(Т2.Номер, 6, 6)

Вариант 2. Подготовка данных в Таблице Значений (рекомендуемый)

Более профессиональный и надежный метод — выгрузить данные в ТаблицаЗначений, обработать номера средствами встроенного языка 1С и загрузить их обратно в запрос. Рассмотрим, как реализовать очистку номера от лишних символов:


Функция ОчиститьНомер(Знач ВходнойНомер)
    Результат = "";
    Для Индекс = 1 По СтрДлина(ВходнойНомер) Цикл
        Символ = Сред(ВходнойНомер, Индекс, 1);
        Если Найти("0123456789", Символ) > 0 Тогда
            Результат = Результат + Символ;
        КонецЕсли;
    КонецЦикла;
    
    // Берем только последние 6 цифр
    Возврат Прав(Результат, 6);
КонецФункции

Разберем алгоритм интеграции:

  1. Выполняем первый запрос для получения списка всех ОтчетПереработчика за период.
  2. Выгружаем результат в ТаблицаЗначений.
  3. В цикле обходим таблицу и в новую колонку ЧисловойНомер записываем результат функции ОчиститьНомер.
  4. Аналогично поступаем с документами ОтчетДавальцу.
  5. Загружаем обе таблицы обратно в новый запрос как параметры.
  6. Выполняем соединение по проиндексированным колонкам ЧисловойНомер и Месяц.

Оптимизация через индексацию временных таблиц

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


Запрос.УстановитьПараметр("ТЗ_Подготовленная", МояТаблицаЗначений);
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ_Подготовленная КАК ТЗ;
               Индексировать ВТ_Данные (ЧисловойНомер, Месяц);
               // Далее основной код соединения...";

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

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

← На главную