AAYMA
RU
Войти

KZen

Сервис для закупщика Электрокомплекта: из Excel-выгрузок 1С (ИЭК, Systeme Electric) считает рекомендуемые заказы поставщикам с пошаговым…

Рабочий MVP
Команда «Kzen» 6💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Kzen
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Рабочий MVP

Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером

Суть

Сервис для закупщика Электрокомплекта: из Excel-выгрузок 1С (ИЭК, Systeme Electric) считает рекомендуемые заказы поставщикам с пошаговым обоснованием, ручными правками, согласованием руководителем и выгрузкой XLSX/CSV для 1С.

Как устроено

Отчёты 1С связываются по коду товара в помесячную историю; разовые накладные (≥10× медианы) и всплески свыше трёх ожидаемых уровней очищаются, сезонные пики сохраняются. Спрос оценивается с учётом тренда, сезонности и месяцев с нулевым остатком; из потребности на срок поставки + период пересмотра вычитаются свободный остаток и поставки в пути (с учётом ETA), результат округляется по минимуму и кратности. Агент закупщика с tools, trace и what-if задержки поставки; LLM только пишет текст объяснения с проверкой чисел, без ключа используется шаблон. Clean architecture (api/application/domain/infrastructure), версии заказа и журнал в памяти.

Ключевые решения

  • очистка выбросов по медиане накладных
  • сезонность и тренд спроса
  • lead time + review period
  • округление по MOQ/кратности
  • what-if задержки поставки
  • agent tools с trace
  • LLM-обоснование с проверкой чисел
  • workflow согласования

Особенности

Жёсткое разделение: количество считает детерминированное расчётное ядро, LLM лишь формулирует объяснение и проверяется на совпадение чисел; экран «Проверки» с пятью сценариями ТЗ и скрипт оценки бизнес-эффекта по ассортименту.

Стек

Python 3.11 · FastAPI · Pydantic · openpyxl · Redis · React 19 · TypeScript · Vite · Docker Compose · nginx

Модели

gpt-4o-mini


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-9cbdba26-kzen.

README

README.md

KZen — рекомендации заказов поставщикам

KZen помогает менеджеру закупок ТОО «Электрокомплект» превратить выгрузки 1С в понятный заказ поставщикам. Сервис рассчитывает количество по каждому товару, показывает причины рекомендации и даёт человеку проверить заказ перед выгрузкой.

Что умеет сервис

  • Загружает Excel-выгрузки ИЭК и Systeme Electric; без файлов запускается на демонстрационных данных.
  • Учитывает продажи, остатки, товар в пути, сезонность, тренд и условия отгрузки. Показывает рекомендации по поставщикам, срочность и расчёт по шагам.
  • Позволяет искать товары, менять параметры расчёта и вручную исправлять количество с указанием причины.
  • Даёт менеджеру отправить заказ на согласование, руководителю — утвердить его, а затем скачать XLSX или CSV для 1С.
  • Показывает пять проверок требований технического задания на отдельном экране.

Как получается рекомендация

Сервис связывает отчёты по коду 1С и собирает историю товара по месяцам. Разовая накладная становится кандидатом на исключение, если она не менее чем в 10 раз больше медианной накладной товара и составляет не менее 50% доступной истории накладных. Месячный всплеск свыше трёх ожидаемых уровней заменяется ожидаемым спросом; повторяющийся сезонный пик сохраняется.

Расчёт оценивает спрос за месяцы с нулевым или пустым начальным остатком, затем учитывает тренд и сезонность. Из потребности на срок поставки и период пересмотра вычитаются свободный остаток и поступления, которые успеют прийти; заказ округляется по минимуму и кратности отгрузки. Оценки отсутствия товара нужно сверять с исходными остатками.

ИИ может только сформулировать текст объяснения: рекомендуемое количество считает расчётное ядро. Без ключа OpenAI показывается локальный шаблон.

Технологии и архитектура

  • Интерфейс: React 19, TypeScript, Vite.
  • Сервер и расчёт: Python 3.11, FastAPI, Pydantic, openpyxl. Redis используется для кэша в Docker.
  • Необязательное текстовое объяснение: OpenAI-совместимый API, по умолчанию модель gpt-4o-mini.

Интерфейс обращается к REST API. В сервере маршруты api вызывают сценарии application, расчётные правила находятся в domain, а чтение Excel, кэш, экспорт и вызов ИИ — в infrastructure. Обучать модель для запуска не нужно.

Запуск

Понадобятся Git и Docker с Docker Compose. На Windows сначала запустите Docker Desktop. В терминале:

git clone https://github.com/BAITC-Hacks/hack-9cbdba26-kzen.git
cd hack-9cbdba26-kzen
docker compose up --build -d

Откройте интерфейс. Документация API доступна по адресу localhost:3000/docs. Первый запуск может занять несколько минут из-за сборки образов. Для остановки выполните docker compose down.

Файлы партнёра не входят в репозиторий, поэтому чистый клон работает на синтетическом демо-наборе. Для реальных расчётов загрузите Excel-файлы на экране «Данные»: первый импорт поставщика требует все шесть отчётов 1С с именами и колонками партнёра, дальше можно загружать любой поднабор. После импорта версии расчёта и ручные правки сбрасываются, потому что считались по старым данным.

Для необязательного текста ИИ создайте в корне .env по образцу .env.example, укажите NARRATOR_BACKEND=openai и свой OPENAI_API_KEY, затем снова выполните docker compose up -d. Файл .env исключён из Git.

Как проверить

  1. Откройте localhost:3000. На экране «Данные» нажмите «Рассчитать рекомендации». Для проверки достаточно демо-данных.
  2. Перейдите в «Рекомендации», откройте товар и посмотрите историю, прогноз и шаги расчёта.
  3. В карточке товара измените количество, укажите причину и сохраните правку.
  4. На экране «Согласование» отправьте версию на согласование. Переключите демонстрационную роль на «Руководитель», утвердите версию и скачайте файл для 1С.
  5. На экране «Проверки» убедитесь, что пять сценариев ТЗ пройдены.

Данные и ограничения

Источники — Excel-отчёты 1С двух поставщиков: продажи, остатки, детализация продаж, товар в пути, условия отгрузки и сезонность. Результат выгружается в XLSX или CSV; прямого подключения к 1С и автоматической отправки поставщикам нет.

  • Нулевой или пустой начальный остаток служит признаком возможного отсутствия товара, но не подтверждает его. У ИЭК нет отдельного текущего снимка свободного остатка: используется начальный остаток последнего месяца. Эти оценки нужно проверить до утверждения заказа.
  • Импорт понимает текущие форматы отчётов партнёров; ручного сопоставления колонок нет.
  • Роли демонстрационные, полноценной авторизации нет. Версии заказа и журнал хранятся в памяти процесса и пропадают после перезапуска.
  • Хронологический бэктест ещё не реализован.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
75
Авторы
3
Файлы
131
Ветки
1

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

teriyaki0 42Aldiyar Amantay 24Mikhail 9

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

  • 2026-09-23 17:55Revert "Импорт принимает любой поднабор файлов: недостающие берутся из текущего набора"Aldiyar Amantay
  • 2026-09-23 17:55Revert "Редизайн интерфейса под product design: дизайн-система, шаги процесса, статусы цветом"Aldiyar Amantay
  • 2026-09-23 17:49README: абзац про импорт корочеAldiyar Amantay
  • 2026-09-23 17:49Таблица рекомендаций: при равном покрытии крупные заказы выше; README про частичный импортAldiyar Amantay
  • 2026-09-23 17:47Импорт принимает любой поднабор файлов: недостающие берутся из текущего набораAldiyar Amantay
  • 2026-09-23 17:46Write concise jury READMEteriyaki0
  • 2026-09-23 17:41Merge origin/main and fix import dependencyteriyaki0
  • 2026-09-23 17:37Clean Markdown docs and update READMEteriyaki0
Все коммиты (75)
  • 2026-09-23 17:35Редизайн интерфейса под product design: дизайн-система, шаги процесса, статусы цветомAldiyar Amantay
  • 2026-09-23 17:35narrate: убрана неиспользуемая переменная, тест импортов отсортирован под ruffAldiyar Amantay
  • 2026-09-23 17:33Fix Redis cache initializationMikhail
  • 2026-09-23 17:32Изменение докер файлаMikhail
  • 2026-09-23 17:29Загрузка выгрузок 1С через интерфейс: импорт по поставщику в фоне, отчёт о качестве, сброс версийAldiyar Amantay
  • 2026-09-23 17:24Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 17:23Distinguish zero stock from restored demandteriyaki0
  • 2026-09-23 17:23Avoid false OpenAI narrative fallbacksteriyaki0
  • 2026-09-23 17:17README по требованияиMikhail
  • 2026-09-23 17:14Show OpenAI narrative source in SKU screenteriyaki0
  • 2026-09-23 17:09Reject unsupported LLM adjustment claimsteriyaki0
  • 2026-09-23 17:02Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 17:02Show tiny forecast value beside SKU chartteriyaki0
  • 2026-09-23 17:01Переменные и адаптер нарратора переименованы под OpenAIAldiyar Amantay
  • 2026-09-23 16:59Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 16:59Use Russian decimals in demand explanationsteriyaki0
  • 2026-09-23 16:58Нарратор переключён на OpenAI (gpt-4o-mini): провайдер задаётся адресом в .envAldiyar Amantay
  • 2026-09-23 16:55Show fractional demand accurately in SKU detailsteriyaki0
  • 2026-09-23 16:54Clarify low-demand SKU history chartteriyaki0
  • 2026-09-23 16:46Не выдавать нулевые месяцы за прогноз без историиteriyaki0
  • 2026-09-23 16:45Показать отсутствие истории вместо пустого прогнозаteriyaki0
  • 2026-09-23 16:41Указать допущение в источнике остатка ИЭКteriyaki0
  • 2026-09-23 16:40Предупредить о неподтверждённом остатке ИЭК в карточкеteriyaki0
  • 2026-09-23 16:38Разрешить локальный адрес API для Viteteriyaki0
  • 2026-09-23 16:31Уточнить объяснение восстановления спроса по пустым остаткамteriyaki0
  • 2026-09-23 16:30Показать фактические продажи и оценку отдельно на графикеteriyaki0
  • 2026-09-23 16:22Исправить высоту столбцов истории и прогнозаteriyaki0
  • 2026-09-23 16:16Обновлять шапку и рекомендации между экранамиteriyaki0
  • 2026-09-23 16:16Синхронизировать согласование и журнал с APIteriyaki0
  • 2026-09-23 16:16Подключить обоснование и шаги агента в карточке позицииteriyaki0
  • 2026-09-23 16:16Подключить пагинацию и сценарии экрана рекомендацийteriyaki0
  • 2026-09-23 16:16Уточнить контракт API для экранов фронтаteriyaki0
  • 2026-09-23 16:05Уточнить структуру экрана данных по прототипуteriyaki0
  • 2026-09-23 16:01Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 16:00Исправить сброс сессии на экране данныхteriyaki0
  • 2026-09-23 15:59LLM-обоснование с проверкой чисел, срочность и обоснование в выгрузке, приоритет разбора у агентаAldiyar Amantay
  • 2026-09-23 15:58Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 15:57Уточнить экран рекомендаций по эталонному макетуteriyaki0
  • 2026-09-23 15:54Посчитать бизнес-эффект по всему ассортиментуMikhail
  • 2026-09-23 15:50Merge remote-tracking branch 'origin/main'teriyaki0
  • 2026-09-23 15:47Перенести экран проверок ТЗ из прототипаteriyaki0
  • 2026-09-23 15:45Перенести проверку заказа и экспорт из прототипаteriyaki0
  • 2026-09-23 15:43Перенести экран объяснения SKU из прототипаteriyaki0
  • 2026-09-23 15:42Перенести экран рекомендаций из прототипаteriyaki0
  • 2026-09-23 15:41Перенести экран данных и общую оболочку из прототипаteriyaki0
  • 2026-09-23 15:27Учесть ETA партий в расчёте заказаMikhail
  • 2026-09-23 15:27Добавить факты для защиты по выбросам и ETAMikhail
  • 2026-09-23 15:26Цифры для защиты и демо-сценарий; тост расчёта считает «к заказу» как таблицаAldiyar Amantay
  • 2026-09-23 15:25bench.py меряет ручки закупщика вместо /predict из каркасаAldiyar Amantay
  • 2026-09-23 15:22Карточка, what-if и агент чистят историю так же, как расчётAldiyar Amantay
  • 2026-09-23 15:21Connect frontend API client to real backendteriyaki0
  • 2026-09-23 15:20pitch_notes: кейс, находки в данных, агент и рабочий процесс, вопросы жюриAldiyar Amantay
  • 2026-09-23 15:19Короткая формула в таблице рекомендаций: потребность − свободно − путьAldiyar Amantay
  • 2026-09-23 15:11Слияние: категория в расчёте (Миша) поверх восстановленной историиAldiyar Amantay
  • 2026-09-23 15:09Восстановлена история main после force push; фронтенд сохранёнAldiyar Amantay
  • 2026-09-23 15:08Учесть категорию в расчёте и описать очистку выбросовMikhail
  • 2026-09-23 15:05Add React TypeScript frontend with 5 screens and design systemteriyaki0
  • 2026-09-23 15:05Initial commit: hackathon ML service skeletonteriyaki0
  • 2026-09-23 14:57API фронта: убраны неработающие настройки, выгрузка по колонкам, полный сброс сессииAldiyar Amantay
  • 2026-09-23 14:52API под контракт фронта (FRONTEND_DATA.md), демо-набор, согласование заказаAldiyar Amantay
  • 2026-09-23 14:44реализованы функции для работы с эксель, тесты самих функцийMikhail
  • 2026-09-23 14:44Первая фича готова, но без адекватного апиMikhail
  • 2026-09-23 14:38Экспорт для 1С: срочность и обоснование по п. 5 ТЗ; сверка чеклиста с кейсомAldiyar Amantay
  • 2026-09-23 14:35Чеклист команды и документация по агенту, версиям и экспорту в 1СAldiyar Amantay
  • 2026-09-23 14:32Агент закупщика: tools, ветвления, trace, what-if задержки поставки, xlsx для 1СAldiyar Amantay
  • 2026-09-23 14:03Рабочий процесс закупщика: версии расчёта, корректировки, утверждение, экспортAldiyar Amantay
  • 2026-09-23 13:25Initial commit: hackathon ML service skeletonteriyaki0
Структура репозитория (131 файлов)
.dockerignore
.env.example
.gitignore
CASE.md
Makefile
README.md
backend/Dockerfile
backend/app/__init__.py
backend/app/api/__init__.py
backend/app/api/deps.py
backend/app/api/errors.py
backend/app/api/middleware.py
backend/app/api/routes/__init__.py
backend/app/api/routes/agent.py
backend/app/api/routes/drafts.py
backend/app/api/routes/health.py
backend/app/api/routes/imports.py
backend/app/api/routes/orders.py
backend/app/api/routes/ui.py
backend/app/api/schemas/__init__.py
backend/app/api/schemas/common.py
backend/app/api/schemas/drafts.py
backend/app/api/schemas/orders.py
backend/app/application/__init__.py
backend/app/application/use_cases/__init__.py
backend/app/application/use_cases/agent.py
backend/app/application/use_cases/drafts.py
backend/app/application/use_cases/imports.py
backend/app/application/use_cases/narrate.py
backend/app/application/use_cases/replenishment.py
backend/app/application/use_cases/selfcheck.py
backend/app/application/use_cases/ui.py
backend/app/application/use_cases/workspace.py
backend/app/core/__init__.py
backend/app/core/config.py
backend/app/core/container.py
backend/app/core/logging.py
backend/app/core/presets.py
backend/app/domain/__init__.py
backend/app/domain/assessment.py
backend/app/domain/demand.py
backend/app/domain/entities.py
backend/app/domain/exceptions.py
backend/app/domain/ports.py
backend/app/domain/workflow.py
backend/app/infrastructure/__init__.py
backend/app/infrastructure/cache/__init__.py
backend/app/infrastructure/cache/memory.py
backend/app/infrastructure/cache/redis_cache.py
backend/app/infrastructure/export/__init__.py
backend/app/infrastructure/export/onec_xlsx.py
backend/app/infrastructure/export/table.py
backend/app/infrastructure/forecasting/__init__.py
backend/app/infrastructure/forecasting/baseline.py
backend/app/infrastructure/forecasting/smoothed.py
backend/app/infrastructure/llm/__init__.py
backend/app/infrastructure/llm/openai_compat.py
backend/app/infrastructure/llm/template.py
backend/app/infrastructure/storage/__init__.py
backend/app/infrastructure/storage/data_quality.py
backend/app/infrastructure/storage/demo_data.py
backend/app/infrastructure/storage/draft_store.py
backend/app/infrastructure/storage/excel_loader.py
backend/app/infrastructure/storage/excel_normalizer.py
backend/app/infrastructure/storage/memory_repo.py
backend/app/main.py
backend/requirements.txt
docker-compose.yml
docs/CHECKLIST.md
docs/FRONTEND_AGENT_TRACE.md
docs/design/METHODOLOGY.md
docs/design/README (1).md
docs/design/prototype.html
docs/design/prototype_source.dc.html
docs/design/styles.css
docs/methodology.md
frontend/.gitignore
frontend/.oxlintrc.json
frontend/Dockerfile
frontend/index.html
frontend/nginx.conf
frontend/package-lock.json
frontend/package.json
frontend/public/favicon.svg
frontend/public/icons.svg
frontend/src/App.css
frontend/src/App.tsx
frontend/src/api/client.ts
frontend/src/assets/hero.png
frontend/src/assets/react.svg
frontend/src/assets/vite.svg
frontend/src/components/ImportPanel.tsx
frontend/src/components/layout/ContextBar.tsx
frontend/src/components/layout/TopNav.tsx
frontend/src/index.css
frontend/src/main.tsx
frontend/src/mock/data.ts
frontend/src/screens/DataScreen.tsx
frontend/src/screens/RecommendationsScreen.tsx
frontend/src/screens/ReviewScreen.tsx
frontend/src/screens/SkuScreen.tsx
frontend/src/screens/ValidationScreen.tsx
frontend/src/styles/components.css
frontend/src/styles/globals.css
frontend/src/styles/tokens.css
frontend/src/types/index.ts
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
metrics.json
ml/__init__.py
ml/notebooks/eda_template.ipynb
ml/src/__init__.py
ml/src/config.py
pyproject.toml
run_config.json
scripts/bench.py
scripts/business_effect.py
tests/conftest.py
tests/test_agent_api.py
tests/test_demand.py
tests/test_drafts_api.py
tests/test_excel_loader.py
tests/test_health.py
tests/test_imports_api.py
tests/test_narrative.py
tests/test_orders_api.py
tests/test_replenishment_core.py
tests/test_ui_api.py
uv.lock

Обсуждение 0 комментариев

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

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