При работе с конфигурацией «1С:Управление торговлей», редакция 11 (УТ 11), разработчики часто сталкиваются с ситуацией, когда при программном заполнении табличных частей документов (например, «Поступление товаров и услуг» или «Реализация товаров и услуг») итоговые суммы документа ведут себя непредсказуемо. Сумма «Всего» может обнуляться или не учитывать часть строк, хотя визуально в колонке Сумма данные заполнены корректно. Рассмотрим подробнее, почему типовой код 1С написан именно так, и разберем внутреннюю логику работы с возвратной тарой.
Проанализируем фрагмент кода, который вызывает наибольшее количество вопросов у начинающих (и не только) разработчиков. Эта процедура обычно находится в модуле формы или в специализированном клиентском модуле управления закупками/продажами:
&НаКлиентеНаСервереБезКонтекста
Процедура РассчитатьИтоговыеПоказателиПоступления(Форма)
// Расчет итога по табличной части "Товары"
КоллекцияТовары = Форма.Объект.Товары;
Форма.СуммаВсего = ?(Форма.Объект.ТребуетсяЗалогЗаТару,
КоллекцияТовары.Итог("СуммаСНДС"),
КоллекцияТовары.Итог("СуммаСНДСБезВозвратнойТары"));
Форма.СуммаНДС = ?(Форма.Объект.ТребуетсяЗалогЗаТару,
КоллекцияТовары.Итог("СуммаНДС"),
КоллекцияТовары.Итог("СуммаНДСБезВозвратнойТары"));
// ....
КонецПроцедуры
На первый взгляд, логика кажется перевернутой: если залог не требуется, система суммирует колонку с длинным названием СуммаСНДСБезВозвратнойТары. Выясним причину такого решения разработчиков фирмы 1С.
В типовых решениях на базе 1С:ERP и УТ 11 используется оптимизированный подход к расчету итогов. Вместо того чтобы в цикле перебирать все строки и проверять условие Строка.Номенклатура.ТипНоменклатуры = ТипыНоменклатуры.МногооборотнаяТара, система использует возможности платформенного метода Итог(). Для этого в табличную часть Товары добавлены служебные (часто скрытые от пользователя) колонки.
Разберем, как они заполняются:
СуммаСНДС и СуммаСНДСБезВозвратнойТары всегда идентичны.СуммаСНДС фиксируется залоговая стоимость тары.СуммаСНДСБезВозвратнойТары всегда записывается 0.Теперь логика типового кода становится прозрачной: если флаг ТребуетсяЗалогЗаТару выключен, задолженность перед поставщиком за тару не возникает. Чтобы быстро получить сумму только за товары (исключив тару), система суммирует колонку СуммаСНДСБезВозвратнойТары, где по строкам с тарой стоят нули. Если же залог нужен, суммируется общая колонка СуммаСНДС, включающая в себя всё.
Основная проблема возникает при программном заполнении документа. Если вы заполняете только стандартные реквизиты (Сумма, СуммаНДС), но игнорируете служебные реквизиты «Без возвратной тары», то при открытии формы или пересчете итогов вы получите нулевую сумму «Всего» (при условии, что флаг залога выключен). Типовые механизмы 1С ожидают, что эти данные подготовлены заранее.
Рассмотрим пример ситуации: разработчик импортирует данные из внешнего файла и заполняет строки. При интерактивном изменении суммы в форме срабатывают обработчики событий (ПриИзменении), которые автоматически обновляют служебные колонки. Однако при программной записи документа эти обработчики не вызываются.
Вариант 1: Программное дублирование сумм (Метод «Заплатки»)
Если вы пишете внешнюю обработку заполнения или загрузку данных, необходимо явно прописать копирование сумм в служебные поля. Проанализируем пример кода:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
// Основные расчеты
СтрокаТЧ.СуммаСНДС = СтрокаТЧ.Сумма + СтрокаТЧ.СуммаНДС;
// Обязательное заполнение служебных колонок для корректных итогов
// Если это не тара (или мы не хотим выделять тару), копируем полностью
СтрокаТЧ.СуммаСНДСБезВозвратнойТары = СтрокаТЧ.СуммаСНДС;
СтрокаТЧ.СуммаНДСБезВозвратнойТары = СтрокаТЧ.СуммаНДС;
КонецЦикла;
Вариант 2: Использование типового модуля пересчета
В УТ 11 существует серверный модуль (обычно это ОбработкаТабличнойЧастиТоварыСервер или аналогичный в зависимости от версии), содержащий процедуры для полного пересчета строки. Правильнее вызывать именно их, так как они учитывают не только тару, но и скидки, автоматические налоги и другие нюансы.
Рассмотрим пример вызова серверного пересчета:
// Пример для документа ПоступлениеТоваровУслуг
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ПересчитатьСумму");
СтруктураДействий.Вставить("ПересчитатьСуммуСНДС");
СтруктураДействий.Вставить("ЗаполнитьДублирующиеРеквизиты", Истина); // Вот этот ключ важен!
ОбработкаТабличнойЧастиТоварыСервер.ОбработатьСтрокуТЧ(СтрокаТЧ, СтруктураДействий, Объект);
В сообществе разработчиков 1С часто возникают споры: почему нельзя было назвать колонки более интуитивно, например СуммаТовара и СуммаЗалога? Ответ кроется в стандартах разработки и обратной совместимости. Для большинства операций (более 90% торгового оборота) возвратная тара не используется. Поэтому базовая колонка СуммаСНДС остается универсальной, а специализированная логика «вычитания» тары выносится в отдельные реквизиты, чтобы не усложнять структуру данных для простых пользователей.
Подведем итог:
СуммаСНДСБезВозвратнойТары и СуммаНДСБезВозвратнойТары при программной работе с документами УТ 11.Использование такого подхода позволит избежать «Стокгольмского синдрома» в разработке на 1С, о котором шутили участники форума, и сделает ваш код стабильным и соответствующим стандартам типовых конфигураций.