Почему в 1С:Управление торговлей 11 не отображаются остатки по организации при использовании запросов к ключам аналитики?

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

При работе с современными конфигурациями на платформе 1С:Предприятие 8.3, такими как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация 2», разработчики часто сталкиваются с загадочным поведением запросов к остаткам. Типичная ситуация: запрос с использованием массива ссылок возвращает верные данные, а аналогичный запрос, использующий временную таблицу или вложенный подзапрос, показывает нулевые остатки. В этой статье мы подробно разберем, почему так происходит, что такое «невидимые» дубли ключей аналитики и как избежать подобных ошибок при доработке системы.

Суть проблемы: когда запрос «обманывает» разработчика

Рассмотрим ситуацию, с которой столкнулся автор темы. Имеется регистр накопления ТоварыОрганизаций. При выполнении прямого проверочного запроса, где в параметры виртуальной таблицы передается массив конкретных ссылок на справочник КлючиАналитикиУчетаНоменклатуры, остатки выбираются корректно:


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

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


"ВЫБРАТЬ
|    Остатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
|    РегистрНакопления.ТоварыОрганизаций.Остатки(&Граница, 
|        АналитикаУчетаНоменклатуры В (ВЫБРАТЬ ВТ.Аналитика ИЗ ВТОтборы КАК ВТ)) КАК Остатки";

На первый взгляд, логика идентична. Но именно здесь кроется ловушка, связанная с тем, как именно были получены данные для временной таблицы ВТОтборы в момент проведения документа или выполнения обработки.

Анализ механизма ключей аналитики в УТ 11

Для оптимизации хранения данных в УТ 11 используется справочник КлючиАналитикиУчетаНоменклатуры. Он объединяет в себе такие измерения, как Номенклатура, Характеристика, Склад, Серия и Назначение. Вместо того чтобы записывать все эти поля в каждый регистр накопления, система записывает одну ссылку на «ключ».

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

Проанализируем ситуацию: в системе уже существуют остатки на «старом» ключе аналитики. В момент проведения доработанного документа система пытается найти нужный ключ. Если в коде документа какой-то из реквизитов (например, «Назначение» или «Склад») был утерян или не заполнен, типовой механизм поиска ключа не находит соответствия и создает новый элемент справочника прямо в транзакции проведения.

Почему это происходит внутри транзакции?

Рассмотрим пошагово, что происходит в базе данных:

  1. Документ начинает проведение. Открывается транзакция.
  2. Программный код формирует движения. Происходит обращение к функции Справочники.КлючиАналитикиУчетаНоменклатуры.ПолучитьКлючАналитики().
  3. Из-за ошибки в доработке (например, очистки реквизита в объекте) функция не находит старый ключ и создает новый пустой ключ.
  4. Запрос внутри этой же транзакции обращается к остаткам по этому новому ключу.
  5. Поскольку на новом ключе еще никогда не было приходов (все остатки числятся за старым ключом), запрос возвращает 0.

Важно понимать: в отладчике вы можете видеть название номенклатуры и склада одинаковыми для обоих ключей, но для СУБД это разные ссылки. Автор темы подтвердил это, обнаружив, что ВерсияДанных у элементов отличается: AAAAAAADUF4= против AAAAAAACpnc=.

Рекомендации по написанию запросов к виртуальным таблицам

Посмотрим на пример запроса, который считается «плохим тоном» в 1С:


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

Использование вложенных запросов в параметрах виртуальных таблиц крайне не рекомендуется по следующим причинам:

Рассмотрим, как правильно организовать получение остатков:

  1. Сначала сформируйте временную таблицу с необходимыми отборами.
  2. Проиндексируйте поля, по которым будет идти соединение.
  3. Используйте ВНУТРЕННЕЕ СОЕДИНЕНИЕ с виртуальной таблицей остатков, передавая в параметры виртуальной таблицы только необходимые общие фильтры (например, Организация).

Пример правильного подхода:


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

Как избежать «дублей» ключей аналитики?

Чтобы не сталкиваться с ситуацией, когда остатки «висят» на одних ключах, а документ пытается списать их с других, следуйте этим правилам:

В завершение подчеркнем: если вы видите, что запрос по массиву работает, а по таблице — нет, первое, что нужно проверить, это соответствие ссылок (UUID). Помните, что визуальное сходство элементов справочника в интерфейсе 1С не гарантирует их идентичность в таблицах SQL.

← На главную