Почему не выбираются остатки по счету 10.07 в 1С:Бухгалтерии 3.0 и как правильно их получить программно

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

Проанализируем частую проблему при попытке получить остатки по счету 10.07 «Материалы, переданные в переработку на сторону» с помощью объектного метода РегистрыБухгалтерии.Хозрасчетный.Остатки(). Выясним, почему фильтр по конкретной номенклатуре может не возвращать данные, разберем типы ошибок при передаче параметров отбора и рассмотрим правильный способ через язык запросов.

Анализ исходного кода и причины возникновения проблемы

Рассмотрим пример кода, в котором при попытке наложить отбор по объекту Товар выборка остатков возвращается пустой:


ВидСубконтоОС = Новый Массив;
ВидСубконтоОС.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагент);
ВидСубконтоОС.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура);

Рег = РегистрыБухгалтерии.Хозрасчетный;
Отбор = Новый Структура("Субконто2, Организация, Счет", Товар, Организация, МойСчет);
Выборка = Рег.Остатки(мДата, ВидСубконтоОС, Отбор);

Если Выборка.Количество() > 0 Тогда
    Сообщить(Выборка[0].КоличествоОстатокДТ);
КонецЕсли;

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

  1. Передача дубля элемента справочника: Самая частая причина — передача в переменную Товар ссылки на элемент-дубль справочника Номенклатура. Наименования позиций могут полностью совпадать, но уникальные ссылки (UUID) в базе данных отличаются. Если движение по счету 10.07 прошло по одному элементу, а в отбор передается его дубль, остаток найден не будет.
  2. Зависимость порядка субконто от массива: В объектном методе Остатки() имена ключей структуры отбора (Субконто1, Субконто2 и т.д.) жестко связаны с порядком добавления элементов в массив ВидСубконтоОС. Поскольку первым в массив был добавлен Контрагент, ему соответствует Субконто1, а элементу Номенклатура — Субконто2. Если изменить порядок заполнения массива, сопоставление фильтра сломается.
  3. Влияние границы времени: При получении остатков на дату типа Дата (без указания времени или объекта Граница) расчет производится на самую раннюю секунду указанного дня (00:00:00). Проводки, сформированные в течение этого же дня, в остаток не войдут.

Ограничения объектного метода получения остатков

Разберем, почему использование объектного метода РегистрыБухгалтерии.Хозрасчетный.Остатки() не рекомендуется для решения практических задач в 1С:

  1. Отсутствие поддержки иерархии: Метод не позволяет выполнять отбор по папкам справочника (В ИЕРАРХИИ) или группам счетов. Потребуется только точное совпадение ссылки.
  2. Ограничения по сложности фильтрации: Объектный метод не поддерживает логические условия ИЛИ, проверки на НЕ РАВНО или фильтрацию по реквизитам субконто.
  3. Проблемы с производительностью в циклах: Вызов метода Остатки() внутри циклов приводит к генерации отдельного SQL-запроса на каждой итерации, что сильно замедляет работу программы.

Рекомендуемое решение: Использование языка запросов

Проанализируем стандартное и наиболее эффективное решение задачи — обращение к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки с помощью языка запросов.

Рассмотрим пример правильного написания кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ХозрасчетныйОстатки.Субконто1 КАК Контрагент,
    |	ХозрасчетныйОстатки.Субконто2 КАК Номенклатура,
    |	ХозрасчетныйОстатки.КоличествоОстатокДт КАК КоличествоОстаток
    |ИЗ
    |	РегистрБухгалтерии.Хозрасчетный.Остатки(
    |		&Период,
    |		Счет = &Счет,
    |		ПВХВидыСубконто,
    |		Организация = &Организация И Субконто2 = &Номенклатура) КАК ХозрасчетныйОстатки";

МассивВидовСубконто = Новый Массив;
МассивВидовСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагент);
МассивВидовСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура);

Запрос.УстановитьПараметр("Период", Новый Граница(КонецДня(мДата), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.МатериалыПереданныеНаСторону); // Счет 10.07
Запрос.УстановитьПараметр("ПВХВидыСубконто", МассивВидовСубконто);
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("Номенклатура", Товар);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить("Номенклатура: " + Выборка.Номенклатура + ", Остаток Дт: " + Выборка.КоличествоОстаток);
КонецЦикла;

В этом примере мы использовали объект Граница с видом ВидГраницы.Включая, чтобы точно учесть все документы на конец указанной даты. Запрос выполняется оптимально на стороне сервера СУБД и исключает ошибки, связанные с неправильной передачей имён субконто в структуре отбора.

← На главную