В системе 1С:ERP часто возникает задача сопоставления «зеркальных» документов, когда одна организация выступает переработчиком, а другая — давальцем. Основная сложность заключается в том, что связь между ними часто не является прямой, а строится на основе реквизитов Номер по данным партнера и Дата по данным партнера. Эти поля являются текстовыми и заполняются вручную, что вносит определенный хаос: номера могут содержать префиксы, лидирующие нули или разделители.
В данной статье мы разберем, как эффективно организовать выборку связанных документов, если условием связи является совпадение месяца и последних 6 цифр номера.
Рассмотрим ситуацию: нам необходимо сопоставить документ ОтчетПереработчика с документом ОтчетДавальцу. Условия связи следующие:
ДатаПоДаннымПартнера у переработчика и стандартная Дата у давальца).Проанализируем технические сложности. Реквизит НомерПоДаннымПартнера имеет длину 30 символов, в то время как стандартный номер документа — 11 символов. Поиск по подстроке в условии соединения запроса — это ресурсоемкая операция, которая может привести к серьезному замедлению работы базы данных (Full Table Scan на уровне SQL-сервера).
Для начала разберем, как реализовать связь по датам непосредственно в запросе. Самый надежный способ — привести обе даты к началу месяца. Рассмотрим пример кода, который формирует временную таблицу:
ВЫБРАТЬ
ОтчетПереработчика.Ссылка КАК ОтчетПереработчика,
ОтчетПереработчика.НомерПоДаннымПартнера КАК НомерПартнера,
НАЧАЛОПЕРИОДА(ОтчетПереработчика.ДатаПоДаннымПартнера, МЕСЯЦ) КАК МесяцПартнера,
ОтчетПереработчикаМатериалы.Номенклатура КАК Материал,
СУММА(ОтчетПереработчикаМатериалы.Количество) КАК Количество
ПОМЕСТИТЬ ВТ_ОтчетыПереработчика
ИЗ
Документ.ОтчетПереработчика.Материалы КАК ОтчетПереработчикаМатериалы
ГДЕ
ОтчетПереработчикаМатериалы.Ссылка.Проведен
И ОтчетПереработчикаМатериалы.Ссылка.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
ОтчетПереработчика.Ссылка,
ОтчетПереработчика.НомерПоДаннымПартнера,
НАЧАЛОПЕРИОДА(ОтчетПереработчика.ДатаПоДаннымПартнера, МЕСЯЦ),
ОтчетПереработчикаМатериалы.Номенклатура;
Проанализируем этот фрагмент. Мы используем функцию НАЧАЛОПЕРИОДА, чтобы подготовить данные для связи. Теперь, при соединении с таблицей ОтчетДавальцу, мы сможем просто сравнить полученные «начала месяцев».
Как отмечалось в обсуждении, номера могут выглядеть как «УП0z-000050», «z-50» или просто «50». Если мы будем использовать ПОДСТРОКА в условии ЛЕВОЕ СОЕДИНЕНИЕ, СУБД не сможет использовать индексы.
Существует два подхода к решению этой проблемы:
Если формат номеров у партнера относительно стабилен (например, всегда фиксированная длина), можно использовать выборку подстроки. Однако это «хрупкое» решение. Выясним причину: любое изменение префикса в будущем сломает связь.
ИЗ
ВТ_ОтчетыПереработчика КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ОтчетДавальцу КАК Т2
ПО НАЧАЛОПЕРИОДА(Т2.Дата, МЕСЯЦ) = Т1.МесяцПартнера
И Т2.Проведен
И ПОДСТРОКА(Т1.НомерПартнера, 25, 6) = ПОДСТРОКА(Т2.Номер, 6, 6)
Более профессиональный и надежный метод — выгрузить данные в ТаблицаЗначений, обработать номера средствами встроенного языка 1С и загрузить их обратно в запрос. Рассмотрим, как реализовать очистку номера от лишних символов:
Функция ОчиститьНомер(Знач ВходнойНомер)
Результат = "";
Для Индекс = 1 По СтрДлина(ВходнойНомер) Цикл
Символ = Сред(ВходнойНомер, Индекс, 1);
Если Найти("0123456789", Символ) > 0 Тогда
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
// Берем только последние 6 цифр
Возврат Прав(Результат, 6);
КонецФункции
Разберем алгоритм интеграции:
ОтчетПереработчика за период.ТаблицаЗначений.ЧисловойНомер записываем результат функции ОчиститьНомер.ОтчетДавальцу.ЧисловойНомер и Месяц.Когда мы передаем подготовленную таблицу обратно в запрос, крайне важно проиндексировать поля связи. Это обеспечит мгновенный поиск даже при тысячах документов в выборке.
Запрос.УстановитьПараметр("ТЗ_Подготовленная", МояТаблицаЗначений);
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ_Подготовленная КАК ТЗ;
Индексировать ВТ_Данные (ЧисловойНомер, Месяц);
// Далее основной код соединения...";
Важный момент: Если конфигурация позволяет вносить изменения, лучшим долгосрочным решением будет добавление реквизита ИндексДляПоиска непосредственно в документ. При записи документа в этот реквизит будет записываться очищенное числовое значение номера. Это позволит выполнять связи в любых отчетах максимально быстро без дополнительных преобразований «на лету».
Таким образом, мы проанализировали ситуацию и пришли к выводу, что для надежной связи документов в ERP лучше всего использовать комбинацию запроса и предварительной обработки строк на стороне сервера 1С. Это гарантирует корректность сопоставления при нестандартном вводе номеров партнерами.