← все кейсы · логистика склада

Система, которая сама раскладывает заказы по грузовикам.

Дистрибьютор автомасел и смазок загружает заказы из 1С, а система математически рассчитывает, что и в какую машину положить — с учётом веса, объёма, коробок и правил упаковки. Менеджер видит готовую раскладку и при желании правит её мышью.

стек · OR-Tools + 1С backend · NestJS + FastAPI в проде, развивается

01 · Контекст и задача

Клиент — оптовый дистрибьютор автомобильных масел, смазок и фильтров. Каждый день со склада уходят заказы, которые надо развезти по адресам. Машин несколько (Газель, Камаз, Лада Вис), у каждой свой кузов и грузоподъёмность. Задача упаковщика — разложить заказы так, чтобы всё влезло и машины не гоняли полупустыми.

Раньше это делалось на глаз и в Excel: ошибки, перевесы, лишние рейсы. Задача: система, которая принимает заказы из 1С и сама считает оптимальную раскладку по машинам — с учётом веса, объёма, габаритов каждого товара, типов коробок и правил упаковки.

Список заказов с импортом из 1С и статусами распределения
Список заказов: импорт из 1С одной кнопкой, статусы «распределён» / «требует внимания». Адреса доставки скрыты

02 · Что было сложно

  • Это задача оптимизации, а не CRUD. «Разложить N товаров по M машинам так, чтобы влезло и оптимально» — это классическая NP-трудная задача упаковки (bin packing). Простым перебором не решить: на десятках позиций комбинаций астрономически много. Нужен настоящий решатель, а не «если-то».
  • Геометрия реальных товаров. Канистра масла, цилиндрическая банка смазки, фильтр в заводской коробке — у каждого свой размер и форма. Что-то едет в фирменной коробке, что-то раскладывается по гофрокоробам со склада, что-то — без упаковки. Все эти правила надо было заложить в расчёт.
  • Расчёт должен быть детерминированным. Если на одних и тех же данных система выдаёт каждый раз разную раскладку — упаковщик ей не поверит. Один и тот же заказ должен раскладываться одинаково, и по возможности — в одну машину.
  • 1С как источник данных. Заказы и товары приходят из 1С, а у 1С нет REST API — обмен идёт XML-файлами по протоколу CommerceML. Нужно было сделать приёмник, который корректно разбирает выгрузку, отличает заказы от служебных файлов и не падает на кривых данных.

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

03 · Решения

Отдельный сервис-оптимизатор на OR-Tools

Расчёт раскладки вынесли в отдельный микросервис на FastAPI + Google OR-Tools — это промышленный решатель задач комбинаторной оптимизации (тот же, что Google использует для своих логистических задач). NestJS-бэкенд готовит данные, передаёт оптимизатору, получает оптимальную раскладку и сохраняет. Решатель учитывает вес, объём, габариты и правила упаковки одновременно.

Распределение заказов по машинам: загрузка по весу и объёму, раскладка по коробкам
Ядро системы: каждая машина с загрузкой по весу и объёму (Газель — 81.8% по весу), товары разложены по коробкам с габаритами. Справа — что не влезло

Ручная корректировка поверх расчёта

Автоматика даёт старт, но последнее слово — за человеком. Менеджер может перетащить позицию из одной машины в другую мышью, и система пересчитает загрузку. После правок «Сохранить ручные правки» фиксирует итоговую раскладку. Машинный расчёт и человеческий контроль работают вместе.

Справочники с реальной геометрией

Товары хранятся с формой (прямоугольник Д×Ш×В или цилиндр), весом и правилом упаковки. Коробки — свой справочник с размерами. Машины — с габаритами кузова и грузоподъёмностью. Часть товаров классифицируется автоматически по литражу. Всё это — данные, на которых работает оптимизатор.

Приёмник 1С по CommerceML

Сделали endpoint, который принимает выгрузку 1С по протоколу CommerceML напрямую (без архивов). Каждая загрузка фиксируется в истории импортов: что пришло, сколько заказов, статус (успех/ошибка), новые и обновлённые. Служебные файлы 1С отсекаются и помечаются отдельно — менеджер видит только реальные заказы.

История импортов из 1С со статусами
История импортов из 1С: тип, файл, статус, число заказов, источник. Видно и успешные, и отклонённые служебные файлы

Роли и аудит

Два уровня доступа: администратор (полный) и менеджер (только заказы, распределение, импорты). Каждое значимое действие пишется в журнал аудита — кто, что и когда. Для склада, где несколько человек работают с заказами, это базовая необходимость.

04 · Результат

Расчёт OR-Toolsпромышленный решатель оптимизации
Интеграция CommerceML, прямой импорт
Архитектура 3 сервисаNestJS · FastAPI · React в Docker

Этап 1 сдан и работает в проде. Менеджер загружает заказы из 1С, нажимает «Рассчитать» — и за секунды получает раскладку по машинам с процентом загрузки каждой. Видно, что влезло, что нет, и в каких коробках едет каждая позиция. Раскладку можно поправить мышью и сохранить.

Расчёт детерминированный: одни и те же заказы дают одну и ту же раскладку, система старается уложить заказ в одну машину. Бизнес получил инструмент, который убирает перевесы и лишние рейсы — то, что раньше считалось на глаз.

05 · Что дальше

Проект развивается этапами. В работе — поддержка паллет (европаллет, американский, китайский) с заданием вместимости машин в паллетах, а не только по весу и объёму. Это следующий слой оптимизации поверх уже работающего ядра.

Архитектура к этому готова: оптимизатор вынесен в отдельный сервис, его логику можно расширять, не трогая бэкенд и интерфейс. Добавление нового типа упаковки или правила — это данные и параметры решателя, а не переписывание системы.

Похожий проект

У вас задача оптимизации — маршруты, загрузка, расписание?

Задачи, где надо «разложить оптимально» — загрузка транспорта, маршрутизация, планирование смен — решаются не перебором, а правильным математическим инструментом. Опишите свою задачу в первом письме — скажем, решаема ли она, каким движком и сколько займёт.