Как рассчитать период задолженности контрагента в днях в 1С:УТП 1.2

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

Одной из наиболее востребованных задач в управленческом учете является контроль дебиторской задолженности не только по сумме, но и по «возрасту». Период задолженности — это количество дней, прошедших с момента возникновения долга до текущей даты. В конфигурации «Управление торговым предприятием для Украины» (УТП), редакция 1.2, этот показатель не хранится в явном виде в регистрах, так как он динамически меняется с каждым новым документом или просто с течением времени. Разберем подробно, как реализовать механизм получения этой информации и какие подходы будут наиболее эффективными.

Постановка задачи и анализ механизмов учета

Прежде чем приступать к разработке, проанализируем ситуацию. Сложность расчета периода задолженности напрямую зависит от того, как ведутся взаиморасчеты по договору. Если в договоре установлена галочка «Вести расчеты по документам», задача упрощается: у нас есть конкретные документы-основания, по которым висит остаток. Однако на практике часто встречается ведение расчетов «По договору в целом». В этом случае система знает только общую сумму долга, и нам придется самостоятельно определять, какие именно поставки остались неоплаченными, используя логику FIFO (First In, First Out).

Рассмотрим основные способы решения этой задачи: от использования типового функционала до написания кастомного запроса.

Решение 1: Использование типового механизма «Дебиторская задолженность по срокам»

В конфигурации УТП 1.2 уже заложен мощный механизм анализа сроков задолженности. Прежде чем писать свой код, проанализируем, как это реализовано в типовом решении. Существует отчет «Дебиторская задолженность по срокам долга».

Для корректной работы этого механизма выполним следующие шаги:

  1. Настроим интервалы задолженности. Зайдем в регистр сведений НастройкаИнтервалов и зададим нужные периоды (например: 0-7 дней, 8-14 дней, 15-30 дней и т.д.).
  2. Посмотрим на алгоритм отчета. Отчет использует специализированные функции, которые распределяют общую сумму долга по периодам возникновения, основываясь на датах документов отгрузки, даже если аналитика по документам в договоре не ведется.

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

Решение 2: Программный расчет методом «Обратного FIFO»

Проанализируем наиболее точный алгоритм определения даты возникновения задолженности. Суть метода заключается в том, что мы берем текущий остаток долга и начинаем «покрывать» его документами отгрузки, двигаясь от самых новых к самым старым. Тот документ, на котором сумма долга будет полностью исчерпана, и будет считаться моментом возникновения «хвоста» задолженности.

Разберем алгоритм по шагам:

  1. Получаем текущее сальдо по контрагенту из регистра накопления ВзаиморасчетыСКонтрагентами на текущую дату.
  2. Если сальдо положительное (нам должны), формируем запрос к этому же регистру, выбирая все записи с видом движения «Приход» (увеличение долга: Реализации, Акты) по данному контрагенту и договору.
  3. Сортируем эти записи по дате в обратном порядке (от новых к старым).
  4. В цикле вычитаем из текущего сальдо суммы документов.
  5. Как только сальдо стало меньше или равно нулю, фиксируем дату текущего документа. Это и есть дата возникновения задолженности.

Пример реализации логики на языке 1С:


// 1. Получаем текущий остаток
ЗапросОстаток = Новый Запрос;
ЗапросОстаток.Текст = "ВЫБРАТЬ
|	ВзаиморасчетыОстатки.СуммаВзаиморасчетовОстаток КАК Остаток
|ИЗ
|	РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&Период, ДоговорКонтрагента = &Договор) КАК ВзаиморасчетыОстатки";
// ... установка параметров ...
ВыборкаОстаток = ЗапросОстаток.Выполнить().Выбрать();
ОстатокДолга = 0;
Если ВыборкаОстаток.Следующий() Тогда
    ОстатокДолга = ВыборкаОстаток.Остаток;
КонецЕсли;

// 2. Если есть долг, ищем дату возникновения
Если ОстатокДолга > 0 Тогда
    ЗапросДокументы = Новый Запрос;
    ЗапросДокументы.Текст = "ВЫБРАТЬ
    |	Взаиморасчеты.Период КАК ДатаДокумента,
    |	Взаиморасчеты.СуммаВзаиморасчетов КАК Сумма
    |ИЗ
    |	РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты
    |ГДЕ
    |	Взаиморасчеты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    |	И Взаиморасчеты.ДоговорКонтрагента = &Договор
    |УПОРЯДОЧИТЬ ПО
    |	Взаиморасчеты.Период УБЫВ";
    // ... выполнение запроса и цикл ...
    Выборка = ЗапросДокументы.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        ОстатокДолга = ОстатокДолга - Выборка.Сумма;
        Если ОстатокДолга <= 0 Тогда
            ДатаВозникновения = Выборка.ДатаДокумента;
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Теперь, имея ДатаВозникновения, мы легко вычислим период в днях с помощью функции РАЗНОСТЬДАТ(ДатаВозникновения, ТекущаяДата, ДЕНЬ).

Решение 3: Оптимизированный запрос для массового отбора

Если нам нужно получить период задолженности сразу для большого списка контрагентов (например, в динамическом списке или сложном отчете), перебор в цикле будет работать слишком медленно. Выясним, как оптимизировать этот процесс.

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

Важный нюанс: Чтобы не «вешать» базу при большом количестве контрагентов, рекомендуется:

Учет условий договора и срока оплаты

Проанализируем еще один важный момент: период задолженности и период просрочки — это не одно и то же. В УТП 1.2 в карточке договора есть реквизит «Допустимое число дней задолженности».

Рассмотрим пример: Если товар отгружен 1-го числа, а в договоре прописана отсрочка 10 дней, то по факту задолженность возникла 1-го числа, но просроченной она станет только 11-го. Для корректного отбора в системе управления торговлей необходимо учитывать этот сдвиг.

В коде это реализуется добавлением дней отсрочки к полученной дате возникновения долга:


ДатаПлатежа = ДобавитьМесяц(ДатаВозникновения, 0); // Копируем дату
ДатаПлатежа = ДатаВозникновения + (Договор.ДопустимоеЧислоДнейЗадолженности * 24 * 3600);
Если ТекущаяДата() > ДатаПлатежа Тогда
    ДнейПросрочки = (ТекущаяДата() - ДатаПлатежа) / (24 * 3600);
КонецЕсли;

Выводы и рекомендации

Мы рассмотрели несколько подходов к определению периода задолженности в УТП 1.2. Подведем итог:

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

Помните, что точность расчета зависит от чистоты ведения учета: перекрыты ли авансы, нет ли «зависших» копеек на разных договорах одного контрагента. Перед запуском алгоритмов рекомендуется убедиться, что выполнено восстановление последовательности расчетов.

← На главную