У большинства SaaS для логистики одна и та же болезнь. Продукт растёт вширь, а не вглубь: чем больше у платформы клиентов, тем больше в ней настроек, режимов и чекбоксов, которые нужны кому-то другому и просто мешают вам. Форма заявки на приём разрастается до сорока полей, хотя на вашей площадке заполняется двенадцать. Админка становится квестом, а внедрение — отдельным проектом с интегратором на несколько месяцев.
Почему TOS для терминалов превращаются в монстров
С контейнерными TOS та же история, только заметнее. Каждый новый клиент приносит вендору свой процесс приёма, свой набор документов, свою логику постановки в бунт. Вендору выгоднее не переписывать ядро под каждого, а добавить ещё один флаг в настройках, ещё один необязательный шаг в мастере, ещё один тип документа в общий список. За несколько лет так набирается система, где половина экрана — это функции, о существовании которых вы даже не подозреваете.
Отдельная боль — любое изменение под вас идёт через очередь вендора и общий релизный цикл: рискованно менять что-то в продукте, которым пользуются ещё сто других терминалов.
Это не ошибка вендоров — это нормальная эволюция SaaS
Здесь не в чем упрекать разработчиков платформы. Чтобы продукт продавался всё большему числу клиентов, он обя зан покрывать всё больше сценариев — это и есть механика роста SaaS. Проблема не в решении вендора, а в том, что вы — не первый и не единственный клиент, а один из тысячи, и ваш процесс похоронен под процессами всех остальных.
Как мы в Altera решаем эту проблему
Модель Altera.CUSTOM устроена иначе: вместо одного огромного ядра «на все случаи» мы строим набор небольших модулей под конкретный бизнес-сценарий терминала, которые не трогают контур остальных клиентов.
Это стало возможно благодаря тому, как изменилась разработка. Раньше написание отдельного экрана с формой, валидацией и связкой с базой данных занимало у команды дни на рутину и только потом — часы на саму бизнес-логику. Сейчас рутинную часть — каркас формы, проверки, типовые запросы к данным — берёт на себя ИИ-инструментарий разработки, и команда сразу занимается тем, что реально отличает ваш процесс от чужого.
Поэтому вместо того чтобы закладывать в ядро продукта ещё один флаг под ваш случай, мы собираем отдельный подмодуль конкретно под него — он живёт в общей системе, использует те же статусы, права доступа и данные, что и остальные модули, но никак не влияет на то, как система работает у другого терминала.
При этом мы не жертвуем ни качеством, ни скоростью поддержки: подмодуль проходит те же проверки и релизный процесс, что и основной продукт — разница только в том, что менять его можно, не оглядываясь на сто других клиентов. В среднем от фиксации требований до готового подмодуля в работе — одна-две недели.
Где на практике нужен отдельный подмодуль
- Более детерминированный процесс приёма с несколькими ролями. На одной площадке в приёме контейнера участвует офис, который оформляет заявку, охранник на КПП, который фиксирует въезд машины, тальман, который составляет акт осмотра, и ричстакер, который подтверждает постановку. Под каждую роль — свой узкий экран: у охранника список ожидаемых машин, у тальмана — форма акта с фото повреждений, у ричстакера — задача на постановку с адресом ячейки. Экраны не пересекаются и не мешают друг другу — это ровно то, что уже устроено в кейсе «Автоматическая фиксация с камер».
- Обратная ситуация — один оператор на весь процесс. На другой площадке весь приём и затарку в смену ведёт один диспетчер при потоке до сотни контейнеров за пару часов. Здесь любой лишний клик или переключение экрана критичны, и подмодуль должен, наоборот, схлопывать процесс в один непрерывный шаг вместо разделения по ролям.
- Нестандартное покрытие территории. На площадке с грунтовым покрытием без чёткой разметки строгая адресная сетка ячеек физически не работает — нужен подмодуль, который группирует контейнеры под конкретную партию на отгрузку, а не привязывает их к жёстким координатам.
Общего у этих трёх сценариев одно: ни один типовой TOS не станет держать в ядре продукта одновременно многоролевой процесс, режим одного оператора и группировку без адресной сетки — а мы можем закрыть любой из них отдельным модулем, не трогая остальные.

