При разработке функционала автоматического резервирования или подбора материалов в 1С часто возникает задача: распределить доступные остатки резервов по строкам табличной части (ТЧ), где одна и та же номенклатура может встречаться несколько раз. Простая попытка поиска по первой найденной строке приводит к некорректным результатам, так как алгоритм должен «видеть» всю картину целиком и постепенно уменьшать доступный остаток при переходе от одной строки к другой.
Основная сложность заключается в том, что стандартный цикл Для каждого по строкам ТЧ работает изолированно для каждого прохода. Если вы просто ищете остатки через НайтиСтроки(), то на каждой итерации алгоритм будет видеть «полный» резерв, не учитывая то, что было списано в предыдущих строках. Чтобы решить эту задачу, нам необходимо использовать внешнее хранилище остатков или массив обработанных элементов, который позволит нам «запоминать» состояние распределения в процессе выполнения цикла.
Рассмотрим подход, при котором мы блокируем повторную обработку уже распределенной номенклатуры или же, наоборот, ведем счетчик доступного остатка для каждой позиции. Если ваша цель — заполнить резерв последовательно «сверху вниз» для всех дублей одной номенклатуры, воспользуйтесь методом контроля через массив. Рассмотрим подробнее этот алгоритм.
Для начала, создадим массив ОбработаннаяНоменклатура. В процессе прохода по циклу мы будем проверять, была ли уже обработана текущая позиция. Это особенно полезно, если вам нужно применить логику к группе строк или рассчитать общее распределение для номенклатуры.
ОбработаннаяНоменклатура = Новый Массив;
Для каждого СтрокаМатериала из ТаблицаСостава Цикл
Если ОбработаннаяНоменклатура.Найти(СтрокаМатериала.НоменклатураСостава) = Неопределено Тогда
// Здесь выполняется логика поиска остатков
// и распределение по всем найденным строкам с этой номенклатурой
ОбработаннаяНоменклатура.Добавить(СтрокаМатериала.НоменклатураСостава);
КонецЕсли;
КонецЦикла;
Более продвинутым и надежным способом является работа с «глобальным» остатком. Вместо обращения к таблице значений напрямую, мы выносим расчет доступного количества в переменную или объект Соответствие. Это позволит нам управлять распределением даже при наличии сотен повторяющихся строк.
ТЗРезервыПоЗаказам, где уже подсчитаны общие остатки в разрезе номенклатуры и характеристик.ТаблицаСостава вы будете вычитать из неё распределенное значение.Мин(). Она позволяет автоматически выбирать меньшее значение между «тем, что требуется по строке» и «тем, что осталось на складе/в резерве».Давайте разберем по шагам, как это должно выглядеть в коде:
// Предполагаем, что ТЗРезервыПоЗааказам уже содержит актуальные данные
Для каждого СтрокаМатериала из ТаблицаСостава Цикл
СтруктураПоиска = Новый Структура("НоменклатураСостава, ХарактеристикаСостава, ЗаказПокупателя",
СтрокаМатериала.НоменклатураСостава,
СтрокаМатериала.ХарактеристикаСостава,
СтрокаМатериала.ЗаказПокупателя);
МассивСтрок = ТЗРезервыПоЗааказам.НайтиСтроки(СтруктураПоиска);
Для каждого СтрокаОстаткаРезерва из МассивСтрок Цикл
ОстатокРезерваМатериала = СтрокаОстаткаРезерва.КоличествоРезервы - СтрокаОстаткаРезерва.Распределено;
Если ОстатокРезерваМатериала > 0 Тогда
КоличествоКРаспределению = Мин(ОстатокРезерваМатериала, СтрокаМатериала.КоличествоСостава - СтрокаМатериала.Резерв);
СтрокаМатериала.Резерв = СтрокаМатериала.Резерв + КоличествоКРаспределению;
СтрокаОстаткаРезерва.Распределено = СтрокаОстаткаРезерва.Распределено + КоличествоКРаспределению;
КонецЕсли;
// Прерываем, если потребность удовлетворена полностью
Если СтрокаМатериала.Резерв >= СтрокаМатериала.КоличествоСостава Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Проанализируем ситуацию с производительностью. Если таблица состава очень большая, метод НайтиСтроки() внутри цикла может существенно замедлить работу программы. Чтобы этого избежать, следуйте этим рекомендациям:
ТаблицаЗначений для хранения резервов, обязательно установите индексы на колонки, по которым идет поиск (Номенклатура, Характеристика). Это ускорит метод Найти() в десятки раз.Следуя этим простым правилам, вы сможете построить гибкую и масштабируемую систему автоматического распределения ресурсов в 1С. Помните, что ключ к успеху — это контроль остатков в режиме реального времени и четкое разделение этапов обработки данных.