Адресное хранение (WMS — Warehouse Management System) — это одна из наиболее интересных и комплексных задач в сфере автоматизации складской логистики. Часто подобные задачи встречаются не только в реальной практике при внедрении учетных систем на крупных предприятиях, но и на экзаменах по платформе «1С:Специалист». Разработчику необходимо не просто создать структуру таблиц, но и заложить эффективные математические алгоритмы для быстрого размещения, отбора и перемещения товаров.
В этой статье мы подробно разберем, как спроектировать оптимальную структуру метаданных в 1С и реализовать ключевые алгоритмы адресного склада: приемку с минимизацией мест хранения, отпуск товаров по оптимальному маршруту обхода, процедуру автоматического уплотнения склада и построение отчета по его загруженности во времени.
Прежде чем приступать к написанию кода, проанализируем требования к структуре хранения данных. Нам необходимо фиксировать физическое расположение каждого товара на складе. Склад состоит из стеллажей, которые делятся на ряды (секции), вертикальные стойки (позиции по горизонтали) и ярусы (уровни по вертикали). Такое деление позволяет однозначно идентифицировать каждую ячейку координатами типа SS-NN-LL (Ряд-Стойка-Ярус).
Для реализации этой топологии создадим следующую структуру объектов конфигурации:
КоэффициентПалетирования. Этот показатель определяет, какое количество единиц конкретного товара полностью заполняет одну стандартную паллету (место хранения).Ряд (Число), Стойка (Число), Ярус (Число). Раздельное хранение координат в виде чисел критически важно для выполнения выборочной инвентаризации по определенному ярусу или ряду.ПорядокОбхода (Число). Этот реквизит задает физическую последовательность обхода ячеек кладовщиком при отборе товара, что позволяет строить оптимальный маршрут движения по складу.Ячейка (Тип: СправочникСсылка.ЯчейкиСклада).Номенклатура (Тип: СправочникСсылка.Номенклатура).Количество (Тип: Число).Рассмотрим важное правило адресного склада, которое мы будем использовать в дальнейших алгоритмах: монотоварность ячеек. В одной конкретной ячейке в каждый момент времени может находиться только один вид товара (SKU). При этом общее количество товара в ячейке не может превышать его КоэффициентПалетирования (вместимость одной паллеты).
Основная задача алгоритма приемки — занять как можно меньше свободных мест на складе, максимально уплотняя хранение. Выясним причину, почему нельзя просто складывать весь пришедший товар на первые попавшиеся пустые места. Если мы будем так делать, склад быстро заполнится полупустыми паллетами, и новые поступления разместить не удастся.
Рассмотрим пошагово оптимальный алгоритм размещения при проведении документа «Прием товара»:
Количество < КоэффициентПалетирования).КоэффициентПалетирования.ПозицииТовара равен нулю). Мы делим оставшийся объем товара на величину КоэффициентПалетирования. Полные паллеты размещаем в пустые ячейки. Дробный остаток (если он есть) кладем в еще одну свободную ячейку.Проанализируем пример программной реализации этого алгоритма в модуле проведения документа «Прием товара»:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Запрос для получения текущих неполных ячеек с таким же товаром
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПозицииТовараОстатки.Ячейка КАК Ячейка,
| ПозицииТовараОстатки.Номенклатура КАК Номенклатура,
| ПозицииТовараОстатки.КоличествоОстаток КАК КоличествоОстаток,
| ПозицииТовараОстатки.Номенклатура.КоэффициентПалетирования КАК КП
|ИЗ
| РегистрНакопления.ПозицииТовара.Остатки(&МоментВремени, Номенклатура В (&СписокТоваров)) КАК ПозицииТовараОстатки
|ГДЕ
| ПозицииТовараОстатки.КоличествоОстаток < ПозицииТовараОстатки.Номенклатура.КоэффициентПалетирования
|УПОРЯДОЧИТЬ ПО
| КоличествоОстаток УБЫВАЮЩИЙ"; // Сначала заполняем самые полные
// Нам также понадобится список полностью свободных ячеек
ЗапросСвободных = Новый Запрос;
ЗапросСвободных.Текст =
"ВЫБРАТЬ
| Ячейки.Ссылка КАК Ячейка
|ИЗ
| Справочник.ЯчейкиСклада КАК Ячейки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПозицииТовара.Остатки(&МоментВремени, ) КАК Остатки
| ПО Ячейки.Ссылка = Остатки.Ячейка
|ГДЕ
| Остатки.Ячейка ЕСТЬ NULL";
КонецПроцедуры
Используя результаты этих двух запросов, мы можем последовательно распределить весь объем поступившей номенклатуры в цикле, сначала заполняя имеющиеся остатки, а затем занимая пустые ячейки. Движения записываются в регистр ПозицииТовара со знаком плюс (приход).
При отпуске товара со склада перед нами стоят две задачи:
Рассмотрим пошагово, как реализовать этот алгоритм:
КоличествоОстаток Возрастающий). Это позволит нам в первую очередь списывать товары из малозаполненных ячеек, тем самым полностью освобождая места хранения для будущих приемок.ПозицииТовара.ЯчейкиСклада и сортируем по полю ПорядокОбхода. Эта упорядоченная таблица выводится в печатную форму накладной.Посмотрим на пример запроса для построения печатной формы задания на отбор:
ЗапросМаршрута = Новый Запрос;
ЗапросМаршрута.Текст =
"ВЫБРАТЬ
| ВременнаяТаблицаСписания.Номенклатура КАК Номенклатура,
| ВременнаяТаблицаСписания.Ячейка КАК Ячейка,
| ВременнаяТаблицаСписания.Количество КАК Количество,
| ВременнаяТаблицаСписания.Ячейка.ПорядокОбхода КАК ПорядокОбхода
|ИЗ
| &ТаблицаСписания КАК ВременнаяТаблицаСписания
|УПОРЯДОЧИТЬ ПО
| ПорядокОбхода ВОЗРАСТАЮЩИЙ";
Такой подход гарантирует, что сборщик склада пройдет по рядам строго по оптимальной траектории, тратя минимум времени на перемещения.
Со временем склад неизбежно фрагментируется: появляется множество ячеек, заполненных лишь частично. Процедура «Уплотнение» позволяет объединить остатки одинаковых товаров и высвободить максимальное количество мест хранения. Ее можно реализовать в виде регламентного задания или интерактивной обработки для начальника склада.
Разберем логику работы алгоритма уплотнения:
КоэффициентПалетирования.КоэффициентПалетирования, мы выбираем следующую неполную ячейку в качестве приемника.Этот алгоритм позволяет держать склад в оптимальном состоянии и избегать ложных ситуаций «склад забит, некуда принимать товар», когда фактически занято много мест, но общий объем товаров невелик.
Для эффективного управления складом руководству необходима наглядная информация о динамике его использования. Нам нужно построить временную диаграмму, которая показывает процент загруженности склада по дням.
Выясним математическую суть показателя загруженности:
Процент загруженности = (Количество занятых ячеек / Общее количество ячеек на складе) * 100%
Ячейка считается занятой, если в ней находится любое количество любого товара (остаток в регистре ПозицииТовара больше нуля). Общее количество ячеек — это общее число записей в справочнике ЯчейкиСклада.
Для реализации этого отчета в Системе компоновки данных (СКД) выполним следующие шаги:
ОстаткиИОбороты или соединение с календарем).В результате мы получим наглядный график, отражающий реальную динамику использования складских площадей во времени, что позволит своевременно принимать решения о расширении склада или проведении внеочередного уплотнения.