При разработке отчетов по взаиморасчетам и контролю оплаты счетов в схеме компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда сумма реализации многократно увеличивается в итогах, а расчет остатка задолженности показывает неверные данные. Проанализируем, почему возникает эта ошибка, и рассмотрим правильные архитектурные подходы к выборке данных по отгрузкам и оплатам в конфигурации 1С:Бухгалтерия 3.0.
Типичная ошибка заключается в попытке связать две таблицы документов — Документ.РеализацияТоваровУслуг и Документ.ПоступлениеНаРасчетныйСчет — напрямую через условие равенства по договору контрагента. Посмотрим на исходный вариант запроса, вызывающий ошибку:
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК ДокументДвижения,
РеализацияТоваровУслуг.Номер,
РеализацияТоваровУслуг.Дата КАК Дата,
РеализацияТоваровУслуг.Контрагент КАК Контрагент,
РеализацияТоваровУслуг.ДоговорКонтрагента КАК Договор,
РеализацияТоваровУслуг.СуммаДокумента КАК СуммаОтгрузки
ПОМЕСТИТЬ Отгрузка
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Дата МЕЖДУ &Дата1 И &Дата2;
ВЫБРАТЬ
ПоступлениеНаРасчетныйСчет.ДоговорКонтрагента КАК ДоговорОплаты,
ПоступлениеНаРасчетныйСчет.СуммаДокумента КАК СуммаОплаты
ПОМЕСТИТЬ Оплата
ИЗ
Документ.ПоступлениеНаРасчетныйСчет КАК ПоступлениеНаРасчетныйСчет;
ВЫБРАТЬ
Отгрузка.ДокументДвижения,
Отгрузка.СуммаОтгрузки,
Оплата.СуммаОплаты,
Отгрузка.СуммаОтгрузки - Оплата.СуммаОплаты КАК ОстатокОплаты
ИЗ
Отгрузка КАК Отгрузка
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Оплата КАК Оплата
ПО Отгрузка.Договор = Оплата.ДоговорОплаты
Выясним причину некорректной работы такого запроса. При соединении таблиц по полю Договор происходит следующее:
ПриходныйКассовыйОрдер), эквайринг (ОперацияПоПлатежнойКарте) или с помощью взаимозачета (КорректировкаДолга). Соединение с конкретным документом искажает общую картину задолженности.Если в договоре или в настройках программы включен учет расчетов по документам, каждая проводка по кредиту счета 62 содержит ссылку на закрываемую накладную в третьем субконто (ДокументыРасчетовСКонтрагентом). В этом случае мы связываем отгрузку с фактическими движениями оплаты по конкретному документу партии:
ВЫБРАТЬ
Реализация.Ссылка КАК ДокументДвижения,
Реализация.Номер КАК Номер,
Реализация.Дата КАК Дата,
Реализация.Контрагент КАК Контрагент,
Реализация.ДоговорКонтрагента КАК Договор,
Реализация.ДоговорКонтрагента.СрокОплаты КАК СрокОплаты,
Реализация.СуммаДокумента КАК СуммаОтгрузки,
ДОБАВИТЬКДАТЕ(Реализация.Дата, ДЕНЬ, Реализация.ДоговорКонтрагента.СрокОплаты) КАК ПланируемаяДатаПоступления
ПОМЕСТИТЬ ВТ_Отгрузка
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &Дата1 И &Дата2;
ВЫБРАТЬ
Отгрузка.ДокументДвижения КАК ДокументДвижения,
Отгрузка.Номер КАК Номер,
Отгрузка.Дата КАК Дата,
Отгрузка.Контрагент КАК Контрагент,
Отгрузка.Договор КАК Договор,
Отгрузка.СрокОплаты КАК СрокОплаты,
Отгрузка.СуммаОтгрузки КАК СуммаОтгрузки,
Отгрузка.ПланируемаяДатаПоступления КАК ПланируемаяДатаПоступления,
ВЫРАЗИТЬ(Хозрасчетный.Регистратор КАК Документ.ПоступлениеНаРасчетныйСчет) КАК ДокументОплаты,
ЕСТЬNULL(Хозрасчетный.Сумма, 0) КАК СуммаОплаты,
Отгрузка.СуммаОтгрузки - ЕСТЬNULL(Хозрасчетный.Сумма, 0) КАК ОстатокОплаты
ИЗ
ВТ_Отгрузка КАК Отгрузка
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
,
,
Регистратор ССЫЛКА Документ.ПоступлениеНаРасчетныйСчет,
,
) КАК Хозрасчетный
ПО Отгрузка.ДокументДвижения = Хозрасчетный.СубконтоКт3
Обратите внимание на обязательное использование функции ЕСТЬNULL. При левом соединении для накладных, по которым еще не было оплат, движения регистра вернут значение NULL. Без проверки на NULL вычитание вернет пустое значение, и остаток долга не рассчитается.
Наиболее надежным и производительным решением в 1С является получение данных из виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты. Это позволяет учесть любые виды оплат и зачетов авансов без привязки к конкретным видам документов:
ВЫБРАТЬ
Взаиморасчеты.Субконто1 КАК Контрагент,
Взаиморасчеты.Субконто2 КАК Договор,
Взаиморасчеты.Субконто3 КАК ДокументДвижения,
Взаиморасчеты.СуммаОборотДт КАК СуммаОтгрузки,
Взаиморасчеты.СуммаОборотКт КАК СуммаОплаты,
Взаиморасчеты.СуммаКонечныйОстатокДт КАК ОстатокДолга
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
&ДатаНачала,
&ДатаОкончания,
Регистратор,
,
Счет В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Покупатели)),
,
Организация = &Организация
) КАК Взаиморасчеты
Такой подход гарантирует, что оборот по дебету отразит факт реализации, оборот по кредиту — все поступившие оплаты за указанный период, а конечный дебетовый остаток покажет актуальную задолженность контрагента.
Если требуется объединить разнородные данные из таблиц документов без риска получить декартово произведение, используем конструкцию ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
Реализация.ДоговорКонтрагента КАК Договор,
Реализация.СуммаДокумента КАК СуммаОтгрузки,
0 КАК СуммаОплаты
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &Дата1 И &Дата2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Поступление.Ссылка,
Поступление.ДоговорКонтрагента,
0,
Поступление.СуммаДокумента
ИЗ
Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
ГДЕ
Поступление.Дата МЕЖДУ &Дата1 И &Дата2
При таком подходе каждая строка попадает в отчет один раз, а агрегация данных по полям СуммаОтгрузки и СуммаОплаты выполняется ресурсами СКД без ошибок задвоения.
Разделим выборку на два отдельных набора данных-запроса внутри схемы компоновки:
На вкладке Связи наборов данных настраиваем связь источника «НаборДанных_Отгрузки» с приемником «НаборДанных_Оплаты» по полю Договор или ДокументДвижения. Платформа 1С самостоятельно выполнит корректное сопоставление записей без размножения строк родительской таблицы.
Если в схеме все же необходимо использовать запрос с левым соединением, для поля СуммаОтгрузки на вкладке Ресурсы следует задать специальную формулу расчета итогов, чтобы избежать суммирования дубликатов:
Сумма(ВычислитьВыражениеСГруппировкойТаблицаЗначений("Максимум(СуммаОтгрузки)", "ДокументДвижения"))
Данное выражение сначала вычисляет максимальное значение суммы для каждого уникального документа накладной, а затем складывает полученные результаты в группировках верхнего уровня.