AAYMA
RU
Войти

Agro-Pulse

CLI на Go, который загружает Excel поставщиков IEK и SystemElectric, чистит спрос от выбросов и stockout и считает рекомендуемый заказ по SKU с…

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

О проекте

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

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

Суть

CLI на Go, который загружает Excel поставщиков IEK и SystemElectric, чистит спрос от выбросов и stockout и считает рекомендуемый заказ по SKU с учётом остатка, поступлений и MOQ. Каждая рекомендация сопровождается объяснением.

Как устроено

Загрузчики через excelize нормализуют SKU с сохранением ведущих нулей. Выбросы винзоризуются по внешней границе Тьюки Q3+3·IQR отдельно для каждого SKU, по транзакциям и по десезонализированному месячному ряду. Затем корректируется подтверждённый stockout. Сезонность нормируется, тренд оценивается методом Theil–Sen. Заказ считается как raw = max(0, forecast − stock − incoming), округляется и подгоняется под MOQ (минимум или кратность). Если реальных входов не хватает, результат получает статус needs_data вместо вымышленного числа. Выход: JSON с группами поставщиков, срочностью и объяснениями.

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

  • Theil–Sen тренд
  • сезонные коэффициенты
  • Tukey outer fence (Q3+3·IQR)
  • винзоризация
  • коррекция stockout
  • MOQ-округление
  • strict mode needs_data

Особенности

Подробно обоснован выбор порога 3·IQR вместо 1.5 и отказ от z-score для скошенных продаж. Режимы строгий (реальные данные) и синтетическое демо жёстко разделены. На реальных данных IEK (3185 SKU) и SystemElectric (724 SKU) все позиции честно получили needs_data, потому что не хватает подтверждённых входов.

Стек

Go · excelize


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

README

README.md

Agro-Pulse

1. Название проекта

Agro-Pulse — автоматический расчёт заказов поставщикам для пополнения склада. Локальный Go MVP для кейса HackAlem / «Электрокомплект».

Быстрый запуск без Excel: go run ./cmd/app --demo.

2. Проблема

Менеджер отдела закупа вручную консолидирует Excel. Из-за трудоёмкости расчёт выполняется редко; разовые крупные продажи искажают регулярный спрос. Результат — избыточные запасы (overstock), дефицит (stockout) и упущенные продажи. Основной пользователь — менеджер отдела закупа.

3. Решение

Agro-Pulse загружает Excel, нормализует SKU, анализирует продажи, ограничивает влияние крупных выбросов и рассчитывает прогноз с сезонностью и устойчивым трендом. При подтверждённых периодах отсутствия товара ядро корректирует спрос. Из прогноза вычитаются текущий остаток и подтверждённые поступления; результат содержит количество, статус и детерминированное объяснение.

Два режима: строгая обработка реальных данных и изолированная синтетическая демонстрация. Недостаток обязательных реальных входов даёт needs_data, а не вымышленное число заказа.

4. Что реализовано

REAL PARTNER DATA (partner_data)

  • Загрузчики IEK и SystemElectric, подключённые к одному cmd/app.
  • Сохранение значимых ведущих нулей и _ в SKU; контроль пустых и конфликтующих данных.
  • Диагностика спроса, выбросов, покрытия источников; проблемные SKU остаются в отчёте.
  • Категория SystemElectric переносится из источника в рекомендацию; коэффициент категории не придумывается.
  • JSON с отдельными группами поставщиков, причинами needs_data и объяснениями.
  • На предоставленных файлах за 22.09.2026 проверено: IEK — 3185 SKU, SystemElectric — 724 SKU; все needs_data, числовых заказов нет.

DEMO MODE (synthetic_demo)

  • Пять сценариев, не требующих Excel, с полными явно заданными входами.
  • Числовой заказ, сезонность, тренд, коррекция выбросов и подтверждённого stockout.
  • Проверка происхождения входов: смешивание demo и partner data отклоняется.
  • Каждый скаляр demo JSON помечен source; расчёт использует то же ядро.

5. Методология расчёта

Ниже описаны допущения MVP, а не согласованные бизнес-правила заказчика.

  1. Используются завершённые месяцы до as-of. Пропуски не превращаются в нули; отрицательные месячные продажи исключаются из оценки с предупреждением.
  2. Регулярный спрос получается после коррекции выбросов. Диагностический baseline — среднее наблюдаемых продаж, regular demand — среднее скорректированных продаж.
  3. Подтверждённые SKU-коэффициенты сезонности нормируются до среднего 1. История очищается от сезонного масштаба; общий профиль компании не назначается SKU.
  4. Устойчивый тренд — Theil–Sen: медиана попарных наклонов. Уровень — медиана пересечений с осью. Короткая история сопровождается предупреждением.
  5. Подтверждённый stockout корректирует историю до прогнозирования. Lost demand не прибавляется к итоговому заказу повторно.
  6. Прогноз восстанавливает сезонный масштаб и учитывает долю календарного месяца в горизонте. По умолчанию горизонт — один месяц, допустимо 1–24.
  7. Учитывается валидный снимок на дату расчёта; исторический остаток не заменяет текущий. Поступления учитываются в интервале [as-of, конец горизонта) при известных датах и количествах.
  8. raw = max(0, forecast − current_stock − incoming). Для штук количество округляется вверх; затем применяется известное правило MOQ: минимум или кратность. В strict mode неподтверждённое правило MOQ блокирует числовой заказ.

Страховой запас не добавляется. Категория и поставщик сохраняются как атрибуты; отдельная модель роста по категориям не реализована.

Формулы

Обозначения: y_t — регулярный спрос месяца t после выбросов и stockout, s_m — сезонный коэффициент календарного месяца m, t — номер месяца от начала истории.

Нормировка сезонности   s_m = S_m / mean(S_1..S_12)                  среднее s_m = 1
Десезонализация         z_t = y_t / s_m(t)
Тренд (Theil–Sen)       b   = median{ (z_j − z_i) / (t_j − t_i) : i < j }
Уровень                 a   = median{ z_t − b · t }
Прогноз на месяц h      F_h = max(0, a + b · t_h) · s_m(h) · доля_месяца_в_горизонте
Прогноз                 Forecast = Σ_h F_h
Сезонное влияние        seasonality_impact = Forecast − Σ_h max(0, a + b · t_h) · доля_h
Сырая потребность       raw = max(0, Forecast − current_stock − incoming)

incoming — сумма партий с датой прибытия в [as-of, as-of + months). Если у партии пустое количество или дата, либо поставка просрочена, incoming считается неизвестным.

MOQ и округление (internal/calculator/calculator.go):

ПравилоДействие
единица шт, упак, комплq = ⌈raw⌉; для м дробное количество допустимо
minimumq > 0 → max(q, MOQ)
multipleq > 0 → ⌈q / MOQ⌉ · MOQ
MOQ не заданбез корректировки, предупреждение MOQ_NOT_PROVIDED
правило неизвестноошибка; в strict — needs_data: moq_rule_unconfirmed

moq_adjustment = q_после_MOQ − q_до_MOQ.

Срочность

ЗначениеУсловие
nowтекущий остаток 0 при положительном прогнозе
within_horizonпри равномерном потреблении внутри месяца остаток уходит в минус до очередного поступления или до конца горизонта
coveredзапаса и поступлений хватает на весь горизонт
unknownна реальных данных: политика срочности не утверждена заказчиком

Поступление считается доступным с начала даты прибытия.

6. Алгоритм исключения выбросов

Используется внешняя граница Тьюки: Q3 + 3 × IQR, где IQR = Q3 − Q1. Реализация: CapOutliers в internal/analytics/outlier.go, вызов — prepareDemand в internal/analytics/forecast.go.

Почему этот метод и этот порог

  • Распределение продаж сильно скошено. Много мелких отгрузок и редкие очень крупные. Z-score опирается на среднее и стандартное отклонение, а их сам же выброс и раздувает, так что крупная продажа маскирует сама себя. Квартили от хвоста не зависят и не требуют нормального распределения.
  • Коэффициент 3, а не 1.5. По Тьюки 1.5·IQR — «подозрительное» значение, 3·IQR — «экстремальное» (far out). У электротехники регулярный опт и так даёт длинный хвост, и граница 1.5 срезала бы обычные оптовые отгрузки. Задача — отсечь только разовые аномально крупные продажи.
  • Граница считается по данным каждого SKU, а не задаётся фиксированным числом штук. Поэтому одна формула подходит и для товара, который продаётся по 10 штук, и для товара, который продаётся по 10 000.

Алгоритм (для каждого SKU)

  1. Выборка транзакций. Строки «Динамики продаж» с документом «Расходная накладная» с 2025 года до месяца as-of (не включая его). Граница строится только по положительным количествам; возвраты и нули в неё не входят.
  2. Минимум данных. Меньше 4 положительных значений — граница не строится, предупреждение insufficient_transactions_for_outlier_fence.
  3. Квартили Q1, Q3 — линейная интерполяция по отсортированным значениям; Fence = Q3 + 3·(Q3 − Q1).
  4. Винзоризация. Каждая транзакция x > Fence заменяется на Fence, а не удаляется. Факт продажи остаётся, в регулярный спрос не попадает только аномальная часть объёма.
  5. Перенос в месячный ряд. Для месяца считается excess = Σ(x − Fence) по его выбросам. Если сумма транзакций месяца совпадает с файлом месячных продаж (допуск 1e-6 · max(1, |месяц|)), regular = max(0, месяц − excess) и applied = true. Если нет, месячное значение не меняется: выброс помечается applied = false, добавляется предупреждение transaction_monthly_mismatches.
  6. Месячная проверка. Затем тот же тест применяется к месячному ряду, очищенному от сезонности (y_t / s_m). Результат снова умножается на s_m. Так страхуются месяцы без сопоставимых транзакций, а сезонный пик не считается выбросом.
  7. Нули и провалы выбросами не считаются, ими занимается коррекция stockout (раздел 8). Пропуски и отрицательные месяцы исключаются с предупреждением.

Что попадает в отчёт

Каждый выброс записывается в outliers[]:

{ "source": { "file": "Динамика продаж_2025-2026.xlsx", "sheet": "Лист_1", "cell": "H13947" },
  "original": 3200, "adjusted": 129,
  "method": "transaction_tukey_outer_fence", "applied": false }

method принимает значения transaction_tukey_outer_fence или monthly_deseasonalized_tukey_outer_fence. В диагностике без сезонности — monthly_unadjusted_tukey_outer_fence.

Ограничения

  • Группировка продаж по клиенту не реализована: в загруженной схеме нет клиентского ID.
  • У SKU с регулярным крупным оптом IQR может срабатывать на обычные отгрузки. Пример: IEK 010500006_ — 949 потенциальных выбросов. Для таких SKU порог нужно проверить вместе с заказчиком.

7. Почему крупный разовый заказ не ломает прогноз

Фактический demo LARGE OUTLIER добавляет 100000 единиц к одной продаже обычного размера 31. Обнаруживается один выброс; после коррекции регулярный спрос и прогноз равны 310, заказ — 276, как в NORMAL DEMAND. Выброс остаётся видимым в диагностике и объяснении.

Результаты запуска на 01.01.2026:

СценарийПрогнозОстатокВ путиЗаказ
NORMAL DEMAND310450276
LARGE OUTLIER310450276
GROWING DEMAND720450675
INCOMING GOODS3104520072
STOCKOUT31000312

GROWING DEMAND сочетает рост и январский сезонный коэффициент 2 (остальные — 1). После нормировки сезонное влияние равно 330, тренд — примерно 21.667 ед./месяц. В остальных сценариях профиль плоский. MOQ — кратность 12; для роста — минимум 400.

8. Stockout

observed demand — фактические продажи; lost demand — оценка упущенного спроса; adjusted/corrected demand — регулярный спрос плюс эта оценка. Ядро умножает подтверждённое число дней отсутствия товара на медианный дневной спрос других наблюдаемых месяцев без stockout.

В demo STOCKOUT за декабрь наблюдалось 0 продаж и подтверждено 31 день отсутствия. Оценка lost demand — 310, скорректированный спрос — 310, прогноз — 310, заказ — 312. Пустая ячейка или месячный нулевой остаток сами по себе не подтверждают период отсутствия товара. Реальные загрузчики не создают такое доказательство автоматически.

9. Архитектура

cmd/app/              единый CLI: demo, IEK, SystemElectric, JSON
internal/model/       входы, результаты и модели адаптера SystemElectric
internal/normalize/   SKU, числа, даты, месяцы
internal/loader/      чтение XLSX и соединение адаптера с общим ядром
internal/analytics/   выбросы, тренд, сезонность, stockout, прогноз
internal/calculator/  остаток, поступления, количество заказа, MOQ
internal/pipeline/    strict/demo orchestration и needs_data
internal/explain/     объяснение из рассчитанных значений
internal/demo/        пять синтетических сценариев и маркированный отчёт
tests/                заготовка под интеграционные тесты (пока без тестов)

Основные действующие тесты находятся рядом с кодом в internal/ и cmd/app/. Корневой main.go сохранён как прежний IEK entry point; для демонстрации используйте cmd/app.

10. Источники данных

IEK — ожидаемые имена файлов:

  • Ежемесячные продажи в количественном выражении за последние 2 года.xlsx
  • Ежемесячные остатки продукции за последние 2 года ИЭК.xlsx
  • Динамика продаж_2025-2026.xlsx
  • MOQ ИЭК.xlsx
  • Путь ИЭК 22.09.2026.xlsx
  • Сезонность ИЭК.xlsx

SystemElectric — автопоиск по ключевым словам имени, проверенная выгрузка:

  • MOQ SystemElectric.xlsx
  • Динамика продаж_Syseme Electric_2025-2026.xlsx
  • Ежемесячные остатки SystemElectric 2024-2026.xlsx
  • Ежемесячные продажи в кол-м выражении SystemElectric 2024-2026.xlsx
  • Сезонность SystemElectric 2024-2026.xlsx
  • Товар в пути_SystemElectric на 22.09.2026.xlsx

partner_data обозначает реальные данные; synthetic_demo — отдельные fixtures. IEK хранит происхождение чисел до файла/листа/ячейки. Мост SystemElectric сохраняет ключ источника в поле Source.File, а лист и координаты — в доступных issue; полная адресация каждой преобразованной числовой точки пока отсутствует. Исходники открываются только для чтения; файлы Excel и результаты с partner data не коммитятся.

11. Технологии

Go 1.25+ (версия из go.mod), Excelize v2, стандартные пакеты Go для CLI, JSON, статистики и тестирования. LLM и внешние AI API не используются.

12. Установка

git clone https://github.com/BAITC-Hacks/hack-c8b7404d-agro-pulse.git
cd hack-c8b7404d-agro-pulse
go mod download

13. Запуск

Demo без файлов партнёра

go run ./cmd/app --demo
go run ./cmd/app --demo --output demo-report.json

Запуск на реальных данных партнёров

Укажите реальные пути к каталогам с Excel-файлами IEK и SystemElectric.

Linux / WSL

go run ./cmd/app \
  --iek-dir "/path/to/Cases/IEK" \
  --se-dir "/path/to/Cases/Systeme electric" \
  --as-of 2026-09-22 \
  --months 1 \
  --output partner-report.json

Параметры CLI

ФлагОписание
--demoпять синтетических сценариев, Excel не нужен
--iek-dirпапка с шестью XLSX IEK (имена — раздел 10)
--se-dirпапка с XLSX SystemElectric
--as-ofдата среза, обязательна для real mode
--monthsгоризонт прогноза, 1–24 месяца (по умолчанию 1)
--outputпуть к JSON-отчёту; без флага — stdout

Пример проверенного запуска в WSL

go run ./cmd/app \
  --iek-dir "/mnt/c/Users/assem/OneDrive/Desktop/Cases/IEK" \
  --se-dir "/mnt/c/Users/assem/OneDrive/Desktop/Cases/Systeme electric" \
  --as-of 2026-09-22 \
  --months 1 \
  --output partner-report.json

Проверенный совместный запуск успешно формирует единый partner-report.json для двух поставщиков.

Пути необходимо заменить на расположение файлов на конкретном компьютере.

В WSL Windows-диск C: доступен через /mnt/c/.

Только IEK

go run ./cmd/app \
  --iek-dir "/path/to/Cases/IEK" \
  --as-of 2026-09-22 \
  --output iek-report.json

Только SystemElectric

go run ./cmd/app \
  --se-dir "/path/to/Cases/Systeme electric" \
  --as-of 2026-09-22 \
  --output se-report.json

В именах двух файлов IEK используются два пробела (…2 года ИЭК.xlsx, MOQ ИЭК.xlsx) — не переименовывайте их.

--output создаёт новый JSON-отчёт. Без этого флага JSON выводится в stdout.

14. Как проверить решение

  1. Выполнить go run ./cmd/app --demo --output demo-report.json.
  2. Открыть JSON: scenarios[].inputs.scenario.value содержит название сценария.
  3. Сравнить NORMAL DEMAND и LARGE OUTLIER: одинаковый заказ, но разное число выбросов.
  4. Посмотреть GROWING DEMAND: положительный тренд и ненулевое сезонное влияние.
  5. Сравнить INCOMING GOODS с NORMAL: поступление 200 снижает заказ с 276 до 72.
  6. Посмотреть STOCKOUT: lost demand 310 и заказ 312.
  7. В metrics.explanation.value проверить обоснование каждого результата.

Быстрая таблица в PowerShell после экспорта:

$demo = Get-Content -Raw -Encoding utf8 demo-report.json | ConvertFrom-Json
$demo.scenarios | ForEach-Object {
    [pscustomobject]@{
        Scenario = $_.inputs.scenario.value
        Forecast = $_.metrics.forecast.value
        Order = $_.metrics.final_recommended_quantity.value
        Explanation = $_.metrics.explanation.value
    }
} | Format-Table -Wrap

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

go test ./... -count=1
go vet ./...
go build ./...

Проверяются монотонность заказа при росте остатка/поступлений, неотрицательность, огромный выброс, подтверждённый stockout, сезонность и рост, MOQ, needs_data, разделение provenance, соответствие explanation объекту и мост SystemElectric.

Тесты реальных Excel включаются отдельно (PowerShell):

$env:AGROPULSE_CASES_DIR = 'C:/path/to/Cases'
$env:SE_DATA_DIR = 'C:/path/to/Cases/Systeme electric'
go test ./... -count=1

Без переменных тесты реальных файлов пропускаются. Финальная проверка 23.09.2026: go test ./... -count=1 — PASS, включая тесты реальных IEK и SystemElectric; go build ./..., go mod tidy, go vet ./... — PASS. Demo и совместный real CLI выполнены успешно. Предыдущие запуски в этой Windows-среде блокировались Application Control; финальный прогон прошёл полностью. При ошибке локального build cache можно задать $env:GOCACHE = Join-Path $PWD '.gocache'; это не снимает ограничения Application Control.

16. Выходной формат

Real JSON: suppliers[] группирует рекомендации по поставщику. Каждая рекомендация содержит sku, supplier, forecast, current_stock, incoming, recommended_quantity, urgency, status, needs_data, explanation. Недоступное числовое значение сериализуется как null.

Demo использует обёртки value/source/derived_from. Реальный фрагмент из scenarios[0].metrics (поля derived_from здесь опущены для краткости):

{
  "sku": {"value": "DEMO-01", "source": "synthetic_demo"},
  "forecast": {"value": 310, "source": "synthetic_demo"},
  "current_stock": {"value": 45, "source": "synthetic_demo"},
  "incoming": {"value": 0, "source": "synthetic_demo"},
  "raw_recommended_quantity": {"value": 265, "source": "synthetic_demo"},
  "final_recommended_quantity": {"value": 276, "source": "synthetic_demo"},
  "status": {"value": "demo_recommendation", "source": "synthetic_demo"},
  "urgency": {"value": "within_horizon", "source": "synthetic_demo"}
}

Поставщик demo находится в inputs.supplier.value, объяснение — в metrics.explanation.value: «прогноз 310.000, остаток 45.000 … учтено в пути 0.000. Исходная потребность 265.000; заказ 276.000 шт.»

17. Ограничения MVP

  • IEK: месячные остатки не являются текущим снимком; правила MOQ и применимость общей сезонности к SKU не подтверждены.
  • SystemElectric: свободный остаток используется только если он явно предоставлен; дата из заголовка поступлений не считается подтверждённой датой доставки. Старый адаптер не различает отсутствующее поступление и явный ноль в пустом списке: мост консервативно оставляет такой incoming неизвестным.
  • Для обоих поставщиков нет подтверждённого SKU-профиля сезонности и длительности stockout; числовой заказ по текущим выгрузкам блокируется.
  • MOQ minimum/multiple, сроки поставки, политика срочности, возвратов и конверсии единиц требуют подтверждения. Strict pipeline выдаёт числовой заказ только в штуках.
  • Нет анализа клиентов, отдельной модели по категориям, UI, интеграции с 1С, бэктеста точности или автоматической отправки заказа.
  • Доказательство числового end-to-end расчёта — явно синтетические demo-сценарии. Решение не заявляется production-ready.

18. Безопасность и ограничения

Заказ не отправляется поставщику автоматически. Финальное решение проверяет и подтверждает сотрудник. Клиентские данные должны оставаться обезличенными. Коммерческие Excel и выгрузки отчётов нельзя публиковать; обработка выполняется локально, без отправки данных в LLM. Исходные Excel не изменяются.

19. Deployed version

Deployed-версия в рамках MVP не предусмотрена; решение запускается локально.

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

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

AlisherBaitas 7assrakhimova 6agabduli 6

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

  • 2026-09-23 17:25docs: update final README and run instructionsassrakhimova
  • 2026-09-23 17:14docs(readme): align markdown tables for readable source viewAlisherBaitas
  • 2026-09-23 17:03chore: remove Go build cacheassrakhimova
  • 2026-09-23 17:00docs(readme): add formulas, outlier threshold rationale and CLI flagsAlisherBaitas
  • 2026-09-23 16:53final: complete Agro-Pulse MVPassrakhimova
  • 2026-09-23 16:09feat: integrate IEK pipeline into mainassrakhimova
  • 2026-09-23 15:31Merge branch 'main' of https://github.com/BAITC-Hacks/hack-c8b7404d-agro-pulseagabduli
  • 2026-09-23 15:31Адаптер данных SystemElectric и аудит данныхagabduli
Все коммиты (19)
  • 2026-09-23 14:54Update main.goassemrs04-boop
  • 2026-09-23 14:32Merge branch 'main' of https://github.com/BAITC-Hacks/hack-c8b7404d-agro-pulseagabduli
  • 2026-09-23 14:32Добавила excelizeagabduli
  • 2026-09-23 14:29docs: add test plan with unit and integration test casesAlisherBaitas
  • 2026-09-23 14:14Merge branch 'main' of https://github.com/BAITC-Hacks/hack-c8b7404d-agro-pulseagabduli
  • 2026-09-23 14:14created main.goagabduli
  • 2026-09-23 14:14Create REQUIREMENTS.mdassemrs04-boop
  • 2026-09-23 14:10chore: init Go moduleAlisherBaitas
  • 2026-09-23 14:10test: add temporary empty stub for integration testsAlisherBaitas
  • 2026-09-23 14:10chore(calculator): add temporary empty stubs for calculator and testsAlisherBaitas
  • 2026-09-23 14:09chore(analytics): add temporary empty stubs for outlier, stockout, forecast and testsAlisherBaitas
Структура репозитория (47 файлов)
.gitignore
Agro-Pulse/DEMO.md
Agro-Pulse/IEK_RUN.md
Agro-Pulse/README.md
Agro-Pulse/REQUIREMENTS.md
DATA_AUDIT_SYSTEMELECTRIC.md
README.md
REQUIREMENTS.md
SYSTEMELECTRIC_DATA_AUDIT.md
TEST_PLAN.md
cmd/app/main.go
cmd/app/main_test.go
data/README.md
go.mod
go.sum
internal/analytics/forecast.go
internal/analytics/forecast_test.go
internal/analytics/outlier.go
internal/analytics/outlier_test.go
internal/analytics/stockout.go
internal/analytics/stockout_test.go
internal/calculator/calculator.go
internal/calculator/calculator_test.go
internal/calculator/inventory.go
internal/demo/demo_test.go
internal/demo/report.go
internal/demo/scenarios.go
internal/explain/explain.go
internal/explain/explain_test.go
internal/loader/iek.go
internal/loader/loader.go
internal/loader/loader_test.go
internal/loader/systemelectric.go
internal/loader/systemelectric_core.go
internal/loader/systemelectric_core_test.go
internal/loader/systemelectric_sources.go
internal/loader/systemelectric_test.go
internal/loader/systemelectric_xlsx.go
internal/model/model.go
internal/model/replenishment.go
internal/normalize/normalize.go
internal/normalize/normalize_test.go
internal/pipeline/demo.go
internal/pipeline/integration_test.go
internal/pipeline/pipeline.go
main.go
tests/integration_test.go
Ветки (2)

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

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

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