При автоматизации производственного учета на базе конфигураций 1С (например, 1С:УПП или 1С:ERP) часто возникает классическая задача: распределить имеющиеся на складах свободные остатки материалов по запланированному выпуску продукции. Проблема существенно усложняется, если изделия имеют многоуровневую структуру спецификаций (полуфабрикаты изготавливаются из других полуфабрикатов), а один и тот же материал встречается несколько раз на разных уровнях вложенности.
Рассмотрим причину возникновения этой проблемы и разберем архитектурно правильные алгоритмы её решения.
Проанализируем классический подход разузлования спецификации от готового изделия (уровень 0) к сырью. Если спускаться по дереву спецификации сверху вниз и вычитать остатки материалов по мере их обнаружения на текущем уровне, мы неизбежно столкнемся с логической ошибкой.
Представим, что материал А используется на уровне 1 (в финальной сборке) и на уровне 5 (при производстве базового полуфабриката). Технологически изготовление полуфабриката на уровне 5 должно произойти раньше, чем сборка готового изделия. Если мы спишем складской остаток материала А на уровне 1, то на уровне 5 возникнет дефицит. В результате производство не сможет даже начать изготовление базовых деталей, и вся цепочка остановится.
С точки зрения теории графов многоуровневая спецификация представляет собой не простое дерево, а ориентированный ациклический граф (DAG). Складские остатки необходимо распределять с учетом хронологической последовательности потребления и технологических приоритетов.
Это наилучший и самый практичный способ решения задачи. Разберем его по шагам:
ДатаПотребности.[ПриоритетЗаказа] -> [ДатаПотребности (возрастание)] -> [УровеньВложенности (убывание)]
Рассмотрим пример реализации сортировки плоской таблицы потребностей в коде 1С:
// Формируем структуру колонок таблицы потребностей
ТЗПотребностей = Новый ТаблицаЗначений;
ТЗПотребностей.Колонки.Добавить("Заказ", Новый ОписаниеТипов("ДокументСсылка.ЗаказПокупателя"));
ТЗПотребностей.Колонки.Добавить("ПриоритетЗаказа", Новый ОписаниеТипов("Число"));
ТЗПотребностей.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗПотребностей.Колонки.Добавить("КоличествоПотребность", Новый ОписаниеТипов("Число"));
ТЗПотребностей.Колонки.Добавить("ДатаПотребности", Новый ОписаниеТипов("Дата"));
ТЗПотребностей.Колонки.Добавить("УровеньВложенности", Новый ОписаниеТипов("Число"));
// Сортируем потребности: сначала ранние даты потребностей и более глубокие переделы
ТЗПотребностей.Сортировать("ПриоритетЗаказа Возр, ДатаПотребности Возр, УровеньВложенности Убыв");
В стандартах MRP II для корректной работы с графами спецификаций используется индекс Low-Level Code (LLC).
Выясним принцип его работы:
Благодаря этому материал гарантированно сначала выделяется на комплектацию самых нижних полуфабрикатов, и только необеспеченные остатки поднимаются на более высокие уровни сборки.
Частая ошибка при распределении сырья — игнорирование готовых полуфабрикатов, уже находящихся на складе. Если полуфабрикат уже произведен, разузловывать его и запрашивать под него исходные материалы не требуется.
Разберем двухпроходный алгоритм:
Пример алгоритмической обработки структуры в 1С при анализе полуфабрикатов:
Функция РазузловатьСУчетомОстатковПФ(НоменклатураУзла, КоличествоПотребное, СборкаОстатков)
// Проверяем остаток полуфабриката на складе
ОстатокПФ = ПолучитьОстатокНаСкладе(НоменклатураУзла, СборкаОстатков);
ОбеспеченоПФ = Мин(КоличествоПотребное, ОстатокПФ);
НеобходимыйВыпуск = КоличествоПотребное - ОбеспеченоПФ;
// Списываем использованный остаток полуфабриката
ЗафиксироватьРасчетОстатка(НоменклатураУзла, ОбеспеченоПФ, СборкаОстатков);
// Если готового полуфабриката не хватило — разузловываем его спецификацию дальше
Если НеобходимыйВыпуск > 0 Тогда
Спецификация = ПолучитьОсновнуюСпецификацию(НоменклатураУзла);
Для Каждого СтрокаСостава Из Спецификация.Состав Цикл
РазузловатьСУчетомОстатковПФ(СтрокаСостава.Номенклатура, СтрокаСостава.Количество * НеобходимыйВыпуск, СборкаОстатков);
КонецЦикла;
КонецЕсли;
КонецФункции
Для корректного распределения остатков материалов по многоуровневым спецификациям необходимо отказаться от простого сплошного списания материалов по дереву спецификации. Выберите подходящую методику: