Каждый начинающий разработчик в среде «1С:Предприятие» рано или поздно сталкивается с ситуацией, когда написанный им запрос не возвращает ожидаемых результатов. Типичный пример — попытка выбрать данные напрямую из документов платежных поручений или непонимание того, как устроены механизмы хранения дополнительных реквизитов, созданных пользователями в режиме предприятия. В этой статье мы подробно разберем, почему простые запросы к платежным поручениям могут не работать, как правильно получать данные о реальных движениях денежных средств и каким образом связать эти документы с дополнительными свойствами договоров контрагентов.
Проанализируем первую проблему, с которой столкнулся автор темы. Был написан простейший запрос к таблице Документ.ПлатежноеПоручение, который в итоге ничего не вернул. Здесь кроются две принципиальные ошибки — техническая и методологическая.
Техническая сторона вопроса. Сам по себе конструктор запросов в конфигураторе лишь формирует текстовую строку запроса. Чтобы этот запрос вернул данные в вашей программе, его необходимо правильно вызвать в коде, передать в базу данных на выполнение и обработать полученную выборку. Рассмотрим классический шаблон программного выполнения запроса в 1С:
// 1. Создаем объект "Запрос"
Запрос = Новый Запрос;
// 2. Задаем текст запроса
Запрос.Текст =
"ВЫБРАТЬ
| ПлатежноеПоручение.Номер КАК Номер,
| ПлатежноеПоручение.Дата КАК Дата
|ИЗ
| Документ.ПлатежноеПоручение КАК ПлатежноеПоручение";
// 3. Выполняем запрос и получаем результат
РезультатЗапроса = Запрос.Выполнить();
// 4. Выгружаем результат в выборку для обхода в цикле
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Здесь пишем код обработки каждой строки, например:
Сообщить("Документ № " + ВыборкаДетальныеЗаписи.Номер + " от " + Формат(ВыборкаДетальныеЗаписи.Date, "ДФ=dd.MM.yyyy"));
КонецЦикла;
Если вы хотите просто проверить работоспособность запроса без написания кода, всегда используйте специальный инструмент — Консоль запросов в режиме «1С:Предприятие».
Методологическая (архитектурная) сторона. Документ ПлатежноеПоручение в большинстве типовых конфигураций 1С (таких как «Бухгалтерия предприятия», «ERP» или «Комплексная автоматизация») является лишь печатной формой — поручением банку списать деньги. Этот документ не проводится и не совершает фактических движений по счетам учета или регистрам денежных средств. Реальное списание денег регистрируется документом СписаниеСРасчетногоСчета, а поступление — документом ПоступлениеНаРасчетныйСчет. Поэтому, если вам нужно получить список реальных оплат, делать запрос к платежным поручениям бессмысленно — нужно обращаться к документам выписки банка.
---
Теперь разберем более сложную задачу: нам необходимо получить список проведенных документов поступления денег за определенный период по договорам, у которых конкретный дополнительный реквизит установлен в значение Истина.
В современных конфигурациях 1С, использующих Библиотеку стандартных подсистем (БСП), пользовательские реквизиты могут создаваться без изменения конфигурации. Они делятся на два типа, и логика запроса для каждого типа будет отличаться.
Если реквизит (например, с именем КонтролироватьОплату и типом Булево) был добавлен физически в свойства справочника ДоговорыКонтрагентов через конфигуратор, то мы можем обратиться к нему напрямую через точку от реквизита договора. Разберем этот пример запроса:
ВЫБРАТЬ
Поступление.Ссылка КАК Ссылка,
Поступление.Дата КАК Дата,
Поступление.Номер КАК Номер,
Поступление.ДоговорКонтрагента КАК Договор
ИЗ
Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
ГДЕ
Поступление.Проведен = ИСТИНА
И Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Поступление.ДоговорКонтрагента.КонтролироватьОплату = ИСТИНА
Если свойство создано пользователем в режиме «1С:Предприятие» как дополнительный реквизит, платформа сохраняет его в подчиненной табличной части справочника договоров. Эта табличная часть называется ДополнительныеРеквизиты. В запросе нам потребуется связать основную таблицу документа с этой табличной частью договора при помощи левого или внутреннего соединения:
ВЫБРАТЬ
Поступление.Ссылка КАК Ссылка,
Поступление.Дата КАК Дата,
Поступление.Номер КАК Номер,
Поступление.ДоговорКонтрагента КАК Договор
ИЗ
Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
// Применяем внутреннее соединение с табличной частью дополнительных реквизитов договора
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов.ДополнительныеРеквизиты КАК ДоговорДопРеквизиты
ПО Поступление.ДоговорКонтрагента = ДоговорДопРеквизиты.Ссылка
ГДЕ
Поступление.Проведен = ИСТИНА
И Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
// Фильтруем по конкретному свойству и проверяем его значение
И ДоговорДопРеквизиты.Свойство = &СвойствоДоговора
И ДоговорДопРеквизиты.Значение = ИСТИНА
Для корректной работы этого запроса в коде обязательно нужно передать параметр &СвойствоДоговора. Это ссылка на элемент плана видов характеристик ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения:
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ИнтервалДатыНачало));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ИнтервалДатыКонец));
// Находим нужное свойство по его наименованию
СсылкаНаСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Контролировать оплату (Договоры)");
Запрос.УстановитьПараметр("СвойствоДоговора", СсылкаНаСвойство);
Если свойство было создано как дополнительное сведение, оно не привязано к самому объекту физически и хранится в независимом регистре сведений ДополнительныеСведения. В этом случае запрос будет выглядеть следующим образом:
ВЫБРАТЬ
Поступление.Ссылка КАК Ссылка,
Поступление.Дата КАК Дата,
Поступление.Номер КАК Номер,
Поступление.ДоговорКонтрагента КАК Договор
ИЗ
Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
// Соединяем документ с регистром сведений по полю Объект
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения
ПО Поступление.ДоговорКонтрагента = ДопСведения.Объект
ГДЕ
Поступление.Проведен = ИСТИНА
И Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И ДопСведения.Свойство = &СвойствоДоговора
И ДопСведения.Значение = ИСТИНА
---
Если ваша конечная задача — построить красивый отчет со списками оплат в Системе компоновки данных (СКД), то вам совершенно не обязательно вручную прописывать сложные соединения с табличными частями или регистрами сведений. Платформа 1С умеет делать это автоматически с помощью встроенного механизма характеристик.
Выполним простую настройку СКД по шагам:
ДоговорыКонтрагентов:
ДоговорКонтрагента).ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.Справочник.ДоговорыКонтрагентов.ДополнительныеРеквизиты (для доп. реквизитов) или таблицу РегистрСведений.ДополнительныеСведения (для доп. сведений).После этой несложной манипуляции при создании отчета в режиме предприятия пользователь сможет развернуть поле договора через стандартные настройки компоновки и увидеть все добавленные дополнительные реквизиты так, будто они являются реальными физическими реквизитами справочника. Платформа сама сгенерирует оптимальные левые соединения при формировании отчета.
---
Проанализируем производительность нашего решения. Выборка данных напрямую из таблиц документов (таких как ПоступлениеНаРасчетныйСчет или СписаниеСРасчетногоСчета) — не самое лучшее решение, если в базе накопились сотни тысяч документов за несколько лет. Такие запросы будут работать медленно.
Для получения информации о платежах гораздо эффективнее обращаться к виртуальным таблицам оборотов соответствующих регистров. В зависимости от вашей конфигурации это могут быть:
РегистрБухгалтерии.Хозрасчетный.Обороты по 51 счету («Расчетные счета») в конфигурации «1С:Бухгалтерия».РегистрНакопления.ДенежныеСредстваБезналичные.Обороты в конфигурациях ERP, КА или УТ.Рассмотрим пример быстрого запроса к регистру бухгалтерии для получения оборотов по расчетным счетам:
ВЫБРАТЬ
ХозрасчетныйОбороты.Регистратор КАК ДокументОплаты,
ХозрасчетныйОбороты.Субконто1 КАК Контрагент,
ХозрасчетныйОбороты.Субконто2 КАК Договор,
ХозрасчетныйОбороты.СуммаОборотДт КАК СуммаПрихода
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.РасчетныеСчета), , , , ) КАК ХозрасчетныйОбороты
ГДЕ
ХозрасчетныйОбороты.Субконто2.КонтролироватьОплату = ИСТИНА
Этот подход гарантирует высокую скорость выполнения запроса даже на крупных корпоративных базах данных, так как платформа обращается к заранее рассчитанным и проиндексированным итогам регистров, а не сканирует тяжелые таблицы документов.