Почему в отчете по дебиторской задолженности отображается долг при наличии возврата товара?

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

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

Анализ структуры отчета и вычисляемых полей

Рассмотрим типовую схему построения отчета на базе системы компоновки данных (СКД). Основной набор данных отчета обращается к виртуальной таблице регистра бухгалтерии для получения остатков и оборотов по счетам расчетов с покупателями:


ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстаток КАК СуммаБухНачальныйОстаток,
    ХозрасчетныйОстаткиИОбороты.СуммаОборотДт КАК Отгрузка,
    ХозрасчетныйОстаткиИОбороты.СуммаОборотКт КАК Оплата,
    ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаБухКонечныйОстаток,
    ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт КАК Дебет,
    ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокКт КАК Кредит,
    ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Контрагент,
    ХозрасчетныйОстаткиИОбороты.Субконто2 КАК ДоговорКонтрагента
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет В ИЕРАРХИИ (&Счет), , ) КАК ХозрасчетныйОстаткиИОбороты

Для вычисления суммы просроченной задолженности на вкладке Вычисляемые поля СКД часто задается формула с вызовом функции общего модуля:


Выбор когда Дебет > 0 тогда ПолучитьПросроченнуюЗадолженностьБух(ДоговорКонтрагента, &КонецПериода) иначе 0 Конец

Если отчет показывает «фантомный» долг, проанализируем две ключевые составляющие: программную реализацию функции расчета и правила ведения взаиморасчетов в учетных документах.

Ошибки в программном коде расчета просрочки

Изучим исходный код функции получения просроченной задолженности и вспомогательной функции определения граничной даты платежа («красной даты»):


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

В данном фрагменте видны критические недочеты:

  1. Если производственный календарь не заполнен или в выборку не попали записи, функция возвращает Неопределено вместо корректной даты, что ломает последующие запросы к виртуальным таблицам.
  2. При обращении к таблице РегистрБухгалтерии.Хозрасчетный.Обороты не задается вторая граница периода. Обороты считываются от &Дата до бесконечности в будущее, искажая расчет.

Исправление алгоритма расчета просроченного долга

Для корректного определения просроченной задолженности необходимо взять актуальный остаток долга на дату отчета и вычесть из него сумму кредитовых оборотов (погашений) за период допустимой отсрочки. Исправим модуль расчета:


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

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

Ошибки учета: оформление возврата не по документу реализации

Даже при корректно работающем алгоритме отчета сумма может попадать в долг из-за методологических ошибок оформления первичных документов. Разберем типовую ситуацию:

  1. Была оформлена накладная реализации товаров на определенную сумму. В регистре бухгалтерии сформировалась проводка по дебету счета 62.01 с указанием документа расчетов.
  2. Пользователь ввел документ Возврат товаров от покупателя, но основанием указал не конкретную накладную реализации, а Заказ покупателя или договор в целом.
  3. При проведении возврата без привязки к исходной накладной система не закрывает дебетовое сальдо по конкретному документу расчетов, а формирует кредитовый остаток (аванс) на счете 62.02 либо оставляет незакрытую аналитику на 62.01.
  4. В результате по счету расчетов сохраняется развернутое сальдо: дебет по исходной накладной считается непогашенным и переходит в разряд просроченной задолженности.

Порядок проверки и устранения проблемы

Для исправления данных выполним следующие шаги:

  1. Проверим проводки документа возврата: откроем движение документа и убедимся, что субконто Документы расчетов с контрагентом заполнено тем же документом реализации, долг по которому закрывается.
  2. Перевыберем документ основания: если возврат был введен на основании заказа, заменим документ расчетов в табличной части или реквизитах возврата на исходную реализацию и перепроведем документ.
  3. Проверим оборотно-сальдовую ведомость: сформируем ОСВ по счету 62 с максимальной детализацией (по субсчетам, договорам и расчетным документам). Убедимся, что дебетовое и кредитовое сальдо между отгрузкой и возвратом полностью схлопнулись.
  4. Выполним регламентные операции: при необходимости запустим обработку восстановления последовательности расчетов (актуализации взаиморасчетов), чтобы система автоматически зачла взаимные долги и авансы.
← На главную