SupplyFlow
Django-сервис для закупщика. Считает, сколько каждого SKU заказать у поставщика (Systeme Electric, IEK), объясняет расчёт по строке, даёт вручную…
О проекте
Команда: AEZ Tech
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Django-сервис для закупщика. Считает, сколько каждого SKU заказать у поставщика (Systeme Electric, IEK), объясняет расчёт по строке, даёт вручную поправить количество с указанием причины, утвердить заказ и выгрузить его в CSV.
Как устроено
XLSX/CSV выгрузки (продажи, остатки, MOQ, товары в пути, периоды stockout) импортируются в SQLite с контролем версий по контрольной сумме. Детерминированный engine.py для каждого SKU берёт прогноз на горизонт «срок поставки + период пересмотра» и учитывает сезонность (сначала по SKU, затем по категории), ограниченный рост, компенсацию упущенного спроса и исключение разовых крупных продаж. Потребность = прогноз + страховой запас − свободный остаток − поступления; затем пересчёт в закупочную единицу, подъём до MOQ и округление до кратности упаковки. Утвердить заказ может только пользователь с правом can_approve_order и только если нет блокировок.
Ключевые решения
- сезонные коэффициенты SKU/категория
- компенсация stockout
- исключение разовых крупных продаж
- страховой запас
- MOQ и кратность упаковки
- дни покрытия для срочности
- аудит ручных правок
Особенности
AI сознательно не используется: каждый фактор расчёта сохраняется в строке рекомендации. Выгрузки с ФИО клиентов отклоняются, принимается только обезличенный customer_hash. Если транзакции не сходятся с помесячным отчётом, позиция блокируется. Есть 11 тестов и демо-SKU для сезонности, разовой крупной продажи и stockout.
Стек
Python 3.11 · Django 5.2 · SQLite · openpyxl · HTML/CSS · серверный SVG
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-0ab753f5-aez-tech.
README
README.mdSupplyFlow — планирование закупок и контроль запасов
SupplyFlow — сервис планирования закупок для менеджеров по снабжению. Он объединяет данные о продажах, доступных остатках, поставках в пути и условиях поставщиков, чтобы формировать прозрачные рекомендации по пополнению склада: какие товары заказать, в каком объёме, по каким причинам и с какой срочностью.
Решение разработано для кейса автоматизации заказов поставщикам. В текущей версии реализован локальный MVP на Django с использованием предоставленных данных Systeme Electric и IEK.
Проблема и целевая аудитория
Менеджеру по закупкам приходится вручную объединять данные о продажах, складских остатках, минимальных партиях и ожидаемых поставках. Такой процесс занимает много времени, выполняется нерегулярно и повышает риск дефицита, избыточных запасов и ошибок в заказах. На точность также влияют сезонность спроса и разовые крупные продажи, которые искажают регулярную потребность.
SupplyFlow предназначен для менеджеров по закупкам и снабжению. Сервис формирует единый прозрачный процесс: загрузка и проверка данных → расчёт потребности → анализ рисков и рекомендаций → корректировка → утверждение → выгрузка заказа поставщику.
Что реализовано
Работа с данными
- Импорт предоставленных XLSX-выгрузок Systeme Electric и IEK.
- Импорт CSV для актуальных остатков, периодов отсутствия товара и справочника категорий/единиц измерения.
- Сохранение версии импорта: имени файла, контрольной суммы, даты, числа строк и предупреждений. Повторная загрузка файла с той же контрольной суммой не дублирует данные.
- Сохранение кода 1С как текста, поэтому ведущие нули и суффиксы SKU не теряются.
- Проверка структуры загружаемых файлов и ограничение размера файла до 30 МБ.
- Защита приватности: транзакционная выгрузка с полями
клиент,фиоилиимя клиентаотклоняется. Для анализа клиента поддерживается только обезличенныйcustomer_hash.
Расчёт потребности
- Прогноз по SKU на горизонт «срок поставки + период пересмотра».
- Сезонность из количественной помесячной истории: сначала для SKU, при недостатке полной истории — по категории, иначе нейтральный коэффициент.
- Устойчивый рост спроса: сравнение последних трёх месяцев с аналогичным периодом прошлого года; рост ограничивается параметром политики закупки.
- Компенсация упущенного спроса в зафиксированные периоды stockout.
- Поиск и исключение разовых крупных продаж по документу или
customer_hash. Исключение применяется, только если транзакции за месяц согласуются с помесячным отчётом; при расхождении позиция блокируется. - Учёт свободного остатка, поступлений до конца горизонта, страхового запаса, MOQ, кратности упаковки и коэффициента пересчёта закупочной единицы в складскую.
- Расчёт срочности по числу дней покрытия запасом.
Работа закупщика
- Панель с показателями расчёта и графиками спроса за 12 месяцев, срочности, структуры заказа по категориям и факторов корректировки.
- Список последних расчётов по поставщикам.
- Объяснение по каждой SKU: прогноз, запас, свободный остаток, поставки в пути, сезонность, рост, stockout, округление и блокирующие проблемы.
- Поиск, фильтры «к заказу / требуют проверки / все позиции» и постраничный вывод.
- Ручная правка количества с обязательной причиной, автором и датой изменения.
- Финальная сводка перед утверждением: объём заказа, высокий риск, ручные правки и блокировки.
- Утверждение доступно только пользователю с правом
planner.can_approve_orderи только при отсутствии блокировок. - Экспорт утверждённого заказа в CSV с кодом 1С, артикулом, наименованием, количеством, единицей измерения и поставщиком.
- Django Admin для справочников, политик, остатков, stockout-периодов, импортов и аудита расчётов.
Как работает решение
- Менеджер входит в сервис и открывает страницу «Данные».
- Сервис показывает последние версии источников и таблицу готовности данных по каждому поставщику: продажи, свободные остатки, MOQ, политика запаса, товары в пути, stockout и обезличенный идентификатор клиента.
- На странице «Панель» менеджер выбирает поставщика, дату расчёта, склад и при необходимости категорию.
- Сервис создаёт сохранённый черновик расчёта. Для каждой SKU рассчитывается потребность и формируется объяснение результата.
- На панели менеджер анализирует графики. На странице «Заказы» открывает расчёт нужного поставщика и проверяет строки заказа.
- При необходимости менеджер корректирует количество и указывает причину правки.
- Пользователь с правом утверждения проверяет финальную сводку и утверждает черновик. При проблемах с входными данными утверждение блокируется.
- После утверждения доступен CSV-файл для дальнейшей работы в учётной системе. Автоматической отправки заказа поставщику в проекте нет.
Логика расчёта
Для каждой позиции рассчитывается:
Потребность = прогноз на горизонт поставки
+ страховой запас
− свободный остаток
− подтверждённые поступления до конца горизонта
Полученная потребность переводится в закупочную единицу, поднимается до MOQ и округляется до кратности упаковки. В строке заказа сохраняются исходная величина до округления и итоговое количество.
Архитектура
flowchart LR
A[XLSX и CSV выгрузки] --> B[Импортёры planner/importers.py]
B --> C[(SQLite / Django ORM)]
C --> D[Расчётный модуль planner/engine.py]
D --> E[CalculationRun и Recommendation]
E --> F[Представления planner/views.py]
F --> G[Панель, Данные, Заказы, карточка расчёта]
G --> H[Ручная правка и утверждение]
H --> I[CSV-экспорт]
| Компонент | Назначение |
|---|---|
planner/models.py | Модели поставщиков, товаров, продаж, запасов, поставок в пути, stockout, политик, расчётов и рекомендаций. |
planner/importers.py | Адаптеры форматов предоставленных Excel-файлов и CSV. |
planner/engine.py | Детерминированный и объяснимый алгоритм прогноза и расчёта заказа. |
planner/views.py | Пользовательский сценарий: панели, импорт, расчёт, правка, утверждение и экспорт. |
planner/templates/planner/ | Адаптивный русскоязычный интерфейс на HTML/CSS; графики строятся сервером в SVG. |
planner/admin.py | Настройка и аудит данных через Django Admin. |
planner/tests.py | Автоматические проверки расчёта и HTTP-экранов сервиса. |
source_audit.py, source_metrics.py, source_deep.py | Read-only скрипты аудита структуры и качества исходных XLSX. |
Технологии
| Технология | Назначение |
|---|---|
| Python 3.11 | Язык приложения, импорта и расчётного алгоритма. |
| Django 5.2 | Веб-приложение, маршрутизация, шаблоны, формы, аутентификация, права, админка и ORM. |
| SQLite | Локальная база данных в файле db.sqlite3. |
| openpyxl 3.1 | Чтение XLSX-выгрузок. |
| HTML, CSS, серверный SVG | Интерфейс и графики без зависимости от JavaScript. |
| Django TestCase | Автоматические тесты бизнес-логики и HTTP-экранов. |
В проекте не используются AI-модели, внешние API, облачные сервисы, брокеры сообщений или сторонние аналитические платформы. Алгоритм намеренно детерминированный: факторы расчёта сохраняются в строке рекомендации и доступны закупщику.
Установка и запуск
Требования
- Windows и PowerShell;
- Python 3.11;
- папка с предоставленными материалами, содержащая каталоги
Systeme electricиIEK.
Команды
В PowerShell перейдите в корень репозитория:
cd C:\Users\Alex\Desktop\HackAlem
Создайте окружение, установите зависимости и примените миграции:
py -3.11 -m venv .venv311
.\.venv311\Scripts\python.exe -m pip install -r requirements.txt
.\.venv311\Scripts\python.exe manage.py migrate
Импортируйте предоставленные файлы и создайте синтетический набор для сквозной демонстрации:
.\.venv311\Scripts\python.exe manage.py import_samples --source-root 'C:\Users\Alex\Desktop\материалы HackAlem'
.\.venv311\Scripts\python.exe manage.py seed_demo
Создайте пользователя администратора и запустите сервер:
.\.venv311\Scripts\python.exe manage.py createsuperuser
.\.venv311\Scripts\python.exe manage.py runserver
Откройте http://127.0.0.1:8000/ и войдите под созданной учётной записью.
Полезные команды:
# Проверка приложения
.\.venv311\Scripts\python.exe manage.py check
# Автоматические тесты
.\.venv311\Scripts\python.exe manage.py test planner
# Повторный импорт, включая файлы с прежней контрольной суммой
.\.venv311\Scripts\python.exe manage.py import_samples --source-root 'C:\Users\Alex\Desktop\материалы HackAlem' --force
Как проверить решение
Полный сценарий жюри можно повторить без изменения исходных Excel-файлов.
-
Выполните команды установки, импорта и
seed_demoиз раздела выше. -
Войдите на сайт и на странице «Данные» откройте таблицу «Готовность данных к расчёту».
-
На «Панели» выберите поставщика «Демо: синтетические данные», дату
2026-09-22и складВсе. Нажмите «Сформировать рекомендации». -
На странице расчёта проверьте блок «Финальная проверка заказа» и раскройте «Показатели расчёта» у строк.
-
Убедитесь, что у демонстрационных SKU отражаются разные факторы:
DEMO-SEASON— выраженная сезонность и поступление в пути;DEMO-BULK— исключение разовой крупной продажи;DEMO-STOCKOUT— компенсация периода отсутствия товара.
-
Измените количество одной позиции, укажите причину и сохраните правку. В финальной сводке увеличится число ручных изменений.
-
Утвердите заказ под суперпользователем и скачайте CSV.
-
Запустите
manage.py test planner. В проекте выполняется 11 тестов: сезонность, stockout, аномалии, остатки и поступления, MOQ, политика категории, права на утверждение, ручная правка, экспорт и основные экраны.
Данные и интеграции
Предоставленные источники
Импортирующая команда поддерживает следующие файлы:
| Поставщик | Используемые источники |
|---|---|
| Systeme Electric | MOQ/кратность, помесячные продажи в штуках, помесячные остатки, динамика продаж по документам, сводный файл на 22.09.2026 со свободными остатками и товаром в пути. |
| IEK | MOQ, помесячные продажи в штуках, помесячные остатки, динамика продаж по документам, файл товара в пути с ожидаемыми датами. |
Файлы сезонности из материалов содержат выручку на уровне поставщика. Они не используются для количественного прогноза SKU: сервис рассчитывает сезонность из помесячных продаж в штуках.
Также поддерживаются CSV:
| Тип | Обязательные поля |
|---|---|
| Актуальные остатки | sku, warehouse, as_of, on_hand, reserved, free |
| Stockout-периоды | sku, warehouse, starts, ends |
| Каталог и единицы | sku и изменяемые поля category, article, name, unit, min_order, pack_multiple, purchase_to_stock_factor |
Исходные XLSX-файлы не копируются в репозиторий и не включаются в Git. Сервис не обращается к внешним API. Выгрузка заказа — универсальный CSV с разделителем ; и UTF-8 BOM для удобного открытия в Excel.
Ограничения текущей версии
- Решение является локальным MVP и использует SQLite. Производственное развёртывание, PostgreSQL, резервное копирование и настройка веб-сервера не реализованы.
- В предоставленных материалах нет актуального свободного остатка IEK на дату расчёта. Можно показать расчёт с начальным остатком месяца, но утверждение таких строк блокируется.
- В исходных материалах нет периодов stockout. Поэтому для реальных строк компенсация упущенного спроса равна нулю; функция проверяется на синтетическом наборе.
- В исходных транзакциях нет
customer_hash. Система находит разовые продажи по документам, но не может объединить несколько документов одного клиента. - В части транзакционных и помесячных данных есть расхождения. Сервис не вычитает аномалии из несогласованного месяца и показывает блокировку.
- Для части номенклатуры IEK неизвестен коэффициент перевода закупочной единицы в складскую, например бухты в метры. Такие позиции блокируются.
- Цена может быть импортирована в
unit_price, но не участвует в оптимизации бюджета или маржинальности. - Экспорт CSV содержит поля, необходимые для проверки заказа, но точный формат импорта в конкретную конфигурацию 1С не реализован.
- Нет автоматической отправки заказа поставщику. Это соответствует ограничению кейса: заказ требует подтверждения ответственного сотрудника.
- Политики поставщиков после импорта создаются с рабочим допущением
30 / 30 / 15дней и имеют статусconfirmed=False. Их принятие выполняется ответственным пользователем в Django Admin.
Развёрнутая версия
Публичная deployed-версия в текущем репозитории отсутствует. Проект запускается локально по адресу http://127.0.0.1:8000/.
Авторы коммитов
История коммитов
- 2026-09-23 16:52Update README.mdzhanitsi
- 2026-09-23 16:47Обновить описание в README.mdApollo-CMYK
- 2026-09-23 16:43Merge latest main updatesAlexandr Sharepin
- 2026-09-23 16:42Refine procurement dashboard copyAlexandr Sharepin
- 2026-09-23 16:38Update README.mdШарепин Александр
- 2026-09-23 16:30Merge remote mainAlexandr Sharepin
- 2026-09-23 16:28Initial MVP implementationAlexandr Sharepin
Структура репозитория (38 файлов)
.gitignore README.md manage.py planner/__init__.py planner/admin.py planner/apps.py planner/engine.py planner/forms.py planner/importers.py planner/management/__init__.py planner/management/commands/__init__.py planner/management/commands/import_samples.py planner/management/commands/seed_demo.py planner/migrations/0001_initial.py planner/migrations/0002_product_requires_conversion.py planner/migrations/0003_alter_calculationrun_options.py planner/migrations/0004_calculationrun_category.py planner/migrations/0005_saleline_unit_price.py planner/migrations/__init__.py planner/models.py planner/templates/planner/base.html planner/templates/planner/data.html planner/templates/planner/home.html planner/templates/planner/login.html planner/templates/planner/orders.html planner/templates/planner/run.html planner/tests.py planner/urls.py planner/views.py requirements.txt source_audit.py source_deep.py source_metrics.py supply_order/__init__.py supply_order/asgi.py supply_order/settings.py supply_order/urls.py supply_order/wsgi.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.