План закупок и BI-аналитика
Локальное Streamlit-приложение: считает потребность и рекомендуемый заказ поставщикам IEK и Systeme Electric по ZIP-выгрузкам, даёт менеджеру…
О проекте
Команда: gronto
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Локальное Streamlit-приложение: считает потребность и рекомендуемый заказ поставщикам IEK и Systeme Electric по ZIP-выгрузкам, даёт менеджеру поправить количество и сравнивает прогноз с фактом.
Как устроено
Пользователь загружает ZIP-архивы поставщика, задаёт начало прогноза и сроки поставки. Модуль procurement/calculate считает прогноз спроса и заказ с учётом кратности. Каждый расчёт сохраняется в SQLite вместе с исходными файлами, параметрами и ручными правками. Вкладка BI показывает динамику продаж, а после загрузки фактического CSV считает точность прогноза (MAE, WAPE, смещение). Проект заказа выгружается в CSV.
Ключевые решения
- прогноз спроса
- кратность заказа
- MAE/WAPE/bias оценка прогноза
- версионирование расчётов
Особенности
Прогнозы неизменяемы, точность меряется отдельно по загруженному полному отчёту о фактических продажах. Отсутствие товара в полном отчёте считается нулевыми продажами, а повторный импорт не удваивает факт. Ручная правка менеджера не влияет на оценку прогноза.
Стек
Python · Streamlit · SQLite · unittest
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-5dd681f6-gronto.
README
README.mdПлан закупок и BI-аналитика
Локальное веб-приложение для подготовки заказов поставщикам IEK и Systeme Electric. Оно рассчитывает потребность в товарах, сохраняет данные и прогнозы, показывает динамику продаж и сравнивает прогноз с фактическими продажами.
Первый запуск: установите Python → откройте папку проекта → запустите
run.bat на Windows или sh run.sh на macOS/Linux → загрузите архив поставщика →
нажмите «Рассчитать заказ».
1. Что понадобится
| Что | Для чего |
|---|---|
Python 3.11–3.13 с pip и venv | Запуск и установка зависимостей |
| Интернет при первой установке | Загрузка Python-зависимостей |
| Браузер | Работа с интерфейсом |
Предоставленные IEK.zip и/или Systeme electric.zip | Расчёт по данным поставщиков; достаточно одного архива |
Архивы не входят в репозиторий и не требуют распаковки. Для основных автоматических тестов они не нужны. Отдельный сервер базы данных не требуется: приложение использует SQLite.
Все команды ниже выполняются из папки проекта, где находятся app.py,
requirements.txt и run.bat.
2. Запуск приложения
Быстрый запуск
Windows PowerShell:
py -3 --version
.\run.bat
Первая команда должна показать Python версии 3.11–3.13. Также можно запустить
run.bat двойным щелчком в проводнике.
macOS / Linux:
python3 --version
sh run.sh
Скрипт создаст окружение .venv, установит зависимости и запустит сервер.
При следующих запусках будет использоваться готовое окружение.
Откройте адрес из терминала, обычно http://localhost:8501. Если браузер не открылся автоматически, перейдите по адресу вручную. Оставьте терминал открытым на время работы. Для остановки нажмите Ctrl+C.
Ручной запуск или другой порт
Если скрипт не запускается или порт 8501 недоступен, используйте команды ниже.
Активация окружения не требуется. Если .venv уже существует, команду создания
окружения можно пропустить.
Windows PowerShell:
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m streamlit run app.py --server.address 127.0.0.1 --server.port 8800
macOS / Linux:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m streamlit run app.py --server.address 127.0.0.1 --server.port 8800
После такого запуска откройте http://127.0.0.1:8800.
Если занят и этот порт, замените 8800 на свободный в команде и адресе браузера.
После обновления requirements.txt повторите команду pip install для своей
системы: скрипты пропускают установку, если уже есть .venv/installed.flag.
3. Проверка расчёта и сохранения данных
В разделе «План закупок» выполните шаги по порядку.
| Шаг | Действие | Ожидаемый результат |
|---|---|---|
| 1 | Загрузите ZIP в поле соответствующего поставщика | Появится подпись «Файл сохранён» |
| 2 | Выберите начало прогноза в будущем, после последнего дня операций в архивах. Проверьте сроки поставки | Параметры доступны для изменения |
| 3 | Нажмите «Рассчитать заказ» | Появятся «Результат расчёта», номер сохранённого расчёта, показатели и таблица заказа |
| 4 | Найдите товар по коду 1С или названию, переключите поставщика | Таблица отфильтруется, расчёт останется доступен |
| 5 | Измените «К заказу, шт.» на положительное число, кратное значению в колонке «Кратность», и нажмите Enter | Правка сохранится; значение «Прогноз» останется прежним |
| 6 | Очистите поиск и повторно найдите товар | Изменённое количество сохранится |
| 7 | Нажмите «Скачать проект заказа · CSV» | Скачается файл со строками текущего фильтра и ручными количествами |
| 8 | Измените срок поставки | Результат скроется до нового расчёта; появится сообщение об изменении параметров |
| 9 | Повторно нажмите «Рассчитать заказ» | Создастся отдельный расчёт с новым номером |
| 10 | Откройте «BI-аналитика» → «История», выберите прежний расчёт и нажмите «Перейти к расчёту» | Восстановятся его параметры, файлы и ручные количества |
Количество заказа должно быть целым, неотрицательным и соответствовать кратности. При нарушении кратности появится ошибка, а скачивание заказа будет недоступно до исправления. В CSV колонка «К заказу, шт.» называется «Рекомендовано». Если указать 0, товар скроется при включённом фильтре «Только позиции к заказу»; выключите фильтр, чтобы снова увидеть его.
Проверка после полного перезапуска
- Откройте сохранённый расчёт, внесите допустимую правку количества и запомните номер расчёта и код товара.
- Остановите сервер через Ctrl+C.
- Запустите его той же командой из той же папки, используя ту же базу данных.
- Обновите страницу браузера и найдите товар.
Должны восстановиться: выбранные файлы, параметры, номер расчёта и ручное количество. Повторно загружать ZIP и запускать расчёт не требуется.
4. Проверка BI-аналитики
| Вкладка | Что проверить |
|---|---|
| Обзор продаж | Есть помесячный график; фильтры поставщика, категории и периода меняют показатели |
| Точность прогноза | Можно выбрать сохранённый прогноз и увидеть статус каждой позиции |
| Загрузить факт | Можно скачать шаблон и сохранить полный отчёт продаж поставщика |
| История | Видны расчёты, параметры, исходные файлы и загрузки фактических продаж |
В обзоре используются последние сохранённые архивы поставщиков. Повторная загрузка одного архива не увеличивает продажи. Последний месяц может быть неполным.
Почему новый прогноз ещё не имеет оценки
Для нового прогноза нормально видеть «Ожидает факта», «0 / N» оценённых позиций и «—» вместо MAE и WAPE. Оценка появится, когда:
- Закончится весь период прогноза.
- Будут загружены полные отчёты продаж, покрывающие каждый день этого периода по соответствующему поставщику.
Период указан во вкладке «Точность прогноза». Он равен сроку поставки плюс интервалу между расчётами и может различаться по поставщикам. Расчёты с началом в день сохранения или раньше доступны по переключателю «Показать также исторические сценарии» и отдельно от прогнозов на будущее.
Как загрузить фактические продажи
Подготовьте CSV в UTF-8 с колонками supplier, code, date, qty.
Пример формата — замените значения на реальные продажи и коды 1С:
supplier;code;date;qty
IEK;001234;2026-09-01;12
IEK;001234;2026-09-02;4
- Откройте «Загрузить факт» и выберите поставщика отчёта.
- Укажите начало и конец отчётного периода включительно.
- Загрузите файл и проверьте число строк, товаров и проданных единиц в предпросмотре.
- Подтвердите, что отчёт полный по всем товарам поставщика за указанный период.
- Нажмите «Сохранить фактические продажи» и проверьте новую запись в «Истории».
- Вернитесь в «Точность прогноза» и выберите нужный расчёт.
Правила отчёта:
- Один файл — один поставщик: точно
IEKилиSysteme Electric. code— код 1С, включая ведущие нули;date— дата в форматеГГГГ-ММ-ДД.qty— неотрицательные валовые продажи в штуках, без вычета возвратов.- Даты строк должны попадать в выбранный период. Повторные строки товара за день суммируются.
- В подтверждённом полном отчёте отсутствие товара или дня означает нулевые продажи. CSV только с заголовками означает нулевые продажи за весь выбранный период.
- Новый отчёт заменяет все продажи поставщика внутри указанных дат, включая обнуление отсутствующих товаров. Продажи вне периода сохраняются. Повторный импорт не удваивает факт; исходные файлы и история импортов сохраняются.
Как читать результат
| Показатель | Значение |
|---|---|
| MAE, шт. | Средняя абсолютная ошибка по оценённым товарам; меньше — лучше |
| WAPE, % | Сумма абсолютных ошибок / сумма фактических продаж × 100; меньше — лучше |
| Смещение, % | Сумма (прогноз − факт) / сумма факта × 100; плюс — завышение, минус — занижение |
При нулевой сумме факта WAPE и процентное смещение не определены; MAE остаётся доступной. Неполные периоды не входят в метрики. Сравнивается сохранённый прогноз спроса, а не исправленное менеджером количество заказа.
5. Автоматические тесты
Запускайте из корня проекта после установки зависимостей. Работающий сервер не требуется. Тесты сохранения используют временные базы и не меняют рабочую.
Windows PowerShell:
.\.venv\Scripts\python.exe -m unittest discover -s tests -v
macOS / Linux:
.venv/bin/python -m unittest discover -s tests -v
Успешный результат: в конце вывода OK или OK (skipped=1), без FAIL и ERROR.
Тесты проверяют расчёт и кратность, границы прогноза, восстановление данных,
неизменяемость прогнозов, импорт факта и показатели BI. Например, для прогноза
10 и факта 8 проверяются MAE = 2, WAPE = 25 % и смещение = +25 %.
Это позволяет проверить оценку точности сразу, без ожидания окончания будущего периода.
Пропуск Optional local mockup archives unavailable допустим: это дополнительная
проверка реальных архивов. Чтобы включить её, положите оба файла в папку upload
рядом с папкой проекта:
родительская-папка/
├── hack-5dd681f6-gronto/
│ ├── app.py
│ └── tests/
└── upload/
├── IEK.zip
└── Systeme electric.zip
Имена должны совпадать с указанными. Если в ../upload/ есть ZIP, проверка запускается
и ожидает оба файла.
6. Хранение и резервная копия
По умолчанию используется data/procurement.sqlite3 в папке проекта. База хранит
исходные файлы, обработанные данные, настройки, прогнозы, ручные количества и факт.
Все сеансы приложения с этой базой используют общее рабочее пространство.
Папка data/ исключена из Git и не переносится при публикации кода.
Резервная копия: остановите приложение и скопируйте всю папку data/.
Восстанавливайте её также при остановленном приложении.
Для ручной проверки на отдельной базе задайте PROCUREMENT_DB_PATH перед запуском.
Сначала остановите предыдущий сервер на выбранном порту.
Windows PowerShell:
$env:PROCUREMENT_DB_PATH = Join-Path $PWD 'data\verification.sqlite3'
.\.venv\Scripts\python.exe -m streamlit run app.py --server.address 127.0.0.1 --server.port 8800
Для возврата к основной базе после остановки выполните
Remove-Item Env:\PROCUREMENT_DB_PATH и запустите приложение обычной командой.
macOS / Linux:
PROCUREMENT_DB_PATH="$PWD/data/verification.sqlite3" .venv/bin/python -m streamlit run app.py --server.address 127.0.0.1 --server.port 8800
В этом примере переменная действует только для указанного запуска.
7. Если что-то не работает
| Проблема | Решение |
|---|---|
py или python3 не найден | Установите Python 3.11–3.13 с pip и venv, откройте новый терминал |
Порт занят или Windows показывает WinError 10013 | Используйте ручной запуск из раздела 2 на другом порту, например 8800 |
No module named pip | Скрипт запуска попробует восстановить pip через ensurepip. Если не получилось, используйте полную установку Python с pip и venv и создайте окружение заново |
No module named streamlit | Повторите установку requirements.txt через Python из .venv, как в разделе 2 |
| Таблица пуста | Очистите поиск, выберите всех поставщиков и выключите «Только позиции к заказу». Проверьте сообщения об исходных данных и наличии остатков |
| После изменения параметров исчез результат | Нажмите «Рассчитать заказ». Старый расчёт доступен в «BI-аналитика» → «История» |
| Нельзя скачать заказ | Исправьте пустые количества и нарушения кратности в показанных строках |
| В BI вместо точности «—» | Проверьте окончание периода прогноза и полноту загруженного факта; отсутствие отчёта не считается нулевыми продажами |
| После переноса проекта нет прежних данных | Перенесите резервную копию data/ и проверьте значение PROCUREMENT_DB_PATH |
8. Данные и ограничения расчёта
Прогноз использует последние шесть завершённых месяцев, сезонность по двум последним полным годам истории, корректировку редких крупных продаж и прирост спроса.
Заказ = max(0, прогноз + страховой запас − остаток − поставки, прибывающие вовремя)
Количество округляется вверх до кратности поставщика. При неизвестном остатке позиция не получает заказ. Товар в пути без даты прибытия не вычитается. Упущенный спрос корректируется только при загрузке журнала отсутствия товара.
В исходном архиве IEK остаток относится к началу сентября 2026 года; дата свободного остатка Systeme Electric не подтверждена. Срок поставки 30 дней — демонстрационное значение. Перед рабочим заказом загрузите актуальные остатки и укажите реальные сроки. Заказы проверяет менеджер; приложение не отправляет их поставщикам. Продажи при отсутствии товара могут быть ниже спроса — BI сравнивает прогноз именно с продажами.
Дополнительные CSV загружаются в «Дополнительные данные · CSV», кодировка UTF-8.
Актуальные остатки:
supplier,code,balance
IEK,010500003_,48
Периоды отсутствия товара:
supplier,code,start,end
IEK,010500003_,2026-08-01,2026-08-07
Поставщик — точно IEK или Systeme Electric. В CSV заказа «Конец прогноза» —
первая дата за пределами прогноза; в BI показывается последний включённый день.
Интерфейс использует оформление ekt.kz. Логотип, шрифт и стили хранятся локально; источники и лицензия шрифта указаны в assets/SOURCES.md.
Авторы коммитов
История коммитов
- 2026-09-23 17:28Document project setup and verification workflowMikhail
- 2026-09-23 17:18Add persistent forecasts and BI accuracy analyticsMikhail
- 2026-09-23 16:56Apply EKT branding and preserve order editsMikhail
- 2026-09-23 15:30Restore pip automatically in local launch scriptsMikhail
- 2026-09-23 15:13Build local supplier order recommendation MVPMikhail
Структура репозитория (26 файлов)
.gitignore .streamlit/config.toml README.md app.py assets/PT-Sans-OFL.txt assets/SOURCES.md assets/app.css assets/ekt-logo.svg assets/pt-sans-bold.ttf assets/pt-sans-regular.ttf bi_ui.py branding.py procurement/__init__.py procurement/analytics.py procurement/calculate.py procurement/ingest.py procurement/storage.py requirements.txt run.bat run.sh tests/test_analytics.py tests/test_app.py tests/test_bi_ui.py tests/test_calculation.py tests/test_ingest.py tests/test_storage.py
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.