Как заполнить табличную часть материалов по спецификациям изделий в документе производства в 1С 8.3?

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

При разработке производственного контура часто возникает задача автоматического расчета и заполнения табличной части Материалы на основе списка готовой продукции из табличной части Изделия и заданных норм расхода (спецификаций). Разберем по шагам, как построить надежную клиент-серверную архитектуру заполнения, сформировать корректный запрос с расчетом количества и избежать типовых ошибок.

1. Клиентская логика и предупреждение пользователя

Проанализируем работу на форме документа. Перед перезаполнением табличной части рекомендуется предупреждать пользователя о том, что существующие строки будут очищены. На управляемых формах диалоговые окна открываются асинхронно с использованием объекта ОписаниеОповещения.

Посмотрим на пример организации обработчиков команды на клиенте:


&НаКлиенте
Процедура ЗаполнитьПоСпецификации(Команда)
    
    Если Объект.Материалы.Количество() > 0 Тогда
        ТекстВопроса = НСтр("ru = 'Перед заполнением табличная часть материалов будет очищена. Продолжить?'");
        Оповещение = Новый ОписаниеОповещения("ЗаполнитьПоСпецификацииЗавершение", ЭтотОбъект);
        ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
    Иначе
        ЗаполнитьПоСпецификацииНаСервере();
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьПоСпецификацииЗавершение(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        ЗаполнитьПоСпецификацииНаСервере();
    КонецЕсли;
    
КонецПроцедуры

2. Серверная обработка и работа с несохраненными данными

Выясним причину частой ошибки начинающих разработчиков: обращение в запросе напрямую к табличной части документа в базе данных через Документ.Производство.Изделия ГДЕ Ссылка = &Ссылка. Если пользователь создал новый документ или изменил строки в форме и нажал кнопку до записи объекта, такой запрос либо вернет пустой результат, либо прочитает устаревшие данные из базы.

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


&НаСервере
Процедура ЗаполнитьПоСпецификацииНаСервере()
    
    ТаблицаИзделий = Объект.Изделия.Выгрузить();
    
    // Если табличная часть изделий пуста, прерываем выполнение
    Если ТаблицаИзделий.Количество() = 0 Тогда
        Объект.Материалы.Очистить();
        Возврат;
    КонецЕсли;
    
    ТаблицаМатериалов = Документы.Производство.ПолучитьТаблицуМатериаловПоСпецификациям(ТаблицаИзделий);
    
    Объект.Материалы.Загрузить(ТаблицаМатериалов);
    
КонецПроцедуры

3. Формирование запроса и расчет количества материалов

Рассмотрим подробнее логику расчета в модуле менеджера документа. Нам необходимо:

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

Посмотрим на пример функции в модуле менеджера:


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

4. Архитектурные особенности и устранение ошибок

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

  1. Ограничение выборки в каждом блоке ОБЪЕДИНИТЬ ВСЕ: Если не добавить фильтрацию ГДЕ Спец.Ссылка В (...) в каждый блок выборки из справочников, СУБД выполнит полное сканирование таблиц (Table Scan), что приведет к сильному падению производительности при росте базы данных.
  2. Исключение задвоения количеств: В исходной таблице документа могут встречаться одинаковые изделия в разных строках. Предварительная группировка во временной таблице ВТ_ИзделияДокумента гарантирует корректный расчет произведения Количество * Норма без мультипликации строк при соединении.
  3. Индексация временных таблиц: Добавление директивы ИНДЕКСИРОВАТЬ ПО Изделие позволяет оптимизатору СУБД использовать эффективные алгоритмы соединения (например, Index Spool или Hash Match).
  4. Нормализация структуры метаданных: Создание отдельного справочника под каждый тип изделия усложняет доработку конфигурации. В типовых решениях 1С используется единый справочник Номенклатура с видами номенклатуры и дополнительными реквизитами, а также отдельный подчиненный справочник Спецификации номенклатуры, что позволяет вести многовариантные и многопередельные нормы без дублирования кода запросов.
← На главную