AAYMA
RU
Войти

Заказы поставщикам

Django-сервис для менеджера закупа ekt.kz: из выгрузок 1С (продажи, остатки, в пути, кратность, сезонность) рассчитывает заказ по поставщикам с…

Доведённый продукт
Команда «ShoqanTandau» 26💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: 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. Публичная версия не развёрнута; ниже дан самостоятельный локальный запуск.

Навигация

1. Запуск на чистой системе

Что требуется

КомпонентТребование
Python3.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 с другого компьютера — создайте её заново.

Вход и права

РольЛогинПарольВозможности
Менеджер закупаmanagermanager12345Расчёт, правка, утверждение, экспорт, запросы AI-агенту
Наблюдательviewerviewer12345Просмотр результатов, товаров и проверки точности; без операций изменения и платных запросов
Администраторadminadmin12345Все действия, загрузка данных и управление пользователями

На странице входа кнопка демо-роли сразу выполняет вход. Для первого сценария выберите менеджера. На чистой базе список предыдущих расчётов пуст — это нормально. На узком экране разделы находятся под кнопкой «Меню».

2. Первый заказ — маршрут проверки жюри

Основной сценарий без API, около 5 минут

  1. Войдите менеджером. На странице «Заказы» выберите «Все поставщики», оставьте стандартные настройки и нажмите «Рассчитать заказ». Первое чтение Excel может занять до полуминуты; дождитесь результата.
  2. Откройте вкладку IEK, найдите код 030201020_. Для неизменённых исходных файлов рекомендация — 107 шт. Откройте «Почему столько?»: видны основания расчёта. Текст без ключа помечается как шаблонный; числа всё равно вычислены алгоритмом.
  3. Измените поле «Заказать» со 107 на 108, сохраните количество кнопкой «Сохранить количества». Отметьте строку галочкой и нажмите «Утвердить». У этого товара кратность равна 1; у других она может отличаться.
  4. Нажмите «Скачать заказ для 1С». В Excel должна появиться выбранная позиция с количеством 108 и обоснованием. Основная кнопка выгружает утверждённые положительные количества активного поставщика. Через соседнее меню доступен отдельный экспорт «Все рекомендации (черновик)».
  5. Измените утверждённое количество ещё раз и сохраните. Утверждение сбросится: изменённый заказ нужно подтвердить заново. Неутверждённая строка не попадёт в основной экспорт.
  6. Откройте «Как считается», выберите IEK и тот же код. Меняйте входы и наблюдайте пересчёт по таблице ниже. Эта страница проверяет сценарии и не меняет сохранённый заказ.
  7. Откройте «Точность» для проверки прогноза на истории. Затем выйдите через меню пользователя и войдите наблюдателем: кнопки расчёта, правки и утверждения недоступны; сервер также проверяет права.

Что подтверждает сценарий: обработку входных файлов, расчёт, объяснение, участие человека, контроль прав и получение выходного артефакта. Числа ниже получены из данных; в коде нет подстановки готового ответа для этих артикулов.

Независимый сценарий IEK 030201020_Заказ, шт.
Стандартный расчёт107
Добавить разовую продажу 698 шт., очистка включена113
Та же продажа, очистка выключена322
Добавить 54 шт. в пути к базовому варианту53
Увеличить остаток со 191 до 24553
Задать плановый прирост +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
Заказы по поставщикам с объяснениемВкладки поставщиков, объяснение каждой строки, правка, утверждение, ExcelMustHave5GroupedWithReasons, 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-агент», выберите ТехноСезон:

  1. «Проверь риски дефицита. Где нужна закупка, а где достаточно ускорить уже заказанный товар?»
  2. «Для товара 3301002_ сравни срок поставки 30 дней вместо 20». Ожидаются 192 → 228, разница +36.
  3. «А если на складе будет 100 штук при том же сроке 30 дней?» Ожидаются 132, разница с предыдущим сценарием −96, со стандартным — −60.
  4. «Сравни вентилятор 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_USERSTrue — локальный режим хакатона с демо-входом
ALLOWED_HOSTS127.0.0.1, localhost, testserver
SECRET_KEYОбщий демонстрационный ключ; перед публичным запуском заменить
SUPPLIERSIEK, Systeme Electric, ТехноСезон; папки и сроки поставки
REVIEW_PERIOD_DAYS30 дней
Срок поставкиIEK — из данных, при отсутствии оценки 40 дней; SE — 40, ТехноСезон — 20
HISTORY_MONTHS, SERVICE_LEVEL_Z12 месяцев, коэффициент страхового запаса 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 checkNo broken requirements found
Django checkНет ошибок конфигурации
test procurement63 теста, OK; отдельная тестовая база, без расхода OpenAI API
verify_demoJSON для 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; открывать дополнительные материалы для первого заказа не обязательно.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
17
Авторы
4
Файлы
83
Ветки
2

Авторы коммитов

AnsaganK 9Codex 6amandykaueshan-stack 1tomaszhan99-netizen 1

История коммитов

  • 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 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.