AAYMA
RU
Войти

HACKALEM AI — автоматизация заказов поставщикам

Сервис расчёта пополнения склада для Электрокомплекта (IEK, Systeme Electric): прогноз спроса с сезонностью и исключением разовых продаж, учёт…

Прототип
Команда «SiS» 8💬 0 комментариевс 23 сентября 2026 г.

О проекте

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

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

Суть

Сервис расчёта пополнения склада для Электрокомплекта (IEK, Systeme Electric): прогноз спроса с сезонностью и исключением разовых продаж, учёт остатков, товаров в пути, MOQ и кратности, ручная корректировка и экспорт заказа.

Как устроено

По README конвейер такой: импорт Excel из ZIP-архивов, объединение по ключу «поставщик + код 1С», исключение крупных разовых операций, затем сезонность, компенсация stockout и тренд. Потребность считается как прогноз плюс страховой запас минус склад и товары в пути, с округлением по MOQ и кратности. Результат в Streamlit с графиками Plotly и экспортом в Excel/CSV. В репозитории вместо описанной в README структуры (app.py, src/) лежат файлы без расширений «1 part», «Part 2 and 3», «part 4 and 5» и т.д.

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

  • сезонный прогноз спроса
  • исключение выбросов
  • компенсация stockout
  • страховой запас
  • MOQ/кратность

Особенности

Подробная методология в README, но код разложен по файлам без расширений и не совпадает с описанной структурой проекта; запустить его как есть вряд ли получится.

Стек

Python · pandas · NumPy · Streamlit · Plotly · OpenPyXL · XlsxWriter


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

README

README.md

hack-baba2015-sis

Hackathon team repository for SiS

HACKALEM AI — автоматизация заказов поставщикам

Сервис поддержки закупочных решений для кейса ТОО «Электрокомплект» (ekt.kz). Проект разработан для олимпиады HACKALEM AI и помогает менеджеру закупа рассчитывать пополнение склада на основе истории продаж, сезонности, динамики спроса, остатков и ожидаемых поставок.

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

Технологии: Python · Pandas · NumPy · Streamlit · Plotly · OpenPyXL · XlsxWriter.

Содержание

Проблема и задача

При ручном планировании менеджеру приходится объединять несколько Excel-отчётов, проверять продажи, учитывать наличие товара и рассчитывать объём закупки. Такой процесс занимает время и затрудняет регулярный пересмотр заказов.

Ошибки возникают, когда:

  • разовая крупная продажа принимается за устойчивый рост спроса;
  • нулевые продажи во время отсутствия товара считаются отсутствием спроса;
  • при заказе не учитываются свободный остаток и товар в пути;
  • сезонные изменения заменяются средним значением за всю историю;
  • рекомендуемое количество не соответствует условиям поставщика.

Задача проекта — автоматизировать расчёт и сделать его проверяемым. Ожидаемый эффект — сокращение времени подготовки заказов и снижение риска дефицита и избыточного запаса. Фактическая экономия требует отдельной проверки на исторических и производственных данных.

Возможности

  • Импорт архивов IEK и Systeme Electric с Excel-выгрузками партнёра.
  • Объединение источников по поставщику и коду товара в 1С.
  • Проверка структуры данных, ключей и числовых значений.
  • Выявление крупных разовых операций по документам, а при наличии обезличенной детализации — по клиентам.
  • Прогноз с учётом сезонности и устойчивой динамики спроса.
  • Компенсация упущенного спроса по подтверждённым периодам stockout.
  • Учёт свободного остатка и дат ожидаемых поступлений.
  • Настройка дополнительного прироста спроса и политики запаса по категориям.
  • Раздельный учёт MOQ и кратности заказа.
  • Приоритизация по риску дефицита.
  • Объяснение каждой рекомендации.
  • Фильтры поставщика и категории, графики истории и прогноза.
  • Экспорт рекомендаций в Excel.
  • Ручная корректировка количества и выгрузка подтверждённого заказа в CSV.
  • Учебный режим с синтетическими дневными данными.

Архитектура

Excel-отчёты в ZIP + дополнительные CSV
                    ↓
           Импорт и проверка данных
                    ↓
      Объединение по поставщику и коду 1С
                    ↓
          Исключение разовых операций
                    ↓
       Сезонность + stockout + тренд спроса
                    ↓
       Прогноз на горизонт пополнения
                    ↓
       Страховой запас − склад − путь
                    ↓
              MOQ и кратность
                    ↓
       Рекомендации с объяснениями
                    ↓
     Проверка менеджером → экспорт заказа

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

Структура проекта

.
├── app.py                       # Точка входа Streamlit
├── src/
│   ├── __init__.py
│   ├── partner_import.py        # Импорт Excel-книг из архивов
│   ├── forecast.py              # Сезонный прогноз и исключение крупных операций
│   ├── partner_ui.py            # Интерфейс кейса, дополнения и проверка заказа
│   └── planning.py              # Дневной учебный расчёт и экспорт Excel
├── data/
│   ├── products.csv             # Синтетический справочник
│   └── sales.csv                # Синтетическая история
├── tests/
│   ├── test_forecast.py
│   ├── test_import.py
│   └── test_planning.py
├── .github/
│   └── workflows/
│       └── tests.yml            # Автоматические проверки
├── .streamlit/
│   └── config.toml              # Настройки локального сервера и оформления
├── .gitignore
├── requirements.txt
└── README.md

Реальные выгрузки компании не должны входить в публичный репозиторий. Для демонстрации без исходных архивов используются синтетические данные из data/.

Быстрый запуск

Требования

  • Python 3.11 или 3.12.
  • Интернет для первоначальной установки зависимостей.
  • Браузер для работы с интерфейсом.

Скачайте репозиторий или распакуйте архив проекта. Откройте терминал в папке, где находится app.py.

Windows PowerShell

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m streamlit run app.py

Linux / macOS

python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m streamlit run app.py

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

http://localhost:8501

Чтобы остановить сервер, нажмите Ctrl+C в терминале.

Если приложение не запускается

  • Убедитесь, что команда выполняется из папки проекта.
  • Устанавливайте зависимости и запускайте приложение одним и тем же интерпретатором из .venv.
  • Если команда python недоступна, установите Python или используйте доступный в вашей системе Python Launcher.
  • Если Windows блокирует нативную библиотеку, например PyArrow, используйте разрешённое Python-окружение или обратитесь к администратору. Приложение не требует отключения системной защиты.

Пользовательский сценарий

  1. Выберите режим кейса Электрокомплект.
  2. Загрузите IEK.zip и Systeme electric.zip.
  3. Проверьте список распознанных источников и предупреждения.
  4. При необходимости загрузите дополнения: актуальные остатки, сроки поставки, ограничения заказа, календарь stockout или обезличенную клиентскую детализацию.
  5. Укажите дату расчёта, период пересмотра и параметры страхового запаса.
  6. Настройте политику запаса по категориям.
  7. Нажмите «Рассчитать заказы по архивам».
  8. Отфильтруйте результат по поставщику или категории.
  9. Изучите объяснение и графики выбранного товара.
  10. Подготовьте и скачайте Excel с рекомендациями.
  11. В разделе проверки скорректируйте количества, подтвердите их и скачайте CSV заказа.

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

Для знакомства без реальных архивов выберите «Дневной учебный пример» и нажмите «Рассчитать заказы».

Входные данные

Архивы партнёра

ИсточникНазначение
Ежемесячные продажиИстория суммарного спроса по товарам
Динамика продажПоиск крупных разовых операций по документам
Ежемесячные остаткиДиагностика возможного дефицита и покрытия данных
Файлы сезонностиПрофиль сезонности поставщика
MOQ / кратностьОграничения количества заказа
Товар в путиОжидаемые поступления и даты
Ведомость Systeme ElectricСвободный остаток, категория, коэффициент роста и связанные поля

Основной ключ объединения — поставщик + код 1С. Артикул поставщика сохраняется отдельным полем. Объединение по похожим названиям не используется.

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

Дополнения к справочнику

CSV содержит обязательные ключи supplier,sku и любое подмножество поддерживаемых полей:

ПолеЗначение
supplierIEK или Systeme Electric
skuКод товара в 1С, строка
stockАктуальный свободный остаток, за вычетом резервов
moqМинимальное ненулевое количество заказа
pack_sizeКратность заказа, не меньше 1
lead_time_daysСрок поставки в днях
growth_pctДополнительный прирост: 0.10 означает +10%
categoryКатегория для выбора политики запаса
unitСогласованная единица учёта
safety_multiplierИндивидуальный множитель страхового запаса

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

Календарь stockout

supplier,sku,month,stockout_days
  • month — первый день соответствующего месяца, например 2026-08-01.
  • stockout_days — подтверждённое целое количество дней отсутствия товара.
  • Значение 0 означает проверенный месяц без stockout.
  • Непереданный месяц означает отсутствие информации, а не подтверждённое наличие товара.

Обезличенная клиентская детализация

supplier,sku,date,document,quantity,customer_id

Допускаются только указанные поля. Пользователь должен подтвердить обезличивание. Файл заменяет детализацию документов для выявления выбросов; месячный отчёт остаётся источником суммарных объёмов.

Номер документа не считается идентификатором клиента. В исходных архивах ID клиента отсутствует, поэтому без дополнения используется анализ документов.

CSV следует сохранять в UTF-8 с разделителем-запятой. Коды товаров необходимо хранить как строки, сохраняя ведущие нули.

Методология

1. Подготовка истории

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

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

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

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

2. Исключение крупных разовых операций

При наличии обезличенного ID клиента продажи агрегируются по клиенту, товару и месяцу. Это позволяет обнаружить крупную покупку, разбитую на несколько документов.

При отсутствии ID клиента анализируются группы «документ + дата + товар».

Для товара с минимум восемью группами рассчитывается робастный порог:

threshold = max(
    5 × median,
    median + 6 × 1.4826 × MAD,
    1
)

MAD = median(|quantity − median(quantity)|)

Операции выше порога исключаются из регулярного спроса, если их количество не превышает max(1, floor(10% числа групп)). Клиент с крупными отклонениями более чем в двух месяцах не считается разовым автоматически.

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

Алгоритм является эвристикой. Для короткой истории, проектных продаж и регулярно крупных покупателей требуется проверка менеджера.

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

Файлы сезонности дают нормализованный профиль поставщика по полным 2024–2025 годам. Поскольку эти таблицы содержат денежные показатели, их профиль используется как приближение сезонности натурального спроса.

Если у товара есть два полных года истории и достаточно ненулевых месяцев, рассчитывается собственный профиль:

  1. Объём месяца переводится в средний дневной спрос.
  2. Дневной спрос нормируется на среднее значение соответствующего года.
  3. Для каждого календарного месяца берётся медиана нормированных значений.
  4. Итоговый профиль объединяет 80% сезонности товара и 20% сезонности поставщика.

При недостаточной истории используется профиль поставщика. Если и он отсутствует, сезонные коэффициенты равны 1.

4. Компенсация упущенного спроса

Для подтверждённого stockout применяется корректировка по числу дней доступности:

recovered_demand = regular_sales × D / (D − d)

Здесь D — число дней месяца, d — число дней отсутствия товара.

Для месяца, когда товар отсутствовал полностью, используется медианная дневная база остальных месяцев с сезонной корректировкой. Если такой базы нет, спрос признаётся неизвестным.

Компенсация включается в восстановленную историю. Отдельно прибавлять её ещё раз к будущему заказу нельзя: это привело бы к двойному учёту.

Нулевой остаток в месячном снимке не означает отсутствие товара весь месяц. Без календаря stockout модель не выдумывает длительность дефицита.

5. Устойчивый рост и дополнительный прирост

База прогноза — средняя восстановленная дневная потребность последних шести полных месяцев после удаления сезонного эффекта.

Исторический тренд рассчитывается по изменениям к тем же месяцам предыдущего года:

  • требуется минимум шесть сравнений;
  • используются последние двенадцать доступных сравнений;
  • изменение считается устойчивым, когда минимум 2/3 сравнений имеют тот же знак, что и медиана;
  • годовой темп ограничивается диапазоном от −50% до +100%.

По настройке интерфейса «Кэф. Роста» из ведомости заменяет историческую оценку. Он трактуется как годовой темп с ограничением от −90% до +200%. Период этого коэффициента необходимо подтвердить у партнёра; допущение отражается в объяснении.

Для будущего дня t:

daily_forecast = base_daily_demand
                 × seasonal_factor
                 × (1 + annual_trend)^(t / 365.25)
                 × (1 + growth_pct)

growth_pct — отдельно заданный бизнес-прогноз прироста. Исторический тренд и коэффициент роста ведомости не применяются одновременно как два независимых эффекта.

6. Горизонт и страховой запас

H = lead_time_days + review_days

Страховой запас для месячной модели:

safety_stock = ceil(
    z × σ × sqrt(H × 30)
      × category_multiplier
      × safety_multiplier
)

σ — стандартное отклонение десезонализированной дневной базы за последние двенадцать месяцев. z — настраиваемый коэффициент запаса.

Политика категорий редактируется в интерфейсе. По умолчанию множители равны 1. Числовые категории источника не интерпретируются как ABC-классы без правил партнёра.

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

7. Остаток, путь и срочность

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

Просроченные поступления требуют проверки фактического прихода. Поставки за пределами горизонта не уменьшают потребность текущего расчёта.

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

8. MOQ и кратность

net_need = max(0, forecast + safety_stock − stock − in_transit)

order_qty = 0, если net_need = 0

order_qty = ceil(max(ceil(net_need), MOQ) / pack_size) × pack_size,
            если net_need > 0

MOQ — минимальный допустимый ненулевой заказ. Кратность — шаг количества. Эти ограничения различаются.

СитуацияРезультат
Нужно 100, на складе 40, в пути 30, без дополнительных ограничений30
Чистая потребность 37, MOQ 50, кратность 150
Чистая потребность 110, MOQ 50, кратность 1110
Чистая потребность 110, MOQ 50, кратность 50150
Чистая потребность 0, MOQ 500

Таким образом, пример 120 + 40 − 30 − 20 даёт 110 единиц до округления. Рекомендация 150 корректна при кратности 50, а не только при MOQ 50.

Результат и экспорт

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

ПолеСмысл
supplier, sku, articleПоставщик, код 1С, артикул поставщика
name, category, unitОписание, категория, единица учёта
forecast, safety_stockПрогноз на горизонт и страховой запас
stock, in_transitСвободный остаток и учтённые поступления
net_needПотребность до ограничений поставщика
moq, pack_size, order_qtyMOQ, кратность, рекомендуемое количество
lost_sales, excluded_qtyКомпенсация дефицита и исключённый разовый объём в истории
urgency, deficit_dateСрочность и ожидаемая дата дефицита
status, explanationКачество исходных данных, допущения и обоснование

Пустое количество заказа означает, что данных недостаточно. Оно не равно нулевой потребности.

Excel содержит отфильтрованные рекомендации и историю расчёта. После проверки менеджером доступна выгрузка подтверждённых количеств в CSV с кодами 1С и артикулами поставщика.

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

Проверка требований ТЗ

Must HaveРеализацияУсловие проверки
Базовая потребность с учётом источниковИстория, склад, путь, категории и прирост участвуют в расчёте или диагностикеИзменение значимых входов меняет результат либо статус
Сезонность и устойчивый ростСезонный профиль и годовой трендСезонный ряд даёт различающийся прогноз по месяцам
Упущенный спросВосстановление по подтверждённым дням отсутствияПри stockout восстановленный спрос выше сырого
Исключение крупных разовых продажАнализ документов или клиента за месяцИскусственный разовый всплеск не увеличивает регулярный прогноз пропорционально объёму
Объяснение и поставщикиОбъяснение каждой строки, сортировка и фильтрацияКаждая позиция проверяется отдельно и в разрезе поставщика

Проверка на реальных клиентах и реальных периодах отсутствия требует дополнительных данных: в предоставленных архивах этих полей нет.

Тестирование

Windows:

.\.venv\Scripts\python.exe -m unittest discover -s tests -v

Linux / macOS:

.venv/bin/python -m unittest discover -s tests -v

Тесты покрывают сезонность, рост, компенсацию дефицита, настоящий нулевой спрос, неизвестный спрос, крупные документы, раздробленный заказ одного клиента, склад, даты пути, категорийную политику, MOQ, кратность, валидацию и экспорт.

Автоматические тесты проверяют бизнес-правила. Они не доказывают точность прогноза или экономический эффект. Для этого требуется backtest на отложенной истории с сопоставлением с базовыми прогнозами и фактическими складскими результатами.

Ограничения прототипа

  1. Текущие остатки IEK. В месячной выгрузке указаны начальные остатки. Они не заменяют актуальный свободный остаток на дату расчёта; до его загрузки количество заказа не определяется.
  2. Календарь stockout. Месячные снимки не позволяют восстановить точную длительность отсутствия. Компенсация по реальным периодам требует отдельного источника.
  3. Клиенты. В исходной динамике нет ID клиента. Без дополнения доступен только анализ документов.
  4. Сроки поставки. При отсутствии подтверждённого срока применяется явно обозначенный сценарный параметр.
  5. Единицы измерения. Метры, штуки и бухты нельзя смешивать. Позиции с несогласованным переводом единиц требуют проверки до заказа.
  6. Склады. Расчёт по архивам консолидирован: источники не дают согласованной детализации месячных продаж и актуальных остатков по каждому складу. Реализован выбор категории.
  7. Сезонность. Денежный профиль поставщика — приближение натурального спроса. Собственная сезонность SKU оценивается до восстановления stockout и может быть смещена длительными дефицитами.
  8. Выбросы. Автоматический порог не заменяет знания менеджера о проектах, акциях и повторяющихся крупных заказах.
  9. Дата снимка. Исходные сведения привязаны к сентябрю 2026 года. Изменение даты в интерфейсе не обновляет источники автоматически.
  10. Производственная эксплуатация. Постоянный журнал утверждений, аутентификация, разграничение прав, плановые загрузки и интеграция с 1С не входят в текущий локальный прототип.

Приватность

  • Реальные данные компании не публикуются в GitHub.
  • Обработка выполняется локально без передачи продаж в облачные LLM или внешние API.
  • Импортированные таблицы хранятся в памяти текущей сессии, без общего глобального кэша.
  • Клиентская детализация допускается только с обезличенными ID. Подтверждение в интерфейсе не заменяет предварительное обезличивание владельцем данных.
  • Исходные архивы не изменяются при импорте.
  • Сервис не отправляет заказ поставщику автоматически.
  • Перед публикацией репозитория необходимо проверить, что в Git не попали реальные выгрузки, промежуточные файлы и секреты.

Дальнейшее развитие

  • Загрузка актуальных остатков, резервов и подтверждённых дат поступления из 1С.
  • Учёт ежедневной доступности товара и точных интервалов stockout.
  • Расчёт по складам и рекомендации по перемещениям между ними.
  • Согласование единиц закупки, MOQ и кратности по каждому поставщику.
  • Проверка качества прогноза на отложенной истории и сравнение с сезонным наивным прогнозом.
  • Учёт промоакций, проектных заказов и товарных замен.
  • Калибровка страхового запаса под целевой уровень обслуживания.
  • Постоянный журнал изменений и утверждений, роли пользователей.
  • Подготовка адаптера экспорта для конкретной конфигурации 1С.

Контекст проекта

Мероприятие: HACKALEM AI.
Кейс: автоматизация формирования заказов поставщикам.
Партнёр: ТОО «Электрокомплект» (ekt.kz).
Основной пользователь: менеджер отдела закупа.

Рекомендации предназначены для проверки ответственным сотрудником перед оформлением закупки.

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

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

nursezimgazetova2005-dotcom 7batyrnursoltanov 5Violet26-u 4

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

  • 2026-09-23 16:40Add anomaly sales correction and base demand calculationViolet26-u
  • 2026-09-23 16:38Analyze data structure and define key algorithm inputsViolet26-u
  • 2026-09-23 16:36README with HACKALEM AI project detailsnursezimgazetova2005-dotcom
  • 2026-09-23 16:33README with HACKALEM AI project detailsnursezimgazetova2005-dotcom
  • 2026-09-23 16:32Implement recommendations and start MOQ integrationnursezimgazetova2005-dotcom
  • 2026-09-23 16:27Implement recommendations and start MOQ analysisnursezimgazetova2005-dotcom
  • 2026-09-23 16:26Add anomaly sales correction and base demand calculationViolet26-u
  • 2026-09-23 16:14Enhance README with project details and structurenursezimgazetova2005-dotcom
Все коммиты (16)
  • 2026-09-23 16:47Create part 6batyrnursoltanov
  • 2026-09-23 16:22Create part 7 and 8batyrnursoltanov
  • 2026-09-23 14:50Create part 4 and 5Violet26-u
  • 2026-09-23 14:48Rename part 2 to part 2 and 3nursezimgazetova2005-dotcom
  • 2026-09-23 14:47Add project overview and data loading detailsnursezimgazetova2005-dotcom
  • 2026-09-23 14:51Add project status and next steps in part 6batyrnursoltanov
  • 2026-09-23 14:43Merge pull request #1 from BAITC-Hacks/batyrnursoltanov-patch-1batyrnursoltanov
  • 2026-09-23 14:39Add project overview and structure for automation servicebatyrnursoltanov
Структура репозитория (7 файлов)
1 part
Part 2 and 3
README.md
part 11 and 12
part 4 and 5
part 6
part 9 and 10
Ветки (2)

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

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

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