Серия «Разработка логистической программы»

5

Logistics_Analyzer расчет зон покрытия

Мне показалось что в последнем посте Logistics_Analyzer "Что если?" и новые функции программы мною не до конца был раскрыт вообще весь смысл анализатора "Что если?", а так же данные были очень корявые и не точные. Сегодня я постараюсь объяснить более детально, наглядно и заодно расскажу о новой функции.

Для начала начнем с данных. Я переработал все данные, создал более грубую но работоспособную модель тестовых значений для программы. Ушел от глобализации на всей карте, в сторону "Меньше объектов, один город, при этом более верные данные".

Новая карта объектов:

Текущая заливка данных, один город и 34 объекта

Текущая заливка данных, один город и 34 объекта

Сама карта — та же самая, что и была ранее, просто вместо 118 объектов теперь их всего 34, и собраны в одном городе.

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

Зон доставок я сделал 5 вариантов, т. е. одинаковые зоны будут у 6 объектов, но это не критично, даже хорошо для проведения анализа.

Основной объект который будет разобран в сегодняшнем обзоре

Основной объект который будет разобран в сегодняшнем обзоре

Возьмем за пример объект с кодом ST_MSK_004 (магазин «Таганская»).

У него есть своя зона доставок, которая сложилась исторически.

Историческая зона доставок

Историческая зона доставок

Примерно так видит зону доставок логист

Примерно так видит зону доставок логист

Мемом выше можно понять, что зона не оптимизирована. Почему этот 004 магазин доставляет в зоны где тоже есть магазины? Загадка, а впрочем, и нет. Это же тест-данные. Я предположил, что, например, есть один объект, у которого каким-то странным образом падала основная часть доставок, и он отдавал сам курьерку. При этом магазин стал слишком мало приносить прибыли, и аренда взлетела, надо закрыть его.

Переработанное окно анализа "Что если"

Переработанное окно анализа "Что если"

Немного переработал интерфейс, дизайн, добавил новые функции и пока что заглушки для будущих умных расчетов.

Выбираем объект 004, ставим учитывать ABC-анализ и анализировать влияние на доставку клиентам и запускаем расчет.

Самое долгое - это влияние на зонирование

Самое долгое - это влияние на зонирование

Пока грузиться процесс, опишу что такое "Влияние на доставку".

У компании Х есть магазин, который они хотят закрыть, надо понять визуально, какое покрытие и кому отдать кусок от «пирога». Вот это как раз и делает программа. И в этом процессе закрылась основная проблема, с которой я долго боролся, на скрине выше, где показана зона, есть маленькие зеленые точки, это исторические данные, куда были произведены отправки. На их основе программа и строит полигональную сетку для визуализации. А как быть с пустыми местами? Вот она, основная проблема. Чуть позже вернемся к этому.

Как раз расчет завершен, предлагаю посмотреть труды.

Окно товарных запасов

Окно товарных запасов

Окно товарных запасов - визуально на табличном примере показываем фактический остаток товара в магазине

Ближайшие объекты

Ближайшие объекты

Ближайшие объекты - показывает то куда можно переместить товар, какое расстояние, емкость и доступность

План перераспределения

План перераспределения

План перераспределения — это уже предлагаемые распределения остатков с закрываемого объекта на ближайшие по следующей логике:

  1. Проверяем товарную матрицу

  2. Проводим АВС анализ (в будущем добавлю и XYZ)

  3. Проверяем вместимость нового объекта

Если не подошло ни под одно действие, либо проверяем все найденные объекты в зоне, либо отправляем на склад, чуть-чуть логики с логов программы ниже:

Логи наверное скажут все за меня и гораздо больше)

Стоимость доставок

Стоимость доставок

Стоимость доставок - вообще должна считать по объему утилизации трака, сейчас как бы тоже (со скрипом) живой вариант, но есть уже накиданная логика, лежит под фичатоглом, надо проверять в будущем.

Влияние на регион - ничего интересного там нету, кейс без особенностей, программа говорит что все отлично


И вот она, та самая "Вишенка" на торте - влияние на доставку

Рассмотрим два типа карт: общая информация и данные о влиянии на время.

Информация о влиянии на время, как считает программа:

  1. Смотрит 3 точки из текущей зоны доставки по закрываемому объекту:

    1. Самая дальняя точка по километражу

    2. Средняя точка

    3. Ближняя точка
      2. Считает время от объекта до каждой из этих точек и берет среднее арифметическое значение

      Кластеризует текущую зону на подзоны для новых объектов и делает аналогичное, как в пункте 1+2, добавляя среднее по всем объектам.

Визуализация перераспределения зон доставки

Визуализация перераспределения зон доставки

Нажимая на "Синюю" кнопку открывается окно в котором при нажатии на пуск - происходит визуализация перераспределения зоны с учетом объектов и введенных параметров (Учет объектов вне зоны км). Состоит данный процесс из 5ти этапов.

  1. Показываем закрываемый объект

2. Показываем все объекты которые находятся внутри текущей зоны и внешние согласно параметра.

3. Показываем фактическую зону доставок

4. Делим зоны на кластеры. И вот тут самое интересное.

Минимальное приближение

Минимальное приближение

Среднее приближение

Среднее приближение

Как сказать программе: «Смотри, есть вот такая зона, в ней есть 10, 15 или 20 объектов, подели рисунок на пропорциональные части с учетом оптимальной логистики?» А ведь внутри родительского кластера есть пустые зоны, в которых исторически не было доставок, а мы все равно должны их учесть и распределить.

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

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

Мы находим в начале объекты и рядом с объектами начинаем раскидывать точки с определенной плотностью.

Дальше мы показываем окончательный процесс (распределения кластеров и привязку их к другим объектам).

На примере одного из кластера. Есть магазин на Павелецкой, есть зона которая перейдет к нему.

Отдаляем карту и чисто визуально мы понимаем, да кластеризация прошла успешно.

Красным написано "Маг" т.е. "Магазин" что бы более наглядно было

Красным написано "Маг" т.е. "Магазин" что бы более наглядно было

Внешние магазины рядом с контуром

Внешние магазины рядом с контуром

Да и отдаленные магазины тоже правильно подхватили кластеры.

Какой же экстаз я словил когда руками проверил и убедился в том что да, все работает как и задумано. Как минимум этот процесс автоматизирован. Не надо теперь руками все это считать, собирать карты по крупицам. Работа которая занимает неделю а то и две может быть выполнена за 1 минуту. Это успех.


На моменте первой визуализации я думал: «Это успех», и лучше уже ничего не добавлять. Но потом пришла мысль, маленькая мысль, которая не давала покоя: «А что, если кому-то этого мало, а если надо показать визуально маршруты, точки из расчета?». Имея готовый скрипт JS и логику, мне просто потребовалось скопировать, вставить и дополнить первоначальный код.

Процесс анимирования занимает гораздо больше времени. Программе надо отправить API запрос, получить ответ, так для каждого объекта по 3 раза.

2025-12-15 16:08:02,800 - INFO - STDOUT - 🌍 Построение маршрута через OSRM (карта: yandex)

2025-12-15 16:08:02,800 - INFO - STDOUT - 🌐 OSRM API: попытка 1/2

2025-12-15 16:08:02,801 - DEBUG - urllib3.connectionpool - Starting new HTTP connection (1): 127.0.0.1:53913

2025-12-15 16:08:03,674 - DEBUG - urllib3.connectionpool - http://127.0.0.1:53913 "GET http://router.project-osrm.org/route/v1/driving/37.6215,55.7... HTTP/1.1" 200 682

2025-12-15 16:08:03,675 - INFO - STDOUT - ✅ Маршрут через OSRM: 0.9 км, 2 мин

2025-12-15 16:08:03,675 - INFO - STDOUT - ✅ Зона 21 добавлена: 1 маршрутов, 10 точек полигона

2025-12-15 16:08:03,675 - INFO - STDOUT - 🔍 Обработка зоны 22: facility=True, polygon=9, points=0

2025-12-15 16:08:03,675 - INFO - STDOUT - ⚠️ Зона 22: нет точек доставки, добавляем без маршрутов

2025-12-15 16:08:03,675 - INFO - STDOUT - ✅ Зона 22 добавлена: 0 маршрутов, 9 точек полигона

2025-12-15 16:08:03,675 - INFO - STDOUT - 🔍 Обработка зоны 23: facility=True, polygon=13, points=0

2025-12-15 16:08:03,675 - INFO - STDOUT - ⚠️ Зона 23: нет точек доставки, добавляем без маршрутов

2025-12-15 16:08:03,675 - INFO - STDOUT - ✅ Зона 23 добавлена: 0 маршрутов, 13 точек полигона

2025-12-15 16:08:03,675 - INFO - STDOUT - 🔍 Обработка зоны 24: facility=True, polygon=10, points=5

Лог работы построения маршрута.

Logistics_Analyzer - умеет работать с геодекодированием, но маршруты - извольте, я даже не знаю как их строить. Интересно было бы посмотреть как создается логика построения маршрута под капотом.

Итог:

Мы получаем кластер с тремя ключевыми точками и путями до них, включая полное описание маршрутов.

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


Давайте подведем итоги кластеризации и перераспределения зон.

На мой взгляд, это успех. Конечно, есть некоторые недочеты, но они едва заметны и будут быстро исправлены. Логика работы выстроена, отчет динамичен. Теперь остается только проверить все на практике и собрать для него ОС от пользователей.

Есть план развития дальше, плюс устранение мелких недочетов. Первую бету версию планирую компилировать в начале марта 26г. Кому ее предлагать - это уже другой вопрос. Буду решать в момент возникновения.


В интерфейсе произошли некоторые изменения. Например, я перешел от скучной бежевой темы к более темным цветам. Часть стилей выделил в QSS и настроил их подключение в Main_window. Меню дашбордов стало напоминать Power BI с Excel, и были внесены другие мелкие правки.

Работаю над проектом по вечерам, уделяя этому 2-3 часа. Основные алгоритмы визуализации были написаны давно, но я долго не мог понять, в чем проблема. То данные распределялись неверно, то пробелы не учитывались. В начале реализации функции был у меня дата-файл, где зоны были более реалистичными, чем сейчас. При перераспределении их покрытие составляло всего 30%. То что "Ну очевидно можно сделать вот так" она делала "Тебе очевидно, а мне нет. Хочешь - делай сам".


Всем спасибо за прочтение. Пишите комментарии кто и что думает. Задавайте вопросы - отвечу)

Показать полностью 25
5

Logistics_Analyzer "Что если?" и новые функции программы

В старых постах:

  1. Разработка своей программы, суровые реальности и как такое продавать?

  2. Logistics_Analyzer виджет панель и как она работает

    Я уже немного рассказал о процессе разработки и функциях программы. Теперь покажу, что удалось улучшить за неделю, и расскажу об отдельной функции "Что если?".

Рассмотрим развитую розничную сеть: в каждом регионе — 10 магазинов и 1 склад. Ключевые особенности текущей операционной модели:

  • Доставка до клиента организована на уровне магазинов (не склада).

  • Товарная матрица жёстко фиксирована: перемещение ассортимента между точками возможно только в рамках допустимых категорий (например, нельзя заменить «Телефоны» на «Хлеб» при перераспределении).

  • Доступны фактические данные по:

    • продажам (с доставкой / без),

    • остаткам на точках,

    • SKU-уровню заказов с доставкой (включая адреса и объёмы).

На основе этих данных можно реализовать следующие аналитические и управленческие модули:

  1. Определение зон покрытия магазинов
    По адресам доставок (без привязки к квартирам) и частоте заказов за период (например, за год) строится геопространственная область — зоны ответственности каждого магазина. Границы определяются экстремальными точками доставок.

  2. ABC-анализ по SKU на уровне точки
    На основе фактических продаж формируется структура ассортимента: приоритетные, средние и низколиквидные SKU — с учётом оборачиваемости и вклада в выручку.

  3. Моделирование альтернативного размещения при закрытии точки
    Сопоставление товарных матриц, зон покрытия и ABC-профилей позволяет идентифицировать подходящие точки-реципиенты для перераспределения остатков — с минимальными логистическими и коммерческими потерями.

  4. Планирование перераспределения
    Комбинируя:

    • текущие остатки (на отправляющей точке),

    • лимиты хранения и нормативы по категориям (на принимающих точках),

    • совместимость товарных матриц,

    • пересечения зон покрытия и клиентской базы,
      формируется оптимальный план перемещения запасов — как при частичной реорганизации сети, так и при полном закрытии объекта.

Пример конфигурации:
Объект А характеризуется своей зоной покрытия и текущими остатками. Объекты Б, В, Г и др. — собственными остатками, ограничениями хранения по категориям, продажной динамикой и клиентскими зонами. Система оценивает все взаимодействия и предлагает планы по перераспределению товаров (Зон ожидается в будущем)

Пример созданный вручную по зонам доставки и расположению объектов.

Пример созданный вручную по зонам доставки и расположению объектов.

Компания Х решила закрыть объект А. Теперь нужно оценить, как это повлияет на:

- остатки товаров в других магазинах и на складе;

- зоны доставки других магазинов;

- среднее время доставки клиентам и стоимость перераспределения товарных остатков.

На основе этого анализа мы составим техническое задание для программы. Вот его основные пункты:

1. Определить регион, в котором находится объект А.

2. Выяснить фактические остатки товаров на этом объекте.

3. Найти ближайшие объекты с аналогичной товарной матрицей.

4. Провести ABC-анализ товаров на всех объектах за последний год.

5. Разработать план перераспределения товаров. Учитывать информацию из пунктов 1–3, а также средние затраты на перевозку одного кубического метра (задается при создании региона). Рассчитать оптимальное перераспределение.

Предложенная логика в целом корректна, однако в текущей реализации не учитывается стоимость доставки как функция пройденного расстояния или объёма груза.

Например, можно оперировать не стоимостью за километр, а средней себестоимостью перевозки на единицу объёма — скажем, при известных затратах в 1,5 млн ₽ на перевозку 160 м³ получаем удельную стоимость ~9,4 тыс. ₽/м³. (Цифра условная и приведена для иллюстрации.)

Более гибкий и масштабируемый подход — задать набор типов транспорта («траков») с атрибутами: тип маршрута, грузоподъёмность, объём и соответствующая средняя стоимость перевозки. Это позволит учитывать различия в логистике более точно.

С учётом этого, скорректирую модель и вернусь к дальнейшей проработке.

Программа, следуя установленным правилам, рассчитывает оптимальное размещение товаров. Если отключить АВС-анализ, она будет учитывать только остатки, местоположение и матрицу.

Ниже приведу пример работы данного функционала, данные заглушка и программа не может правильно разместить товары, поэтому все = 0.


P.S. Сейчас создание достоверных данных не является приоритетом.

Окно фактических остатков

Окно фактических остатков

Окно ближайших объектов в регионе состоящий из магазинов с доступным хранением.

Окно ближайших объектов в регионе состоящий из магазинов с доступным хранением.

План перераспределения остатков.

План перераспределения остатков.

Да, так как и писал - данные тестовые и в самом деле в регионе нет аналогичных матриц

Аналогично скрину выше, не нашли куда перевозить, доставка = 0.


И теперь основной вопрос "А что будет с доставкой? Как сильно закрытие повлияет на SLA по скорости?". Данный расчет сейчас является приоритетной доработкой которой я занимаюсь.
Логика которая мною вкладывает в анализ - следующая:

  1. Смотреть на расстояние различных точек на карте

  2. Делить действующую зону на кластеры

  3. Определить оптимальные объекты по времени которые находятся рядом

  4. Сделать ренден всех 3-ех пунктов и показывать изменения в зонировании доставки с отчетом об изменении среднего времени и какие районы слишком далеко.

Для инфраструктуры это очень важный фактор, от которого зависит многое. Так же этот фактор должен работать и при открытии нового объекта. Но сейчас такой функционал не реализован


Функция выбора источника данных для программы и совместная работа с одним исполняемым файлом.

В параллели с влиянием на регион, мне удалось внести не большую доработку в систему. Теперь пользователи могут выбирать исполняемый файл.

Окно выбора исполняемой БД на SQLite 3

Окно выбора исполняемой БД на SQLite 3

2 пользователя работают с одним исполняемым файлом, вносят корректировки, строят дашборды, удаляют или дополняют данными программу. Но как копии приложения узнать что внесены изменения в хранилище? Для этого было реализовано metadata таблица. исполняемое приложение запускается, запоминает метаданные времени БД и проверяет обновления, в случае изменения метаданных моментально сигнализирует о том что необходимо обновить данные.

Если выбрать "Позже" то обновление данных будет отложено на 30 секунд.

Если выбрать "Позже" то обновление данных будет отложено на 30 секунд.

В рамках подготовки программы к первому тестированию на живых данных в нашей компании была реализована функция "Отправить отчет об ошибке".

Окно ввода сообщения для описания проблемы

Окно ввода сообщения для описания проблемы

После отправки - логи приходят ко мне в ТГ через бота. Все логи запаковываются в zip архив, параллельно запускает процесс удаления логов из папки.

Информирования о проблеме у определенного пользователя.

Информирования о проблеме у определенного пользователя.


Почему я быстрее реализовал совместный доступ и отправку логов, вместо того что бы наполнить данными и показать на примере где все логично? Наверное потому что лень тратить много времени на создание данных, а потом их дополнять и править. Программа не окончательная, система хранения меняется. Например сейчас я понял что стоимость доставки и распределения товара можно завязать на типы траков - буду реализовывать и менять хранение. Менее затратно по времени дописать скрипт, чем создавать новую логику в 1000 строк данных.


Всем спасибо за то что дочитали.

Если есть желание предоставить тестовые данные с логикой - буду очень рад, поможет при тестировании. Шаблон данных могу предоставить.

Показать полностью 9
9

Logistics_Analyzer виджет панель и как она работает

В прошлом посте я рассказывал, что занимаюсь разработкой программы для логистической инфраструктуры в одиночку. (Ознакомиться тут: Разработка своей программы, суровые реальности и как такое продавать? )

В посте мною были раскрыта часть интерфейса и немного рассказал о том на какие требования должна отвечать программа.

Теперь поговорим о виджет панели, зачем я ее создал и как она по моему мнению должна упростить операционку.



Рассмотрим следующую ситуацию:

Два специалиста, отвечающих за логистические операции, готовят свои отчеты. Оба используют одни и те же скрипты и алгоритмы для обработки информации. Однако у них разные задачи: один должен предоставить общие цифры, а другой — детализированные данные по конкретным параметрам.

P.S. Такие случаи встречаются довольно часто, особенно когда компании чрезмерно увеличивают штат сотрудников.

Как упростить эту модель? Программа не является WebView, она десктопная, не имеет серверов и хранит данные локально. "Решение есть!" — скажу я вам. Виджет панель с сохранением состояний в JSON. Получаем универсальную настройку программа у каждого пользователя, но работающего с одной системой.


Элемент включения правого окна панели управления

Элемент включения правого окна панели управления

Включая правую панель с виджетами, мы можем выбрать преднастроенные карточки, либо добавлять свои карточки на дашборды.

Панель виджетов.

Панель виджетов.

Что бы добавить новый виджет или выключить существующий необходимо просто прожать чекбокс.

А состояние мы просто сохраним в JSON формате.

Нажатие на "Добавить ссылку на дашборд" запускает процесс получения данных из системы. Получается компонент опрашивает БД через отдельное ядро "Есть ли у нас созданные дашборды? Да? Верни название страницы, я создам список для пользователя"

Окно выбора страницы для создания виджета

Окно выбора страницы для создания виджета

Код ответил "Да, у нас есть страница с названием (Тестовый шаблон)", далее дроп окно нам показывает название и имеет возможность выбора из нескольких вариантов.
Для удобства настройки - предоставлена возможность выбор иконки для виджета и создания названия виджета.

Окно выбора иконки. При наведении на иконку, если она GIF - запускается анимация и происходит выделение цветом.

Окно выбора иконки. При наведении на иконку, если она GIF - запускается анимация и происходит выделение цветом.

Вот мы добавили новый тип виджета "Ссылка на дашборды".

Мы добавили новый виджет

Мы добавили новый виджет

При нажатии на элемент виджета программа перенаправит нас на страницу с настроенными графиками и информацией, которые так же настроил пользователь.

Открытая страница дашборда.

Открытая страница дашборда.

Если сравнить с предыдущим постом, видно, что окно с графиком изменилось. Это правильно, ведь для настройки через аналитический куб доступно меню редактирования. В этом режиме пользователь может добавить страницу, новый график или фильтр. Также можно настроить DAX-поле и провести расчеты по нему.

Я уже говорил, что программа имеет декомпозированную структуру. Создание нового виджета не требует больших усилий. Чтобы разработать виджет на заказ или под конкретные требования, нужно добавить новый файл в список, описать его пользовательский интерфейс и логику.

Структура панели.

Структура панели.


Ах, да. Говоря о возможностях правой панели, я потерял нить: "Как же это улучшит работу?".

Программа использует переменную, позволяющую выбрать между локальным хранилищем SQLite3 и сетевым. Это обеспечивает совместную работу всех пользователей с одними данными и возможность добавления новых. Человек ИКС настроил скрипты для получения данных, подходящих под программу. Другие пользователи могут не только просматривать наборы кириллицы и латиницы, но и визуализировать данные на карте с интерактивным просмотром. Они также могут создавать свои собственные графики и дашборды.

Хотя я не претендую на замену BI-систем, я понимаю, что не у всех есть средства для внедрения полноценных аналитических систем. JSON структура позволяет настроить уникальный формат панели в соответствии с предпочтениями пользователя.


Чрезмерно благодарен за уделенное время прочтения статьи. Впереди третья часть в следующую среду)

P.S. Местами есть разногласия в теме дизайна, активно перевожу на централизованный QSS стиль темы. Это позволит изменять один файл и менять тему везде. Сейчас частично стили интегрированы в код

Показать полностью 10
11

Разработка своей программы, суровые реальности и как такое продавать?

Начнем пожалуй с предыстории.

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

- Нам нужно создать модель которая посчитает нам условия закрытия одного из объектов и как это может повлиять на инфраструктуру, сроки вчера. Чем быстрее тем лучше.

И в этот момент целый департамент принялся проводить анализы, рассчитывать долгосрочную прибыль, затраты и все в этом ключе.

В тот же момент я задумался "А есть ли вообще аналогичная программа, что бы не сидеть и не считать все в табличках, не писать большие запросы в БД?" - ответ был "Есть, но дорого и компания не пойдет на такие затраты".

Спустя время мы конечно закрыли проект со всеми расчетами, применили изменения. Но только вдумайтесь, целый департамент на протяжении пары месяцев считает рентабельность изменения целой инфраструктуры и влияние на него всего лишь закрытием 1-2 объектами. Это колоссальные затраты для компании.

Со временем я перешел в IT, сменил свою сферу деятельности, в свободное время изучал различные языки программирования, фреймворки и понял "А что если разработать аналог для логистической инфраструктуры. Да, конечно дизайн будет не броский, но нам важна лишь функциональность и работоспособность данной программы". Соответственно в начале 25г мною было принято решение начать разработку. Как раз время AI инструментов, не идеальные, но какие-то нюансы они могут подтянуть что бы не лезть в тех доку на изучение той или иной функции/метода/условия.


Язык: Python.

Библиотеки для интерфейса: PyQt6.

Хранилище всей информации: SQLite3.

Частично использовалось: HTML, JS.

И множество второстепенных библиотек для кодирования информации, реализации возможности подключения внешних БД, работы с таблицами и т.п.


Python — язык не самый лучший, да и PyQt библиотека своеобразная и довольно хорошо нагружает систему, сама программа начинает весить тоже немало. Но ведь мы не гонимся за «вау-эффектом».

Перед началом создания программы мною были проведены анализы существующих аналогов. Были варианты на европейском рынке, но все не то либо очень дорого. В основном по моим запросам выдавались программы для

«Оптимизации доставок», «1С:Транспорт», «SAP», «Транспортный анализ» и т.п. Но ни одной подходящей под мое описание программы не было.

Что включало в себя мое виденье всей системы:

  1. Интерактивная карта с маркерами объектов.

  2. Автоматический расчет зонирования регионов в зависимости от исторических данных продаж с доставками.

  3. Отображение линий снабжения объекта прям на карте в формате «Объект А -> Объект Б -> Объект С».

  4. Планирование маршрута при выборе определенных объектов.

  5. Возможность построение интерактивных дашбордов.

  6. Возможность создание различных интерактивных виджетов и их настройка.

  7. Внутренний аналитический куб.

  8. Подключение к внешним БД как к источнику данных и тонкая настройка самим пользователем с маппингом полей.

  9. Создание регионов по складам (ручное выделение самого региона на карте).

И прочие функции, по типу DAX-языка при создании вычислительных полей.

Вишенка на торте всей программы:

10. Анализ инфраструктуры автоматически на ядре программы в формате «Что если?».

А что, если мы закроем магазин на Савеловской — как это повлияет на зону доставок ближайших магазинов/складов. А куда перевозить товар? Сколько машин надо и какая утилизация будет? А какие магазины есть в регионе? А что будет с инфраструктурой, если мы закроем целый склад? Кто теперь будет снабжать товаром магазины? А какая матрица товара есть сейчас? Как изменится структура поставок от основного склада на магазин, будем ли мы задействовать транзитные склады?

Первое, что я начал делать — накидывать БД, да, мы не имеем сервера, поэтому нам надо хранить данные для работы программы локально. Почему не сделать под клиента? Ну-у-у... Возможно, потому что у всех своя структура хранения, а аналитики есть везде, написать SQL-запрос и выгрузить данные по шаблону куда проще, чем делать программу с адаптивом. Имея опыт в работе с логистикой и инфраструктурой, я понимал, какая +- система хранения у всех компаний, труда собрать хранение мне не составило.

Вторым моим шагом стало изолирование всех действий с БД в программе. Т.е. все методы программы не должны общаться на прямую с хранением, а ходить через выделенный файл (ресурс).

Третий шаг — создание интерфейса, вкладок, виджетов и т.д. Можно было сделать через WebView, писать отдельно файлы форм, настраивать JS-логику, передавать сигналы в .py-файлы и т.д. Но это слишком усложняет весь проект, расширяя его код. В таком случае один я уже не смог бы вывести. Поэтому выбрал PyQt6. Долго анализировал, как лучше сделать, но ничего умнее не придумал. Так и родился первый интерфейс программы:

Один из вариантов левого меню.

Один из вариантов левого меню.

Возможность группировать объекты в рамках ближних зон и разгруппировать при приближении.

Возможность группировать объекты в рамках ближних зон и разгруппировать при приближении.

Система отображения линий снабжения.

Система отображения линий снабжения.

Возможность выбрать среди нескольких типов карт.

Возможность выбрать среди нескольких типов карт.

Построение тепловой карты по зонированию доставки с учетом исторических данных. К сожалению, данные были сгенерированы через бота, поэтому есть проблемы в формате историчности.

Построение тепловой карты по зонированию доставки с учетом исторических данных. К сожалению, данные были сгенерированы через бота, поэтому есть проблемы в формате историчности.

Создание отдельных связей между нестандартными таблицами, на этой основе можно построить запросы.

Создание отдельных связей между нестандартными таблицами, на этой основе можно построить запросы.

Возможность построить свои дашборды. Перемещать, настраивать и т.д. 

Возможность построить свои дашборды. Перемещать, настраивать и т.д. 

Подключить внешнюю БД (на примере sqlite как заглушка).

Подключить внешнюю БД (на примере sqlite как заглушка).

Анализ «Что если?». В анализе пока что реализована лишь один тип «Закрытие объекта», в будущем планируется добавить еще множество конструкторов и методов.

Анализ «Что если?». В анализе пока что реализована лишь один тип «Закрытие объекта», в будущем планируется добавить еще множество конструкторов и методов.

Пример работы анализа. Данные не фактические, лишь заглушки для проверки работы.

Пример работы анализа. Данные не фактические, лишь заглушки для проверки работы.

Также есть toolbar с интерактивностью. Наводя на кнопки, они расширяются в бок, показывая текст кнопки.

Также есть toolbar с интерактивностью. Наводя на кнопки, они расширяются в бок, показывая текст кнопки.

Скриншотами выше я показал лишь часть того, что реализовано в программе. В действительности функционал гораздо больше.

Четвертый шаг — создание ядра всего мыслительного процесса, пользователь нажал на кнопку, а что дальше? Дальше как раз таки отдельные компоненты, которые получают запрос и идут по логике дальше, забирают/обновляют/удаляют данные через шаг 2, интерпретируют их и отдают ответы на модули, которые вызывали.

Да, конечно, с ядром программы я возился довольно долго. Ввиду того что это не 1С, а свой, по сути, уникальный продукт, мне на 80% удалось создать полный конструктор ядра. Что это значит? Значит то, что всю дальнейшую логику мне надо лишь описывать в исполняемых файлах core. Это дало прирост к написанию более качественного кода, более чистого. Да, репозиторий программы увеличился с 15 mvp файлов до 80. Отдельный исполняемый файл практически на каждую форму и отдельно логический файл. Зато мы сразу имеем максимально декомпозированную структуру, которую легко править и изменять процессы.

Далее было много различных шагов, криптография подключения к БД, логирование действий для отслеживания ошибок программы, перевод карты на формат HTML+JS. Получение API ключей и т.д.


В последний момент я задался вопросом: «Как распространять обновления программы? Ведь если я внесу новые правки — пользователь должен их получить. Также я должен делать логирование для использования программы».

Долго я думал над тем, как сделать это все на бесплатном формате. Получилось сделать обновление через Яндекс Диск, авторизацию выделено и рассылку информации о грядущих обновлениях пользователям.

Окно авторизации.

Окно авторизации.

Провал авторизации.

Провал авторизации.

Окно после успешной авторизации с новостной панелью.

Окно после успешной авторизации с новостной панелью.

Интерфейс для лаунчера я накидал быстро с помощью нейронки, вручную написал код для авторизации на js с py. Настроил всё и протестировал. И «О чудо!» не имея большого бюджета у меня получилось реализовать это всё, над безопасностью авторизации еще, безусловно, стоит потрудиться.

Через некоторое время написал тест кейсы, написал алгоритм для тестирования всех модулей, поправил баги, которые вызывали сбои. Сейчас готова версия 0.5.8. До релиза v1.0.0 еще далеко, много разделов, которые моя голова хочет реализовать.

Что делать дальше? Когда я только начинал, был уверен, что проект можно продать. Я видел такие кейсы и раньше. Думал, что смогу развивать его сам, возможно, еще на год разработки в свободное время меня хватит, и я не погрязну во всей архитектуре. Но год спустя сомнения все чаще берут верх. Может, я зря трачу время?

Возможно, данным постом я смогу найти тех, кого воодушевит мой проект или просто он кому-то приглянется. А возможно, просто получу дельные советы.


Если у вас есть идея и желание реализовать её самостоятельно, смело действуйте.

В скором времени постараюсь выложить еще пост о новых функциях программы.

Делитесь своими комментариями и мнениями.

Показать полностью 14
Отличная работа, все прочитано!