AAYMA
RU
Войти

Logix

Помощник менеджера закупок «Электрокомплекта»: детерминированно считает объяснимые рекомендации по пополнению склада для Systeme Electric и IEK…

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

О проекте

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

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

Суть

Помощник менеджера закупок «Электрокомплекта»: детерминированно считает объяснимые рекомендации по пополнению склада для Systeme Electric и IEK; менеджер правит и утверждает строки и выгружает Excel для 1С или CSV.

Как устроено

engine.py объединяет Excel-файлы кейса (накладные, помесячные продажи, остатки, товары в пути, кратности, сезонность) по коду 1С. Отсекает разовые отгрузки (больше 20 медиан строки и больше половины месячного объёма) и восстанавливает спрос в месяцы дефицита. Считает 12 сезонных коэффициентов с иерархией товар → категория → поставщик, базу как усечённое среднее за март–август и тренд, ограниченный от −40 до +60%. Страховой запас: z×σ×√((L+R)/30), σ по MAD, z из ABC-класса. Заказ = потребность − остаток − в пути, округлённый вверх до кратности (кабели — бухтами по 305 м). Вкладки «Заказ», «Проверка», «Аналитика»; AI-вкладка не реализована.

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

  • seasonality coefficients
  • one-off order filter (median rule)
  • stockout demand correction
  • trimmed mean
  • MAD-based safety stock
  • ABC classification
  • MOQ rounding

Особенности

Методика подробно описана «простыми словами»: учёт потерянного спроса при нулевом остатке, фильтр разовых проектных отгрузок, иерархическая сезонность со смешиванием профилей, округление кабеля бухтами. Все числа считает движок, LLM их не выбирает, заказы поставщикам автоматически не уходят.

Стек

Python · Excel/CSV export


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

README

README.md

Logix — hack-d408c6e1-aqshai

Hackathon team repository for Aqshai

Logix is a purchasing assistant for Elektrokomplekt, built for HackAlem AI 2026. It calculates explainable replenishment recommendations for Systeme Electric and IEK using deterministic formulas, historical demand, stock, goods in transit and supplier order multiples. Managers review and approve orders before downloading Excel or CSV files for 1C; the app never sends orders to suppliers automatically.

For the jury: run the existing app locally with START_DEMO_WINDOWS.bat (Windows) or START_DEMO_MAC.command (Mac). Python 3.10+ is required; dependencies are installed on first launch. No hosting, account or API key is needed for orders and analytics. Быстрый запуск и сценарий демонстрации.

Проблема

Менеджеру закупок ТОО «Электрокомплект» нужно вовремя пополнять склад в Алматы, не замораживая деньги в избыточных запасах. Обычного среднего продаж недостаточно: сезонность меняет спрос, крупная разовая отгрузка завышает прогноз, а отсутствие товара на складе скрывает неудовлетворённый спрос. Данные о продажах, остатках, поставках и упаковках находятся в разных Excel-файлах.

Что делает Logix

Приложение объединяет данные по текстовому коду 1С и рассчитывает план заказа для Systeme Electric (SE) и IEK. Для каждого товара оно показывает количество, срочность, прогнозную дату исчерпания запаса и объяснение на русском языке.

На вкладке «📦 Заказ» можно:

  • выбрать поставщика, срочность и категорию, найти товар по коду, артикулу или названию;
  • посмотреть число позиций к заказу, сумму в тенге и число критичных позиций;
  • изменить количество, отметить «✔ Утвердить» или нажать «Утвердить всё видимое» и заполнить поле «Утвердил»;
  • скачать только утверждённые позиции с положительным количеством: Excel для 1С с отдельными листами SE и IEK либо CSV с разделителем ; и кодировкой UTF-8 с BOM.

Excel содержит код 1С, артикул, наименование, количество, единицу измерения, цену, сумму, срочность и причину заказа; над таблицей указаны поставщик, ответственный и дата. Цена SE — себестоимость «СС реал», цена IEK — каталожная цена с НДС, поэтому суммы поставщиков имеют разную ценовую основу.

В текущем составе репозитория работают движок, вкладки «📦 Заказ», «✅ Проверка», «📊 Аналитика» и выгрузка листа менеджера SE. «🤖 AI помощник» показывает «Вкладка в разработке», пока отсутствует tab_ai.py; после его добавления приложение подключит модуль через общий контракт.

Правки количества сохраняются при смене фильтров и сразу обновляют сумму. Изменение количества снимает утверждение строки; изменение параметров расчёта сбрасывает правки и утверждения для повторной проверки нового плана. Выгрузка включает все утверждённые строки, в том числе скрытые текущим фильтром: их число показано над кнопками скачивания. Некратные упаковке количества нужно исправить перед выгрузкой; кнопка «Снять все утверждения» очищает выбор.

Ничего не отправляется поставщикам автоматически. Ответственный сотрудник проверяет рекомендации, утверждает строки и скачивает файл.

Метод расчёта простыми словами

Все количества вычисляет engine.py. При одинаковых данных и настройках результат одинаковый: языковая модель не выбирает числа заказа. Подробная спецификация находится в SPEC.md, контракт функций и таблиц — в INTERFACE.md.

1. Подготовка данных и очистка спроса

Исходные файлы кейса уже находятся в data/: накладные, помесячные продажи и остатки, товары в пути, кратности, каталог IEK, лист менеджера SE и сезонность поставщиков. Исходные Excel-файлы не изменяются. Коды товаров и номера документов читаются как текст, чтобы сохранить ведущие нули и специальные символы.

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

Данные заканчиваются 22.09.2026. Для расчёта базового спроса используются полные месяцы до августа 2026 включительно: сентябрь не считается полным месяцем. Сведения за 2024 год из помесячного отчёта нужны для сезонности. В настройках можно переключиться с накладных на «Ежемесячный отчёт компании».

2. Разовые заказы

Медиана — это типичное значение в середине упорядоченного ряда, на которое меньше влияют редкие большие числа. Строка накладной считается разовой, только если одновременно выполнены три условия:

  1. У товара есть не менее 10 строк накладных с 01.01.2025.
  2. Количество в строке больше 20 медианных количеств строки этого товара.
  3. Количество в строке больше половины медианного месячного объёма этого товара.

Такие строки исключаются из регулярного спроса в режиме накладных, но сохраняются в деталях расчёта с датой, номером документа, количеством и обычным размером строки. Например, крупная проектная поставка не должна превращаться в ежемесячную потребность. В режиме месячного отчёта построчный фильтр не меняет месячные продажи; дополнительную защиту от всплесков даёт усечённое среднее.

3. Сезонность

Для каждого товара рассчитываются 12 коэффициентов: выше 1 — месяц сильнее среднего, ниже 1 — слабее.

  • Для поставщика используются формы продаж в единицах за полные 2024 и 2025 годы; их средний профиль смешивается 50/50 с профилем из денежного отчёта сезонности за те же годы.
  • Если в категории не менее 10 товаров, используется её профиль. Для IEK категория берётся из каталога, для SE — серия в кавычках в названии. Для меньших групп применяется профиль поставщика.
  • Собственная сезонность товара принимается, если в каждом из двух лет продано не менее 60 единиц, а сходство месячных профилей (корреляция) не ниже 0,5. Тогда собственный профиль получает вес 60%, профиль категории — 40%.

Коэффициенты ограничиваются диапазоном 0,3–3,0, затем приводятся к среднему 1. В объяснении сохраняется уровень сезонности: товар, категория или поставщик. Рост оценивается в единицах товара, а не в тенге, чтобы изменение цен не выдавать за рост спроса.

4. Дефицит и потерянный спрос

Низкие продажи могут означать отсутствие товара, а не отсутствие покупателей. Сначала оценивается обычный спрос без сезонности: медиана за последние 12 полных месяцев, которые начинались с положительным остатком. Если таких месяцев меньше трёх, используются все 12.

Месяц считается дефицитным, если остаток в его начале или в начале следующего месяца не положителен, а продажи ниже 70% ожидаемого объёма. Ожидаемый объём равен предварительной базе, умноженной на сезонный коэффициент.

Для такого месяца спрос повышается до ожидаемого значения. Разница записывается как оценка потерянных продаж; детали содержат месяц, фактический и ожидаемый объём. Коррекцию можно отключить через disable_stockout_adjustment в overrides, чтобы сравнить результаты.

5. База, тренд и прогноз

Из скорректированных месячных продаж сначала убирается сезонность делением на соответствующий коэффициент. База — усечённое среднее за март–август 2026: лучший и худший месяцы исключаются, остальные четыре усредняются. По спецификации при истории короче четырёх месяцев используется обычное среднее.

Тренд сравнивает усечённые суммы за март–август 2026 и те же месяцы 2025 года. Если обе суммы не меньше 30 единиц, годовое изменение ограничивается диапазоном от −40% до +60%; иначе тренд равен нулю.

Прогноз месяца = база × сезонность месяца × плавный вклад годового тренда × план роста менеджера. Точный множитель тренда — (1 + g)^(t / 12), где g — годовой тренд, а t — число месяцев от июня 2026. План роста 10% даёт множитель 1,10.

6. Остатки, товары в пути и страховой запас

Для SE доступный остаток — сумма «Свободный остаток», «Остаток ТЗ», «Розничный склад» и «Витрина». Резерв повторно не вычитается: он уже исключён из свободного остатка.

Для IEK текущий остаток оценивается как остаток на 01.09.2026 минус регулярные сентябрьские отгрузки, не ниже нуля. Так же оцениваются товары SE, которых нет в листе менеджера. Сентябрьская разовая отгрузка требует сверки с 1С: если она ушла с этого склада, фактический остаток может быть ниже оценки.

В пути учитываются количества из листа SE и шести заказов IEK; для SE дата берётся из заголовка или комментария, для IEK — из заголовков заказов. Модель вычитает суммарное количество в пути, поэтому сроки поступления стоит сверять перед утверждением.

Заказ покрывает срок поставки L и период до следующего заказа R. По умолчанию IEK — 35 + 14 дней, SE — 30 + 30 дней. Для статуса IEK «Заказная» срок поставки увеличивается в 1,5 раза. Прогноз на это окно складывается по дням с учётом длины месяцев.

Страховой запас защищает от колебаний спроса:

σ = max(1,4826 × MAD, 0,2 × база)
Страховой запас = z × σ × √((L + R) / 30)

MAD — медиана абсолютных отклонений от медианы за последние 12 месяцев после удаления сезонности. Она устойчивее обычного стандартного отклонения к одиночному всплеску.

Коэффициенты сервиса: A — 1,65 (95%), B — 1,28 (90%), C — 0,84 (80%). Для SE категории 1/2/3/5 соответствуют A/B/C/B. Для IEK товары ранжируются по стоимости регулярных продаж за 12 месяцев: первые 80% стоимости — A, следующие 15% — B, остальные — C; если цены нет, используются единицы продаж.

7. Количество и кратность заказа

Потребность = спрос на окно L + R + страховой запас
Заказ до округления = max(0, потребность − доступный остаток − товары в пути)
Заказ = округлить вверх до кратности поставщика

Для SE используется «Кратность», для IEK — минимальная отгрузка как минимум и кратность. При отсутствии значения IEK берётся минимум из каталога, затем 1. Например, потребность 23 при кратности 10 означает заказ 30.

Кабели IEK, закупаемые бухтами по 305 м, округляются до целого числа бухт; в расчёте количество остаётся в метрах, а объяснение показывает «N бухт (N×305 м)».

Для SE категории 7 и названий с «!!!», а также для IEK «Распродажа» рекомендация обнуляется с объяснением. При отсутствии регулярных продаж за шесть месяцев заказ также обнуляется, если за этот период не выявлен дефицит. Для новинок IEK с менее чем тремя месяцами продаж выводится просьба проверить расчёт вручную. Менеджер может изменить количество в таблице.

8. Срочность и объяснения

Средний дневной спрос равен прогнозу на окно, делённому на число дней окна.

  • 🔴 Критично: остатка вместе с товарами в пути не хватит на срок поставки.
  • 🟡 Заказать: критического дефицита нет, но рекомендуемый заказ положителен.
  • 🟢 Не требуется: нет критического дефицита и заказ равен нулю.

Внутри поставщика сначала показываются критичные позиции, затем позиции к заказу; при одинаковой срочности выше товары с большей стоимостью дневного спроса. «Хватит до» оценивается по запасу вместе с товарами в пути. При нулевом спросе дата не определяется. Критичность показывает риск дефицита и может сохраняться даже у товара с запретом повторного заказа.

Каждая строка получает русское объяснение: база спроса, применимые разовые заказы и дефицит, сезонность, тренд, потребность, запас и округление либо причина нулевого заказа.

Допущения и вопросы для «Электрокомплекта»

  1. Источник регулярного спроса SE. Помесячный отчёт примерно вдвое ниже накладных. Исключены ли оптовые или проектные поставки и какой источник считать основным? Пока менеджер выбирает источник в настройках.
  2. Сроки и частота заказа. Подтвердить реальные сроки для каждого поставщика и направления доставки. По умолчанию IEK — 35 дней поставки и 14 дней между заказами, SE — 30 и 30.
  3. Текущий остаток IEK. Нужна актуальная выгрузка из 1С. Пока используется оценка от остатка на 1 сентября за вычетом сентябрьских регулярных продаж; разовые отгрузки проверяются отдельно.
  4. Категории SE и маркировка. Что означают категории 5 и 7 и «!!!» в названии? Сейчас 5 считается классом B, а 7 и «!!!» — признаком запрета повторного заказа.

Демонстрация рассчитана на фиксированный срез 22.09.2026: изменение даты в интерфейсе не обновляет исходные данные и исторические окна автоматически. До применения в реальных закупках нужно подтвердить эти допущения и сверить текущие остатки и поставки.

Как запустить

Демо для жюри — без хостинга

Это то же приложение app.py с данными кейса, а не скриншоты и не упрощённый макет. Оно работает только на вашем компьютере; данные не отправляются на сервер. Репозиторий уже содержит папку data/, ключ API и файл .env для заказа, проверок и аналитики не нужны.

  1. Получите последнюю версию репозитория. Если скачали ZIP, сначала распакуйте всю папку, а не только файл запуска. Папка должна быть доступна для записи кэша.
  2. Нужен установленный Python 3.10 или новее (наша Windows-сборка проверена на 3.14.2). На Windows при установке включите Add Python to PATH. Интернет нужен для первой установки зависимостей.
  3. Windows: дважды нажмите START_DEMO_WINDOWS.bat в папке проекта. Используется глобальный Python, виртуальное окружение не создаётся.
  4. Mac: в Terminal перейдите в папку проекта и один раз выполните chmod +x START_DEMO_MAC.command, затем откройте этот файл двойным щелчком. Альтернатива без изменения разрешений: bash START_DEMO_MAC.command. Локальное окружение venv/ создаётся автоматически; глобальные пакеты Mac не изменяются.

Лаунчер установит зависимости и откроет браузер на свободном локальном порту. Если браузер не открылся, скопируйте адрес http://127.0.0.1:... из окна запуска. Не закрывайте это окно, пока работаете с демо; для остановки нажмите Ctrl+C. После успешной установки повторный запуск использует установленные пакеты без повторного скачивания, пока requirements.txt и Python не изменились. Первый расчёт может занимать около минуты; установка пакетов идёт отдельно и может занять несколько минут.

При блокировке файла политиками компьютера не отключайте защиту: используйте ручной запуск из Terminal/PowerShell ниже или обратитесь к администратору. На Mac лаунчер не проверен на физическом устройстве; ручные команды ниже служат запасным способом запуска.

Сценарий для жюри — 1–2 минуты после загрузки:

  1. Оставьте дату 22.09.2026. На «📦 Заказ» выберите IEK, в поиске введите 130300780_ и посмотрите количество и объяснение «Почему» (прокрутите таблицу вправо).
  2. Измените «Кол-во» на 14 000, нажмите Enter: сумма обновится. Количество должно соответствовать колонке «Кратность».
  3. Поставьте «✔ Утвердить», заполните «Утвердил», скачайте «Заказ для 1С (Excel)». Без утверждения выгрузка недоступна; файл сохраняется браузером, поставщику ничего не отправляется.
  4. Очистите поиск и переключитесь на Systeme Electric; затем откройте «📊 Аналитика», чтобы посмотреть показатели и графики.
  5. Для подробной проверки алгоритма откройте «✅ Проверка». «Запустить все проверки» выполняет несколько полных перерасчётов и может занять несколько минут — это не часть короткого сценария. В одном из предыдущих прогонов этот шаг превысил лимит интеграционного теста 90 секунд; в проверке перед добавлением лаунчеров все 18 тестов прошли. Скорость зависит от компьютера; лаунчер не ускоряет сам расчёт.

AI-вкладка пока является заглушкой; для демонстрации используйте заказ, проверки и аналитику. Изменения количества и утверждения живут в сессии браузера и не меняют исходные Excel-файлы. Для новой демонстрации откройте новую сессию; после перезапуска приложение заново рассчитает рекомендации.

Ручной запуск (запасной вариант)

Нужен Python 3 с поддержкой зависимостей из requirements.txt; текущая сборка проверялась на Windows с Python 3.14.2. Данные кейса уже включены в приватный репозиторий, отдельно скачивать их не нужно. Все команды выполняются из корня репозитория, где лежат app.py, requirements.txt и папка data/.

Windows — PowerShell, без виртуального окружения

Если репозиторий клонирован в стандартную папку GitHub Desktop:

cd "$env:USERPROFILE\Documents\GitHub\hack-d408c6e1-aqshai"
python --version
pip install -r requirements.txt
streamlit run app.py

Если папка другая, замените путь в команде cd. Если pip или streamlit не найдены, используйте тот же установленный Python:

python -m pip install -r requirements.txt
python -m streamlit run app.py

macOS — Terminal, окружение ./venv

cd ~/Documents/GitHub/hack-d408c6e1-aqshai
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
streamlit run app.py

Создайте venv один раз. При следующих запусках откройте папку проекта, выполните source venv/bin/activate, затем streamlit run app.py. При другом месте клонирования замените путь.

Первый запуск и проверка заказа

Откройте адрес, который напечатает Streamlit, обычно http://localhost:8501. Первый запуск читает Excel, сохраняет основные очищенные таблицы в data/cache/*.parquet и рассчитывает план; повторные обращения ускоряются кэшем Streamlit. Parquet-кэш перестраивается, когда исходный файл новее сохранённого кэша.

Оставьте дату 22.09.2026, перейдите на «📦 Заказ», выберите поставщика и откройте объяснение в колонке «Почему». Проверьте количество и кратность, отметьте нужные строки, укажите имя в «Утвердил» и скачайте «Заказ для 1С (Excel)» или CSV. Остановить приложение в терминале можно сочетанием Ctrl+C.

Для расчётов и заказа ключ OpenAI не нужен. Подключение AI-помощника — отдельный этап Person 2; секреты хранятся локально в .env, который исключён из Git.

Как запускать проверки

После установки зависимостей в Windows, а на Mac — после активации venv, выполните из корня проекта:

pytest -q

Если команда не найдена:

python -m pytest -q

В репозитории есть tests/test_acceptance.py и tests/test_person2.py. Сообщение no tests ran не означает успешную проверку: убедитесь, что команда запущена из корня репозитория с папкой tests/.

Приёмочные тесты проверяют влияние входных данных на заказ, сезонный профиль, рост потребности после коррекции дефицита, устойчивость к фиктивной крупной отгрузке и наличие объяснений с корректной фильтрацией по поставщику. Дополнительно проверяются интерфейс, показатели аналитики и сохранение формул при экспорте листа SE. Интерактивные проверки доступны на «✅ Проверка»: нажмите «Запустить все проверки» и дождитесь пяти результатов.

Уже сейчас можно проверить расчёт для обоих поставщиков без интерфейса:

python -c "import engine; data = engine.load_all(); plan, details = engine.build_plan(data, engine.Settings()); assert set(plan.supplier) == set(engine.SUPPLIERS); assert plan.reason.fillna('').str.strip().ne('').all(); print(plan.groupby('supplier').size())"

После этого запустите streamlit run app.py и убедитесь, что вкладка «📦 Заказ» открывается с таблицей.

Скриншоты

Скриншоты сделаны до переименования: прежнее название SmartZakup в них относится к тому же приложению Logix.

Рекомендованный заказ

Настройки расчёта, фильтры по поставщику и срочности, показатели закупок и таблица рекомендаций с объяснениями.

Рекомендованный заказ Logix

Аналитика

Оценка избыточного запаса и потерянных продаж, число разовых заказов и динамика регулярного спроса по категории.

Аналитика Logix

Как мы использовали Codex

Команда из двух участников распределила работу между отдельными сессиями Codex: Person 1 отвечает за engine.py, app.py и этот README, Person 2 — за проверки, аналитику, AI-помощника, экспорт листа менеджера и тесты. Такое разделение позволяет работать параллельно; до подключения настоящего движка Person 2 может использовать временный engine_stub.py и app_preview.py.

Общий файл INTERFACE.md фиксирует имена функций, параметры Settings, колонки плана, детали расчёта и проверки через overrides. SPEC.md задаёт бизнес-логику, а AGENTS.md — правила работы и владение файлами.

В сессии Person 1 Codex прочитал спецификацию, подготовил движок и экран заказа, установил зависимости, выполнил проверки расчёта и запуска Streamlit и подготовил документацию. Решения о бизнес-допущениях и утверждении заказа остаются за людьми. Предусмотренный AI-помощник будет объяснять результаты и вызывать расчётные функции; количества заказов всегда должны поступать из детерминированного движка.

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

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

Nurzhigit-dev 7Sul1aa 4

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

  • 2026-09-23 17:52chore: rename app and demo branding to LogixNurzhigit-dev
  • 2026-09-23 17:39feat: add local demo launchers and jury quick-start guideNurzhigit-dev
  • 2026-09-23 17:17Merge remote-tracking branch 'origin/main'Nurzhigit-dev
  • 2026-09-23 17:17fix: stabilize order editing approvals and exportsNurzhigit-dev
  • 2026-09-23 17:08Merge main documentation and preserve README screenshotsSul1aa
  • 2026-09-23 17:06docs: add order and analytics screenshots to READMESul1aa
  • 2026-09-23 16:50Merge remote-tracking branch 'origin/main'Nurzhigit-dev
  • 2026-09-23 16:46docs: add Russian README with methodology and setup instructionsNurzhigit-dev
Все коммиты (11)
  • 2026-09-23 16:21Integrate real-engine tabs and SE export; remove preview stubsSul1aa
  • 2026-09-23 15:58Add Person 2 checks, analytics, manager-sheet export and acceptance testsSul1aa
  • 2026-09-23 15:45Build purchasing engine and order appNurzhigit-dev
Структура репозитория (33 файлов)
.env.example
.gitattributes
.gitignore
AGENTS.md
INTERFACE.md
README.md
SPEC.md
START_DEMO_MAC.command
START_DEMO_WINDOWS.bat
app.py
data/iek_catalog.xlsx
data/iek_in_transit.xlsx
data/iek_moq.xlsx
data/iek_sales_invoices.xlsx
data/iek_sales_monthly.xlsx
data/iek_seasonality.xlsx
data/iek_stock_monthly.xlsx
data/se_manager_sheet.xlsx
data/se_moq.xlsx
data/se_sales_invoices.xlsx
data/se_sales_monthly.xlsx
data/se_seasonality.xlsx
data/se_stock_monthly.xlsx
demo_launcher.py
docs/screenshots/analytics.png
docs/screenshots/order.png
engine.py
export_manager_sheet.py
requirements.txt
tab_analytics.py
tab_checks.py
tests/test_acceptance.py
tests/test_person2.py
Ветки (2)

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

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

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