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