Как правильно получить состав спецификации и остатки комплектующих в запросе 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

Анализ исходной проблемы и технических ошибок в коде

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


ВЫБРАТЬ ПЕРВЫЕ 1
    ЗаданиеНаПроизводствоВыпускТехПроцесс.Спецификация
ПОМЕСТИТЬ ВТ_Спецификации
ИЗ
    Документ.ЗаданиеНаПроизводство.ВыпускТехПроцесс КАК ЗаданиеНаПроизводствоВыпускТехПроцесс
ГДЕ
    ЗаданиеНаПроизводствоВыпускТехПроцесс.Номенклатура = &Номенклатура
    И ЗаданиеНаПроизводствоВыпускТехПроцесс.НоменклатурнаяГруппа = &НоменклатурнаяГруппа
СГРУППИРОВАТЬ ПО
    ЗаданиеНаПроизводствоВыпускТехПроцесс.Спецификация,
    ЗаданиеНаПроизводствоВыпускТехПроцесс.НоменклатурнаяГруппа;

Первая критическая ошибка здесь — использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 без секции УПОРЯДОЧИТЬ ПО. В системе 1С (и в SQL в целом) без явной сортировки порядок записей не гарантирован. Это означает, что запрос вернет «первую попавшуюся» спецификацию из базы данных, которая может оказаться неактуальной, пустой или не соответствующей последнему производственному заданию. Если вам нужна последняя спецификация, обязательно добавляйте упорядочивание по дате или ссылке документа.

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

Проблема соединений и обработки пустых значений

Когда мы переходим ко второму этапу — получению комплектующих из справочника — важно правильно настроить связи между таблицами. Рассмотрим, как исправить соединение с табличной частью спецификации:


ВЫБРАТЬ
    ВТ_Спецификации.Спецификация,
    ИсходныеКомплектующие.Номенклатура,
    СУММА(ЕСТЬNULL(ИсходныеКомплектующие.Количество, 0)) КАК Количество
ПОМЕСТИТЬ ВТ_ИсходКомплект
ИЗ
    ВТ_Спецификации КАК ВТ_Спецификации
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК ИсходныеКомплектующие
        ПО ВТ_Спецификации.Спецификация = ИсходныеКомплектующие.Ссылка
СГРУППИРОВАТЬ ПО
    ИсходныеКомплектующие.Номенклатура,
    ВТ_Спецификации.Спецификация;

При использовании ВНУТРЕННЕГО СОЕДИНЕНИЯ (ВНУТРЕННЕЕ СОЕДИНЕНИЕ) функция ЕСТЬNULL в секции суммы технически не нужна, так как строки, для которых в справочнике нет комплектующих, просто не попадут в результат. Однако она становится критически важной на следующем этапе — при левом соединении с остатками.

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

Правильный подход: всегда выбирайте «ведущие» поля (наименование, спецификацию) из основной таблицы (ВТ_ИсходКомплект), а числовые показатели из таблицы остатков оборачивайте в ЕСТЬNULL(..., 0).

Главная проблема: Вложенные спецификации (Разузлование)

Часто выясняется, что «Поддон», который мы хотим произвести, состоит не из «Досок» и «Гвоздей», а из «Поддона неокрашенного», который сам является полуфабрикатом со своей спецификацией. Это называется многоуровневой спецификацией.

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

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

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

Для того чтобы запрос работал быстро и корректно, условия по складу и номенклатуре следует передавать непосредственно в параметры виртуальной таблицы, а не в секцию ГДЕ. Проанализируем правильную структуру финального запроса:


ВЫБРАТЬ
    ВТ_ИсходКомплект.Спецификация КАК Спецификация,
    ВТ_ИсходКомплект.Номенклатура КАК Номенклатура,
    ВТ_ИсходКомплект.Количество КАК ТребуемоеКоличество,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК ОстатокНаСкладе
ИЗ
    ВТ_ИсходКомплект КАК ВТ_ИсходКомплект
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, 
            Склад = &Склад 
            И Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ВТ_ИсходКомплект)
        ) КАК Остатки
        ПО ВТ_ИсходКомплект.Номенклатура = Остатки.Номенклатура

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

Итоговые рекомендации

Подведем итог. Чтобы ваш запрос к спецификациям отрабатывал корректно, придерживайтесь следующих правил:

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

← На главную