Как правильно получить задолженность по контрагенту и договору через БухгалтерскиеИтоги в 1С 7.7?

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке документов и отчетов в платформе 1С:Предприятие 7.7 часто требуется получить актуальное сальдо расчетов с контрагентами. Начинающие разработчики нередко сталкиваются с ошибками типизации параметров, падением производительности при выполнении запросов в цикле и системной ошибкой «Неверное имя атрибута». Разберем подробно, как устроен механизм бухгалтерских итогов, какие ошибки допускаются при фильтрации данных и как написать оптимальный код.

Анализ типичных ошибок при работе с объектом БухгалтерскиеИтоги

Рассмотрим частые ошибки, возникающие при выборке остатков по счетам взаиморасчетов (например, счет 62):

  1. Передача строкового литерала вместо ссылки на субконто. Метод ИспользоватьСубконто() вторым параметром принимает ссылку на конкретный элемент справочника (или объект СписокЗначений для множественного отбора). Если передать строку вида "Договор" в кавычках, система не найдет совпадений в регистре бухгалтерии, и сальдо всегда будет равно нулю.
  2. Избыточное использование функции ПолучитьАтрибут(). В модуле формы документа обращение к реквизитам шапки и табличной части доступно напрямую по их идентификаторам. Использование конструкции ПолучитьАтрибут("Договор") без необходимости усложняет код и приводит к ошибке «Неверное имя атрибута», если передано имя во множественном числе (например, "Договоры" вместо "Договор") или реквизит отсутствует.
  3. Вызов метода ВыполнитьЗапрос() внутри цикла. Инициализация объекта БухгалтерскиеИтоги и выполнение запроса на каждой итерации обхода строк документа создают огромную нагрузку на базу данных и вызывают сильные зависания.
  4. Некорректный выбор периода расчета. Функция КонКвартала(ТекущаяДата()) возвращает дату конца квартала. Если дата уходит в будущее относительно рассчитанных в базе итогов, платформа 1С 7.7 запускает расчет проводок «на лету» от точки актуальности итогов, что существенно замедляет работу.
  5. Попытка фильтрации по реквизиту, не являющемуся субконто. В типовом плане счетов 1С 7.7 на счете 62 субконто «Менеджер» отсутствует. На счетах взаиморасчетов обычно используются субконто Контрагенты, Договоры и Документы расчетов. Отфильтровать итоги по менеджеру напрямую через ИспользоватьСубконто(ВидыСубконто.Менеджеры, ...) нельзя.

Решение 1: Получение задолженности по конкретному договору в функции

Если требуется рассчитать сальдо для одного конкретного контрагента и договора (например, при изменении реквизита в шапке документа или при расчете поля на форме), используем прямое обращение к переменным документа:


Функция ЗадолженностьПоДоговору()
    Перем Ит, Взс;
    
    Если ПустоеЗначение(Контрагент) = 1 Тогда
        Возврат 0;
    КонецЕсли;
    
    Ит = СоздатьОбъект("БухгалтерскиеИтоги");
    // Передаем ссылку на контрагента и договор напрямую
    Ит.ИспользоватьСубконто(ВидыСубконто.Контрагенты, Контрагент, 2);
    Если ПустоеЗначение(Договор) = 0 Тогда
        Ит.ИспользоватьСубконто(ВидыСубконто.Договоры, Договор, 2);
    КонецЕсли;
    
    // Выполняем запрос на текущую дату или дату документа
    Ит.ВыполнитьЗапрос(, ДатаДок, "62.1",,,,, "С");
    
    // СКД - дебетовое сальдо (долг покупателя), СКК - кредитовое сальдо (аванс)
    Взс = Ит.СКД() - Ит.СКК();
    Возврат Взс;
КонецФункции

Решение 2: Оптимальная выборка итогов для табличной части документа

Разберем правильный алгоритм работы с табличной частью документа. Чтобы избежать зависаний, запрос к итогам выполняется один раз до начала цикла с разворотом по договорам (флаг разворота равен 1). Внутри цикла выполняется только позиционирование по субконто с помощью метода ПолучитьСубконто():


Процедура ЗаполнитьЗадолженностьТабличнойЧасти()
    Перем Ит;
    
    Если ПустоеЗначение(Контрагент) = 1 Тогда
        Предупреждение("Не выбран контрагент в шапке документа!");
        Возврат;
    КонецЕсли;
    
    Ит = СоздатьОбъект("БухгалтерскиеИтоги");
    // Отбор по контрагенту из шапки (режим 2 - фиксированный отбор)
    Ит.ИспользоватьСубконто(ВидыСубконто.Контрагенты, Контрагент, 2);
    // Разворот по всем договорам (режим 1 - разворачивать выборку)
    Ит.ИспользоватьСубконто(ВидыСубконто.Договоры, , 1);
    
    // Выполняем запрос один раз на дату документа
    Если Ит.ВыполнитьЗапрос(, ДатаДок, "62.1") = 1 Тогда
        ВыбратьСтроки();
        Пока ПолучитьСтроку() = 1 Цикл
            Если ПустоеЗначение(Договор) = 0 Тогда
                // Позиционируемся на договоре из текущей строки
                Если Ит.ПолучитьСубконто(ВидыСубконто.Договоры, , Договор) = 1 Тогда
                    Задолженность = Ит.СКД() - Ит.СКК();
                Иначе
                    Задолженность = 0;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Решение 3: Отбор итогов по менеджеру без изменения плана счетов

Если менеджер хранится как реквизит в справочнике Договоры, для выборки сальдо по всем договорам конкретного менеджера сформируем список значений и передадим его в метод ИспользоватьСубконто():


Процедура ЗадолженностьПоМенеджеру()
    Перем СпрД, СписДоговоров, Ит, ОбщийДолг;
    
    Если ПустоеЗначение(Менеджер) = 1 Тогда
        Возврат;
    КонецЕсли;
    
    // Заполняем список договоров нужного менеджера
    СписДоговоров = СоздатьОбъект("СписокЗначений");
    СпрД = СоздатьОбъект("Справочник.Договоры");
    СпрД.ВыбратьЭлементы();
    Пока СпрД.ПолучитьЭлемент() = 1 Цикл
        Если СпрД.Менеджер = Менеджер Тогда
            СписДоговоров.ДобавитьЗначение(СпрД.ТекущийЭлемент());
        КонецЕсли;
    КонецЦикла;
    
    Ит = СоздатьОбъект("БухгалтерскиеИтоги");
    // Передаем СписокЗначений во второй параметр для отбора по списку
    Ит.ИспользоватьСубконто(ВидыСубконто.Договоры, СписДоговоров, 2);
    Ит.ВыполнитьЗапрос(, ТекущаяДата(), "62.1");
    
    ОбщийДолг = Ит.СКД() - Ит.СКК();
    Сообщить("Сумма задолженности по менеджеру: " + ОбщийДолг);
КонецПроцедуры
← На главную