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