О проекте
Команда: ShoqanTandau
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Доведённый продукт
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Django-сервис для менеджера закупа ekt.kz: из выгрузок 1С (продажи, остатки, в пути, кратность, сезонность) рассчитывает заказ по поставщикам с объяснением, правкой, утверждением и экспортом в Excel для 1С.
Как устроено
Загрузчик читает и очищает xlsx-выгрузки 1С по поставщикам (IEK, Systeme Electric, синтетический ТехноСезон). Статистический движок строит прогноз спроса с исключением разовых крупных продаж, компенсацией скрытого дефицитом спроса, сезонностью, плановым ростом, учётом товара в пути и кратности. Менеджер правит количества и утверждает (правка сбрасывает утверждение), экспорт только утверждённых строк. Дополнительный ограниченный OpenAI-агент вызывает инструменты сценариев и объясняет результат; без ключа — шаблонный текст. Есть бэктест точности прогноза и роли менеджер/наблюдатель/админ.
Ключевые решения
- статистический прогноз спроса
- исключение выбросов (разовые продажи)
- компенсация дефицита
- сезонность
- кратность/MOQ
- бэктест на истории
- function calling агент со сценарными инструментами
- журнал решений
Особенности
Таблица чувствительности для жюри по одному артикулу (разовая продажа, в пути, остаток, рост, сезонность) показывает, как каждый фактор меняет заказ; синтетический поставщик для крайних случаев; утверждение сбрасывается при изменении количества; числа считает алгоритм, LLM только объясняет.
Стек
Python · Django · SQLite · Bootstrap · openpyxl/xlsx · GitHub Actions
Модели
OpenAI API
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-af5480b5-shoqantandau.
README
README.mdЗаказы поставщикам — HACKALEM AI
Объяснимое пополнение склада из выгрузок 1С для ТОО «Электрокомплект» (ekt.kz). Продукт помогает менеджеру закупа определить, что заказать, в каком количестве и почему. На выходе — рекомендации по поставщикам, риск дефицита, возможность ручной правки, утверждение и Excel с заказом.
Ручное сведение таблиц замедляет закупки. При этом крупная разовая продажа завышает регулярную потребность, отсутствие товара скрывает спрос, а уже заказанная партия может приехать слишком поздно. Сервис учитывает эти ситуации в одном расчёте и показывает основания каждого решения.
Основной путь: Excel → проверка и объединение данных → прогноз → рекомендации → решение менеджера → экспорт. Числа вычисляет статистический алгоритм. Дополнительный AI-агент выбирает инструменты анализа, сравнивает сценарии и объясняет результаты. Автоматической отправки заказов поставщику нет.
Для проверки используйте ветку
main. Основной сценарий работает без API-ключей, доступа к 1С и внешней базы. В комплекте 12 реальных файлов партнёра и 6 синтетических файлов. Дата исходных данных — 22.09.2026. Публичная версия не развёрнута; ниже дан самостоятельный локальный запуск.
Навигация
- Запуск на чистой системе
- Первый заказ и проверка жюри
- Пять обязательных требований кейса
- Методика, данные, проверка прогноза
- Подключение AI-агента
- Конфигурация и сохранённые данные
- Тесты и воспроизводимость
- Архитектура и безопасность
- Решение проблем запуска
- Ограничения и развитие
1. Запуск на чистой системе
Что требуется
| Компонент | Требование |
|---|---|
| Python | 3.12, 64-bit, с pip и venv. Проверено на Windows x64 / Python 3.12.14 |
| ОС | Windows — проверенный путь. Команды для Linux/macOS приведены отдельно, локально на этих ОС не проверялись |
| Браузер | Современный браузер; Excel/LibreOffice нужен только для просмотра скачанного .xlsx |
| Интернет | Первое скачивание проекта и пакетов; далее только для необязательного OpenAI API |
| Папка проекта | Доступ на запись: здесь создаются .venv, SQLite и кэш. Полностью распакуйте ZIP перед запуском |
| Не требуется | Node.js, npm, Docker, PostgreSQL, Redis, Microsoft Excel для расчёта, установка 1С, GPU |
Python можно установить с официальной страницы для Windows. Выберите ветку 3.12 и 64-битную установку с pip; после установки откройте новый PowerShell. Обычный Windows installer (64-bit) для локальной проверки доступен, например, в разделе Files выпуска 3.12.10; наши проверки выполнены на 3.12.14. Не используйте embeddable package. Если Python уже установлен, сначала проверьте версию командой ниже.
Windows — рекомендуемый путь
Шаг 1. Получите код. Если установлен Git:
git clone --branch main https://github.com/BAITC-Hacks/hack-af5480b5-shoqantandau.git
cd hack-af5480b5-shoqantandau
Без Git: на странице репозитория выберите main → Code → Download ZIP, распакуйте архив и откройте PowerShell в папке, где лежат manage.py и requirements.txt. Не запускайте команды внутри ZIP или на уровень выше этой папки.
Шаг 2. Проверьте Python и создайте отдельное окружение.
py -3.12 --version
py -3.12 -m venv .venv
Ожидается Python 3.12.x. Если команда py отсутствует, но python --version показывает 3.12.x, вместо второй команды выполните python -m venv .venv. Если обе команды отсутствуют, завершите установку Python и заново откройте терминал.
Шаг 3. Установите зависимости и создайте базу. Выполняйте команды по порядку; при ошибке не переходите к следующей.
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m pip check
.\.venv\Scripts\python.exe manage.py migrate --noinput
.\.venv\Scripts\python.exe manage.py check
Ожидается No broken requirements found, у миграций — OK, у проверки Django — System check identified no issues. Миграции сами создают db.sqlite3, роли и демо-пользователей. createsuperuser, импорт базы и ручное заполнение таблиц не нужны.
Шаг 4. Запустите приложение.
.\.venv\Scripts\python.exe manage.py runserver 127.0.0.1:8000
Дождитесь Starting development server at http://127.0.0.1:8000/ и откройте http://127.0.0.1:8000/. Терминал должен оставаться открытым. Остановка — Ctrl+C. Для следующего запуска достаточно последней команды из корня проекта; расчёты и решения сохраняются.
Активация окружения через Activate.ps1 не требуется: все команды явно используют его Python. Это поддерживаемый способ работы с venv. Установка пакетов выполняется в .venv, системный Python не изменяется.
В репозитории также есть start.ps1: powershell -File .\start.ps1 создаёт окружение, устанавливает пакеты, выполняет миграции и запускает сервер. Если политика PowerShell запрещает сценарии, используйте ручные команды выше — менять системную политику для проверки проекта не нужно.
Linux / macOS
Предварительно установите Python 3.12 с поддержкой venv и pip средствами вашей ОС. В Debian/Ubuntu, где доступна версия 3.12, модуль venv может требовать отдельного пакета python3.12-venv. На macOS используйте установленный полный Python 3.12, а не системный интерпретатор другой версии.
После клонирования или распаковки, из папки с manage.py:
python3.12 --version
python3.12 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m pip check
.venv/bin/python manage.py migrate --noinput
.venv/bin/python manage.py check
.venv/bin/python manage.py runserver 127.0.0.1:8000
Если интерпретатор называется python3, замените только первые две команды, предварительно проверив python3 --version. Для дальнейших команд используйте .venv/bin/python. sh start.sh — сокращённый вариант, который использует python3; сначала убедитесь, что это нужная версия. Не переносите .venv с другого компьютера — создайте её заново.
Вход и права
| Роль | Логин | Пароль | Возможности |
|---|---|---|---|
| Менеджер закупа | manager | manager12345 | Расчёт, правка, утверждение, экспорт, запросы AI-агенту |
| Наблюдатель | viewer | viewer12345 | Просмотр результатов, товаров и проверки точности; без операций изменения и платных запросов |
| Администратор | admin | admin12345 | Все действия, загрузка данных и управление пользователями |
На странице входа кнопка демо-роли сразу выполняет вход. Для первого сценария выберите менеджера. На чистой базе список предыдущих расчётов пуст — это нормально. На узком экране разделы находятся под кнопкой «Меню».
2. Первый заказ — маршрут проверки жюри
Основной сценарий без API, около 5 минут
- Войдите менеджером. На странице «Заказы» выберите «Все поставщики», оставьте стандартные настройки и нажмите «Рассчитать заказ». Первое чтение Excel может занять до полуминуты; дождитесь результата.
- Откройте вкладку IEK, найдите код
030201020_. Для неизменённых исходных файлов рекомендация — 107 шт. Откройте «Почему столько?»: видны основания расчёта. Текст без ключа помечается как шаблонный; числа всё равно вычислены алгоритмом. - Измените поле «Заказать» со 107 на 108, сохраните количество кнопкой «Сохранить количества». Отметьте строку галочкой и нажмите «Утвердить». У этого товара кратность равна 1; у других она может отличаться.
- Нажмите «Скачать заказ для 1С». В Excel должна появиться выбранная позиция с количеством 108 и обоснованием. Основная кнопка выгружает утверждённые положительные количества активного поставщика. Через соседнее меню доступен отдельный экспорт «Все рекомендации (черновик)».
- Измените утверждённое количество ещё раз и сохраните. Утверждение сбросится: изменённый заказ нужно подтвердить заново. Неутверждённая строка не попадёт в основной экспорт.
- Откройте «Как считается», выберите IEK и тот же код. Меняйте входы и наблюдайте пересчёт по таблице ниже. Эта страница проверяет сценарии и не меняет сохранённый заказ.
- Откройте «Точность» для проверки прогноза на истории. Затем выйдите через меню пользователя и войдите наблюдателем: кнопки расчёта, правки и утверждения недоступны; сервер также проверяет права.
Что подтверждает сценарий: обработку входных файлов, расчёт, объяснение, участие человека, контроль прав и получение выходного артефакта. Числа ниже получены из данных; в коде нет подстановки готового ответа для этих артикулов.
Независимый сценарий IEK 030201020_ | Заказ, шт. |
|---|---|
| Стандартный расчёт | 107 |
| Добавить разовую продажу 698 шт., очистка включена | 113 |
| Та же продажа, очистка выключена | 322 |
| Добавить 54 шт. в пути к базовому варианту | 53 |
| Увеличить остаток со 191 до 245 | 53 |
| Задать плановый прирост +30% в год | 164 |
| Отключить компенсацию дефицита | 94 |
| Отключить сезонность | 72 |
Сравнивайте каждый вариант со стандартными настройками, не накапливая изменения предыдущего эксперимента. После замены файлов и параметров числа могут отличаться. Дата данных берётся из последних накладных, а не из календаря компьютера.
Наглядные случаи на синтетическом поставщике
ТехноСезон — вымышленный поставщик, 13 товаров, 45 месяцев, 2 334 строки накладных. Он уже подключён; повторная загрузка его шести файлов не нужна. Выберите его при расчёте. В результате включите «Весь список», чтобы видеть нулевые рекомендации.
| Код | Что проверяем | Ожидаемый результат при стандартных настройках |
|---|---|---|
3301001_ | На складе уже 5 000 шт. | Заказ 0 |
3301002_ | Пустой склад, нет поставок | Заказ 192 |
3301003_ | Остаток 80 и своевременная партия 240 | Заказ 0, низкая срочность |
3301004_ | Пустой склад, 240 шт. приедут 02.10 | Заказ 0, высокая срочность: разрыв до прибытия |
3301007_ | 300 шт. приедут лишь 30.11 | Заказ 180: поздняя партия вне горизонта |
3301006_ | Две покупки одного клиента по 600 шт. за день | Разовый всплеск обрабатывается вместе; заказ 156 |
В разделе «Товары» откройте 1101001_ (вентилятор) и 2201001_ (конвектор). Таблица «Зима и лето» показывает независимые 30-дневные сценарии: у вентилятора заказ в январе/июле 80 / 200, у конвектора — 180 / 80. Условия одинаковые, рост и поступления отключены. Это проверка влияния сезонности, а не последовательный календарный план. Все сценарии и данные.
3. Соответствие обязательным требованиям
| Требование кейса | Реализация и наблюдаемое подтверждение | Автоматическая проверка |
|---|---|---|
| Все источники участвуют в расчёте | История продаж, остаток, товар в пути, категория, прирост; изменение входа меняет рекомендацию на странице «Как считается» | MustHave1AllSourcesUsed, MustHave1CategoryMatters |
| Сезонность и устойчивый рост | Профили товара/категории/поставщика и рост год к году; противоположные зимний и летний товары | MustHave2Seasonality, ForecastBoundaries, test_synthetic.py |
| Компенсация упущенного спроса | Оценка по остаткам либо точные загруженные периоды stockout; переключатель меняет потребность | MustHave3Stockout, StockoutEdgeCases, OptionalSources |
| Исключение разовых крупных заказов | По накладным и месячным всплескам; при наличии client_id — по клиенту за день | MustHave4OneOffOrders, ForecastBoundaries, test_synthetic.py |
| Заказы по поставщикам с объяснением | Вкладки поставщиков, объяснение каждой строки, правка, утверждение, Excel | MustHave5GroupedWithReasons, OrderWorkflow |
Для ориентации в предоставленной команде копии правил технический отбор распределён так: функциональность — 20, реализация — 25, README — 20, воспроизводимость — 20, надёжность и безопасность — 15. Этот README даёт маршрут проверки каждого блока: разделы 2–3, методика и архитектура, установка, тесты и ограничения. Это карта доказательств, а не заявление о полученных баллах; актуальность сохранённой копии правил подтверждает организатор.
Методика
Подготовка
Ключ объединения — строковый код 1С с сохранением ведущих нулей. Спрос берётся из месячного отчёта; накладные используются для поиска крупных покупок. Их суммы существенно расходятся с месячными отчётами — предупреждение видно в интерфейсе. Отрицательные месячные продажи обрезаются до нуля; модуль отрицательных строк накладных используется только для выявления аномалий. Смысл знаков требует подтверждения партнёра.
База — последние 12 полных месяцев; для роста используются 24 месяца. Незавершённый месяц и будущие значения не входят в сезонный профиль поставщика. Товарам без продаж за окно спрос автоматически не придумывается.
Исключение выбросов
Строки одного товара группируются по накладной. При наличии обезличенного client_id накладные одного клиента за день объединяются. Выброс одновременно превышает:
- максимум из медианы +
5 × max(1, 1.4826 × MAD)и трёх медиан; - 1,5 медианы положительных месячных продаж;
- 40% объёма месяца в накладных.
Из месячного спроса вычитается превышение над обычной покупкой. Второй фильтр сглаживает месячные всплески без крупной накладной: после снятия сезонности порог равен максимуму из медиана + 5 × 1.4826 × MAD и четырёх медиан. Даты и величины корректировки сохраняются в объяснении.
Сезонность, категории, рост
Профили поставщика и группы — отношение продаж к центрированной скользящей средней. Профиль товара — средние очищенные продажи по месяцам года при достаточной истории. Вес товара — 2, категории — 1, поставщика — 1; отсутствующие профили исключаются, итог нормируется к среднему 1.
У SE используется переданная «Категория 2026» (SE-1, SE-2 и т.д.). Для остальных позиций группа выводится из первых четырёх цифр кода 1С. Коды категорий не интерпретируются как заданные уровни сервиса.
Рост — ограниченное отношение последних 12 месяцев к предыдущим 12 на уровне товара, группы и поставщика. Плановый процент заменяет исторический рост. Учитывается возраст базы и длина будущего горизонта. −100% даёт нулевой прогноз.
Упущенный спрос
Без точных периодов stockout предполагается по неположительному остатку на начало текущего или следующего месяца. Ожидаемый спрос оценивается по месяцам с наличием с учётом сезона. При точных датах добавляется ожидаемый спрос за отсутствующие дни; пересечения периодов учитываются один раз.
Длительное отсутствие (6 месяцев подряд) и !!! требуют ручной проверки. Для !!! принято консервативное, не подтверждённое партнёром допущение: автоматическое предложение равно нулю, расчётная потребность видна в объяснении, менеджер может задать заказ вручную. Политика не зависит от переключателя stockout.
Заказ и срочность
H = срок поставки L + период между заказами R
F = сумма прогнозного дневного спроса за H дней
SS = z × max(1.4826 × MAD, sqrt(базовый спрос)) × sqrt(H / 30)
Потребность = max(0, F + SS − свободный остаток − поставки в горизонте)
Заказ = округление потребности вверх до кратности
Деление месячной базы на 30 — приближение. Страховой запас охватывает весь период защиты при периодическом заказе; z=1.65 не доказывает достигнутый уровень сервиса 95%.
Каждая партия сохраняет дату. Партии вне горизонта и просроченные партии не уменьшают заказ. Неизвестная дата явно помечается и в сценарии заменяется сроком поставки. Риск дефицита проверяется по дням с поступлениями в их даты. Позиция может быть срочной при нулевом заказе: товар уже в пути, но придёт после исчерпания остатка. В таком случае нужны ускорение или перемещение.
Файлы и дополнительные данные
По шесть обязательных файлов в data/demo/iek/, data/demo/se/ и data/demo/techno/. Все 18 файлов уже включены в репозиторий:
| Файл | Содержание |
|---|---|
sales_transactions.xlsx | Дата, накладная, код, товар, единица, склад, количество |
sales_monthly.xlsx | Продажи по месяцам |
stock_monthly.xlsx | Месячные остатки |
in_transit.xlsx | Партии IEK или сводная ведомость SE |
moq.xlsx | Кратность / минимальный объём отгрузки |
seasonality.xlsx | Месячные продажи поставщика в деньгах |
Для первого запуска загружать ничего не нужно. В дальнейшем администратор может заменить файл через «Данные из 1С». Используйте структуру соответствующего файла из data/demo/: парсеры настроены на эти выгрузки 1С, произвольный Excel с другими заголовками не является поддерживаемым форматом. Некорректная загрузка откатывается. Загрузки приоритетнее демо-файлов и лежат в data/uploads/.
Дополнительно поддерживаются:
stock_current.xlsx: Код 1с, Свободный остаток, Дата. Уникальные коды, неотрицательные количества, дата совпадает с датой расчёта. Точные остатки заменяют оценку совпавших позиций.stockouts.xlsx: Код 1с, Начало, Конец. Даты включительны. Для перечисленных товаров периоды приоритетнее месячной оценки; за их пределами известный stockout равен нулю. Для остальных сохраняется оценка.- Столбец
client_idв накладных: только обезличенный ID, без персональных данных.
В исходных файлах нет ID клиентов и точных периодов stockout. Накладная не выдаётся за идентификатор клиента. Покупки одного клиента в разные дни остаются отдельными наблюдениями.
Проверка прогноза на истории
Каждый месяц марта–августа 2026 прогнозируется по предшествующей истории. Товары без прогноза учитываются с нулевым предсказанием. База сравнения — среднее за предыдущие 12 месяцев, не воспроизведение реального процесса Excel компании.
Результаты на исходных файлах после учёта переданных категорий SE:
| Поставщик и единица | WAPE сервиса | WAPE среднего | Смещение сервиса |
|---|---|---|---|
| IEK, штуки | 36,0% | 36,6% | +0,6% |
| IEK, метры | 59,0% | 63,0% | +8,6% |
| IEK, упаковки | 49,8% | 56,8% | +14,5% |
| SE, штуки | 27,8% | 28,4% | −16,1% |
WAPE = Σ|прогноз − факт| / Σфакт; при нулевом факте метрика не определена. Разные единицы не смешиваются. У SE сохраняется систематическое занижение; страховой запас не гарантирует его исправление.
Продажи ограничены наличием, включают разовые сделки; исторического справочника товаров нет. Бэктест оценивает наблюдаемые продажи, а не скрытый спрос, излишки или фактическую экономию. Разница сумм двух рекомендаций — расчётная оценка. Шесть месяцев не гарантируют будущую точность.
4. AI-агент — необязательное подключение
Для расчёта, утверждения, экспорта и всех 63 тестов ключ не нужен. Для живого диалога на странице /agent/ нужен собственный ключ OpenAI API с доступом к gpt-5-mini, доступ к api.openai.com и средства/кредиты в API-проекте. Подписка ChatGPT сама по себе не подключает API к приложению.
Агент понимает вопрос, выбирает разрешённые инструменты и получает результат Python-алгоритма. Реализованы поиск товара, обзор дефицита и избытка, подробный расчёт, изменение условий и сравнение сезонов. Под ответом — ссылки на карточки, дата данных, оценка расхода, вызванные инструменты; для сценария отдельно показаны числа алгоритма.
Подключение без ключа в истории команд
Из корня проекта в PowerShell запустите команду и вставьте ключ в скрытый запрос:
.\.venv\Scripts\python.exe -c "from getpass import getpass; from pathlib import Path; key = getpass('OpenAI API key: ').strip(); assert key, 'Empty key'; Path('.openai-key').write_text(key, encoding='utf-8'); print('Key saved locally')"
На Linux/macOS используйте тот же аргумент -c, заменив путь к Python на .venv/bin/python. Файл .openai-key уже исключён из Git. Он читается при запросе: после сохранения обновите страницу агента, должна появиться отметка «Ключ подключён». Эта отметка подтверждает наличие ключа; доступ к API проверяется первым вопросом.
Другой вариант — переменная окружения OPENAI_API_KEY в процессе сервера. При изменении окружения перезапустите сервер. Приоритет: переменная окружения → OPENAI_API_KEY в local_constants.py → .openai-key. Не публикуйте ключи, не вставляйте их в README и не пересылайте в чат. В клоне и ZIP ключей нет.
Проверка агента
Войдите менеджером, откройте «AI-агент», выберите ТехноСезон:
- «Проверь риски дефицита. Где нужна закупка, а где достаточно ускорить уже заказанный товар?»
- «Для товара 3301002_ сравни срок поставки 30 дней вместо 20». Ожидаются 192 → 228, разница +36.
- «А если на складе будет 100 штук при том же сроке 30 дней?» Ожидаются 132, разница с предыдущим сценарием −96, со стандартным — −60.
- «Сравни вентилятор 1101001_ и конвектор 2201001_ в январе и июле».
Кнопки примеров заполняют вопрос; отправка — «Спросить агента». Ответ обычно занимает 10–40 секунд, при проблемах сети возможен более долгий ответ или сообщение об ошибке. Формулировки могут меняться; числа проверяйте по карточке алгоритма. «Новый диалог» и смена поставщика очищают контекст, последние 6 сообщений сохраняются в серверной сессии.
Границы полномочий и расходов
- Агент не меняет остатки, не создаёт, не утверждает и не отправляет заказы. Он рассчитывает текущие файлы со стандартными настройками; ручные правки сохранённого заказа не учитываются.
- В OpenAI идут вопрос, короткий контекст и агрегаты выбранных товаров. Исходные Excel, клиентские ID и локальный ключ в ответ не передаются. Коммерческую передачу реальных агрегатов следует согласовать с владельцем данных; для демонстрации есть синтетический поставщик.
- Используется Responses API и фиксированный набор проверяемых функций. Произвольный код, SQL и внешние действия модели недоступны.
store=falseне следует трактовать как гарантию нулевого хранения провайдером. - Локальный бюджет агента $5 хранится в SQLite; перед вопросом резервируется $0.10. Максимум 4 обращения к модели и 6 исполняемых инструментов на вопрос. При неизвестном результате сетевого запроса резерв остаётся учтённым.
- Расход — оценка по токенам, без скидки за кэш. Это не баланс аккаунта OpenAI и не ограничение расходов других приложений. Отдельная старая кнопка AI-объяснения строки не входит в этот бюджет.
- При отсутствии ключа или ошибке API чат сообщает об этом. Шаблонный ответ не выдаётся за ответ агента. Обычный расчёт продолжает работать.
Подробности реализации и параметров — docs/AGENT.md, procurement/agent_config.py.
5. Конфигурация и сохранённые данные
Обязательных переменных окружения для локальной проверки нет. Основные настройки находятся в constants.py, при необходимости переопределяются в local_constants.py в корне проекта. Сам файл .env приложение не читает.
| Параметр | Значение / поведение по умолчанию |
|---|---|
DEBUG, SHOW_DEMO_USERS | True — локальный режим хакатона с демо-входом |
ALLOWED_HOSTS | 127.0.0.1, localhost, testserver |
SECRET_KEY | Общий демонстрационный ключ; перед публичным запуском заменить |
SUPPLIERS | IEK, Systeme Electric, ТехноСезон; папки и сроки поставки |
REVIEW_PERIOD_DAYS | 30 дней |
| Срок поставки | IEK — из данных, при отсутствии оценки 40 дней; SE — 40, ТехноСезон — 20 |
HISTORY_MONTHS, SERVICE_LEVEL_Z | 12 месяцев, коэффициент страхового запаса 1.65 |
OPENAI_API_KEY | Пустой; необязателен. Агент поддерживает окружение и .openai-key |
| Модель агента и локальный бюджет | gpt-5-mini, $5 в procurement/agent_config.py |
Период заказа, сроки, прирост и переключатели корректировок можно менять в форме расчёта без изменения кода. Пустой прирост означает оценку по истории; 0 — заданный нулевой прирост. Процент прироста трактуется как годовой. OPENAI_MODEL в constants.py управляет старым объяснением строки, а не моделью нового агента. Старая функция читает ключ из constants.py/local_constants.py; .openai-key подключает именно агента.
| Что создаётся локально | Назначение |
|---|---|
.venv/ | Зависимости конкретного компьютера |
db.sqlite3 | Пользователи, расчёты, правки, утверждения, сессии, учёт бюджета агента |
data/cache/ | Повторно создаваемый кэш чтения Excel |
data/uploads/ | Файлы, загруженные администратором; приоритетнее демонстрационных |
.openai-key, local_constants.py | Локальные секреты/настройки при подключении |
Эти файлы исключены из Git. Для переноса исходников копируйте репозиторий и создавайте окружение заново; для сохранения рабочих решений отдельно сделайте резервную копию базы и загрузок при остановленном сервере. Не подменяйте кэш файлами из недоверенного источника: это внутренний Python pickle, а не формат пользовательского обмена.
Для возврата к воспроизводимой демонстрации удобнее распаковать свежую копию проекта в новую папку и выполнить установку. Существующая база с решениями при этом останется сохранной. После обновления кода: остановите сервер, обновите зависимости, выполните migrate --noinput, затем запустите его снова. Загруженные файлы и правки могут объяснять отличие результатов от таблиц README.
6. Автоматическая проверка и воспроизводимость
Из корня проекта, во втором PowerShell либо после остановки сервера:
.\.venv\Scripts\python.exe -m pip check
.\.venv\Scripts\python.exe manage.py check
.\.venv\Scripts\python.exe manage.py test procurement --verbosity 1
.\.venv\Scripts\python.exe manage.py verify_demo --backtest
На Linux/macOS замените .\.venv\Scripts\python.exe на .venv/bin/python.
| Проверка | Ожидаемый результат |
|---|---|
pip check | No broken requirements found |
Django check | Нет ошибок конфигурации |
test procurement | 63 теста, OK; отдельная тестовая база, без расхода OpenAI API |
verify_demo | JSON для iek, se, techno: дата, количество позиций, срочность, предупреждения; проверяются конечность, неотрицательность и кратность количеств |
verify_demo --backtest | Дополнительно метрики прогноза на истории; время зависит от машины |
verify_demo не создаёт и не утверждает заказы. Предупреждения о качестве исходных данных ожидаемы и не равны падению проверки. Тесты покрывают пять обязательных требований, точные/оценочные остатки, stockout, категории, поздние поставки, единицы измерения, права, экспорт, синтетические сценарии, инструменты агента, бюджет и сетевые ошибки. В тестах внешние ответы API подменяются контролируемыми; реальные вызовы агента проверялись отдельно.
Проверка установки 23.09.2026: исходники из Git распакованы в отдельную папку; создана новая .venv на Python 3.12.14 / Windows x64; установлены все 11 зафиксированных пакетов; миграции применены к новой SQLite; pip check, Django check и 63 теста прошли. Проверка выполнялась без local_constants.py, .openai-key, старой базы и кэша. Пакеты для этой повторной проверки установлены из заранее скачанных wheel-файлов тех же версий. Это проверка чистого окружения приложения на Windows, не новой установки ОС и не подтверждение запуска на Linux/macOS.
В этой же копии прошёл verify_demo --backtest: расчёт трёх поставщиков занял 9,37 секунды до запуска бэктеста. Дополнительно через HTTP-интерфейс Django test client проверены созданные миграциями пользователи и полный путь: вход менеджера → все поставщики → IEK 107 → правка 108 → утверждение → фактический XLSX с 108 → новая правка снимает утверждение. Запрос наблюдателя на изменение получил 403. Это отдельная интеграционная проверка описанного сценария, без вызовов OpenAI; время на другом оборудовании может отличаться.
В .github/workflows/tests.yml подготовлен CI для Python 3.12. На момент проверки GitHub не запускал задание из-за блокировки аккаунта по оплате (account is locked due to a billing issue). Удалённый CI не заявляется как пройденный; приведённые результаты получены локально.
7. Архитектура и техническая реализация
18 XLSX / загрузки администратора
→ loaders.py: проверка, нормализация, объединение по коду 1С
→ engine.py: очистка спроса → сезон/рост → потребность → даты поставок/MOQ
→ services.py: атомарное сохранение расчёта в SQLite
→ Django: таблица → ручная правка → утверждение → XLSX
Вопрос менеджера → OpenAI → разрешённый инструмент → тот же engine.py
← числа и источники ←
→ объяснение и проверяемый сценарий
| Компонент | Ответственность |
|---|---|
constants.py, supply/settings.py | Настройки данных и приложения |
procurement/loaders.py | Парсеры выгрузок, текущие остатки, категории, кэш |
procurement/engine.py | Детерминированный прогноз и расчёт заказа |
procurement/services.py, models.py | Запуск, строки заказа, решения и авторы |
procurement/forms.py, views.py | Валидация, права, сценарии, загрузка, экспорт |
procurement/backtest.py | Последовательная проверка на истории |
procurement/agent*.py | Инструменты, ограниченный цикл OpenAI, бюджет, HTTP-интерфейс |
procurement/templates/, static/ | Django HTML, Bootstrap, JavaScript, SVG-графики |
procurement/migrations/ | Воспроизводимая схема и демо-роли |
procurement/tests.py, test_regressions.py, test_synthetic.py, test_agent.py | Автоматические проверки |
docs/ | Сценарий защиты, синтетические данные и инструкция агента |
Стек: Django 5.2.17, pandas 3.0.1, NumPy 2.3.5, openpyxl 3.1.5, python-calamine 0.8.2, SQLite, Bootstrap и Bootstrap Icons. Полный список с точными версиями — requirements.txt. Сборки frontend нет. Bootstrap и иконки локальные; веб-шрифт Google Fonts необязателен, при отсутствии сети используется запасной шрифт. При разработке использовались AI-помощники; функциональность проверяется кодом, входами и тестами.
Надёжность и безопасность
- Все рабочие страницы требуют входа; операции расчёта, правки, утверждения, экспорта и загрузки проверяют права на сервере. Изменения через POST защищены CSRF.
- Ввод проверяется сервером: сроки и период 1–365 дней, годовой прирост −100…300%, конечные неотрицательные остатки и поставки, кратность заказанного количества.
- Сохранение расчёта атомарно. Ошибка не оставляет частичного заказа. Некорректная загрузка откатывается.
- Правка утверждённой строки сбрасывает её утверждение и старое AI-объяснение. В основной экспорт входят утверждённые положительные количества; черновик выгружается явно отдельно.
- Строки из Excel записываются в экспорт как текст, без исполнения формул. Ответы агента выводятся как текст, без выполнения HTML.
- Агент ограничен выбранным поставщиком и разрешёнными функциями, не имеет инструментов отправки заказа. Ключ остаётся на сервере; ошибки API не показывают сырые ответы провайдера.
- Сохраняются автор и время последнего решения. Полного неизменяемого журнала всех предыдущих решений пока нет.
Локальная конфигурация содержит известные демо-пароли, демонстрационный SECRET_KEY, включённые DEBUG и демо-вход. Не публикуйте её как есть в интернете. Для публичной эксплуатации потребуются замена секретов и паролей, отключение демо-входа/DEBUG, HTTPS, рабочий сервер, конфигурация статики, резервирование, общий ограничитель запросов и проверка доступа к данным. Это отдельный этап; см. официальный checklist Django.
8. Если что-то не запускается
| Симптом | Что проверить / сделать |
|---|---|
py или python не найден | Установить полный Python 3.12 x64 и открыть новый терминал. Если python --version показывает 3.12, использовать его вместо py -3.12 при создании окружения |
| Открывается Microsoft Store вместо Python | Использовать py -3.12 или полный путь к установленному Python; проверить, что интерпретатор действительно установлен |
Не найден manage.py или requirements.txt | Перейти в распакованную папку проекта. Не запускать из ZIP и из родительской папки |
Запуск .ps1 запрещён | Использовать ручной путь из раздела 1; Activate.ps1 не нужен |
No module named django/pandas/... | Выполнить установку через Python именно этой .venv; запускать приложение тем же интерпретатором |
No matching distribution, ошибка сборки NumPy/pandas | Проверить Python 3.12 x64 и доступность пакетов. Не переиспользовать окружение от другой версии/ОС |
pip не может подключиться / ошибка сертификата | Проверить интернет, системную дату и настройки корпоративного proxy/сертификатов. Не отключать TLS-проверку. Повторить установку после восстановления доступа |
venv / ensurepip отсутствует на Linux | Установить модуль venv для той же версии Python средствами ОС, затем повторить создание окружения |
no such table, сообщение о неприменённых миграциях | Из корня проекта выполнить команду manage.py migrate --noinput через Python .venv |
| Порт 8000 занят | Запустить manage.py runserver 127.0.0.1:8001 и открыть http://127.0.0.1:8001/ |
| Страница не открывается | Проверить вывод терминала; сервер должен работать. Открывать http, не https. Использовать 127.0.0.1, не адрес другой машины |
DisallowedHost | Для локальной проверки использовать 127.0.0.1 или localhost; они разрешены в конфигурации |
| Нет файлов / ошибка Excel | Проверить 18 .xlsx в трёх папках data/demo. Убедиться, что загруженная замена соответствует структуре исходной выгрузки |
| Числа отличаются от README | Проверить поставщика, стандартные настройки, data/uploads, локальные переопределения и ручные правки. Для эталона использовать свежую копию |
| Не виден товар с заказом 0 | Включить фильтр «Весь список» |
| Скачать заказ не удаётся | Отметить строку, нажать «Утвердить», убедиться, что количество положительное и после этого не было правки; либо выбрать экспорт черновика |
| «Ключ подключён», но AI не отвечает | Проверить права/кредиты API-проекта, доступ к модели и сеть. Наличие ключа не доказывает его действительность. Ошибки 401/403/429 поясняются в интерфейсе |
Ключ положен в .env, агент его не видит | .env не загружается. Использовать .openai-key, окружение процесса или local_constants.py |
| Локальный лимит агента исчерпан | Обычные расчёты доступны. Не путать этот лимит с балансом OpenAI; бюджет настраивается отдельно в agent_config.py |
Если ошибка остаётся, сохраните текст ошибки без секретов, версию Python, ОС и точную команду. Эти сведения позволят воспроизвести сбой; не пересылайте .openai-key или содержимое локальных настроек с ключами.
9. Известные ограничения
- Остаток IEK оценён без поступлений текущего месяца. Для коммерческого заказа нужна точная ведомость; её загрузка поддерживается. У позиций SE, отсутствующих в сводке, также используется оценка.
- В реальных исходниках нет клиентских ID и точных периодов отсутствия. Накладная не подменяет клиента. Группировка по обезличенному клиенту за день проверяется на синтетических данных; покупки в разные дни остаются отдельными.
- Один склад Алматы; межскладская оптимизация отсутствует. Метры автоматически не переводятся в бухты. MOQ трактуется как кратность — это требуется согласовать с поставщиком.
- Значение категорий и пометки
!!!, возвраты и знаки количеств требуют уточнения у партнёра. Срок SE 40 дней — настройка; срок IEK из открытых заказов может быть нерепрезентативен. - Новые товары без истории не прогнозируются автоматически. Месячные остатки не дают точных внутримесячных периодов отсутствия. Денежная сезонность зависит также от цен и ассортимента.
- Бэктест измеряет ошибку наблюдаемых продаж; фактическое сокращение дефицита и затрат пока не измерено. Синтетические примеры показывают поведение алгоритма, а не бизнес-эффект.
- Excel содержит код 1С, артикул, количество, единицу, кратность, срочность и обоснование. Импорт в конкретную конфигурацию 1С не проверен, API-интеграции и отправки поставщику нет, несмотря на краткое название кнопки экспорта.
- AI может ошибаться в формулировках; числовые результаты доступны отдельно. Для нескольких процессов нужен общий ограничитель одновременных запросов; текущий предназначен для локальной демонстрации.
10. Ценность и развитие после хакатона
Продукт объединяет подготовку заказа и его проверку в одном рабочем процессе. Отличие от простого среднего — совместный учёт разовых покупок, скрытого спроса при отсутствии, сезонности, роста, дат партий и кратности. Особенно показателен нулевой заказ с высоким риском: закупать ещё не требуется, но уже заказанное нужно ускорить. Агент позволяет исследовать эти причины обычным языком, используя тот же расчётный код.
Польза, которую предстоит измерить в пилоте: время подготовки заказа, доля дефицита, дни запаса, избыточный запас и упущенные продажи. Денежная экономия сейчас не заявляется как достигнутая.
| Этап | Что нужно сделать | Критерий успеха |
|---|---|---|
| Подготовка пилота | Согласовать справочники, категории, MOQ, единицы, сроки; получить ежедневные остатки и поступления | Проверенная полнота источников и согласованные правила расчёта |
| Пилот с закупщиком | Сравнивать рекомендации и фактические решения на сопоставимых группах | Изменение времени работы, дефицита и дней запаса без ухудшения доступности |
| Интеграция | Проверить формат с конкретной 1С, автоматизировать обмен и резервирование | Повторяемый импорт/экспорт и отслеживаемые решения |
| Масштабирование | Несколько складов, дополнительные адаптеры поставщиков, PostgreSQL/фоновые задания при росте нагрузки | Измеренные время расчёта, устойчивость и изоляция доступа |
Новый поставщик сейчас подключается через адаптер данных и SUPPLIERS; универсального мастера добавления организаций нет. Следующий этап — подтвердить качество источников и эффект на ограниченном пилоте, затем расширять автоматизацию.
Дополнительные материалы: сценарий защиты, ТехноСезон, AI-агент. Все команды основного запуска и проверки приведены в этом README; открывать дополнительные материалы для первого заказа не обязательно.
Авторы коммитов
История коммитов
- 2026-09-23 17:35Show AI response preloader with elapsed time and reliable cleanupCodex
- 2026-09-23 17:27Fix header overflow with responsive two-row navigationCodex
- 2026-09-23 17:19Document clean setup, jury walkthrough and verified procurement behaviorCodex
- 2026-09-23 17:04Add bounded OpenAI procurement agent with verifiable scenario toolsCodex
- 2026-09-23 16:30Add synthetic supplier workbooks and winter-summer comparisonCodex
- 2026-09-23 15:56Make procurement calculations reproducible and validate order workflowCodex
- 2026-09-23 15:20Вход и роли (менеджер, наблюдатель, администратор), журнал решений, Bootstrap, таблицы с поиском и фильтрамиAnsaganK
- 2026-09-23 15:05Интерфейс для менеджера: простой язык, быстрые фильтры, панель действий; ускорение загрузки и расчётаAnsaganK
Все коммиты (17)
- 2026-09-23 14:53Сумма заказа в деньгах (SE), загрузка выгрузок через интерфейс, бэктест точности прогнозаAnsaganK
- 2026-09-23 14:32Выводимые позиции и долгий дефицит, всплески в месячном отчёте, группа товаров в прогнозе, справочник сроков поставкиAnsaganK
- 2026-09-23 14:31README: методика, алгоритм исключения выбросов, запуск, проверка, ограниченияAnsaganK
- 2026-09-23 14:30Объяснение рекомендации (AI с запасным шаблоном), график спроса, дни покрытия с учётом сезонаAnsaganK
- 2026-09-23 14:28Правка и утверждение заказа, экспорт в xlsx, страница проверки сценариевamandykaueshan-stack
- 2026-09-23 14:17Движок расчёта: разовые заказы, дефицит, сезонность, рост, кратность; тесты must-havetomaszhan99-netizen
- 2026-09-23 14:13Загрузка и очистка выгрузок 1С, сводка по данным, карточка артикулаAnsaganK
- 2026-09-23 14:12Загрузка и очистка выгрузок 1С, сводка по данным, карточка артикулаAnsaganK
- 2026-09-23 14:10Каркас Django-проекта, модели заказа, данные партнёра (IEK, Systeme Electric)AnsaganK
Структура репозитория (83 файлов)
.github/workflows/tests.yml .gitignore README.md constants.py data/demo/iek/in_transit.xlsx data/demo/iek/moq.xlsx data/demo/iek/sales_monthly.xlsx data/demo/iek/sales_transactions.xlsx data/demo/iek/seasonality.xlsx data/demo/iek/stock_monthly.xlsx data/demo/se/in_transit.xlsx data/demo/se/moq.xlsx data/demo/se/sales_monthly.xlsx data/demo/se/sales_transactions.xlsx data/demo/se/seasonality.xlsx data/demo/se/stock_monthly.xlsx data/demo/techno/in_transit.xlsx data/demo/techno/moq.xlsx data/demo/techno/sales_monthly.xlsx data/demo/techno/sales_transactions.xlsx data/demo/techno/seasonality.xlsx data/demo/techno/stock_monthly.xlsx docs/AGENT.md docs/DEMO.md docs/TECHNOSEASON.md local_constants.example.py manage.py procurement/__init__.py procurement/admin.py procurement/agent.py procurement/agent_config.py procurement/agent_tools.py procurement/agent_views.py procurement/apps.py procurement/backtest.py procurement/charts.py procurement/engine.py procurement/forms.py procurement/llm.py procurement/loaders.py procurement/management/__init__.py procurement/management/commands/__init__.py procurement/management/commands/verify_demo.py procurement/migrations/0001_initial.py procurement/migrations/0002_needs_review.py procurement/migrations/0003_cost.py procurement/migrations/0004_roles_audit.py procurement/migrations/0005_demo_roles_users.py procurement/migrations/0006_agentbudget_agentcall.py procurement/migrations/__init__.py procurement/models.py procurement/services.py procurement/static/procurement/agent.js procurement/static/procurement/app.css procurement/static/procurement/table.js procurement/templates/403.html procurement/templates/procurement/agent.html procurement/templates/procurement/backtest.html procurement/templates/procurement/base.html procurement/templates/procurement/catalog.html procurement/templates/procurement/check.html procurement/templates/procurement/index.html procurement/templates/procurement/login.html procurement/templates/procurement/run_detail.html procurement/templates/procurement/run_form.html procurement/templates/procurement/search.html procurement/templates/procurement/sku.html procurement/templatetags/__init__.py procurement/templatetags/procurement_extras.py procurement/test_agent.py procurement/test_regressions.py procurement/test_synthetic.py procurement/tests.py procurement/urls.py procurement/views.py requirements.txt start.ps1 start.sh supply/__init__.py supply/asgi.py supply/settings.py supply/urls.py supply/wsgi.py
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.