Проанализируем частую проблему при попытке получить остатки по счету 10.07 «Материалы, переданные в переработку на сторону» с помощью объектного метода РегистрыБухгалтерии.Хозрасчетный.Остатки(). Выясним, почему фильтр по конкретной номенклатуре может не возвращать данные, разберем типы ошибок при передаче параметров отбора и рассмотрим правильный способ через язык запросов.
Рассмотрим пример кода, в котором при попытке наложить отбор по объекту Товар выборка остатков возвращается пустой:
ВидСубконтоОС = Новый Массив;
ВидСубконтоОС.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагент);
ВидСубконтоОС.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура);
Рег = РегистрыБухгалтерии.Хозрасчетный;
Отбор = Новый Структура("Субконто2, Организация, Счет", Товар, Организация, МойСчет);
Выборка = Рег.Остатки(мДата, ВидСубконтоОС, Отбор);
Если Выборка.Количество() > 0 Тогда
Сообщить(Выборка[0].КоличествоОстатокДТ);
КонецЕсли;
При этом, если убрать отбор по номенклатуре (или вывести всю таблицу остатков), нужная номенклатурная позиция и остаток по ней присутствуют в выборке. Посмотрим на основные причины такого поведения:
Товар ссылки на элемент-дубль справочника Номенклатура. Наименования позиций могут полностью совпадать, но уникальные ссылки (UUID) в базе данных отличаются. Если движение по счету 10.07 прошло по одному элементу, а в отбор передается его дубль, остаток найден не будет.Остатки() имена ключей структуры отбора (Субконто1, Субконто2 и т.д.) жестко связаны с порядком добавления элементов в массив ВидСубконтоОС. Поскольку первым в массив был добавлен Контрагент, ему соответствует Субконто1, а элементу Номенклатура — Субконто2. Если изменить порядок заполнения массива, сопоставление фильтра сломается.Дата (без указания времени или объекта Граница) расчет производится на самую раннюю секунду указанного дня (00:00:00). Проводки, сформированные в течение этого же дня, в остаток не войдут.Разберем, почему использование объектного метода РегистрыБухгалтерии.Хозрасчетный.Остатки() не рекомендуется для решения практических задач в 1С:
В ИЕРАРХИИ) или группам счетов. Потребуется только точное совпадение ссылки.ИЛИ, проверки на НЕ РАВНО или фильтрацию по реквизитам субконто.Остатки() внутри циклов приводит к генерации отдельного SQL-запроса на каждой итерации, что сильно замедляет работу программы.Проанализируем стандартное и наиболее эффективное решение задачи — обращение к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки с помощью языка запросов.
Рассмотрим пример правильного написания кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Субконто1 КАК Контрагент,
| ХозрасчетныйОстатки.Субконто2 КАК Номенклатура,
| ХозрасчетныйОстатки.КоличествоОстатокДт КАК КоличествоОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(
| &Период,
| Счет = &Счет,
| ПВХВидыСубконто,
| Организация = &Организация И Субконто2 = &Номенклатура) КАК ХозрасчетныйОстатки";
МассивВидовСубконто = Новый Массив;
МассивВидовСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагент);
МассивВидовСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура);
Запрос.УстановитьПараметр("Период", Новый Граница(КонецДня(мДата), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.МатериалыПереданныеНаСторону); // Счет 10.07
Запрос.УстановитьПараметр("ПВХВидыСубконто", МассивВидовСубконто);
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("Номенклатура", Товар);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Номенклатура: " + Выборка.Номенклатура + ", Остаток Дт: " + Выборка.КоличествоОстаток);
КонецЦикла;
В этом примере мы использовали объект Граница с видом ВидГраницы.Включая, чтобы точно учесть все документы на конец указанной даты. Запрос выполняется оптимально на стороне сервера СУБД и исключает ошибки, связанные с неправильной передачей имён субконто в структуре отбора.