В Архангельске есть Пивзавод Суркова. Сорок лет там не варили пиво: последнюю партию сварили в конце 1985 года, а 3 марта 2026-го варку запустили снова. Рядом свой ресторан, одиннадцать танков, шесть сортов, и к осени пиво стало уходить быстрее, чем его успевали посчитать.
Я собрал для них систему планирования варок. Расскажу, как она считает, откуда берёт данные и почему внутри нет ни одной нейросети, хотя писал я её вместе с ИИ-агентами.
Задача
Главный вопрос цеха простой: какой сорт и до какого дня поставить в варку, чтобы кран не опустел. Сложность в сроках. Лагер после варки около месяца зреет в танке, поэтому решение принимается за месяц до того, как пиво кончится. Опоздали с варкой на день, и на день кран стоит пустой.
Вторая сложность в танках. Их одиннадцать, и один отдан только под фильтрованный лагер. Сварили лишнего, и под нужный сорт места уже нет.
До системы всё держалось на трёх источниках: продажи в кассе iiko, отгрузки юрлицам в 1С и остатки маркером на доске в цеху. Сводили их руками.
Почему без прогноза
Первое желание в такой задаче: обучить модель спроса. Мы от него отказались. Истории мало, завод варит с марта. Пивовар должен понимать, почему система говорит «вари сегодня». И цеху важнее запас по времени, чем точный прогноз: рост продаж закрывается запасом в днях.
Поэтому вся логика собрана из правил цеха и арифметики, которую можно раскрыть на экране до последней цифры.
Где лежит пиво
У каждого места своё правило:
-
ЦКТ: варка, брожение, потом готовое пиво стоит в танке, пока его сливают частями;
-
форфасы, четыре по 500 л: из них льются основные краны зала и магазин «с собой»;
-
кеги по 20 л: безалкогольное и сезонный сорт, терраса и юрлица. Из кеги обратно в форфас пиво не идёт;
-
стекло 0,33: разливают заранее, лежит партиями с днём розлива.
Путь партии: две варки в один танк, брожение со сроком по сорту, у лагера фильтрация в отдельный танк, потом «готово», слив частями, «танк пуст», день мойки, и танк снова свободен.
Формула «варить до»
Каждое утро система считает для каждого сорта:
-
запас = готовое пиво в танках + форфасы + кеги + стекло; партии, которые ещё бродят, прибавляются в день готовности;
-
расход в день = среднее за 14 последних дней, когда сорт продавался, но не дальше 28 дней назад;
-
день, когда пиво кончится, из запаса, расхода и будущих партий;
-
«варить до» = день, когда пиво кончится, минус срок брожения, минус дни варки сверх первого, минус 5 дней подстраховки.
Для лагера выходит 30 + 1 + 5 = 36 дней до конца запаса. Если «варить до» наступает сегодня, завтра или уже прошло, сорт попадает управляющему в блок «Решить сегодня».
Отдельно про среднее. День без продаж сорта в него не идёт. Мы прогнали правило по прошлым продажам: если считать дни пустого крана нулями, после такого провала среднее падает, и следующую варку система советует ставить позже, чем надо. Ошибка сама себя усиливает.
Танки
Вместе с днём варки система подбирает танк: свободный к этому дню, с учётом мойки и того, что ЦКТ 8 держат только под фильтрованный лагер. На экране танков видно, какие свободны сейчас и какие освободятся за неделю, а календарь показывает шесть недель вперёд.
Откуда данные
-
Касса. Отчёты iiko система забирает сама по API сервера дважды в день. Отчёт ищется по имени: переделают отчёт, id сменится, имя останется.
-
1С. Партнёр клиента по 1С настроил выгрузку, файл каждое утро приходит письмом. В расход идут только внешние покупатели: передача пива в собственный ресторан в 1С тоже оформлена продажей, иначе литры посчитались бы дважды.
-
Списания (пролив, дегустации) приходят актами из iiko.
Есть позиции, которые по названию не разобрать. «Бутылка» в кассе может быть стеклом со склада, а может быть налита с крана при покупателе. Гостевые сорта тоже. Такие позиции система не угадывает: один раз спрашивает управляющего на экране «Данные», запоминает ответ и до ответа не пускает эти литры в расход.
Журнал отметок
Всё, что происходит в цеху, попадает в систему отметками пивовара с планшета: «Принял» задание, «Сварил», «Слил» (куда и сколько), «Танк пуст», утренняя проверка танков. Готового состояния цеха в базе нет: его каждый раз собирает свёртка журнала по времени события. Отметка, сделанная вчера без связи и отправленная сегодня, встаёт на своё место во времени. Исправленная отметка видна в журнале обеими строками.
Когда расчёт расходится с фактом, система ставит задачу, например пересчитать кеги. А если пивовар отвечает «Танк пуст», хотя по расчёту там ещё оставалось, разница записывается в потери при сливе.
Экраны
Ролей три. Управляющий видит план: что решить сегодня, календарь, танки и кнопку «Поставить варку». После неё пивовару на планшет приходит задание. Собственник видит одну сводку: хватит ли пива по всем сортам. Экраны сделаны по брендбуку пивзавода, система выглядит как страница их меню.
Как собирали
Сначала разобрали цех и отдали команде страницу на сверку: путь партии, танки, форфасы, кто что отмечает. За расчёт сели только после ответов пивовара и управляющей. Стек: Python 3.12, FastAPI, SQLite, интерфейс на чистом JS, считает только сервер. Писал я это вместе с ИИ-агентами (Claude Code), от разбора цеха до пилота ушло чуть больше месяца. К старту пилота в проекте 999 тестов на Python и 318 сквозных сценариев в браузере.
Пилот
Со 2 ноября система работает в цеху. Таблицу цеха пока ведут параллельно, и каждое утро система сверяется с ней. Решения принимают люди, система считает и подсказывает. Посмотрим, кто кого.
Цифры на экранах в статье учебные, со стенда для показа. Кейс с роликом: evdokimov.ai/works/pivzavod/
ссылка на оригинал статьи https://habr.com/ru/articles/1102916/