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