Как найти контрагентов, у которых не было продаж более полугода и отсутствует задолженность

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Управленческий учет Торговля и дистрибуция
← На главную

В работе отдела продаж или маркетинга часто возникает задача выявить «уснувших» клиентов — тех, кто перестал совершать покупки определенное время назад (например, 6 месяцев), но при этом полностью закрыл свои обязательства перед компанией. В этой статье мы подробно разберем, как реализовать такой отчет на языке запросов 1С, проанализируем типичные ошибки начинающих разработчиков и составим эффективный алгоритм получения данных.

Постановка задачи и логика решения

Для корректного решения нам необходимо выполнить три основных действия:

  1. Определить дату самой последней продажи для каждого контрагента.
  2. Отфильтровать тех контрагентов, у которых эта дата наступила раньше, чем 6 месяцев назад.
  3. Исключить из списка тех, по кому в данный момент числится остаток задолженности (дебиторской или кредиторской).

Шаг 1. Поиск даты последней продажи и типичные ошибки группировки

Рассмотрим первую попытку реализации запроса. Часто новички пытаются получить данные напрямую из документов РеализацияТоваровУслуг. Однако здесь кроется главная ловушка — неправильное использование группировок.

Посмотрим на пример ошибочного запроса:


ВЫБРАТЬ
    РеализацияТоваровУслуг.Контрагент,
    МАКСИМУМ(РеализацияТоваровУслуг.Дата) КАК ДатаПоследнейПродажи
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслуг.Контрагент,
    РеализацияТоваровУслуг.Ссылка // ОШИБКА!

Проанализируем ситуацию: если мы включаем РеализацияТоваровУслуг.Ссылка в блок СГРУППИРОВАТЬ ПО, система будет выводить каждую накладную отдельной строкой. В этом случае функция МАКСИМУМ не сработает в разрезе контрагента, так как группировка идет по уникальному документу. Чтобы получить именно последнюю дату, мы должны группировать только по Контрагенту.

Шаг 2. Использование условия ИМЕЮЩИЕ (HAVING)

Чтобы отобрать контрагентов, чья последняя продажа была «давно», нельзя просто использовать блок ГДЕ. Почему? Потому что условие ГДЕ фильтрует исходные записи до того, как они будут сгруппированы. Нам же нужно отфильтровать уже агрегированный результат (максимальную дату).

Для этого в языке запросов используется секция ИМЕЮЩИЕ. Разберем правильный синтаксис:


ВЫБРАТЬ
    РеализацияТоваровУслуг.Контрагент КАК Контрагент,
    МАКСИМУМ(РеализацияТоваровУслуг.Дата) КАК ДатаПоследнейПродажи
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
    РеализацияТоваровУслуг.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслуг.Контрагент
ИМЕЮЩИЕ
    МАКСИМУМ(РеализацияТоваровУслуг.Дата) < &ДатаПолгодаНазад

Шаг 3. Проверка отсутствия задолженности

Теперь выясним, как исключить должников. Взаиморасчеты в 1С обычно хранятся в регистрах накопления (в УТ или ERP) или на счетах бухгалтерского учета (в Бухгалтерии предприятия). Для универсальности рассмотрим пример с использованием бухгалтерского регистра Хозрасчетный.Остатки (счет 62).

Нам необходимо получить список всех контрагентов, у которых СуммаОстаток не равна нулю, а затем исключить их из нашего основного списка с помощью левого соединения.

Итоговое решение с использованием временных таблиц

Рассмотрим наиболее профессиональный и производительный подход — использование временных таблиц. Это позволит нам четко разделить логику получения продаж и логику получения остатков.


// 1. Получаем список тех, кто должен (или кому мы должны)
ВЫБРАТЬ
    ХозрасчетныйОстатки.Субконто1 КАК Контрагент
ПОМЕСТИТЬ КонтрагентыСДолгами
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет В (&Счета62), , ) КАК ХозрасчетныйОстатки
ГДЕ
    ХозрасчетныйОстатки.СуммаОстаток <> 0
ИНДЕКСИРОВАТЬ ПО
    Контрагент
;

// 2. Получаем последнюю продажу тех, кто не покупал 6 месяцев
ВЫБРАТЬ
    РеализацияТоваровУслуг.Контрагент КАК Контрагент,
    МАКСИМУМ(РеализацияТоваровУслуг.Дата) КАК ДатаПоследнейПродажи
ПОМЕСТИТЬ СбежавшиеПокупатели
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
    РеализацияТоваровУслуг.Проведен
СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслуг.Контрагент
ИМЕЮЩИЕ
    МАКСИМУМ(РеализацияТоваровУслуг.Дата) < &ДатаПолгодаНазад
ИНДЕКСИРОВАТЬ ПО
    Контрагент
;

// 3. Соединяем таблицы и оставляем только тех, по кому нет долгов
ВЫБРАТЬ
    СбежавшиеПокупатели.Контрагент,
    СбежавшиеПокупатели.ДатаПоследнейПродажи
ИЗ
    СбежавшиеПокупатели КАК СбежавшиеПокупатели
ЛЕВОЕ СОЕДИНЕНИЕ КонтрагентыСДолгами КАК КонтрагентыСДолгами
    ПО СбежавшиеПокупатели.Контрагент = КонтрагентыСДолгами.Контрагент
ГДЕ
    КонтрагентыСДолгами.Контрагент ЕСТЬ NULL // Оставляем только тех, кого нет в таблице долгов

Важные рекомендации по оптимизации

Проанализируем, как сделать этот запрос еще лучше:

Используя данный подход, мы получаем чистый список клиентов, которые давно не проявляли активности и не имеют перед нами финансовых обязательств, что является идеальной базой для работы отдела маркетинга по возвращению покупателей.

← На главную