В производственных отраслевых конфигурациях (в частности, в полиграфии и производстве этикеточной продукции при ротационной высечке) часто возникает задача учета износа режущего инструмента. Разберем по шагам, как устроен этот механизм: где хранятся данные, по какой формуле рассчитывается наработка оснастки и как оптимизировать код чтения и записи движений.
Рассмотрим функцию, которая собирает итоговый пробег инструмента за указанный интервал времени. В исходном коде конфигурации использовался следующий запрос:
Функция ПодсчитатьПробег(НачалоИспользования, ОкончаниеИспользования);
ЗапросПробега = Новый Запрос("ВЫБРАТЬ
| ПробегНожей.Пробег
|ИЗ
| РегистрСведений.ПробегНожей КАК ПробегНожей
|ГДЕ
| ПробегНожей.Период МЕЖДУ &НачалоПериода И &КонецПериода
| И ПробегНожей.Нож = &Нож");
ЗапросПробега.УстановитьПараметр("НачалоПериода", НачалоИспользования);
ЗапросПробега.УстановитьПараметр("КонецПериода", ОкончаниеИспользования);
ЗапросПробега.УстановитьПараметр("Нож", Объект.Ссылка);
Выборка = ЗапросПробега.Выполнить().Выбрать();
Пробег = 0;
Пока Выборка.Следующий() Цикл
Пробег = Пробег + Выборка.Пробег;
КонецЦикла;
Возврат Пробег;
КонецФункции
Проанализируем работу этого алгоритма. Программа выбирает все записи из регистра сведений РегистрСведений.ПробегНожей, фильтруя их по конкретному инструменту и диапазону дат, после чего в цикле перебирает выборку и суммирует значения ресурса Пробег.
В данном фрагменте кода сразу видны узкие места:
Пока Выборка.Следующий() неоправданно расходует ресурсы сервера и память. СУБД выполняет агрегацию значительно быстрее.МЕЖДУ с датой окончания, не приведенной к концу дня через КонецДня(), приводит к потере документов, проведенных в течение последних суток периода.Оптимизируем данный запрос, переложив расчет суммы на сторону СУБД:
Функция ПодсчитатьПробег(НачалоИспользования, ОкончаниеИспользования)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕСТЬNULL(СУММА(ПробегНожей.Пробег), 0) КАК ОбщийПробег
|ИЗ
| РегистрСведений.ПробегНожей КАК ПробегНожей
|ГДЕ
| ПробегНожей.Период МЕЖДУ &НачалоПериода И &КонецПериода
| И ПробегНожей.Нож = &Нож";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоИспользования));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ОкончаниеИспользования));
Запрос.УстановитьПараметр("Нож", Объект.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.ОбщийПробег;
КонецЕсли;
Возврат 0;
КонецФункции
Чтобы понять, что именно физически означает числовое значение пробега, выясним причину появления записей в регистре. Для этого обратимся к модулю документа-регистратора (документа выпуска продукции или отчета производства за смену) в процедуру ОбработкаПроведения.
Формирование записи выглядит следующим образом:
// движения по регистру ножей
Если ЗначениеЗаполнено(Нож) Тогда
ВремТабДвиженияПробег = Движения.ПробегНожей.ВыгрузитьКолонки();
Движение = ВремТабДвиженияПробег.Добавить();
Движение.Период = Дата;
Движение.Регистратор = Ссылка;
Движение.Нож = Нож;
Движение.Пробег = Материалы.Итог("КоличествоФактическиИзрасходорванноеПогМ") / Нож.Раппорт * 1000;
Движения.ПробегНожей.Загрузить(ВремТабДвиженияПробег);
Движения.ПробегНожей.Записывать = Истина;
КонецЕсли;
Разберем математическую и отраслевую составляющую формулы:
Пробег = КоличествоФактическиИзрасходорванноеПогМ / Нож.Раппорт * 1000
Материалы в погонных метрах.3.175 — это стандартный шаг шестерни цилиндра в полиграфии ($1/8$ дюйма), где деление раппорта на 3,175 определяет количество зубьев ($Z$).Таким образом, пробег ножа измеряется не в километрах, а в количестве полных оборотов (ударов/оттисков) цилиндра, выполненных при прогоне указанного метража материала.
В коде проведения присутствуют критические ошибки и неоптимальные конструкции платформы 1С:
Раппорт, документ упадет с ошибкой времени выполнения.ВыгрузитьКолонки() и последующей загрузкой таблицы является антипаттерном. Она может затирать ранее добавленные строки и неэффективно использует память. Поле Регистратор заполнять вручную в коде не нужно — платформа назначает его автоматически.Перепишем блок формирования движений по стандартам разработки 1С:
Если ЗначениеЗаполнено(Нож) Тогда
Если Нож.Раппорт = 0 Тогда
ВызватьИсключение "Для ножа """ + Строка(Нож) + """ не указан раппорт! Проведение невозможно.";
КонецЕсли;
// Корректное добавление движения напрямую в коллекцию
Движение = Движения.ПробегНожей.Добавить();
Движение.Период = Дата;
Движение.Нож = Нож;
// Расчет количества оборотов (ударов) инструмента
РасходМетров = Материалы.Итог("КоличествоФактическиИзрасходорванноеПогМ");
Движение.Пробег = (РасходМетров * 1000) / Нож.Раппорт;
КонецЕсли;
Использование подчиненного регистра сведений для накопления числовых показателей — архитектурный компромисс. С ростом базы данных суммирование записей по регистру сведений за большие интервалы времени будет замедляться, так как таблица не хранит агрегированных итогов.
Для правильного учета наработки оборудования рекомендуется использовать Регистр накопления:
Обороты.