В практике сопровождения систем на базе 1С часто возникает ситуация, когда между документами (например, приходом и списанием) не были установлены явные связи (через реквизит ДокументОснование или ведущие регистры). Если таких документов накопилось много за несколько лет, ручной поиск превращается в кошмар. Рассмотрим, как автоматизировать процесс подбора пар документов, основываясь на идентичности их табличных частей Товары.
Представим ситуацию: нам нужно найти документ оприходования, который соответствует конкретному документу списания. Единственный критерий — в обоих документах должен быть одинаковый набор товаров и их количеств. Основные проблемы, с которыми мы сталкиваемся:
Первым делом проанализируем подход с использованием запроса. Чтобы избежать проблем с дублированием строк, мы должны сначала «свернуть» табличные части обоих документов по номенклатуре (и, если есть, по характеристикам). Рассмотрим пример запроса, который собирает данные из документов СписаниеНедостачТоваров и ВводОстатков.
Сначала подготовим данные по списаниям во временной таблице:
ВЫБРАТЬ
СписаниеТовары.Ссылка КАК Ссылка,
СписаниеТовары.Номенклатура КАК Номенклатура,
СУММА(СписаниеТовары.Количество) КАК Количество
ПОМЕСТИТЬ втСписано
ИЗ
Документ.СписаниеНедостачТоваров.Товары КАК СписаниеТовары
ГДЕ
СписаниеТовары.Ссылка.Проведен
И СписаниеТовары.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
СГРУППИРОВАТЬ ПО
СписаниеТовары.Ссылка,
СписаниеТовары.Номенклатура;
Затем аналогичным образом подготовим данные по документам прихода (например, ВводОстатков или ПрочееОприходованиеТоваров):
ВЫБРАТЬ
ПриходТовары.Ссылка КАК Ссылка,
ПриходТовары.Номенклатура КАК Номенклатура,
СУММА(ПриходТовары.Количество) КАК Количество
ПОМЕСТИТЬ втПриход
ИЗ
Документ.ВводОстатков.Товары КАК ПриходТовары
ГДЕ
ПриходТовары.Ссылка.Проведен
СГРУППИРОВАТЬ ПО
ПриходТовары.Ссылка,
ПриходТовары.Номенклатура;
Если документов тысячи, прямое соединение таблиц «всех со всеми» по номенклатуре будет крайне неэффективным. Разберем более изящный метод — сравнение по контрольным суммам или сигнатурам. Мы можем рассчитать для каждого документа два простых числа: общее количество позиций и сумму всех количеств.
Рассмотрим логику: если в Документе №1 сумма количеств равна 12 и в нем 3 уникальных товара, а в Документе №2 те же показатели, то с высокой долей вероятности это наши кандидаты на соответствие. Проанализируем, как это выглядит в коде:
ВЫБРАТЬ
втСписано.Ссылка КАК ДокСписания,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ втСписано.Номенклатура) КАК ВсегоСтрок,
СУММА(втСписано.Количество) КАК ОбщееКоличество
ПОМЕСТИТЬ втСигнатурыСписания
ИЗ
втСписано КАК втСписано
СГРУППИРОВАТЬ ПО
втСписано.Ссылка;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
втПриход.Ссылка КАК ДокПрихода,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ втПриход.Номенклатура) КАК ВсегоСтрок,
СУММА(втПриход.Количество) КАК ОбщееКоличество
ПОМЕСТИТЬ втСигнатурыПрихода
ИЗ
втПриход КАК втПриход
СГРУППИРОВАТЬ ПО
втПриход.Ссылка;
Теперь мы можем быстро соединить эти две таблицы по ВсегоСтрок и ОбщееКоличество. Это мгновенно отсеет 99% неподходящих документов.
Как отмечалось в обсуждении, поиск по всей базе за 5 лет выдаст множество ложных совпадений (одни и те же наборы товаров могут списываться ежемесячно). Выясним, как правильно наложить ограничение по времени. Проанализируем два варианта условия в блоке ГДЕ:
ГДЕ
РАЗНОСТЬДАТ(ДокСписания.Дата, ДокПрихода.Дата, ДЕНЬ) МЕЖДУ -5 И 5
МЕЖДУ, чтобы система могла использовать индексы.Важно: Специалисты рекомендуют использовать именно РАЗНОСТЬДАТ для гибкости, но при очень больших объемах данных лучше заранее подготовить выборку по периоду.
Для программистов, стремящихся к абсолютной точности, разберем метод хеширования. Если сигнатуры по количеству строк совпали, нужно убедиться, что состав полностью идентичен. Рассмотрим алгоритм построения хеша:
1. Выгружаем ТЧ документа в таблицу значений.
2. Сортируем таблицу по номенклатуре (и характеристикам).
3. Формируем строку вида "IDНоменклатуры_Количество;IDНоменклатуры_Количество;".
4. От этой строки вычисляем MD5 или другой хеш-код.
Хранение такого хеша в дополнительном реквизите позволит находить точные копии документов за доли секунды. В типовых конфигурациях 1С для этого можно использовать функции платформы или БСП.
Проанализировав все способы, выработаем оптимальную последовательность действий для полуавтоматической обработки:
Рассмотрим пример финального соединения, который объединяет логику сопоставления:
ВЫБРАТЬ
Списания.ДокСписания,
Приходы.ДокПрихода
ИЗ
втСигнатурыСписания КАК Списания
ВНУТРЕННЕЕ СОЕДИНЕНИЕ втСигнатурыПрихода КАК Приходы
ПО Списания.ВсегоСтрок = Приходы.ВсегоСтрок
И Списания.ОбщееКоличество = Приходы.ОбщееКоличество
ГДЕ
РАЗНОСТЬДАТ(Списания.ДокСписания.Дата, Приходы.ДокПрихода.Дата, ДЕНЬ) МЕЖДУ -5 И 5
И Списания.ДокСписания.Склад = Приходы.ДокПрихода.Склад
Такой подход позволяет сэкономить сотни часов ручного труда, обеспечивая при этом высокую точность сопоставления складских операций.