Как автоматизировать распределение грузов по объему и точкам доставки в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В современной логистике часто возникает задача оптимального распределения заказов по транспортным средствам. Типичный пример: необходимо сгруппировать пункты назначения так, чтобы в один рейс попадало не более 3 точек, а суммарный объем груза составлял около 30 кубических метров. При этом важно соблюдать направление (кластеризацию) и минимизировать «пустые» пробеги.

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

Анализ задачи: почему «цикл в цикле» — это не лучший выход

С технической точки зрения описанная проблема относится к классу NP-трудных комбинаторных задач, а именно к задаче о бункере (Bin Packing Problem) с дополнительным ограничением на количество элементов (Cardinality Constraint). Попытка решить её простым перебором (цикл в цикле) на больших объемах данных (например, более 50–100 заказов) приведет к экспоненциальному росту времени расчета, что сделает работу системы крайне медленной.

Проанализируем основные ограничения, которые нам необходимо учитывать:

  1. Географический кластер: Заказы должны принадлежать одному направлению.
  2. Лимит по объему: Сумма кубатуры не должна превышать (или должна стремиться к) 30 м³.
  3. Лимит по точкам: В одном рейсе может быть не более 3 различных адресов доставки.

Вариант 1: Эвристический алгоритм (FFD) внутри 1С

Если бюджет проекта не позволяет использовать внешние сервисы, мы можем реализовать алгоритм First Fit Decreasing (FFD). Рассмотрим этот метод подробнее: сначала мы сортируем все заказы внутри кластера по убыванию объема, а затем последовательно пытаемся «упаковать» их в существующие или новые рейсы.

Давайте посмотрим на пример логики, которую можно реализовать в коде 1С:


// Пример упрощенного распределения заказов по алгоритму FFD
Процедура РаспределитьЗаказыПоРейсам(ТаблицаЗаказов)
    // 1. Сортируем таблицу по Кластеру и по Объему (убывание)
    ТаблицаЗаказов.Сортировать("Кластер Возр, Объем Убыв");
    
    Рейсы = Новый ТаблицаЗначений;
    Рейсы.Колонки.Добавить("НомерРейса");
    Рейсы.Колонки.Добавить("ОбщийОбъем");
    Рейсы.Колонки.Добавить("КоличествоТочек");
    
    Для Каждого СтрокаЗаказа Из ТаблицаЗаказов Цикл
        Упаковано = Ложь;
        
        // Пытаемся найти подходящий существующий рейс
        Для Каждого Рейс Из Рейсы Цикл
            Если Рейс.ОбщийОбъем + СтрокаЗаказа.Объем <= 30 
                И Рейс.КоличествоТочек < 3 Тогда
                
                // Добавляем заказ в этот рейс
                Рейс.ОбщийОбъем = Рейс.ОбщийОбъем + СтрокаЗаказа.Объем;
                Рейс.КоличествоТочек = Рейс.КоличествоТочек + 1;
                СтрокаЗаказа.НомерРейса = Рейс.НомерРейса;
                Упаковано = Истина;
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        // Если не влезло ни в один рейс, создаем новый
        Если Не Упаковано Тогда
            НовыйРейс = Рейсы.Добавить();
            НовыйРейс.НомерРейса = Рейсы.Количество();
            НовыйРейс.ОбщийОбъем = СтрокаЗаказа.Объем;
            НовыйРейс.КоличествоТочек = 1;
            СтрокаЗаказа.НомерРейса = НовыйРейс.НомерРейса;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Этот метод работает быстро и дает результат, близкий к оптимальному. Однако он не учитывает последовательность объезда точек, что подводит нас к следующему этапу оптимизации.

Вариант 2: Полуавтоматическое распределение через АРМ логиста

Как показывает практика, часто наиболее эффективным решением для 1С является создание Рабочего места (АРМ), где система делает предварительную группировку, а логист финально утверждает рейсы. Выясним причину популярности такого подхода: реальная жизнь часто подкидывает условия, которые сложно описать математически (ремонт дорог, габариты груза, личные предпочтения водителей).

Рассмотрим структуру такого АРМ:

  1. Левая часть: Список нераспределенных заказов, отсортированный по кластерам и убыванию объема.
  2. Центральная часть: Таблица формируемых рейсов с индикаторами заполнения (цветовая шкала объема).
  3. Механизм «флажков»: Логист отмечает заказы, и система сразу показывает суммарный объем и количество точек. Если лимит в 30 кубов превышен, система выдает предупреждение.

Вариант 3: Использование внешних API и библиотек

Если задача требует максимально плотной загрузки транспорта и учета расстояний, стоит рассмотреть интеграцию с внешними сервисами. Проанализируем ситуацию: зачем изобретать велосипед, если существуют готовые облачные решения?

Популярные сервисы для интеграции:

Пример схемы взаимодействия с внешним сервисом из 1С:


// Пример отправки данных на внешний сервис оптимизации
Функция ПолучитьОптимальныеРейсы(ДанныеЗаказов)
    Запрос = Новый HTTPЗапрос("/v1/optimize");
    Запрос.УстановитьТелоИзСтроки(СформироватьJSON(ДанныеЗаказов));
    
    Соединение = Новый HTTPСоединение("api.logistics-service.com");
    Ответ = Соединение.ОтправитьДляОбработки(Запрос);
    
    Если Ответ.КодСостояния = 200 Тогда
        Возврат ДесериализоватьJSON(Ответ.ПолучитьТелоКакСтроку());
    КонецЕсли;
КонецФункции

Вариант 4: Линейное программирование и Excel

Для небольших компаний интересным вариантом может стать использование возможностей Microsoft Excel. В Excel встроен мощный инструмент «Поиск решения» (Solver), который умеет решать задачи линейного программирования. Программист 1С может выгрузить данные в Excel через COMОбъект, запустить макрос поиска решения и забрать результат обратно в 1С.

Этот путь сложен в поддержке (требует установленного Excel на сервере/клиенте), но позволяет решать задачи оптимизации без покупки дорогостоящих TMS-систем.

Рекомендации по реализации

Подводя итог, при выборе способа решения логистической задачи в 1С, мы рекомендуем придерживаться следующего плана:

  1. Начните с сортировки: Простое упорядочивание заказов по кластерам и объему (от большего к меньшему) уже решит 70% проблем логиста при ручном выборе.
  2. Внедрите контроль ограничений: Добавьте в интерфейс проверку — не более 3 точек и не более 30 кубов. Это предотвратит ошибки человеческого фактора.
  3. Используйте фоновые задания: Если вы решили внедрять сложные алгоритмы перебора, обязательно выносите расчет в ФоновыеЗадания, чтобы не блокировать работу пользователя.
  4. Рассмотрите типовые конфигурации: В современных версиях 1С:ERP и 1С:Управление торговлей 11 уже есть встроенные механизмы планирования доставки. Прежде чем писать свое решение, проанализируйте возможности подсистемы «Доставка».

Выбор конкретного метода зависит от размерности ваших данных и требований к точности. Для малого бизнеса достаточно удобного АРМ с флажками, для крупного дистрибьютора с сотнями машин — необходима интеграция с математическими решателями или полноценной TMS.

← На главную