Часто в работе бухгалтерии или отдела продаж возникает задача: банк присылает общую сумму поступления по эквайрингу, а в системе числится множество документов ОплатаОтПокупателяПлатежнойКартой с разными суммами. Задача состоит в том, чтобы подобрать документы, сумма которых точно (или максимально близко) соответствует приходу от банка. Давайте разберемся, как подходить к этому вопросу профессионально.
Многие разработчики, столкнувшись с этой задачей впервые, пытаются решить её «в лоб» — с помощью кросс-соединений (CROSS JOIN) нескольких таблиц в одном запросе 1С. Рассмотрим, почему это не лучший путь:
Прежде чем приступать к написанию сложных алгоритмов, зададимся вопросом: действительно ли нам нужно «подбирать» суммы? Чаще всего в управленческом учете используется принцип ФИФО (первым пришел — первым ушел). Вместо поиска комбинации, которая дает сумму 100 рублей, мы просто закрываем самые старые неоплаченные документы, пока сумма поступления не будет исчерпана.
Почему это лучше:
Если специфика бизнеса все же требует точного попадания «в копейку» (например, из-за специфических требований банковской выверки), не стоит использовать запрос. Используйте встроенный язык 1С для работы с массивами в памяти. Рассмотрим пример реализации:
// Пример упрощенной логики подбора через рекурсию в памяти
Функция НайтиКомбинацию(Суммы, ЦелеваяСумма, Индекс = 0, ТекущаяСумма = 0)
// Базовые условия выхода из рекурсии...
// Итерация по списку сумм документов
КонецФункции
Разберем, почему перенос вычислений в код 1С эффективнее:
Массив или СписокЗначений в оперативной памяти сервера.Для понимания того, чего стоит избегать, проанализируем структуру, которую часто предлагают в попытках решить задачу через ВТ (Временные таблицы):
ВЫБРАТЬ
ВТ_Множества_1.ОплатаКартой КАК Оплата1,
ВТ_Множества_2.ОплатаКартой КАК Оплата2,
ВТ_Множества_1.Сумма + ВТ_Множества_2.Сумма КАК Итого
ИЗ
ВТ_Множества КАК ВТ_Множества_1,
ВТ_Множества КАК ВТ_Множества_2
ГДЕ
ВТ_Множества_1.ОплатаКартой <> ВТ_Множества_2.ОплатаКартой
Этот код создает декартово произведение. Если у вас 100 документов, запрос попытается создать таблицу из 10 000 строк. Если добавить 3-й уровень (3 документа в связке), это будет уже 1 000 000 строк. Никогда не используйте подобные конструкции для больших объемов данных — это приведет к блокировкам таблиц и падению производительности всей конфигурации.
В завершение, подведем итог, как вам лучше поступить:
ФИФО. Это сэкономит недели разработки и отладки.Массив и используйте алгоритмы динамического программирования или классический поиск в глубину на встроенном языке.Помните, что лучший код — это тот, который не только работает, но и легко поддерживается другими разработчиками. Сложные алгоритмы поиска подмножеств в 1С — это редкая задача, требующая документирования, поэтому всегда оставляйте комментарии в коде, объясняющие логику подбора!