О проекте
Команда: GrimStack
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Доведённый продукт
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Сервис автозаказа поставщикам IEK и Systeme Electric по выгрузкам 1С. Прогнозирует спрос, рассчитывает количество по SKU с учётом остатка, товара в пути и кратности, объясняет каждую строку, даёт менеджеру поправить и утвердить заказ и выгрузить XLSX.
Как устроено
Слой app/ingest нормализует XLSX 1С в Dataset. app/engine удаляет разовые крупные заказы (правила B/U: 5×медиана, Q3+3·IQR), восстанавливает упущенный спрос при дефиците и прогнозирует по формуле база × сезонность × тренд с ограничением ×0.67–1.5; для прерывистого спроса используется классификация Syntetos–Boylan. Политика заказа: S = прогноз(L+R) + z·σ·√((L+R)/30), затем округление до кратности; объяснение раскладывает количество по шагам. Результат сравнивается с Excel-методом (среднее за 12 месяцев) и проверяется бэктестом на 6 точках. Есть сценарий «задержка поставщика». LLM-сводка (gpt-4o-mini через OpenAI-совместимый API) кэшируется, товарные группы размечены офлайн моделью Laya.
Ключевые решения
- IQR outlier cleaning
- stockout demand restoration
- seasonality + trend forecast
- Syntetos–Boylan classification
- safety stock (z·σ·√L)
- MOQ rounding
- backtest vs Excel baseline
- what-if lead time scenario
- LLM summary with cache
Особенности
Прозрачная «водопадная» декомпозиция рекомендации: сумма шагов (прогноз, страховой запас, минус остаток, минус в пути, округление) точно равна количеству. Есть what-if сценарий задержки поставщика и тест на границы слоёв архитектуры. Собранный фронтенд лежит в репозитории, поэтому для запуска нужен только Python.
Стек
Python · FastAPI · Pydantic · pandas · NumPy · openpyxl · React · TypeScript · Vite · TanStack Query · ApexCharts · SQLite · Docker
Модели
GPT-4o-mini · NVIDIA NIM (OpenAI-compatible) · Laya
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-aa7e8423-grimstack.
README
README.mdGrimStack
Планирование заказов поставщикам по выгрузкам 1С: прогноз спроса, рекомендации по SKU и контроль решений менеджера.
Запуск за минуту
Нужен Python 3.12 или новее; Node.js и API-ключ не нужны. Из корня проекта:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m app
Через 10–15 секунд, после строки Application startup complete, откройте http://localhost:8000. Windows, Docker и запуск на другом порту описаны в разделе «Быстрый старт», сценарий для проверки — в разделе «Проверка работы».
Содержание
- Запуск за минуту
- Назначение
- Возможности
- Сценарий работы
- Архитектура
- Методология расчёта
- Технологии
- Данные и интеграции
- Быстрый старт
- Проверка работы
- Основные команды
- API и ошибки
- Качество прогноза
- Известные ограничения
- Внешние материалы и AI-инструменты
- Развёртывание
Назначение
Сейчас количество к заказу считают Excel-методом — по среднему сырых продаж за последние 12 месяцев. Такой расчёт не учитывает месяцы без товара, разовые крупные заказы, сезонность и тренд. GrimStack помогает менеджеру закупок подготовить заказы IEK и Systeme Electric по выгрузкам 1С. Сервис рассчитывает количество для каждого SKU с учётом спроса, остатка, товара в пути и кратности поставки. Менеджер проверяет рекомендацию, при необходимости меняет количество и утверждает заказ.
Возможности
Приложение покрывает путь от загрузки выгрузок до утверждения и экспорта заказа.
| Возможность | Что получает менеджер |
|---|---|
| Данные | Встроенные XLSX-выгрузки IEK и SE или загрузка собственных файлов; для нового поставщика — ввод названия и выбор формата IEK/SE |
| Расчёт | Прогноз с обработкой разовых продаж, месяцев без товара, сезонности и тренда; сравнение с Excel-методом |
| Работа с заказом | История SKU, объяснение рекомендации, правка количества с проверкой кратности, утверждение и экспорт XLSX |
| Сводка | Запрос к OpenAI-совместимому API или подготовленный образец из samples/cache/ |
| Проверка метода | Бэктест прогноза на шести контрольных точках в data/backtest/report.json |
| Сценарий «что если» | «Аналитика» → блок «Задержка поставщика»: второй расчёт с увеличенным сроком поставки и изменения количества, срочности и суммы (POST /api/runs/compare) |
Сценарий работы
От входных выгрузок до результата менеджер проходит четыре шага:
- Выбирает встроенные данные поставщика или загружает собственные XLSX-файлы. Для нового поставщика вводит название и выбирает формат выгрузок 1С — как у IEK или SE.
- Запускает расчёт и сравнивает рекомендацию с базовым Excel-методом.
- Проверяет историю и объяснение по SKU, при необходимости меняет итоговое количество с учётом кратности.
- Утверждает заказ и скачивает XLSX для 1С. Сервис не отправляет заказ поставщику автоматически.
Архитектура
Один процесс FastAPI обслуживает API и собранный React-интерфейс. Данные проходят через нормализацию, расчёт и проверку заказа:
flowchart LR
XLSX["Выгрузки 1С · XLSX"] --> Ingest["app/ingest · нормализация"]
Ingest --> Engine["app/engine · прогноз и заказ"]
Engine --> API["app/api · FastAPI"]
UI["frontend/dist · React"] <--> API
API --> Store["app/store · прогоны и утверждения"]
API --> AI["app/ai · кэш или LLM"]
app/ingest/ приводит выгрузки 1С к единому Dataset. app/engine/ очищает спрос, восстанавливает спрос в месяцы без товара, прогнозирует и рассчитывает заказ. app/api/ вызывает ядро, проверяет изменения менеджера и отдаёт JSON/XLSX. app/store.py держит наборы и прогоны в памяти. frontend/ показывает параметры, строки заказа и историю SKU.
analyze учитывает очистку, stockout, сезонность и тренд. baseline использует среднее сырых продаж за последние 12 закрытых месяцев без этих поправок при той же политике остатка, товара в пути и кратности.
Формы данных заданы в app/contracts.py и повторены в frontend/src/api/types.ts. Подробности алгоритма находятся в docs/design.md, структура проекта — в docs/structure.md.
Методология расчёта
Расчёт идёт по каждому SKU на месячной сетке, дата данных — 22.09.2026 (app/engine/, полное описание — docs/design.md §4).
-
Исключение разовых крупных заказов (
cleaning.py). По строкам расходных накладных 2025+ для SKU считаются медиана, квартили и вторая по величине строка. Нужно не меньше 5 строк у IEK и 20 у SE. Строка считается разовой, если выполнено одно из правил:- B — все условия сразу:
q > 5 × медиана,q > Q3 + 3·IQR,q ≥типичного месяца SKU, и такие строки были не больше чем в 3 месяцах (у SE — в 4). Иначе это регулярный опт; - U — «беспрецедентная» строка:
q ≥ 2 ×вторая по величине иq > 5 × медиана.
Разовая строка заменяется медианной, излишек вычитается из месяца. Документ с тремя и более такими строками помечается как проектный заказ одного клиента. Паллетный поток SE (кратные партии) в статистику не входит.
- B — все условия сразу:
-
Упущенный спрос при дефиците (
stockout.py). Месяц с нулевым или низким остатком получает добавкубаза × (1 − доля дней в наличии). База — медиана 6 предыдущих месяцев, когда товар был в наличии; добавка не больше2 × база. -
Прогноз (
forecast.py):база × сезонность(месяц) × тренд × (1 + прирост %). База — среднее очищенного и восстановленного спроса за 12 закрытых месяцев без сезонности. Сезонность считается по товарной группе, а при длинной устойчивой истории подмешивается собственный профиль SKU. Тренд — последние 6 месяцев к тем же месяцам год назад, ограничен ×0,67…×1,5 и сжат при короткой истории. Редкий спрос (Syntetos–Boylan: intermittent/lumpy) заказывается не меньше медианной продажи. -
Заказ (
policy.py):S = прогноз на (L + R) + z·σ·√((L + R)/30), где уровень сервиса z зависит от категории SKU.заказ = ⌈(S − остаток − в пути с ETA в горизонте) / кратность⌉ × кратность. Срочность — по дням покрытия: меньше L — срочно, меньше L + R — скоро. -
Обоснование (
explain.py). У каждой строки есть главная причина текстом и разложение количества по шагам: прогноз, страховой запас, минус остаток, минус в пути, округление. Сумма шагов равна рекомендации.
Технологии
Стек подтверждён requirements.txt, frontend/package-lock.json и Dockerfile.
| Область | Технологии | Назначение |
|---|---|---|
| Сервер и API | Python 3.12+, FastAPI, Pydantic, Uvicorn | HTTP-контракт, валидация и выдача интерфейса |
| Расчёт и файлы | pandas, NumPy, openpyxl | Обработка выгрузок, прогноз и экспорт XLSX |
| Интерфейс | React, TypeScript, Vite, TanStack Query, ApexCharts | Работа с расчётом, заказами и графиками |
| Запуск | Docker или локальный Python | Один серверный процесс с готовым frontend/dist |
| AI | Laya (офлайн), OpenAI-совместимый API (gpt-4o-mini по умолчанию; NVIDIA NIM через OPENAI_BASE_URL) | Товарные группы по наименованиям; текстовая сводка по готовым цифрам заказа |
Данные и интеграции
В репозитории есть выгрузки 1С IEK и Systeme Electric в data/raw/iek/ и data/raw/se/. Через интерфейс можно загрузить собственный набор XLSX-файлов для одного из них или добавить нового поставщика: указать название, выбрать формат файлов IEK/SE и загрузить выгрузки тех же ролей. Это два поддерживаемых формата, а не универсальный импорт произвольной таблицы 1С. После загрузки интерфейс выбирает созданный набор и поставщика для следующего расчёта. Профиль данных описан в docs/data-profile.md, состав файлов и API — в docs/API.md.
Товарные группы читаются из data/categories/sku_categories.csv. Для подготовки этого справочника отдельно применялась модель Laya; при запуске сервиса она не нужна. Сводка заказа использует OpenAI-совместимый API с необязательными OPENAI_API_KEY, OPENAI_BASE_URL и MODEL. Без ключа основные расчёты, правка и экспорт работают; для исходных расчётов доступны образцы из samples/cache/. Если подходящего образца нет, сводка возвращает 503.
Быстрый старт
Для запуска готового приложения достаточно Docker или Python 3.12 и новее (проверено на 3.12 и 3.14). Node.js не нужен: собранный интерфейс frontend/dist уже находится в репозитории. Все команды выполняются из корня проекта; остановка сервера — Ctrl+C.
Docker: macOS, Linux и Windows
Установите и запустите Docker Desktop (macOS/Windows) или Docker Engine (Linux). В macOS используйте терминал zsh/bash, в Linux и Windows WSL — bash, в Windows без WSL — CMD. Команды одинаковы во всех этих терминалах:
docker build -t grimstack .
docker run --rm -p 8000:8000 -v grimstack-var:/srv/var grimstack
Docker выбирает поддерживаемый вариант базового образа для своей платформы. Именованный том grimstack-var сохраняет базу утверждений SQLite var/app.db между запусками контейнера. При повторном запуске достаточно второй команды.
Python: macOS, Linux и Windows WSL
Установите Python 3.12 или новее с модулями venv и pip; версию покажет python3 --version. В macOS в терминале zsh/bash, а в Linux и Windows WSL в bash выполните из корня проекта:
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m app
Окружение .venv создаётся для текущей ОС. Если проект используется и из Windows, и из WSL, держите отдельную копию проекта с собственным .venv для каждой среды.
Python: Windows CMD
Установите Python 3.12 или новее с Python Launcher (py) и pip. В CMD из корня проекта выполните:
py -3 -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe -m app
После сообщения Uvicorn о старте откройте http://localhost:8000. Адрес http://localhost:8000/health должен вернуть {"status":"ok"}. Первая загрузка встроенных XLSX может занять время; дождитесь сообщения о старте перед проверкой.
Если порт 8000 занят (в логе address already in use), запустите сервис на другом порту и откройте http://localhost:8001:
PORT=8001 .venv/bin/python -m app
В Windows CMD сначала выполните set PORT=8001, затем .venv\Scripts\python.exe -m app.
Настройка окружения
Необязательные настройки задаются переменными окружения или файлом .env в корне проекта. Для локального Python можно скопировать .env.example и заполнить нужные значения. Для Docker в macOS zsh/bash, Linux/WSL bash или Windows CMD добавьте --env-file .env перед именем образа:
docker run --rm -p 8000:8000 -v grimstack-var:/srv/var --env-file .env grimstack
| Переменная | Назначение |
|---|---|
OPENAI_API_KEY | Ключ LLM для новых сводок |
OPENAI_BASE_URL | Адрес OpenAI-совместимого провайдера, в том числе NVIDIA NIM |
MODEL | Идентификатор модели у выбранного провайдера |
PORT | Порт сервиса; по умолчанию 8000 |
Если меняете PORT при запуске Docker, укажите тот же порт с обеих сторон аргумента -p.
Проверка работы
Дождитесь запуска Uvicorn и откройте http://localhost:8000/health: ответ {"status":"ok"} подтверждает, что встроенные данные загружены. Основной сценарий проверяется без API-ключа:
- Запустите приложение по инструкции для своей ОС в разделе «Быстрый старт» и откройте
http://localhost:8000. - Откройте раздел «Данные и расчёт», выберите Systeme Electric из встроенных данных
data/raw/se/, оставьте метод «Наш расчёт» и параметры по умолчанию, нажмите «Рассчитать». Затем перейдите в «Заказы». - В поиске введите
030200193_и откройте строку IMT35150. Видно 37 800 шт. в пути, рекомендацию 22 680 шт. и сравнение с Excel-методом 0 шт. - Нажмите «Сводка» у поставщика: появится сохранённый текст с пометкой «Из кэша». Нажмите «Excel для 1С»: скачается
order_SE_<дата>.xlsx. - Для проверки управляемости измените итоговое количество IMT35150 на
26 460(семь упаковок по3 780) и сохраните: в строке появится26 460. Затем утвердите заказ. После утверждения правка блокируется; автоматической отправки поставщику нет.
Основные команды
После первой установки запускайте сервис и тесты из корня проекта командами для своей среды.
| Задача | macOS zsh/bash, Linux и WSL bash | Windows CMD |
|---|---|---|
| Повторный запуск | .venv/bin/python -m app | .venv\Scripts\python.exe -m app |
| Тесты | .venv/bin/python -m pytest -q | .venv\Scripts\python.exe -m pytest -q |
Для повторной сборки интерфейса нужны Node.js 24 или новее и npm. В macOS zsh/bash, Linux/WSL bash или Windows CMD выполните из корня проекта:
npm ci --prefix frontend
npm run build --prefix frontend
Сборка обновляет frontend/dist; обычный запуск готового приложения Node.js не требует.
API и ошибки
Маршруты API имеют префикс /api. Ошибки возвращаются в едином JSON-формате {"detail": "...", "code": "...", "meta": {}}.
| HTTP | code | Ситуация |
|---|---|---|
| 404 | not_found | Нет прогона, SKU, поставщика, набора данных или маршрута API; неверный метод у маршрута /api/* |
| 404 | backtest_not_found | Файл отчёта бэктеста отсутствует |
| 405 и другие HTTP-ошибки | http_error | Неподдерживаемый запрос вне /api, например неверный метод у /health |
| 409 | conflict | Заказ уже утверждён |
| 422 | validation_error | Запрос не прошёл проверку схемы |
| 422 | invalid_input | Некорректное количество или форма загрузки, файл больше 30 МБ |
| 422 | unknown_role, missing_file, empty_file, not_xlsx, bad_format | Ошибка XLSX; роль файла в meta.file_role, когда известна |
| 503 | unavailable | Сводка недоступна через провайдера и в кэше нет подходящего ответа |
| 500 | internal_error | Неожиданная ошибка; детали пишутся в серверный лог |
Качество прогноза
Отчёт бэктеста хранится в data/backtest/report.json и доступен по GET /api/backtest; методика описана в docs/backtest.md. На шести контрольных точках с марта по август 2026 года WAPE по очищенным продажам составил 0,3972 у IEK против 0,4055 у базового метода; у SE — 0,230 против 0,275. Это оценка прогноза спроса, а не экономического эффекта или качества итогового заказа.
Известные ограничения
Ограничения важны для интерпретации рекомендаций и выбора среды запуска.
- Прогоны и загруженные наборы хранятся в памяти одного процесса и пропадают после перезапуска. База утверждений и их истории хранится в SQLite
var/app.db; учётных записей и авторизации нет. - Новый поставщик добавляется только в загруженный набор данных. Его выгрузки должны соответствовать выбранному формату IEK или SE; отдельной постоянной регистрации поставщиков нет.
- Текущий остаток IEK является нижней оценкой из-за неизвестных приходов сентября. Цен IEK в данных нет, поэтому сумма заказа для него не показывается.
- Срочность во многом держится на этой оценке: из 382 срочных позиций 377 рассчитаны по оценочному остатку (в интерфейсе — подпись под показателем и значок ≈ у остатка). Перед утверждением остаток стоит сверить с 1С.
- Склад: в выгрузках один склад (Алматы); у SE текущий остаток — сумма складских остатков (свободный, витрина, ТЗ, РЦ, розница), поэтому расчёт ведётся по складу целиком. Выбор «по категории» работает по товарным группам и по классам поставщика.
- У SKU, где накладных меньше 5 (IEK) или 20 (SE), разовые заказы не распознаются: статистики строк недостаточно, и крупная продажа такого редкого товара поднимет рекомендацию. Клиента в выгрузках нет, поэтому «одного клиента» заменяет документ-накладная.
- Транзакции доступны только с 2025 года. Разовые продажи 2024 года нельзя проверить по документам; без необязательного
sales_txанализ разовых заказов и дней наличия ограничен. Паллетный поток SE не входит в базовый спрос. - Срок поставки SE основан на допущении в 40 дней; параметры расчёта можно изменить в интерфейсе. Новые LLM-сводки требуют проверки по числовым строкам заказа.
- Готовые сводки в
samples/cache/есть только для исходных расчётов с параметрами по умолчанию. После правки количества или смены параметров безOPENAI_API_KEYкнопка «Сводка» показывает объяснение вместо текста (код503); расчёт, правка и экспорт от этого не зависят. - Бэктест использует исторические срезы с текущими справочниками SKU; внешняя проверка на других наборах данных не проводилась.
Внешние материалы и AI-инструменты
Раскрытие по п. 6.4 Положения.
- Данные: выгрузки 1С IEK и Systeme Electric, предоставленные партнёром кейса (ТОО «Электрокомплект»), в
data/raw/. Других внешних датасетов в расчёте нет. - Библиотеки: сервер — FastAPI, Uvicorn, Pydantic, pandas, NumPy, openpyxl, python-dotenv, OpenAI Python SDK (
requirements.txt); интерфейс — React, TypeScript, Vite, TanStack Query, ApexCharts, Radix UI и др. (frontend/package.json). - Модель Laya (
convaiinnovations/laya, мультиязычный чекпойнт, Convai Innovations, Apache 2.0) — офлайн-классификация наименований по товарным группам (scripts/classify_laya.py), в сервис не входит. Правила по ключевым словам определили 3 037 из 3 667 SKU (83 %); ответ модели принимался только при уверенности ≥ 0,9 — на размеченных правилами SKU она совпадает с ними в 81 % случаев. Моделью размечено 11 SKU, 619 неуверенных ответов отнесены к «Прочее». Замер —data/categories/laya_eval.json, сырые ответы —data/categories/laya_raw.csv. - LLM
gpt-4o-miniчерез OpenAI-совместимый API — текст сводки по заказу поставщику (app/ai/llm.py). Модель получает уже посчитанные цифры и ничего не пересчитывает. 8 ответов сохранены вsamples/cache/для запуска без ключа. - AI-инструменты разработки: Claude Code (Anthropic) — ядро расчёта, AI-слой, бэктест, тесты, документация и правки интерфейса; Codex (OpenAI) — API и интерфейс. Сгенерированный код проверен автотестами (
pytest) и вручную в браузере. - Готовые шаблоны интерфейса не использовались.
Развёртывание
Публичной развёрнутой версии нет. Рабочее приложение запускается локально по разделу «Быстрый старт»: FastAPI раздаёт API и собранный интерфейс на http://localhost:8000. Для публичного доступа текущей реализации необходимы авторизация и постоянное хранилище прогонов.
Авторы коммитов
История коммитов
- 2026-09-23 17:47fix(frontend): исправлено расположение фильтров заказовdunanhub
- 2026-09-23 17:42feat(readme): добавлен раздел «Методология расчёта» с описанием алгоритмов и подходов к прогнозированию fix(pipeline): уточнено условие для предупреждений о текущем остатке для поставщика IEK fix(cachNurkanat Aliar
- 2026-09-23 17:42chore(docker): исключил временные каталоги pytest из образа и git, сохранив чистую рабочую веткуdunanhub
- 2026-09-23 17:41feat(suppliers): добавил загрузку нового поставщика по шаблону выгрузок 1с, связав форму с расчётом и экспортомdunanhub
- 2026-09-23 17:23fix(ui): убрал внешние отступы панели и скрытую подпись графика, исправив отображение на весь экранdunanhub
- 2026-09-23 17:21docs(readme): вернул раздел «Внешние материалы и AI-инструменты» (п. 6.4), удалённый при обновлении документации; проблема в «Назначении»Nurkanat Aliar
- 2026-09-23 17:20feat(data): обновил экран параметров и загрузки, уплотнив форму и адаптировав действия для телефонаdunanhub
- 2026-09-23 17:18feat(analytics): обновил графики и таблицы аналитики, разделив количества по единицам и улучшив чтение на телефонеdunanhub
Все коммиты (92)
- 2026-09-23 17:14feat(orders): обновил реестр заказов, оформив таблицу, карточки и объяснение товара для мобильного просмотраdunanhub
- 2026-09-23 17:12feat(overview): перестроил обзор закупок, разместив графики над показателями и улучшив карточки для мобильных экрановdunanhub
- 2026-09-23 17:10fix(frontend): различимые цвета срочности и изменений в новой теме; тест сравнения сценариевNurkanat Aliar
- 2026-09-23 17:10feat(ui): перестроил каркас панели закупок, добавив светлую рамку, навигацию с иконками и компактный мобильный вариантdunanhub
- 2026-09-23 17:07feat(ui): обновил общую светлую тему, оформив элементы управления, статусы, модальные окна и карточки показателейdunanhub
- 2026-09-23 16:58feat: обновление документации по структуре проекта, правилам разработки и интерфейсуSNOWNUMB
- 2026-09-23 16:56refactor(core): прямые импорты вместо заглушек времени разработкиNurkanat Aliar
- 2026-09-23 16:54docs(readme): путь к сценарию задержки без снятой надписи «Что если»Nurkanat Aliar
- 2026-09-23 16:53docs: SQLite для утверждений в design/structure, фактические файлы app/api, маршруты compare, approvals и backtest в API.mdNurkanat Aliar
- 2026-09-23 16:53docs(readme): запуск за минуту, Python 3.12+, занятый порт, сценарий «что если», точные коды ошибокNurkanat Aliar
- 2026-09-23 16:53fix(frontend): окно утверждения считает правки и оценочный остаток по всему заказу, а не по фильтруNurkanat Aliar
- 2026-09-23 16:51chore: добавил .claude/ в .gitignore для исключения временных файловNurkanat Aliar
- 2026-09-23 16:50docs(project): уточнил хранение утверждений в sqlite и поддержку nvidia nim, добавив источник модели layadunanhub
- 2026-09-23 16:45chore(frontend): обновил собранные файлы сайта после добавления графиков, разделив тяжёлый apexcharts и основные экраныdunanhub
- 2026-09-23 16:44feat(frontend): добавил сравнение сценариев задержки поставщика, подключив расчёт через api и раздельные графики по единицамdunanhub
- 2026-09-23 16:44feat(frontend): добавил график шагов расчёта товара, показав вклад каждого слагаемого и итог рекомендованного заказаdunanhub
- 2026-09-23 16:43feat(frontend): добавил графики ошибки прогноза и уровня сервиса в бэктест, сохранив табличные значения по поставщикамdunanhub
- 2026-09-23 16:36docs(readme): раскрытие внешних материалов и AI-инструментов (п. 6.4), SQLite вместо approvals.jsonNurkanat Aliar
- 2026-09-23 16:32style(frontend): спокойный интерфейс рабочего инструмента вместо шаблонного дашбордаNurkanat Aliar
- 2026-09-23 16:30fix(frontend): расчёт по товарной группе, честные KPI и понятные сообщения по сценарию ТЗNurkanat Aliar
- 2026-09-23 16:27docs: утверждения хранятся в SQLite var/app.db, а не в JSONNurkanat Aliar
- 2026-09-23 16:24feat(docs): обновил описание проекта и содержание в README.mdSNOWNUMB
- 2026-09-23 16:20feat(api): перенёс утверждения в sqlite, добавив историю заказов и импорт старых записей без потери данныхdunanhub
- 2026-09-23 16:20fix(frontend): округлил количество и деньги, добавив знаки к шагам объяснения заказаSNOWNUMB
- 2026-09-23 16:20feat(frontend): добавил бэктест в аналитику, сравнив точность прогноза и уровень сервиса поставщиковSNOWNUMB
- 2026-09-23 16:20feat(frontend): пересчитал расхождения методов по абсолютной разнице и показал товары с подписями значенийSNOWNUMB
- 2026-09-23 16:20feat(frontend): обновил график истории, выделив четыре ряда и периоды дефицита разными цветамиSNOWNUMB
- 2026-09-23 16:19feat(frontend): обновил показатели обзора, вынеся сумму заказа и излишки в главные карточкиSNOWNUMB
- 2026-09-23 16:17feat(frontend): переставил ключевые столбцы заказа и перенёс обоснование под название товара для быстрого просмотраSNOWNUMB
- 2026-09-23 16:16fix(frontend): пересобрал опубликованные ресурсы интерфейса, синхронизировав ссылки на стили и скрипты в distSNOWNUMB
- 2026-09-23 16:11feat(api): улучшил экспорт заказа в excel, добавив итоговую строку и лист параметров расчётаdunanhub
- 2026-09-23 16:10cache: сводки LLM под итоговые обоснования (8 шт., промпт v2)Nurkanat Aliar
- 2026-09-23 16:08core: причина в обосновании — только то, что реально двигает прогнозNurkanat Aliar
- 2026-09-23 16:07style(frontend): обновил оформление рабочего экрана, сохранив исходную палитру и адаптировав карточки, навигацию и таблицуSNOWNUMB
- 2026-09-23 16:05cache: сводки LLM под итоговое ядро (8 шт., промпт v2)Nurkanat Aliar
- 2026-09-23 16:02core: сезонность только там, где она есть; понятные ошибки загрузкиNurkanat Aliar
- 2026-09-23 16:01feat(api): оформил swagger на русском, добавив схемы ошибок и файлов для всех публичных маршрутовdunanhub
- 2026-09-23 15:54feat(api): добавил сравнение двух прогонов, сохранив оба расчёта и выделив изменения количества по товарамdunanhub
- 2026-09-23 15:50fix(api): ограничил ручное количество заказа, уточнив проверку кратности и добавив ранний лог загрузки данныхdunanhub
- 2026-09-23 15:50docs(tasks): задание Ф на полировку интерфейса по ревью «глазами жюри»Nurkanat Aliar
- 2026-09-23 15:46docs(readme): исправил факты о модели и сводках, уточнив ограничения расчёта, варианты запуска и ссылки на документациюSNOWNUMB
- 2026-09-23 15:43feat(api): добавил маршрут отчёта бэктеста, сохранив исходное содержимое и предусмотрев отдельную ошибку при отсутствии файлаdunanhub
- 2026-09-23 15:41docs(readme): обновил раздел деплоя, указав отсутствие проверенной ссылки и способ локального запуска сервисаSNOWNUMB
- 2026-09-23 15:37feat(core): объединил уточнения расчёта и кэша сводок, обновив обоснования, примеры ответов и проверкиSNOWNUMB
- 2026-09-23 15:36feat(api): объединил запуск и логирование запросов, добавив измерение времени ответа и проверку поведения APISNOWNUMB
- 2026-09-23 15:35core: месяц в обосновании, излишки по всей выборке, предупреждение об оценочном остатке; кэш LLMNurkanat Aliar
- 2026-09-23 15:34chore(git): объединил новые изменения API и сводок, обновив ключи кэша после смены версии промптаSNOWNUMB
- 2026-09-23 15:33feat(api): настроил загрузку локального окружения и логирование запуска и запросов, добавив измерение времени и проверку поведенияdunanhub
- 2026-09-23 15:31test(api): обновил фикстуру маршрутов, изолировав подмешивание товарных групп и генерацию сводки при проверкахSNOWNUMB
- 2026-09-23 15:30chore(git): объединил локальные и удалённые изменения, сохранив единый API, актуальные сводки и проверенный бэктестSNOWNUMB
- 2026-09-23 15:28ai: сводка в тенге, числа с пробелом, без сравнения Excel с самим собой (промпт v2)Nurkanat Aliar
- 2026-09-23 15:28test(api): исправил фейк загрузки, вернув настоящий датасет вместо словаря и убрав обход обработки товарных группdunanhub
- 2026-09-23 15:22test(api): исправил фикстуру загрузки после добавления товарных групп, изолировав обработку категорий и создание сводкиdunanhub
- 2026-09-23 15:20feat(project): добавил единый запуск и обновил интерфейс закупок, дополнив API, бэктест, документацию и собранное приложениеSNOWNUMB
- 2026-09-23 15:09docs: деплоя нет — проверка локальным запуском, Docker как запасной способNurkanat Aliar
- 2026-09-23 15:07backtest: наш метод против Excel-метода на реальной истории, без утечки будущегоNurkanat Aliar
- 2026-09-23 15:06ai: LLM-сводка по заказу с кэшем и товарные группы (правила + Laya с измеренным порогом)Nurkanat Aliar
- 2026-09-23 15:04test(api): исправил проверки маршрутов после подключения реального ядра, изолировав тестовые ответы и убрав жесткие количестваdunanhub
- 2026-09-23 15:01core: группы Laya и для загруженных выгрузок; llm_available только по *.json в кэшеNurkanat Aliar
- 2026-09-23 14:56feat(project): добавил API заказов и сводок, подключил графики, бэктест и классификацию товаровSNOWNUMB
- 2026-09-23 14:53feat(api): добавил маршруты расчёта и экспорта заказов, настроив хранение прогонов и единый формат ошибокdunanhub
- 2026-09-23 14:52fix(frontend): сбросил устаревший прогон после загрузки файлов, улучшил доступность таблицы и пересобрал приложениеSNOWNUMB
- 2026-09-23 14:47feat(frontend): дополнил таблицу поставками и прогнозом, описал проверку проекта и обновил собранное приложениеSNOWNUMB
- 2026-09-23 14:40feat(frontend): обновил демоданные реальным расчётом, вывел сроки поставки и пересобрал клиент без клиентского экспортаSNOWNUMB
- 2026-09-23 14:37test: граница слоёв проверяет и app/ai — без веб-слоя, клиент openai разрешёнNurkanat Aliar
- 2026-09-23 14:35feat: добавлены моковые данные для метаданных, результатов прогонов и истории SKUSNOWNUMB
- 2026-09-23 14:35feat: добавлены функции для сохранения блобов, форматирования чисел и валют, а также проверки валидности количестваSNOWNUMB
- 2026-09-23 14:35feat: добавлены компоненты для панели SKU, графика истории и загрузки данныхSNOWNUMB
- 2026-09-23 14:35fix(frontend): исправил сборку и деморежим интерфейса, добавив стили страницы, поддержку ref, шрифты и цвета из токеновSNOWNUMB
- 2026-09-23 14:35fix(frontend): исправил обработку загрузки и ошибок API, обновил деморежим и зафиксировал собранные ресурсы интерфейсаSNOWNUMB
- 2026-09-23 14:26docs: итоговая структура репозитория и инженерные правила; тест границ слоёвNurkanat Aliar
- 2026-09-23 14:23core: правки по ревью — точный водопад, минимум редкого спроса, группы Laya, sales_tx необязателенNurkanat Aliar
- 2026-09-23 14:16core: реальный расчёт заказов — загрузчики IEK/SE и конвейер engineNurkanat Aliar
- 2026-09-23 14:10refactor: удалён статический предпросмотр дизайн-системыSNOWNUMB
- 2026-09-23 14:08feat: добавлен дизайн-контракт для экрана менеджера закупаSNOWNUMB
- 2026-09-23 13:51build: Dockerfile моносервиса и .dockerignoreNurkanat Aliar
- 2026-09-23 13:46docs(tasks): KeyError из engine.history → 404; какие тесты гонять APINurkanat Aliar
- 2026-09-23 13:44core: Dataset, помощники разбора 1С, конфиг, синтетика и приёмка must-haveNurkanat Aliar
- 2026-09-23 13:40docs: план ядра; Docker и Northflank за Aliar; разовая строка заменяется типичнойNurkanat Aliar
- 2026-09-23 13:37core: заглушки ingest/engine/ai с финальными сигнатурами; задания для API и фронтаNurkanat Aliar
- 2026-09-23 13:35contract: Pydantic-модели ядро↔API↔фронт, JSON-моки и их проверкаNurkanat Aliar
- 2026-09-23 13:30docs: архитектура, алгоритм и контракт сервиса автозаказа; профиль данныхNurkanat Aliar
- 2026-09-11 15:14Update README to remove 'First commit' lineSNOWNUMB
- 2026-09-11 14:26Add initial project description to READMENurkanat Aliar
Структура репозитория (141 файлов)
.dockerignore .env.example .gitignore Dockerfile README.md app/__init__.py app/__main__.py app/ai/__init__.py app/ai/groups.py app/ai/llm.py app/api/__init__.py app/api/routes.py app/api/schemas.py app/contracts.py app/engine/__init__.py app/engine/cleaning.py app/engine/config.py app/engine/explain.py app/engine/forecast.py app/engine/pipeline.py app/engine/policy.py app/engine/stockout.py app/ingest/__init__.py app/ingest/common.py app/ingest/dataset.py app/ingest/iek.py app/ingest/se.py app/main.py app/store.py contracts/sample_meta.json contracts/sample_run.json contracts/sample_sku_history.json data/backtest/report.json data/categories/laya_eval.json data/categories/laya_raw.csv data/categories/sku_categories.csv data/raw/iek/in_transit.xlsx data/raw/iek/monthly_sales.xlsx data/raw/iek/monthly_stock.xlsx data/raw/iek/moq.xlsx data/raw/iek/sales_tx.xlsx data/raw/iek/seasonality.xlsx data/raw/se/in_transit.xlsx data/raw/se/monthly_sales.xlsx data/raw/se/monthly_stock.xlsx data/raw/se/moq.xlsx data/raw/se/sales_tx.xlsx data/raw/se/seasonality.xlsx docs/API.md docs/backtest.md docs/data-profile.md docs/design.md docs/plans/2026-09-23-core-engine.md docs/structure.md docs/tasks/api.md docs/tasks/frontend-polish.md docs/tasks/frontend.md frontend/.gitignore frontend/AGENTS.md frontend/DESIGN.md frontend/PLAN.md frontend/design-contract.md frontend/design-preview.html frontend/design-tokens.json frontend/eslint.config.js frontend/implementation-handoff.md frontend/index.html frontend/package-lock.json frontend/package.json frontend/references/main-screen.png frontend/src/App.module.css frontend/src/App.tsx frontend/src/api/ProcurementApi.ts frontend/src/api/client.ts frontend/src/api/liveClient.ts frontend/src/api/mock-data/meta.json frontend/src/api/mock-data/run.json frontend/src/api/mock-data/sku-history.json frontend/src/api/mockClient.ts frontend/src/api/types.ts frontend/src/features/BacktestPanel.module.css frontend/src/features/BacktestPanel.tsx frontend/src/features/RunCharts.module.css frontend/src/features/RunCharts.tsx frontend/src/features/ScenarioPanel.module.css frontend/src/features/ScenarioPanel.tsx frontend/src/features/SkuPanel.module.css frontend/src/features/SkuPanel.tsx frontend/src/features/WaterfallChart.module.css frontend/src/features/WaterfallChart.tsx frontend/src/features/historyChart.module.css frontend/src/features/historyChart.tsx frontend/src/main.tsx frontend/src/shared/download.ts frontend/src/shared/format.ts frontend/src/shared/quantity.ts frontend/src/shared/ui/index.tsx frontend/src/shared/ui/ui.module.css frontend/src/styles/global.css frontend/src/styles/tokens.css frontend/src/vite-env.d.ts frontend/tsconfig.app.json frontend/tsconfig.json frontend/tsconfig.node.json frontend/vite.config.ts requirements.txt samples/cache/.gitkeep samples/cache/1e09c2a78c5c9158.json samples/cache/2fa55ecb835cce04.json samples/cache/43562c82d8e2101d.json samples/cache/65f3f00badfac4d4.json samples/cache/93d27e2af4be5689.json samples/cache/957d5b2fed854cdc.json samples/cache/a8be9a77d81c447d.json samples/cache/e4714ebe49097ce0.json scripts/backtest.py scripts/classify_laya.py scripts/warm_llm_cache.py tests/__init__.py tests/ai/__init__.py tests/ai/test_groups.py tests/ai/test_summary.py tests/api/__init__.py tests/api/test_api.py tests/api/test_reliability.py tests/api/test_routes.py tests/engine/__init__.py tests/engine/factory.py tests/engine/test_acceptance.py tests/engine/test_backtest.py tests/engine/test_common.py tests/engine/test_custom_supplier.py tests/engine/test_ingest_iek.py tests/engine/test_ingest_se.py tests/engine/test_meta.py tests/engine/test_product_groups.py tests/engine/test_real_data.py tests/engine/test_units.py tests/ingest/test_custom_supplier.py tests/test_boundaries.py tests/test_contracts.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.