Как правильно получить список зарезервированных товаров по заказам покупателей в 1С:УНФ с помощью запроса?

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

При работе в 1С:Управление нашей фирмой (УНФ) часто возникает необходимость проанализировать, какие товары уже зарезервированы под конкретные заказы покупателей. Это позволяет контролировать доступность товаров, планировать отгрузки и избегать ситуаций, когда один и тот же товар пытаются продать дважды. Однако корректное формирование запроса к данным о резервах может вызвать вопросы, особенно у тех, кто только начинает работать с этим механизмом. В этой статье мы подробно разберем, как эффективно и правильно построить запрос для получения информации о резервах товаров в 1С:УНФ.

Мы вместе рассмотрим механизм резервирования, проанализируем распространенные ошибки в запросах и выясним, как использовать возможности платформы 1С для получения точных и актуальных данных.

Понимание механизма резервирования в 1С:УНФ

Прежде чем мы перейдем к технической части, давайте разберемся, что такое резервирование запасов в 1С:УНФ и для чего оно нужно. Этот механизм позволяет временно закрепить определенное количество товара за конкретным документом, чаще всего это ЗаказПокупателя. Это предотвращает продажу или использование данного товара в других операциях, гарантируя его наличие для выполнения обязательств перед клиентом.

Основные аспекты работы резервов:

  1. Назначение резервов: Резервирование критически важно для позаказного производства, обеспечения выполнения обязательств по предоплаченным заказам или при работе с дефицитными товарами.
  2. Включение функционала: Для использования резервов необходимо активировать соответствующую настройку в системе. Обычно это делается через раздел "Настройки" — "Еще больше возможностей" — "Склад" — "Резервирование запасов".
  3. Способы резервирования:
    • В документе ЗаказПокупателя: Вы можете вручную указать количество в колонке "В резерв" или использовать команду "Заполнить в резерв по свободным остаткам". Резерв формируется на дату заказа при наличии товара на складе.
    • Через ЗаказПоставщику и ПриходнуюНакладную: Если товар закупается под конкретный заказ, он может быть автоматически зарезервирован при поступлении на склад.
    • Документом РезервированиеЗапасов: Этот документ используется, если резерв устанавливается отдельно от заказа покупателя, например, когда товар уже поступил на склад, а заказ был оформлен ранее.
    • Через ЗаказНаПроизводство: Для готовой продукции собственного производства.
  4. Контроль остатков: Система 1С:УНФ осуществляет контроль наличия товаров. Если запасов недостаточно для резервирования, документ не будет проведен или вы получите соответствующее сообщение об ошибке.

Основы работы с запросами к резервам: Виртуальные таблицы остатков

Для получения актуальной информации об остатках и резервах в 1С мы будем использовать виртуальные таблицы остатков регистра накопления. В нашем случае это будет РегистрНакопления.РезервыТоваровОрганизаций.Остатки. Давайте рассмотрим подробнее, как они работают.

Виртуальные таблицы остатков:

Разбираем некорректный запрос и ищем ошибки

Давайте проанализируем пример запроса, с которым возникли сложности, и выясним, в чем заключались его недочеты. Это поможет нам лучше понять логику построения правильного запроса.

Исходный запрос выглядел так:


Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
|   РезервыТоваровОрганизацийОстатки.ЗаказПокупателя КАК Заказ,
|   ЗаказПокупателяТест.Дата КАК ДатаОтгрузки,
|   ЗаказПокупателяТест.Контрагент КАК Контрагент,
|   РезервыТоваровОрганизацийОстатки.КоличествоОстаток КАК Резерв
|ИЗ
|   РегистрНакопления.РезервыТоваровОрганизаций.Остатки(&Период, Номенклатура = &Номенклатура) КАК РезервыТоваровОрганизацийОстатки
|   ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя КАК ЗаказПокупателяТест
|   ПО РезервыТоваровОрганизацийОстатки.ЗаказПокупателя = ЗаказПокупателяТест.Ссылка
|ГДЕ
|   ЗаказПокупателяТест.Ссылка <> &ЗаказПокупателяСсылка
|   И ЗаказПокупателяТест.ПометкаУдаления = ЛОЖЬ
|   И РезервыТоваровОрганизацийОстатки.КоличествоОстаток <> 0
|   И ЗаказПокупателяТест.Проведен = ИСТИНА";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ЗаказПокупателяСсылка", ЗаказПокупателяСсылка);
Запрос.УстановитьПараметр("Период", ТекущаяДата());

Мы видим несколько моментов, которые требовали доработки:

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

Правильное решение: Оптимизированный запрос к резервам

Теперь, когда мы выяснили причины проблем, давайте построим корректный и оптимизированный запрос. Мы будем использовать виртуальную таблицу остатков и обращение к реквизитам "через точку".

Шаг 1: Создаем новый объект запроса.


Запрос = Новый Запрос;

Шаг 2: Формируем текст запроса.

В тексте запроса мы сразу обращаемся к виртуальной таблице РегистрНакопления.РезервыТоваровОрганизаций.Остатки. Обратите внимание, что мы передаем условия отбора по &Период и Номенклатура = &Номенклатура непосредственно в параметры виртуальной таблицы. Это позволяет платформе сразу отфильтровать данные, прежде чем они будут переданы в основной запрос.

Далее, для получения данных из документа ЗаказПокупателя, который является измерением регистра, мы используем обращение "через точку": Резервы.ЗаказПокупателя.Дата и Резервы.ЗаказПокупателя.Контрагент. Это делает запрос более лаконичным и читаемым.

В секции ГДЕ мы добавляем условия для исключения текущего заказа (если это требуется), а также для отбора только проведенных документов и ненулевых остатков.


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

Шаг 3: Устанавливаем параметры запроса.

Здесь мы используем корректное значение для параметра &Период, как мы обсуждали ранее, чтобы учесть все движения за текущий день. Также мы передаем значения для &Номенклатура и &ЗаказПокупателяСсылка.


Запрос.УстановитьПараметр("Период", КонецДня(ТекущаяДата()) + 1);
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ЗаказПокупателяСсылка", ЗаказПокупателяСсылка);

Шаг 4: Выполняем запрос и получаем результат.

И, конечно, не забываем вызвать метод Выполнить() и выгрузить результат, например, в таблицу значений.


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

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


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

Запрос.УстановитьПараметр("Период", КонецДня(ТекущаяДата()) + 1);
Запрос.УстановитьПараметр("Номенклатура", Номенклатура); // Номенклатура - это переменная, содержащая ссылку на элемент справочника Номенклатура
Запрос.УстановитьПараметр("ЗаказПокупателяСсылка", ЗаказПокупателяСсылка); // ЗаказПокупателяСсылка - это переменная, содержащая ссылку на текущий ЗаказПокупателя, который нужно исключить

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

Дополнительные рекомендации и важные аспекты

Давайте рассмотрим несколько дополнительных рекомендаций и возможных проблем, которые могут возникнуть при работе с резервами и запросами к ним.

  1. Фильтрация по проведенным документам и ненулевым остаткам: Мы уже включили эти условия в наш запрос (Резервы.ЗаказПокупателя.Проведен = ИСТИНА и Резервы.КоличествоОстаток <> 0). Это крайне важно, чтобы получать только актуальные и значимые данные, игнорируя черновики или полностью отгруженные резервы.
  2. Исключение текущего документа: Если ваша цель — увидеть резервы, установленные *другими* документами, помимо текущего, условие Резервы.ЗаказПокупателя.Ссылка <> &ЗаказПокупателяСсылка является обязательным. Это позволяет избежать циклического учета или неверного отображения данных.
  3. Ошибки резервирования:
    • Двойное резервирование: Иногда товар может быть ошибочно зарезервирован дважды, например, сначала в ЗаказеПокупателя, а затем повторно при поступлении через ПриходнуюНакладную, если настройки не позволяют автоматическое связывание.
    • Некорректное списание из резерва: Ошибки при списании товаров из резерва могут привести к тому, что в отчетах будут отображаться зарезервированные товары, которых фактически нет на складе, или наоборот.
  4. Отчетность по резервам: Помимо запросов, мы можем использовать стандартные отчеты 1С:УНФ для анализа резервов. Например, отчеты "Остатки товаров на складах" или "Резервы по заказу" могут предоставить наглядную информацию. В этих отчетах часто можно расшифровать данные, чтобы увидеть, каким именно документом зарезервирован товар.

Таким образом, для корректной работы с запросами по резервам в 1С:УНФ необходимо глубоко понимать механизм резервирования, правильно использовать виртуальные таблицы остатков, особенно их параметр &Период с учетом особенностей расчета "на начало секунды", и применять эффективные методы обращения к данным, такие как "запрос через точку". Используя эти знания, вы сможете получать точную и полную информацию о резервах товаров.

← К списку