О проекте
Команда: NovaCoders
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Система расчёта заказов поставщику: по шести Excel-отчётам считает потребность с учётом сезонности, остатков, товаров в пути и MOQ, помечает аномалии, а менеджер правит и подтверждает заказ с экспортом в CSV.
Как устроено
Go-бэкенд на Excelize разбирает шесть XLSX (MOQ, продажи по месяцам и детально, остатки, сезонность, товар в пути) и объединяет их по code1C. AI-сервис на FastAPI детерминированно считает: прогноз спроса + страховой запас − свободный остаток − товар в пути, с округлением вверх до MOQ. Он же находит разовые крупные продажи и периоды stockout и выставляет статусы BUY/NO_BUY/REVIEW. LLM через OpenAI SDK только анализирует спорные позиции и пишет объяснения, количество не придумывает. Менеджер правит и подтверждает позиции в React-интерфейсе, после чего формируется CSV.
Ключевые решения
- seasonal demand forecast
- safety stock
- MOQ rounding
- anomaly detection (one-off sales)
- stockout detection
- human-in-the-loop approval
Особенности
Количество считает код, AI только объясняет и помечает спорные позиции. Статус REVIEW отправляет аномалии менеджеру вместо автоматического исключения. Коды 1С хранятся строками, чтобы не терять ведущие нули.
Стек
Go · Excelize · Python · FastAPI · Pydantic · React · TypeScript · Vite · Tailwind CSS · Recharts
Модели
OpenAI (OPENAI_MODEL, настраивается)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ca2b30ac-novacoders.
README
README.mdSupplyLens

AI-assisted система для планирования закупок и пополнения склада.
SupplyLens превращает разрозненные Excel-отчёты в проверяемые рекомендации для закупщика. Система объединяет продажи, остатки, сезонность, MOQ и товары в пути, рассчитывает потребность, отмечает подозрительные операции и формирует готовый заказ в CSV.
Решение разработано командой NovaCoders для трека «Логистика» хакатона HackAlem AI.
Что умеет SupplyLens
- Загружает и проверяет шесть Excel-источников.
- Объединяет данные по точному коду товара
code1C. - Рассчитывает спрос с учётом сезонности и динамики продаж.
- Учитывает свободный остаток, резервы и товар в пути.
- Находит разовые крупные продажи и отправляет спорные позиции на проверку.
- Округляет заказ до установленной кратности MOQ.
- Показывает понятное объяснение каждого решения.
- Позволяет менеджеру изменить и подтвердить количество.
- Экспортирует подтверждённый заказ в CSV.
Архитектура
flowchart LR
U[Менеджер] --> F[React Frontend]
F -->|Excel и действия| B[Go Backend]
B -->|Нормализованный JSON| A[FastAPI AI Service]
A -->|Расчёт и объяснение| B
B -->|Рекомендации| F
F -->|Подтверждение| B
B --> C[CSV-заказ]
| Компонент | Ответственность |
|---|---|
| Frontend | Загрузка файлов, параметры расчёта, таблица рекомендаций, подтверждение и экспорт |
| Go Backend | Проверка и разбор XLSX, хранение данных в памяти, вызов AI Service, решения менеджера и CSV |
| AI Service | Детерминированный расчёт потребности, анализ аномалий и понятное объяснение результата |
Frontend обращается только к Go Backend. API-ключи и адрес AI Service не передаются в браузер.
Технологии
| Слой | Стек |
|---|---|
| Frontend | React, TypeScript, Vite, Tailwind CSS, Recharts |
| Backend | Go, net/http, Excelize |
| AI Service | Python, FastAPI, Pydantic, OpenAI SDK |
| Хранение | In-memory |
| Входные данные | XLSX |
| Результат | JSON и CSV |
Быстрый запуск
Требования
- Go 1.26.1+
- Node.js 22.12+ и npm
- Python 3.11–3.13
- Три отдельных терминала
Сервисы рекомендуется запускать в таком порядке:
AI Service → Backend → Frontend
1. AI Service
Из корня проекта:
cd ai-service
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-dev.txt
AI_MODE=mock \
ALLOW_EXTERNAL_AI=false \
AI_LOCAL_MODE=true \
AI_SERVICE_TOKEN= \
python -m uvicorn app.main:create_app --factory \
--host 127.0.0.1 \
--port 8001 \
--no-proxy-headers
Проверка:
curl --fail-with-body http://127.0.0.1:8001/health
Mock-режим не использует внешние API и подходит для локальной разработки и демонстрации. Расчёт количества остаётся настоящим — без внешнего AI выполняются локальный анализ и шаблонное объяснение.
2. Go Backend
Откройте второй терминал:
cd backend
AI_SERVICE_URL=http://127.0.0.1:8001 \
AI_SERVICE_TOKEN= \
go run ./cmd/api/main.go
Backend будет доступен по адресу http://127.0.0.1:8080.
Проверка:
curl --fail-with-body http://127.0.0.1:8080/healthz
3. React Frontend
Откройте третий терминал:
cd frontend
npm ci
VITE_API_BASE_URL=http://127.0.0.1:8080 npm run dev
Откройте в браузере адрес, который выведет Vite. По умолчанию:
http://127.0.0.1:5173
Повторный локальный запуск
После первоначальной установки зависимостей достаточно трёх команд в отдельных терминалах.
AI Service:
cd ai-service
source .venv/bin/activate
AI_MODE=mock ALLOW_EXTERNAL_AI=false AI_LOCAL_MODE=true AI_SERVICE_TOKEN= \
python -m uvicorn app.main:create_app --factory --host 127.0.0.1 --port 8001 --no-proxy-headers
Backend:
cd backend
AI_SERVICE_URL=http://127.0.0.1:8001 AI_SERVICE_TOKEN= go run ./cmd/api/main.go
Frontend:
cd frontend
VITE_API_BASE_URL=http://127.0.0.1:8080 npm run dev
Запуск AI Service с OpenAI
Для реальных AI-объяснений задайте секреты только в окружении AI Service:
cd ai-service
source .venv/bin/activate
export AI_MODE=live
export ALLOW_EXTERNAL_AI=true
export AI_LOCAL_MODE=false
export AI_SERVICE_TOKEN="change-me"
export OPENAI_API_KEY="your-openai-api-key"
export OPENAI_MODEL="your-available-model"
python -m uvicorn app.main:create_app --factory \
--host 127.0.0.1 \
--port 8001 \
--no-proxy-headers
Передайте тот же внутренний токен Backend:
cd backend
AI_SERVICE_URL=http://127.0.0.1:8001 \
AI_SERVICE_TOKEN="change-me" \
go run ./cmd/api/main.go
Не помещайте
OPENAI_API_KEYили другие секреты вVITE_*, исходный код, Git и HTTP-запросы Frontend.
Пользовательский сценарий
- Откройте раздел импорта.
- Загрузите шесть Excel-файлов одного поставщика.
- Проверьте найденные товары и предупреждения.
- Укажите горизонт прогноза, срок поставки и страховой запас.
- Запустите расчёт.
- Проверьте позиции со статусом
REVIEW. - При необходимости измените рекомендуемое количество.
- Подтвердите позиции заказа.
- Скачайте итоговый CSV.
Необходимые Excel-файлы
| Источник | Для чего используется |
|---|---|
| MOQ | Минимальная партия и кратность заказа |
| Ежемесячные продажи | Основная история спроса по товарам |
| Детальные продажи | Поиск разовых крупных операций |
| Ежемесячные остатки | Поиск периодов отсутствия товара |
| Сезонность | Корректировка ожидаемого спроса по месяцам |
| Товар в пути | Свободный остаток, резервы, поставки и стоимость |
Backend принимает формат .xlsx. Пустое значение и настоящий ноль не считаются одним и тем же. Коды 1С обрабатываются как строки, поэтому ведущие нули и завершающий символ _ сохраняются.
Решения системы
| Статус | Значение |
|---|---|
BUY | Товар рекомендуется заказать |
NO_BUY | Текущего и ожидаемого запаса достаточно |
REVIEW | Требуется решение менеджера из-за аномалии или качества данных |
AI не принимает окончательное решение за закупщика. Спорные продажи не исключаются автоматически, а итоговый заказ формируется только после подтверждения менеджером.
Основные API
Go Backend
| Метод | Endpoint | Назначение |
|---|---|---|
GET | /healthz | Состояние Backend |
POST | /api/v1/import | Импорт шести XLSX-файлов |
GET | /api/v1/datasets/{datasetId} | Результат проверки импорта |
POST | /api/v1/runs | Запуск формирования рекомендаций |
GET | /api/v1/runs/{runId} | Получение результата расчёта |
PATCH | /api/v1/runs/{runId}/items/{code1C} | Решение менеджера и изменение количества |
POST | /api/v1/runs/{runId}/approve-export | Формирование подтверждённого CSV |
AI Service
| Метод | Endpoint | Назначение |
|---|---|---|
GET | /health | Состояние AI Service |
POST | /v1/recommendations | Расчёт рекомендаций из нормализованного JSON |
Подробные модели запросов и ответов находятся в ai-service/contracts/.
Переменные окружения
Frontend
| Переменная | Пример | Назначение |
|---|---|---|
VITE_API_BASE_URL | http://127.0.0.1:8080 | Адрес Go Backend |
Backend
| Переменная | Пример | Назначение |
|---|---|---|
HTTP_ADDR | 127.0.0.1:8080 | Адрес HTTP-сервера |
CORS_ORIGINS | http://127.0.0.1:5173 | Разрешённые адреса Frontend |
AI_SERVICE_URL | http://127.0.0.1:8001 | Адрес AI Service |
AI_SERVICE_TOKEN | change-me | Внутренний токен между Backend и AI Service |
AI Service
| Переменная | Default | Назначение |
|---|---|---|
AI_MODE | mock | Режим mock или live |
ALLOW_EXTERNAL_AI | false | Разрешение внешних AI-вызовов |
AI_LOCAL_MODE | false | Разрешение локального mock без токена |
AI_SERVICE_TOKEN | пусто | Внутренняя авторизация сервиса |
OPENAI_API_KEY | пусто | Ключ OpenAI для live-режима |
OPENAI_MODEL | задаётся окружением | Модель OpenAI |
AI_REQUEST_TIMEOUT_SECONDS | 30 | Общий deadline одного запроса |
Проверки
Frontend:
cd frontend
npm run lint
npm run typecheck
npm test
npm run build
Backend:
cd backend
go test ./...
go vet ./...
go build ./...
AI Service:
cd ai-service
source .venv/bin/activate
python -m pytest -q
python -m compileall -q app tests
python -m pip check
Структура проекта
.
├── frontend/ # React-приложение
├── backend/ # Go API, XLSX и CSV
├── ai-service/ # FastAPI, расчёт и AI-анализ
└── README.md
Ограничения MVP
- Данные хранятся в памяти и сбрасываются после перезапуска Backend.
- Решение рассчитано на данные поставщика SystemElectric и формат предоставленных XLSX.
- Неполный сентябрь 2026 года не должен использоваться как полный месяц истории.
- Stockout определяется по месячным данным, без ежедневной истории остатков.
- Заказ поставщику не отправляется автоматически.
- Авторизация пользователей и постоянная база данных не входят в MVP.
Принцип расчёта
Прогноз спроса
+ страховой запас
- свободный остаток
- товар в пути
= сырая потребность
→ округление вверх до MOQ
Итоговое количество вычисляется кодом. AI используется для анализа спорных ситуаций и формирования понятного объяснения, но не придумывает количество заказа.
SupplyLens — меньше ручной работы в Excel, больше прозрачности в закупках.
Авторы коммитов
История коммитов
- 2026-09-23 17:54Merge branch 'main' of https://github.com/BAITC-Hacks/hack-ca2b30ac-novacodersdespi4
- 2026-09-23 17:54Connect Go backend to AI service and document integrationdespi4
- 2026-09-23 17:50readmedespi4
- 2026-09-23 17:32addalibek
- 2026-09-23 17:23minor changesdespi4
- 2026-09-23 17:21Merge branch 'alibek' of https://github.com/BAITC-Hacks/hack-ca2b30ac-novacodersdespi4
- 2026-09-23 17:14feat: connect backend and frontenddespi4
- 2026-09-23 17:06feat: ai-servicealibek
Все коммиты (14)
- 2026-09-23 16:08Merge branch 'main' of https://github.com/BAITC-Hacks/hack-ca2b30ac-novacodersdespi4
- 2026-09-23 16:07backenddespi4
- 2026-09-23 16:05frontendaibagalmbekov-alt
- 2026-09-23 15:15promptdespi4
- 2026-09-23 14:22add frontdespi4
- 2026-09-23 13:07feat: base structuredespi4
Структура репозитория (127 файлов)
.gitignore README.md ai-service/.env.example ai-service/.gitignore ai-service/AGENTS.md ai-service/README.md ai-service/app/__init__.py ai-service/app/algorithm.py ai-service/app/analysis/__init__.py ai-service/app/analysis/context.py ai-service/app/analysis/providers.py ai-service/app/analysis/schemas.py ai-service/app/analysis/service.py ai-service/app/compat.py ai-service/app/explanation/__init__.py ai-service/app/explanation/service.py ai-service/app/http_guard.py ai-service/app/main.py ai-service/app/pipeline.py ai-service/app/prompts/analysis_v1.txt ai-service/app/prompts/explanation_v1.txt ai-service/app/providers/__init__.py ai-service/app/providers/clients.py ai-service/app/routes.py ai-service/app/schemas.py ai-service/app/settings.py ai-service/contracts/README.md ai-service/contracts/legacy.request.example.json ai-service/contracts/request.example.json ai-service/contracts/response.example.json ai-service/docs/audit.md ai-service/docs/implementation.md ai-service/docs/mvp.md ai-service/docs/openai-analysis.md ai-service/docs/pipeline.md ai-service/pyproject.toml ai-service/requirements-dev.txt ai-service/requirements.txt ai-service/scripts/smoke_pipeline.py ai-service/tests/conftest.py ai-service/tests/test_analysis.py ai-service/tests/test_api.py ai-service/tests/test_calculation.py ai-service/tests/test_contract.py ai-service/tests/test_live_pipeline.py ai-service/tests/test_settings_providers.py backend/.env.example backend/.gitignore backend/cmd/analyze/main.go backend/cmd/api/main.go backend/cmd/api/main_test.go backend/cmd/demo/main.go backend/docs/ai-integration.md backend/docs/data-audit.md backend/go.mod backend/go.sum backend/internal/anomaly/detect.go backend/internal/anomaly/detect_test.go backend/internal/demo/workbooks.go backend/internal/domain/model.go backend/internal/forecast/forecast.go backend/internal/forecast/forecast_test.go backend/internal/importer/directory.go backend/internal/importer/directory_test.go backend/internal/importer/iek_test.go backend/internal/importer/importer.go backend/internal/importer/importer_test.go backend/internal/importer/parse.go backend/internal/recommendation/client.go backend/internal/recommendation/client_test.go backend/internal/recommendation/history.go backend/internal/recommendation/realdata_test.go backend/internal/recommendation/request.go backend/internal/recommendation/response.go backend/internal/service/history.go backend/internal/service/history_test.go backend/internal/service/recommendations.go backend/internal/service/service.go backend/internal/service/service_test.go backend/internal/store/store.go backend/internal/store/store_test.go backend/internal/transport/http/contracts.go backend/internal/transport/http/contracts_test.go backend/internal/transport/http/http.go backend/internal/transport/http/http_test.go backend/internal/transport/http/local.go backend/internal/transport/http/local_test.go backend/internal/transport/http/recommendations_test.go frontend/.env.example frontend/.gitignore frontend/README.md frontend/eslint.config.js frontend/frontPrompt.md frontend/index.html frontend/package-lock.json frontend/package.json frontend/public/favicon.svg frontend/src/App.tsx frontend/src/api/client.ts frontend/src/api/contracts.test.ts frontend/src/api/imports.ts frontend/src/api/recommendations.ts frontend/src/api/types.ts frontend/src/components/AnomalyReview.tsx frontend/src/components/CalculationSettings.tsx frontend/src/components/DataWarnings.tsx frontend/src/components/ErrorBoundary.tsx frontend/src/components/ExportBar.tsx frontend/src/components/FileImportPanel.tsx frontend/src/components/RecommendationDrawer.tsx frontend/src/components/RecommendationFilters.tsx frontend/src/components/RecommendationTable.tsx frontend/src/components/StagePrerequisite.tsx frontend/src/components/SummaryCards.tsx frontend/src/lib/filters.ts frontend/src/lib/format.test.ts frontend/src/lib/format.ts frontend/src/lib/workflow.test.ts frontend/src/lib/workflow.ts frontend/src/main.tsx frontend/src/styles.css frontend/supplylens.code-workspace frontend/tsconfig.json frontend/vite.config.ts go.work go.work.sum image.png
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.