Технология кэширования результата разузлования продукции по спецификации

10.06.19

Разработка - Механизмы типовых конфигураций

Рассматривается технология кэширования результата разузлования продукции по спецификации. Данная технология может оказаться полезной для значительного ускорения работы системы в части разузлования в конфигурациях УПП. Тестировалось на платформе 1С 8.3.12.1469, релизы УПП 1.2, 1.3.

Скачать исходный код

Наименование Файл Версия Размер
Технология кэширования результата разузлования продукции по спецификации:
.cf 15,36Kb
6
.cf 15,36Kb 6 Скачать

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

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

Очевидно, что для хранения и использования результата разузлования нужен регистр сведений.

В качестве измерений будут объект разузлования (Номенклатура, Характеристика) и спецификация.

Ресурс - таблица материалов, в которой будут храниться рассчитанные по спецификации материалы.

Однако выяснилось, что результат разузлования при расчете зависит еще и от параметров, таких как КоличествоУровнейРазузлования, ПараметрыВыпуска и т.д.

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

Регистр сведений КЭШ_Разузлование

Измерения:
- Номенклатура
- ХарактеристикаНоменклатуры
- Спецификация
- ХэшПараметров (
тип Строка, 100)

Ресурсы:
- ТаблицаМатериалов (
тип ХранилищеЗначения)



Т.е. в регистре хранится готовая таблица материалов для объекта разузлования по определенной спецификации и определенным параметрам расчета.

Перейдем к коду. Непосредственно разузлование продукции производится в УПП (1.2, 1.3) в общем модуле "РазузлованиеНоменклатуры" в функции "РазузловатьНоменклатуру"


Добавим в начале функции следующий код. Задача - получить хэш параметров разузлования. Причем из параметров необходимо исключить те параметры, которые не влияют на результат разузлования (например такой параметр как ДатаСпецификации). Также рекомендую добавить константу "ИспользоватьКэш", чтобы можно было регулировать использование данного механизма (пригодится при начальной отладке).

Функция РазузловатьНоменклатуру(Источник, Результат = Неопределено, Параметры = Неопределено) Экспорт

    Если Константы.ИспользоватьКэш.Получить() Тогда
       
        КопияПараметры = Новый Структура();
        Для Каждого Параметр Из Параметры Цикл

            // Исключаем параметры, не влияющие на результат разузлования
            Если Параметр.Ключ = "ДатаСпецификации" Тогда
                Продолжить;
            КонецЕсли;
            КопияПараметры.Вставить(Параметр.Ключ, Параметр.Значение);
        КонецЦикла;
        стрXML = СериализоватьОбъектXDTO(КопияПараметры);
        ХэшПараметров= ХэшПараметров(стрXML);


   КонецЕсли;


....      

Функции СериализоватьОбъектXDTO и ХэшПараметров содержатся в конфигурации, прилагаемой к статье.

В процессе разработки выяснилось, что таблицу материалов (результат разузлования) необходимо формировать из расчета на 1 шт объекта разузлования (чтобы в дальнейшем при разузловании например 30 штук продукции, просто умножить каждое количество материала из исходной таблицы на 30).
Для этого было принято решение,  если в данную функцию РазузловатьНоменклатуру передано количество продукции для разузлования не равное 1 (это определяется по параметру передаваемому в функцию Источник.Количество), выполнить вначале разузлование на 1 единицу и сохранить результат разузлования в наш регистр. Причем повторное разузлование не будет выполняться далее, т.к. эту же таблицу мы уже и сможем использовать (будет понятно ниже).

Т.е. добавляем к нашему коду следующее:
   

Если Источник.Количество <> 1 Тогда
            
            УжеРазузловано = Ложь;
            НаборЗаписей = РегистрыСведений.Кэш_Разузлование.СоздатьНаборЗаписей();
            НаборЗаписей.Отбор.Номенклатура.Установить(Источник.Номенклатура);
            НаборЗаписей.Отбор.ХарактеристикаНоменклатуры.Установить(Источник.ХарактеристикаНоменклатуры);
            НаборЗаписей.Отбор.Спецификация.Установить(Источник.Спецификация);
            НаборЗаписей.Отбор.ХэшПараметров.Установить(ХэшПараметров);
            НаборЗаписей.Прочитать();
            УжеРазузловано = (НаборЗаписей.Количество() <> 0);

              Если Не УжеРазузловано Тогда

                    // Создадим копии структур Источник и Параметры для расчета на 1 единицу
                    КопияИсточник= Новый Структура;
                    Для Каждого ЭлементСтруктуры Из Источник Цикл
                        КопияИсточник.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение);
                    КонецЦикла;
                    КопияПараметры = Новый Структура;
                    Для Каждого ЭлементСтруктуры Из Параметры Цикл
                        КопияПараметры.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение);
                    КонецЦикла;

                    // Вот здесь укажем что надо разузловать на 1 единицу объекта разузлования
                    КопияИсточник.Количество = 1;
                    // Выполним разузлование на 1 единицу (причем результат разузлования на 1 единицу
                    // будет записан в наш регистр в конце данной функции (это будет описано чуть ниже)
                    Рез = РазузловатьНоменклатуру(КопияИсточник, Результат, КопияПараметры);
            КонецЕсли;
          


И ниже собственно производим считывание из нашего регистра таблицы материалов (из расчета на 1 шт) для данного объекта разузлования по данной спецификации для данного набора параметров. Если таблица есть, выполним пересчет количества материалов в ней на переданное количество и возвратим таблицу материалов как результат разузлования.
    

  // Типовой код функции
        ИнициализацияПараметров(Параметры);
        ИнициализацияРезультатаРазузлования(Результат, Источник);
        
        МассивОшибок = Новый Массив;
        Уровень = 0;
        // Типовой код функции

        НаборЗаписей = РегистрыСведений.Кэш_Разузлование.СоздатьНаборЗаписей();

        НаборЗаписей.Отбор.Номенклатура.Установить(Источник.Номенклатура);
        НаборЗаписей.Отбор.ХарактеристикаНоменклатуры.Установить(Источник.ХарактеристикаНоменклатуры);
        НаборЗаписей.Отбор.Спецификация.Установить(Источник.Спецификация);
        НаборЗаписей.Отбор.ХэшПараметров.Установить(ХэшПараметров);
        НаборЗаписей.Прочитать();
        

        // Если есть таблица материалов ее и вернем
        Если НаборЗаписей.Количество() <> 0 Тогда
                ЗаписьРегистра = НаборЗаписей[0];
                ТаблицаРазузлования = ЗаписьРегистра.ТаблицаМатериалов.Получить();
                // Пересчитаем количество материалов
                Если Источник.Количество <> 1 Тогда
                    Для Каждого СтрМатериал Из ТаблицаРазузлования Цикл
                        СтрМатериал.Количество = СтрМатериал.Количество * Источник.Количество;
                    КонецЦикла;
                КонецЕсли;
                Результат.ИсходныеКомплектующие = ТаблицаРазузлования ;
                Возврат МассивОшибок;
         КонецЕсли;

Вот и все, осталось только в самом конце функции РазузловатьНоменклатуру (куда при данном алгоритме мы попадем только если разузлование еще не было выполнено) добавить код, записывающий в наш регистр сформированную таблицу материалов (на 1 шт).

........
 

     Если Константы.ИспользоватьКэш.Получить() И Источник.Количество = 1 И МассивОшибок.Количество() = 0 Тогда

             Менеджер = РегистрыСведений.Кэш_Разузлование.СоздатьМенеджерЗаписи();
             ЗаполнитьЗначенияСвойств(Менеджер, Источник);
             Менеджер.ТаблицаМатериалов = Новый ХранилищеЗначения(Результат.ИсходныеКомплектующие, Новый СжатиеДанных(9));
             Менеджер.ХэшПараметров = ХэшПараметров ;
             Менеджер.Записать();

        КонецЕсли;
    
        Возврат МассивОшибок;
    
КонецФункции


В результат функция РазузловатьНоменклатуру выглядит так:


Функция РазузловатьНоменклатуру(Источник, Результат = Неопределено, Параметры = Неопределено) Экспорт
    
    Если Константы.ИспользоватьКэш.Получить() Тогда
        
        КопияПараметры = Новый Структура();
        Для Каждого Параметр Из Параметры Цикл
            Если Параметр.Ключ = "ДатаСпецификации" Тогда
                Продолжить;
            КонецЕсли;
            КопияПараметры.Вставить(Параметр.Ключ, Параметр.Значение);
        КонецЦикла;
        
        стрXML = СериализоватьОбъектXDTO(КопияПараметры);
        ХэшПараметров = ХЭШ(стрXML);
        
        // разузлуем на 1 шт, чтобы потом взять из кэша
        Если Источник.Количество <> 1 Тогда
            
            УжеРазузловано = Ложь;
            НаборЗаписей = РегистрыСведений.Кэш_Разузлование.СоздатьНаборЗаписей();
            НаборЗаписей.Отбор.Номенклатура.Установить(Источник.Номенклатура);
            НаборЗаписей.Отбор.ХарактеристикаНоменклатуры.Установить(Источник.ХарактеристикаНоменклатуры);
            НаборЗаписей.Отбор.Спецификация.Установить(Источник.Спецификация);
            НаборЗаписей.Отбор.ХэшПараметров.Установить(ХэшПараметров);
            НаборЗаписей.Прочитать();
            УжеРазузловано = (НаборЗаписей.Количество() <> 0);
            
            Если Не УжеРазузловано Тогда
                
                // Создадим копии структур Источник и Параметры для расчета на 1 единицу
                КопияИсточник= Новый Структура;
                Для Каждого ЭлементСтруктуры Из Источник Цикл
                    КопияИсточник.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение);
                КонецЦикла;
                КопияПараметры = Новый Структура;
                Для Каждого ЭлементСтруктуры Из Параметры Цикл
                    КопияПараметры.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение);
                КонецЦикла;
                
                // Вот здесь укажем что надо разузловать на 1 единицу объекта разузлования
                КопияИсточник.Количество = 1;
                // Выполним разузлование на 1 единицу (причем результат разузлования на 1 единицу
                // будет записан в наш регистр в конце данной функции (это будет описано чуть ниже)
                Рез = РазузловатьНоменклатуру(КопияИсточник, Результат, КопияПараметры);
            КонецЕсли;
        КонецЕсли;
        
        // Типовой код УПП
        ИнициализацияПараметров(Параметры);
        ИнициализацияРезультатаРазузлования(Результат, Источник);
        
        МассивОшибок = Новый Массив;
        Уровень = 0;
        // Типовой код УПП
        
        
        НаборЗаписей = РегистрыСведений.Кэш_Разузлование.СоздатьНаборЗаписей();
        НаборЗаписей.Отбор.Номенклатура.Установить(Источник.Номенклатура);
        НаборЗаписей.Отбор.ХарактеристикаНоменклатуры.Установить(Источник.ХарактеристикаНоменклатуры);
        НаборЗаписей.Отбор.Спецификация.Установить(Источник.Спецификация);
        НаборЗаписей.Отбор.ХэшПараметров.Установить(ХэшПараметров);
        НаборЗаписей.Прочитать();
        
        // Если есть таблица материалов ее и вернем
        Если НаборЗаписей.Количество() <> 0 Тогда
            ЗаписьРегистра = НаборЗаписей[0];
            ТаблицаРазузлования = ЗаписьРегистра.ТаблицаМатериалов.Получить();
            // Пересчитаем количество материалов
            Если Источник.Количество <> 1 Тогда
                Для Каждого СтрМатериал Из ТаблицаРазузлования Цикл
                    СтрМатериал.Количество = СтрМатериал.Количество * Источник.Количество;
                КонецЦикла;
            КонецЕсли;
            Результат.ИсходныеКомплектующие = ТаблицаРазузлования ;
            Возврат МассивОшибок;
        КонецЕсли;        
        
    КонецЕсли;
    
    ИнициализацияПараметров(Параметры);
    ИнициализацияРезультатаРазузлования(Результат, Источник);
    
    МассивОшибок = Новый Массив;
    Уровень = 0;

    
    // типовой код УПП..
    // типовой код УПП..
    // типовой код УПП..
  
    
    // Запишем результат разузлования в регистр
    Если Константы.ИспользоватьКэш.Получить() И Источник.Количество = 1 И МассивОшибок.Количество() = 0 Тогда
        Менеджер = РегистрыСведений.Кэш_Разузлование.СоздатьМенеджерЗаписи();
        ЗаполнитьЗначенияСвойств(Менеджер, Источник);
        Менеджер.ТаблицаМатериалов = Новый ХранилищеЗначения(Результат.ИсходныеКомплектующие, Новый СжатиеДанных(9));
        Менеджер.ХэшПараметров = ХэшПараметров ;
        Менеджер.Записать();
    КонецЕсли;
    
    Возврат МассивОшибок;    
    
КонецФункции // ВыполнитьРазузлование()


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

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

Т.е. при изменении спецификации - очищаем все записи регистра по данной спецификации (выполняем в модуле справочника СпецификацииНоменклатуры).
При изменении узла спецификации - очищаем все записи регистра по данному узлу и по спецификации, в которой используется этот узел (выполняем в модуле справочника СпецификацииНоменклатуры).
При изменении свойства характеристики - очищаем все записи регистра по данной характеристике (выполняем в модуле набора записей регистра сведений ЗначенияСвойствОбъектов).

Это пожалуй самый "узкий" момент, т.к. ошибка здесь чревата получением некорректных данных из регистра. Но результат того стоит, поверьте))

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

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

УПП разузлование продукции спецификация кэширование производство производственный учет

См. также

Ценовая власть. Выносим из цикла схему СКД

Механизмы типовых конфигураций Ценообразование, анализ цен Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Абонемент ($m)

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

1 стартмани

11.04.2024    540    tango    0    

3

Формула в реквизите. Приквелл к сериалу "Ценовая власть"

Механизмы типовых конфигураций Платформа 1С v8.3 1С:Управление торговлей 11 Россия Абонемент ($m)

Какому-либо элементу списка сопоставляется числовое значение, зависящее от других значений, причем эта зависимость изменяется от элемента к элементу. Так, в справочнике "Валюты" курс какой-либо валюты может быть задан формулой (или даже запросом) от значения другой валюты. А в справочнике "Виды цен" формула определяет расчет цены для товарной позиции, т.е. элементов справочника "Номенклатура", у которых в карточке указан этот вид цены. А в 1С:ERP, например, этот механизм используется в ресурсной спецификации.

10 стартмани

11.04.2024    422    tango    5    

4

Ценовая власть. Второй сезон

Механизмы типовых конфигураций Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Бесплатно (free)

В первом сезоне мы рассмотрели (с точки зрения программиста) внутренний механизм, помещающий цены в регистр "Цены". Из этого регистра цена попадает в исходящие УПД (в продажи). Но эта цена (в прайс-листе) дифференцирована (ценообразована) в разрезах свойств самой номенклатуры. Но стратегия ценообразования, ценовая власть - это в первую очередь о работе с ценами для клиента. И тут вступает в дело второй акт марлезонского, Скидки (наценки) и кешбек.

08.04.2024    791    tango    0    

2

Ценовая власть (УТ 11.5) - 2

Механизмы типовых конфигураций Платформа 1С v8.3 1С:Управление торговлей 11 Бесплатно (free)

В прошлый раз специальной обработкой мы выбрали объекты УТ 1.5, группируя по подсистемам. Оказалось, что состав подсистем не вполне корректно отображает функциональную структуру, но зато мы нашли процедуру, которая, вроде бы, должна содержать в себе всё, что нас интересует. Обновление цен должно ведь следовать выбранной стратегии ценообразования, верно? Иначе что она обновляет...

06.04.2024    483    tango    1    

1

Ценовая власть или Управление ценообразованием (УТ 11.5)

Ценообразование, анализ цен Механизмы типовых конфигураций Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 11 Россия Управленческий учет Абонемент ($m)

Ценовая власть - это способность (возможность) компании изменять в некоторых пределах отпускную цену своего товара (услуг, продукции). Чем в более широких пределах вы можете играть в цену продажи, тем больше этой власти у вас. Если вы не можете управлять отпускной ценой, то это или не ваш бизнес, или не бизнес вовсе. Здесь в рубрике "База знаний аналитика и руководителя проекта" слово проект не ограничено "проектом в 1С". Посмотрим, что для этого есть в УТ 11.5.

1 стартмани

05.04.2024    599    tango    12    

2

Расширяем возможности дополнительных обработок и настраиваем их отладку

БСП (Библиотека стандартных подсистем) Механизмы типовых конфигураций Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Уже не одна веб-страница исписана знаниями о дополнительных обработках, как создать, как подключить. Есть масса вариантов, как их можно отладить. Я разобрался в кишках работы библиотеки и покажу, как можно расширить возможности дополнительных отчетов, а также покажу удобный способ отладки.

07.02.2024    2682    YA_418728146    11    

45

Регистры накопления в 1С:КА2 и 1С:ERP для расчета НДФЛ, страховых взносов и взаиморасчетов с сотрудниками на январь 2024 года. Краткое описание

Зарплата Механизмы типовых конфигураций Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Бухгалтерский учет НДФЛ Абонемент ($m)

Для расчета зарплаты и соответствующих налогов в конфигурациях 1С:КА2 и 1С:ERP используется 22 регистра накопления, 7 регистров сведений, 1 регистр расчета и бухгалтерские проводки. В таблице приведены названия этих регистров, указаны основные регистраторы и виды движений приход/расход. В описании приводится краткое функциональное назначение регистров в основных зарплатных процессах. Описание регистров родилось из черновиков при написании различных отчетов и обработок при эксплуатации 1С-овских конфигураций и исправлении ошибок по НДФЛ, взаиморасчетов с сотрудниками и прочих. Информация не претендует на полноценное описание работы регистров, скорее это дискуссионный материал. Но, возможно, кому-то пригодится и сократит время при подготовке отчетности за непростой (в плане учета зарплаты) 2023 год. А возможно, кто-то поделится своим опытом.

1 стартмани

10.01.2024    1213    8    2ncom    6    

8

Шаблоны новых объектов 1С для 1С:Бухгалтерии предприятия

Инструментарий разработчика БСП (Библиотека стандартных подсистем) Механизмы типовых конфигураций Платформа 1С v8.3 1С:Бухгалтерия 3.0 Бесплатно (free)

Используются для создания новых объектов в конфигурации, чтобы не забыть, что нужно сделать. Сделано на примере 1С:Бухгалтерия предприятия, в других конфигурациях могут быть другие, а могут быть и похожие объекты.

28.12.2023    5037    mrXoxot    11    

101
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Mkonst 57 01.03.19 08:26 Сейчас в теме
Не проще разузлование делать в несколько потоков, (ФоновыеЗадания использовать) ?
2. NoRazum 29 03.11.22 06:55 Сейчас в теме
Такое для ЕРП делал.
В УПП не стал реализовывать.
3. user1959620 15.06.23 13:59 Сейчас в теме
Как то сложно, мне удобнее так:

&НаКлиенте
Процедура ОткрытьСпецификацию(Команда)
ТСТЧ =Элементы.Список.ТекущиеДанные;
Если ТСТЧ<>Неопределено Тогда
Док = ВернутьСпецификацию(ТСТЧ.Ссылка);
ПараметрыФормы = Новый Структура("Ключ", Док);
ПараметрыФормы.Вставить("Изделие", ТСТЧ.Ссылка);
ОткрытьФорму("Документ.Спецификация.ФормаОбъекта", ПараметрыФормы, ЭтаФорма, УникальныйИдентификатор);
Иначе
Сообщить("Нужно установить курс на издетелие, по которому необходимо открыть спецификацию");
КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ВернутьСпецификацию(Изделие)
Возврат Документы.Спецификация.НайтиПоРеквизиту("Изделие", Изделие);
КонецФункции // ()

и в документе спецификация:

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