Когда варить пиво: планировщик для пивоварни на правилах и открытой арифметике

—

от автора

В Архангельске есть Пивзавод Суркова. Сорок лет там не варили пиво: последнюю партию сварили в конце 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/