В практике разработки на платформе 1С часто возникает задача сопоставления данных из разных контуров учета, которые имеют разные временные границы. Например, когда заказ оформлен в одном месяце, а оплаты по нему приходят частями в течение последующих периодов. Разберем подробно, как реализовать отчет, который покажет суммы поступлений за выбранный интервал, сгруппирует их по месяцам возникновения заказов и при этом отфильтрует только те заказы, которые были оплачены полностью.
Для решения задачи нам необходимо оперировать двумя источниками данных. Первый — это регистр, фиксирующий информацию о заказах (сумма заказа, менеджер, вид услуги). Второй — это регистр, учитывающий взаиморасчеты или фактические поступления денежных средств. Основная сложность заключается в том, что нам нужно наложить два разных условия по времени: период, за который мы смотрим обороты по деньгам, и период (месяц), к которому относится сам документ-основание.
Рассмотрим наиболее эффективный подход — использование временных таблиц в запросе. Это позволит нам избежать проблем с производительностью и обеспечит гибкость при наложении фильтров.
Проанализируем ситуацию: прямое соединение виртуальных таблиц ОстаткиИОбороты в одном запросе может работать медленно на больших базах. Правильнее будет сначала подготовить данные в оперативной памяти сервера 1С. Выполним следующие шаги:
Заказ.ИНДЕКСИРОВАТЬ ПО полю Заказ. Это значительно ускорит последующее соединение.Выясним причину, почему простая фильтрация по оборотам может не сработать. Если мы будем смотреть только на оплаты внутри выбранного периода, мы не узнаем, был ли заказ оплачен до этого или остался ли долг после. Чтобы корректно определить статус «Полностью оплачен», необходимо обратиться к виртуальной таблице Остатки регистра оплат на дату окончания периода отчета.
Условием полной оплаты будет являться отсутствие остатка по конкретному заказу. В запросе это выглядит как проверка на NULL или равенство остатка нулю. Рассмотрим пример фрагмента запроса:
ВЫБРАТЬ
ВзаиморасчетыОстатки.Заказ КАК Заказ
ИЗ
РегистрНакопления.Взаиморасчеты.Остатки(&КонецПериода, ) КАК ВзаиморасчетыОстатки
ГДЕ
ВзаиморасчетыОстатки.СуммаОстаток <= 0
Для удобства пользователя в СКД рекомендуется разделить параметры. Вместо одного стандартного периода НачалоПериода и КонецПериода, создадим собственные параметры:
В схеме компоновки данных на закладке «Связи наборов данных» мы можем связать таблицу заказов и таблицу оплат. Однако, как показывает практика, проще объединить их в одном запросе через ВНУТРЕННЕЕ СОЕДИНЕНИЕ, если нам нужны только оплаченные позиции, или через ЛЕВОЕ СОЕДИНЕНИЕ, если мы хотим видеть все заказы, но с информацией об оплатах.
Чтобы получить требуемую градацию (заказы января, февраля и т.д.), в поле запроса необходимо преобразовать дату заказа к началу месяца. Используем для этого стандартную функцию:
НАЧАЛОПЕРИОДА(Заказ.Дата, МЕСЯЦ) КАК МесяцЗаказа
В настройках отчета СКД это поле следует использовать в качестве группировки. Для наглядности можно настроить формат поля, чтобы выводилось только название месяца и год.
При соединении таблиц «один ко многим» (один заказ — несколько платежек в выбранном периоде) сумма заказа может продублироваться в итоговых строках. Чтобы этого не произошло, проанализируем настройки ресурсов в СКД. Для поля СуммаЗаказа в выражении расчета ресурса стоит использовать функцию МАКСИМУМ или СРЕДНЕЕ по группировке Заказ, но СУММА по вышестоящим группировкам. Это гарантирует точность финансовых показателей в отчете.
Важный момент: если логика вашего предприятия допускает переплаты, то условие СуммаОстаток <= 0 будет корректным. Если же важна именно точная оплата копейка в копейку, используйте равенство нулю. Помните, что использование внутреннего соединения отсечет те заказы, по которым не было движений в выбранном интервале оплат, даже если они закрыты в ноль. Если такие заказы должны попадать в отчет, используйте объединение (UNION) или левое соединение с проверкой оборотов.