Как устранить задвоение сумм отгрузок и оплат в запросах СКД в 1С:Бухгалтерии?

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

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

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

Типичная ошибка заключается в попытке связать две таблицы документов — Документ.РеализацияТоваровУслуг и Документ.ПоступлениеНаРасчетныйСчет — напрямую через условие равенства по договору контрагента. Посмотрим на исходный вариант запроса, вызывающий ошибку:


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

ВЫБРАТЬ
    ПоступлениеНаРасчетныйСчет.ДоговорКонтрагента КАК ДоговорОплаты,
    ПоступлениеНаРасчетныйСчет.СуммаДокумента КАК СуммаОплаты
ПОМЕСТИТЬ Оплата
ИЗ
    Документ.ПоступлениеНаРасчетныйСчет КАК ПоступлениеНаРасчетныйСчет;

ВЫБРАТЬ
    Отгрузка.ДокументДвижения,
    Отгрузка.СуммаОтгрузки,
    Оплата.СуммаОплаты,
    Отгрузка.СуммаОтгрузки - Оплата.СуммаОплаты КАК ОстатокОплаты
ИЗ
    Отгрузка КАК Отгрузка
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Оплата КАК Оплата
        ПО Отгрузка.Договор = Оплата.ДоговорОплаты

Выясним причину некорректной работы такого запроса. При соединении таблиц по полю Договор происходит следующее:

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

Способ 1. Получение оплат через регистр бухгалтерии по документам расчетов

Если в договоре или в настройках программы включен учет расчетов по документам, каждая проводка по кредиту счета 62 содержит ссылку на закрываемую накладную в третьем субконто (ДокументыРасчетовСКонтрагентом). В этом случае мы связываем отгрузку с фактическими движениями оплаты по конкретному документу партии:


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

ВЫБРАТЬ
    Отгрузка.ДокументДвижения КАК ДокументДвижения,
    Отгрузка.Номер КАК Номер,
    Отгрузка.Дата КАК Дата,
    Отгрузка.Контрагент КАК Контрагент,
    Отгрузка.Договор КАК Договор,
    Отгрузка.СрокОплаты КАК СрокОплаты,
    Отгрузка.СуммаОтгрузки КАК СуммаОтгрузки,
    Отгрузка.ПланируемаяДатаПоступления КАК ПланируемаяДатаПоступления,
    ВЫРАЗИТЬ(Хозрасчетный.Регистратор КАК Документ.ПоступлениеНаРасчетныйСчет) КАК ДокументОплаты,
    ЕСТЬNULL(Хозрасчетный.Сумма, 0) КАК СуммаОплаты,
    Отгрузка.СуммаОтгрузки - ЕСТЬNULL(Хозрасчетный.Сумма, 0) КАК ОстатокОплаты
ИЗ
    ВТ_Отгрузка КАК Отгрузка
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
        ,
        ,
        Регистратор ССЫЛКА Документ.ПоступлениеНаРасчетныйСчет,
        ,
        ) КАК Хозрасчетный
        ПО Отгрузка.ДокументДвижения = Хозрасчетный.СубконтоКт3

Обратите внимание на обязательное использование функции ЕСТЬNULL. При левом соединении для накладных, по которым еще не было оплат, движения регистра вернут значение NULL. Без проверки на NULL вычитание вернет пустое значение, и остаток долга не рассчитается.

Способ 2. Использование виртуальной таблицы «ОстаткиИОбороты» (рекомендуемый)

Наиболее надежным и производительным решением в 1С является получение данных из виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты. Это позволяет учесть любые виды оплат и зачетов авансов без привязки к конкретным видам документов:


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

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

Способ 3. Объединение выборок вместо соединений

Если требуется объединить разнородные данные из таблиц документов без риска получить декартово произведение, используем конструкцию ОБЪЕДИНИТЬ ВСЕ:


ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    Реализация.ДоговорКонтрагента КАК Договор,
    Реализация.СуммаДокумента КАК СуммаОтгрузки,
    0 КАК СуммаОплаты
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Дата МЕЖДУ &Дата1 И &Дата2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Поступление.Ссылка,
    Поступление.ДоговорКонтрагента,
    0,
    Поступление.СуммаДокумента
ИЗ
    Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
ГДЕ
    Поступление.Дата МЕЖДУ &Дата1 И &Дата2

При таком подходе каждая строка попадает в отчет один раз, а агрегация данных по полям СуммаОтгрузки и СуммаОплаты выполняется ресурсами СКД без ошибок задвоения.

Способ 4. Использование связей наборов данных в СКД

Разделим выборку на два отдельных набора данных-запроса внутри схемы компоновки:

  1. НаборДанных_Отгрузки: выбирает список документов реализации и их реквизиты.
  2. НаборДанных_Оплаты: выбирает документы оплаты.

На вкладке Связи наборов данных настраиваем связь источника «НаборДанных_Отгрузки» с приемником «НаборДанных_Оплаты» по полю Договор или ДокументДвижения. Платформа 1С самостоятельно выполнит корректное сопоставление записей без размножения строк родительской таблицы.

Корректный расчет ресурсов СКД при наличии подчиненных строк

Если в схеме все же необходимо использовать запрос с левым соединением, для поля СуммаОтгрузки на вкладке Ресурсы следует задать специальную формулу расчета итогов, чтобы избежать суммирования дубликатов:


Сумма(ВычислитьВыражениеСГруппировкойТаблицаЗначений("Максимум(СуммаОтгрузки)", "ДокументДвижения"))

Данное выражение сначала вычисляет максимальное значение суммы для каждого уникального документа накладной, а затем складывает полученные результаты в группировках верхнего уровня.

← На главную