В практике работы с конфигурацией «1С:Торговля и Склад 9.2» (платформа 7.7) программисты часто сталкиваются с ситуацией, когда итоговая сумма по строкам документа не соответствует значению реквизита СуммаВзаиморасчетов в шапке. Это критическая ошибка, так как именно значение из шапки идет в регистры взаиморасчетов (Поставщики, Покупатели), что приводит к неверному отображению долга в отчетах.
Рассмотрим подробно причины возникновения этой коллизии, проанализируем внутренние механизмы платформы 7.7 и разберем по шагам, как исправить программный код, чтобы избежать подобных проблем в будущем.
В 1С версии 7.7, в отличие от более современных версий, расчетные итоги часто хранятся как физические реквизиты в таблицах заголовков документов (файлы DH*.dbf или таблицы _1SJOURN). Реквизит СуммаВзаиморасчетов — это не вычисляемое «на лету» поле, а переменная, значение которой записывается в момент проведения или сохранения документа.
Проанализируем основные причины, по которым это значение может стать неактуальным:
ПриИзмененииРеквизита). Если документ создается или изменяется внешней обработкой, эти процедуры не вызываются, и итоги в шапке остаются старыми.Рассмотрим ситуацию, описанную в теме форума. При вводе поступления на основании заказа, если товара пришло меньше, чем заказывали, сумма взаиморасчетов оставалась равной сумме всего заказа. Это классический пример ошибки в процедуре ВводНаОсновании.
Посмотрим на пример «неправильного» кода, который мог привести к ошибке:
Процедура ВводНаОсновании(ДокОсн)
// Копирование реквизитов шапки
Контрагент = ДокОсн.Контрагент;
Договор = ДокОсн.Договор;
// ОШИБКА: Жесткое копирование суммы из заказа
СуммаВзаиморасчетов = ДокОсн.СуммаВзаиморасчетов;
// Заполнение табличной части
ДокОсн.ВыбратьСтроки();
Пока ДокОсн.ПолучитьСтроку() = 1 Цикл
НоваяСтрока();
Товар = ДокОсн.Товар;
Количество = ДокОсн.Количество; // Здесь может быть логика уменьшения количества
Цена = ДокОсн.Цена;
Сумма = Количество * Цена;
КонецЦикла;
КонецПроцедуры
В данном примере, даже если мы изменим Количество в строках, реквизит СуммаВзаиморасчетов останется равен сумме из ДокОсн, так как он был присвоен в самом начале и более не пересчитывался.
Для того чтобы документ всегда содержал актуальные данные, необходимо инициировать пересчет итогов после заполнения табличной части. Выполним следующие действия:
ПоступлениеТМЦ.ВводНаОсновании.Правильный вариант реализации должен выглядеть так:
Процедура ВводНаОсновании(ДокОсн)
// Стандартное заполнение шапки
глЗаполнитьШапкуНаОсновании(Контекст, ДокОсн);
// Заполнение ТЧ с учетом частичного поступления
ДокОсн.ВыбратьСтроки();
Пока ДокОсн.ПолучитьСтроку() = 1 Цикл
// Здесь логика подбора товара, например, через глПриходованиеНаОсновании
КонецЦикла;
// ОБЯЗАТЕЛЬНО: Вызов функции пересчета итогов
// В типовой ТиС это обычно делается через глПересчетТабличнойЧасти(Контекст)
// или прямым вызовом функций модуля формы, если заполнение идет там.
// Если мы работаем в модуле документа, нужно явно рассчитать итог:
СуммаВзаиморасчетов = Итог("Сумма");
// С учетом НДС и валюты договора (вызов глобальной функции)
глПересчетИтоговДокумента(Контекст);
КонецПроцедуры
Важный нюанс: В 1С 7.7 функции пересчета часто вынесены в Глобальный модуль (с префиксом гл). Использование глПересчетИтоговДокумента или глРассчитатьНалоги гарантирует, что СуммаВзаиморасчетов будет рассчитана корректно с учетом всех налогов, скидок и курсов валют.
Проанализируем ситуацию: если таких документов в базе накопилось много, их нужно найти и программно исправить. Для этого можно написать простую обработку. Рассмотрим пример кода для поиска расхождений:
Док = СоздатьОбъект("Документ.ПоступлениеТМЦ");
Док.ВыбратьДокументы(ДатаНач, ДатаКон);
Пока Док.ПолучитьДокумент() = 1 Цикл
РасчетнаяСумма = Док.Итог("Сумма");
Если Док.СуммаВзаиморасчетов <> РасчетнаяСумма Тогда
Сообщить("Документ " + Док + " имеет расхождение!");
// Для исправления:
// Док.СуммаВзаиморасчетов = РасчетнаяСумма;
// Док.Записать();
КонецЕсли;
КонецЦикла;
Внимание: При автоматическом исправлении обязательно учитывайте валюту. Если валюта договора отличается от валюты документа, СуммаВзаиморасчетов не должна быть равна Итог("Сумма") в валюте документа — она должна быть равна этой сумме, пересчитанной по курсу договора.
Рассмотрим подробнее влияние других реквизитов, о которых упоминалось в обсуждении:
Количество * Коэффициент * Цена.глТекущийДолг: Как было замечено в сообщениях, иногда пользователи путают текущее сальдо по контрагенту с суммой документа. Помните, что СуммаВзаиморасчетов в документе — это только сумма текущей операции, а не весь остаток долга по регистру.Подводя итог, можно сказать, что проблема расхождения сумм в 1С 7.7 почти всегда носит программный характер и связана с человеческим фактором при кастомизации типовых конфигураций. Рекомендуется всегда использовать типовые глобальные функции для пересчета итогов и избегать прямого присвоения сумм в обход логики конфигурации.
Для профилактики подобных ошибок полезно периодически проводить аудит документов с помощью внешних отчетов, сравнивающих физические реквизиты шапок с расчетными итогами табличных частей.