Как правильно рассчитать дебиторскую задолженность по складам в 1С:Управление торговлей 11?

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

При разработке отчетов по взаиморасчетам в конфигурации «1С:Управление торговлей 11» разработчики часто сталкиваются с ситуацией, когда прямое вычисление разницы между суммами отгрузок и оплат выдает неверные числовые значения. Особенно остро эта проблема встает при попытке детализировать задолженность до склада, если в одном документе реализации содержатся товары с нескольких складов. Разберем по шагам, почему возникают искажения данных и как правильно построить запрос.

Проанализируем типичную попытку соединения регистра расчетов и документов, с которой начинаются подобные задачи:


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

Причины возникновения ошибок в запросе

Выясним причину некорректного поведения приведенного выше запроса. Здесь присутствуют три критические ошибки архитектуры запросов 1С:

  1. Размножение строк (эффект декартова произведения): Когда виртуальная таблица соединяется с табличной частью Документ.РеализацияТоваровУслуг.Товары, каждая строка взаиморасчетов дублируется столько раз, сколько строк содержится в документе реализации. При последующем суммировании суммы оплат умножаются на количество товарных позиций.
  2. Необработанные значения NULL: В левом соединении для расчетного документа отгрузки поля таблицы ПоступлениеБезналичныхДенежныхСредств возвращают NULL. Любая арифметическая операция вида Сумма - NULL дает в результате NULL. Значения необходимо обязательно оборачивать в функцию ЕСТЬNULL.
  3. Ошибочные условия в секции ГДЕ: Наложение фильтра ГДЕ на поля правой таблицы превращает ЛЕВОЕ СОЕДИНЕНИЕ во ВНУТРЕННЕЕ СОЕДИНЕНИЕ, отсекая все записи, где правая таблица не заполнилась. Условия для присоединенных таблиц следует переносить в условие соединения ПО.

Вариант 1. Использование временных таблиц с предварительной группировкой

Рассмотрим правильный подход к построению пакетного запроса. Чтобы избежать задвоения сумм и некорректного подсчета, разобьем вычисления на независимые временные таблицы (ВТ).


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

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОстаткиВзаиморасчетов.Контрагент КАК Контрагент,
    ЕСТЬNULL(КонтактнаяИнформация.Представление, "") КАК Адрес,
    СУММА(ЕСТЬNULL(ВТ_ТоварыПоСкладу.СуммаПоСкладу, 0)) КАК СуммаОтгрузкиСклада,
    СУММА(ЕСТЬNULL(ВТ_ОстаткиВзаиморасчетов.ДолгКлиента, 0)) КАК СуммаДолга
ИЗ
    ВТ_ОстаткиВзаиморасчетов КАК ВТ_ОстаткиВзаиморасчетов
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ТоварыПоСкладу КАК ВТ_ТоварыПоСкладу
        ПО ВТ_ОстаткиВзаиморасчетов.РасчетныйДокумент = ВТ_ТоварыПоСкладу.Документ
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.КонтактнаяИнформация КАК КонтактнаяИнформация
        ПО ВТ_ОстаткиВзаиморасчетов.Контрагент = КонтактнаяИнформация.Ссылка
        И (КонтактнаяИнформация.Вид = &Вид)
СГРУППИРОВАТЬ ПО
    ВТ_ОстаткиВзаиморасчетов.Контрагент,
    КонтактнаяИнформация.Представление

Вариант 2. Пропорциональный расчет долга по складу

Проанализируем типовую особенность конфигурации «Управление торговлей 11»: в регистрах РасчетыСКлиентами и РасчетыСКлиентамиПоДокументам нет измерения «Склад». Оплата регистрируется на документ реализации в целом. Если в одной накладной находятся товары с разных складов, определить точный остаток долга конкретного склада можно только путем расчета доли склада в общей сумме накладной.

Разберем алгоритм вычисления доли:

  1. Вычисляем общую сумму документа реализации: СуммаДокумента.
  2. Вычисляем сумму строк документа, относящихся к выбранному складу: СуммаСклада.
  3. Определяем долю склада: Коэффициент = СуммаСклада / СуммаДокумента.
  4. Умножаем фактический остаток долга по документу из регистра на полученный коэффициент: ДолгПоСкладу = ОстатокДолга * Коэффициент.

ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    СУММА(Реализация.Сумма) КАК ОбщаяСуммаДокумента,
    СУММА(ВЫБОР
            КОГДА Реализация.Склад = &Склад
                ТОГДА Реализация.Сумма
            ИНАЧЕ 0
        КОНЕЦ) КАК СуммаСклада
ПОМЕСТИТЬ ВТ_ДолиСкладов
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Реализация
СГРУППИРОВАТЬ ПО
    Реализация.Ссылка
ИНДЕКСИРОВАТЬ ПО
    Документ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Остатки.АналитикаУчетаПоПартнерам.Контрагент КАК Контрагент,
    СУММА(Остатки.СуммаОстаток * (ВТ_ДолиСкладов.СуммаСклада / ВЫБОР
                КОГДА ВТ_ДолиСкладов.ОбщаяСуммаДокумента = 0
                    ТОГДА 1
                ИНАЧЕ ВТ_ДолиСкладов.ОбщаяСуммаДокумента
            КОНЕЦ)) КАК ЗадолженностьПоСкладу
ИЗ
    РегистрНакопления.РасчетыСКлиентамиПоДокументам.Остатки(&Период, ) КАК Остатки
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ДолиСкладов КАК ВТ_ДолиСкладов
        ПО Остатки.РасчетныйДокумент = ВТ_ДолиСкладов.Документ
ГДЕ
    ВТ_ДолиСкладов.СуммаСклада > 0
СГРУППИРОВАТЬ ПО
    Остатки.АналитикаУчетаПоПартнерам.Контрагент

Рекомендации по настройке отчета в СКД

Если отчет разрабатывается в системе компоновки данных (СКД), обратите внимание на следующие правила:

  1. Вычисляемые поля: Не выполняйте сложные разности несвязанных сумм в тексте основного запроса при помощи соединений. Переносите расчет разностей (например, СуммаРеализаций - СуммаОплат) на вкладку Вычисляемые поля схемы компоновки данных.
  2. Объединение наборов данных: Если необходимо вывести данные по отгрузкам и платежам параллельно, используйте оператор ОБЪЕДИНИТЬ ВСЕ или связывайте разные наборы данных в СКД, вместо использования прямых левых соединений табличных частей с регистрами.
← На главную