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