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