«Да я сам за выходные накидаю приложение под ТСД»: анатомия одного архитектурного заблуждения и как устроена платформа для ТСД под капотом
В основу этой статьи легли живые технические воркшопы, которые разработчик платформы Mobile SMARTS Саргис проводил в разных городах — от Новосибирска и Красноярска до Краснодара и Ставрополя, — а также те самые честные кулуарные разговоры с программистами и интеграторами, которые начинаются уже после официальной части, когда выключается проектор и люди подходят со своими реальными болями.
На одном из таких воркшопов произошел показательный диалог. В зале сидела классическая сборная солянка: разработчики 1С и директора небольших франчайзи, авторы самописных учетных систем, опытные интеграторы (уже проходившие базовое обучение и заглянувшие послушать про тонкости написания кода внутри платформы) и пара программистов, которые случайно зашли на огонек с первого дня конференции.
В разгар демонстрации один парень из зала, явно считавший себя хардкорным технарем, скептически поднял руку: — Слушайте, ну это всё понятно, это базовые вещи для широкой публики. А можно в следующий раз придет кодер платформы? Я хочу спросить, как оно внутри устроено. Саргис посмотрел на него, улыбнулся и ответил: — Так я и есть кодер платформы. Какие у вас вопросы? Давайте разбираться, как это работает под капотом.
Они проговорили пятнадцать минут — про объектный слой, XML-схему базы, работу гибридных справочников и механику синхронизации. Скептицизм быстро улетучился: собеседник признал, что слегка недооценил глубину кроличьей норы.
Этот эпизод отлично вскрывает главную детскую болезнь всей индустрии мобильной автоматизации. Когда обычному разработчику — неважно, пишет он на C#, Kotlin, Python или 1С, — прилетает задача «прикрутить терминалы сбора данных (ТСД) к нашей учетной системе», первая мысль в его голове почти всегда звучит одинаково:
«Господи, да что там делать? Экранчик с двумя кнопками, текстовое поле под штрихкод и отправка JSON по REST API на бэкенд. Зачем мне разбираться в какой-то сторонней платформе, если я сам напишу своё приложение и мне там всё будет понятно? Тем более сегодня, с Cursor и Codex!»
И знаете что? Давайте сразу будем честны друг с другом. В некоторых случаях самописка — это действительно рабочее решение.
Если у вас один небольшой магазин или крошечный склад, ровно один ТСД, одна намертво застывшая конфигурация учетной системы, которую никто не обновляет, а в ваших процессах нет (и никогда не будет) обязательной маркировки — открывайте любимую IDE, запускайте ИИ-ассистента, пилите свое мини-приложение и даже не читайте эту статью дальше. Вы справитесь за месяц и забудете об этой задаче. А разгребать за вами эту задачу потом уже будет другой программист, с внутренним миром богаче вашего, которого будет ломать разбираться в вашей разработке (но это уже проблемы бизнеса, а не ваши).
Однако если у вас больше одного терминала, живой растущий бизнес, дырявый складской Wi-Fi, зоопарк штрихкодов от поставщиков или товары, подпадающие под «Честный ЗНАК», — добро пожаловать в реальный мир. Давайте разберем по косточкам и без маркетинговой шелухи, почему «простое приложение для сканера» неизбежно превращается в долгострой, какие архитектурные паттерны лежат внутри зрелой платформы для ТСД (даже без привязки к бренду Клеверенс) и как готовая платформа с коннекторами экономит разработчикам месяцы жизни.
Почему «просто пикнуть штрихкод» превращается в инженерный ад
Чтобы понять, почему самописные клиенты для ТСД так быстро обрастают костылями, нужно начать с фундаментального конфликта двух систем. Разработчики ERP, WMS и учетных систем привыкли мыслить категориями офисного или серверного софта. Но учетная система и мобильный терминал в руках кладовщика решают принципиально разные физические задачи:
Задача ERP — аккуратно зафиксировать прошлое. Транзакция уже произошла. Оператор сидит за большим монитором со стабильным интернетом, и у него есть 5–10 минут, чтобы без спешки разнести накладную, сверить реквизиты и провести документ.
Задача мобильной платформы на ТСД — управлять настоящим в реальном времени. Транзакция совершается прямо сейчас. Кладовщик стоит в холодном проходе между стеллажами, в одной руке коробка, в другой — терминал. Ему нужно зафиксировать операцию за доли секунды (в идеале — быстрее 0,8 секунды на скан), тут же получить от системы проверку по бизнес-правилам и увидеть следующий шаг маршрута. Мобильное приложение здесь — не «удаленная форма ввода в БД», а навигатор, который ведет работника по процессу и физически отсекает ошибки до того, как они попадут в учетную систему.
Именно поэтому попытки пробросить на ТСД десктопные экраны ERP через удаленный рабочий стол (RDP) или открыть в браузере терминала обычную веб-форму учетки всегда проваливаются: функционально на экране есть всё, но работать на 4-дюймовом дисплее в таком режиме невозможно.
Когда же разработчик решает написать собственный мобильный клиент с нуля, он последовательно наступает на три системные мины.
Мина №1. Реальное складское железо, периферия и ловушка UI-потока
В офисе программист тестирует свое приложение на мощном ноутбуке в эмуляторе или на современном смартфоне. Но на реальных складах работают совсем другие устройства. Самые массовые рабочие лошадки на рынке — это бюджетные и среднебюджетные промышленные терминалы (уровня Atol Smart.Lite, Smart.Prime, Urovo DT40), а на многих предприятиях в строю до сих пор стоят устройства на старых версиях Android (от 5 до 11) и даже терминалы на Windows CE / Windows Mobile.
Попробуйте запустить на бюджетном ТСД приложение, собранное на тяжелом кроссплатформенном фреймворке вроде Flutter или на базе сложного веб-движка (как в современных банковских супераппах или сервисах доставки). Вы обнаружите, что холодный старт такого приложения на слабом процессоре ТСД занимает от 2 до 5 минут. Любой синхронный сетевой вызов или лишняя перерисовка интерфейса в главном потоке мгновенно вешает окно и вызывает ANR (Application Not Responding) — системную плашку «Приложение не отвечает». На практике даже замена простой линейной полоски прогресса (ProgressBar) на обычный крутящийся спиннер в окне загрузки на медленном ТСД отъедает 10–15% времени старта и ускоряет разряд батареи просто за счет лишних вызовов отрисовки.
А дальше начинается аппаратная интеграция. Вам предстоит вручную подружить приложение:
со встроенными аппаратными считывателями штрихкодов разных вендоров (у каждого свои broadcast-интенты и SDK);
с внешними Bluetooth-сканерами и RFID-считывателями (работающими в том числе по низкоуровневому протоколу LLRP);
с мобильными и стационарными принтерами этикеток и чеков, чтобы печатать маркировку напрямую с терминала по Bluetooth или Wi-Fi даже при полном отсутствии связи с сервером;
с аппаратной индикацией самого ТСД — звуком и виброоткликом (потому что при потоковом сканировании или работе с прайс-чекером человек ориентируется на звук ошибки, а не вглядывается в экран).
Если писать и поддерживать всё это самому, то, как лаконично заметил Саргис на воркшопе, «можно просто устать». В специализированной платформе весь аппаратный слой уже абстрагирован: перехват сканирования работает в любом визуальном окне из коробки, а управление вибрацией, звуком или записью в системный лог вызывается одной командой встроенного объекта.
Мина №2. Изменчивость среды: «Честный ЗНАК» и обновления учетной системы
Предположим, вы победили железо и через месяц выкатили первую версию своей самописки. Она отлично сканирует линейные штрихкоды и складывает их в вашу базу.
Но через три месяца в бизнес приходят изменения: вводится обязательная маркировка для новой товарной группы (или меняются правила проверки в «Честном ЗНАКе»), поставщики начинают присылать паллеты с агрегированными кодами, а заодно выходит очередное обновление вашей ERP или конфигурации 1С, в котором поменялась структура документов.
Вот здесь самописный проект встает колом. Разработчику приходится "вручную" разбирать спецификации GS1 и DataMatrix, писать логику разделения идентификаторов применения (AI), высчитывать криптохвосты и учить свой парсер понимать, что именно сейчас пикнул кладовщик — пачку молока, бутылку воды или пару обуви, но самое сложное понять к какой товарной группе принадлежит маркированный товар и в этом случае надо пилить еще больше исключений из правил и еще больше интеграций. В платформе эта головная боль снята архитектурно: там уже живет готовый системный объект маркировки, который обновляется вендором платформы. Разработчику не нужно парсить сырую строку символов — после сканирования штрихкода в коде операции сразу доступны готовые типизированные поля марки.
Мина №3. Bus Factor = 1 и стоимость поддержки
У любого кастомного приложения под ТСД, написанного внутри компании на Java, Kotlin или C#, есть фатальная уязвимость: оно держится на том единственном разработчике, который его создал.
Как только этот человек увольняется или переходит на другой проект, бизнес остается один на один с репозиторием, который некому поддерживать. Найти на рынке мобильного разработчика, который согласится разбираться в чужом узкоспециализированном коде складского терминала ради мелких правок бизнес-логики, — задача долгая и экономически нерентабельная.
Анатомия платформенного решения: четыре инженерных паттерна под капотом
Давайте теперь посмотрим на задачу без привязки к брендам, с позиции системной инженерии. Какие архитектурные механизмы отличают специализированную платформу, связывающую парк ТСД и учетную систему, от простого «клиента для REST API»?
Паттерн 1. Эволюция оффлайн-хранения, гибридная БД и парадокс серверного кэша
Проследим, как обычно развивается мысль разработчика, когда он проектирует обмен данными для ТСД.
Первый соблазн — сделать тонкий онлайн-клиент: отсканировал штрихкод →→ отправил HTTP-запрос в ERP →→ получил ответ. В офисе всё работает идеально. Но склад — это клетка Фарадея из металлических стеллажей, бетонных стен и паллет с жидкостями. В мертвых зонах Wi-Fi пакеты теряются, соединение рвется, и тонкий клиент превращается в кирпич.
«Хорошо, — решает архитектор, — делаем Offline-First с локальной базой на устройстве». Но тут выясняется фундаментальное ограничение: для мобильных ОС вроде Android не существует тяжеловесных реляционных СУБД корпоративного класса (уровня Oracle или MS SQL Server), которые умели бы работать локально на слабом мобильном чипе и при этом из коробки обеспечивать двустороннюю репликацию с центральной базой. У вас есть только локальный движок SQLite, а поверх него вам придется самостоятельно спроектировать целый стек синхронизации:
Определить, какие справочники нужно держать в памяти ТСД целиком, какие — запрашивать с промежуточного сервера, а за какими обращаться напрямую в ERP.
Построить систему версионирования данных и дифференциальной синхронизации, чтобы при обмене передавать только компактные бинарные дельты изменений, а не перекачивать гигабайтные таблицы по слабой сети.
Вынести за скобки основных транзакций тяжелые бинарные данные (фотографии товаров, сканы документов), организовав их фоновую покусочную (чанковую) докачку при появлении связи.
Реализовать идемпотентность сетевых вызовов при коллективной работе: если связь оборвалась в момент отправки запроса, повторный запрос после реконнекта должен распознаваться по уникальному
GUID, чтобы сервер не создал дубликат документа, а вернул клиенту результат уже выполненной операции.
Именно эта инженерная задача в платформе Mobile SMARTS решена через технологию HYDB (Hybrid Database — гибридная база данных). Под капотом она объединяет локальный движок SQLite, систему XML-метаданных и поисковых индексов (включая тяжелые индексы для быстрого поиска по подстроке), отдельное хранилище бинарных блобов и собственный слой ORM.
Для разработчика прикладного уровня вся эта сложность скрыта: он работает с данными через простые запросы SELECT и транзакции, не задумываясь о физическом расположении записей. В свойствах любой таблицы достаточно задать её поведение:
хранится ли она в реляционном формате или в виде XML;
выгружается ли таблица на терминал или живет только на сервере (
Server Table);разрешен ли для неё прямой внешний вызов в учетную систему (
External Call) и с каким интервалом устаревания кэша (Data Refresh Period).
Практический кейс с воркшопов: ловушка гибридного справочника Саргис рассказывает, что именно на гибридных таблицах у разработчиков чаще всего случается показательный затык. Представьте ситуацию: программист настроил онлайн-обращение к 1С за остатками товара, но одновременно с этим вчера вечером выгрузил справочник остатков из 1С на сервер платформы. За ночь в 1С остаток товара изменился и стал равен 10 штукам, а в выгруженной на сервер платформы таблице со вчерашнего дня осталась лежать старая запись — 5 штук. Утром кладовщик сканирует товар на ТСД. Терминал делает запрос... и показывает на экране 5 штук! Разработчик в недоумении: «Почему он не сходил в 1С, у меня же включен онлайн?!» Ответ кроется в архитектуре разрешения запросов
HYDB: когда мобильный клиент запрашивает данные гибридной таблицы, сервер платформы сначала проверяет свою локальную серверную таблицу. Поскольку запись по этому товару там найдена (пусть и со вчерашним значением 5 штук),HYDBсчитает запрос успешно выполненным и не идет дальше во внешний вызов к ERP, экономя сетевые ресурсы и не нагружая учетную систему. Внешний запрос срабатывает как каскадный fallback тогда, когда локальная выборка вернула пустой результат. Понимание этой цепочки («Локальная БД ТСД →→ БД сервера платформы →→ Внешняя ERP») позволяет тонко управлять тем, какие данные должны кэшироваться, а какие — всегда тянуться вживую.
Паттерн 2. Умное управление объемом данных: Table Slices и Table Extensions
Когда бизнес вырастает до сети магазинов или нескольких распределительных центров, в центральной базе легко накапливается 1 000 000 записей остатков и цен по 10 филиалам. Выгружать весь этот миллион строк на каждый терминал бессмысленно — устройству в конкретном магазине нужны данные только своего филиала.
В платформенной архитектуре эта проблема решается двумя комплементарными механизмами:
Нарезка таблиц (
Table Slices): специальный коннектор на сервере (TableSlicerConnector) берет общую таблицу (например,Stock), делит её по указанной колонке (например,WarehouseId) и раскладывает на диске сервера по отдельным физическим подпапкам. Когда конкретный ТСД запрашивает обновление таблицы, на клиенте вычисляется выражение привязки (например,CurrentWarehouse.Id), и сервер отдает терминалу только его персональный срез данных. При этом разработчик сам задает политику обработки ошибок (Error Behavior): что делать, если выражение среза не удалось вычислить — отдать пустой ответ (оставив старые данные) или переслать полную таблицу (понимая риск сетевого шторма).Расширения таблиц документа (
Table Extensions): еще более тонкий механизм оптимизации внутриHYDB. Когда на ТСД выгружается конкретный документ задания (допустим, заказ поставщику №10021), прямо внутрь этого экземпляра документа упаковывается микро-таблица расширения (Stock table extension), содержащая остатки, серии и адресные ячейки только по товарам этого конкретного заказа.Инженерная красота здесь в том, что структура колонок (метаданные) расширения на 100% совпадает со структурой основной таблицы
Stock. Прикладной код на ТСД выполняет обычный запрос к таблицеStock, даже не зная о существовании кэша: платформа сама перехватывает обращение и мгновенно отдает данные из локального расширения документа. Если же кладовщик сканирует товар, которого не было в заказе, запрос к расширению возвращает0 записей— и только в этот момент платформа автоматически пробрасывает запрос к серверу или ERP. Более того, в ходе приемки мобильное приложение может дописывать новые строки прямо в это расширение, формируя готовый пакет изменений для последующей синхронизации с бэкендом.
Паттерн 3. Двухсписочная транзакционная модель документа (Expected vs Actual) и контейнерный учет
Новички, пишущие свою первую складскую программу, почти всегда делают в документе одну таблицу товаров: выгружают из ERP плановый список (Товар А — План: 10, Факт: 0) и при каждом скане просто увеличивают число в колонке Факт.
На реальном складе такая схема рушится в первый же день. Почему? Потому что 10 штук Товара А по факту приезжают в двух разных коробках по 5 штук, каждая коробка лежит на паллете со своим уникальным серийным кодом транспортировки (SSCC), у них разные серии, а следом кладовщик вообще сканирует 1 штуку Товара С, которого не было в заказе поставщика. Если вы просто инкрементируете число в одной строке плана, вы безвозвратно теряете детальную структуру принятых грузомест.
Поэтому в платформе документ при конвертации из ERP всегда разделяется минимум на два связанных табличных списка:
Expected Items(Плановые строки): исходное задание из ERP (Item A — Expected: 10, Actual: 10;Item B — Expected: 3, Actual: 1;Item C — Expected: 0, Actual: 1).Actual Items(Фактические строки): детальная расшифровка каждого скана с тарой, сериями и таймстампами. При этом в каждой строке факта тоже присутствует колонкаExpected Qty, но в ней отражается не вся сумма заказа, а аллоцированная доля плана, приходящаяся конкретно на эту строку факта:
Item Code | Item Name | Expected Qty (доля плана) | Actual Qty (факт) | SSCC (код паллеты/короба) |
|---|---|---|---|---|
101 | Item A | 5 (из 10) | 5 |
|
101 | Item A | 5 (из 10) | 5 |
|
102 | Item B | 1 (из 3) | 1 | — |
103 | Item C | 0 (вне плана) | 1 | — |
В момент каждого скана платформа синхронно обновляет три структуры: «грязную» таблицу сырых сканов, витрину для мгновенного отображения прогресса в UI и итоговую таблицу документа для выгрузки в ERP. Все три записи выполняются внутри одной атомарной транзакции: при любой ошибке происходит полный откат (rollback), поэтому рассогласование между экраном и базой исключено.
Поверх этого работает встроенная модель Упаковок (Packings) с коэффициентами пересчета к базовой единице измерения и Контейнеров (Containers) — индивидуально отслеживаемых паллет, весовых монокоробов и сборных микс-коробов.
Паттерн 4. Декларативные шаблоны штрихкодов (Barcode Data Templates)
В идеальном мире из учебников все товары промаркированы стандартным EAN-13 или GS1-128 с разделителями групп. В реальном мире, как подтверждает Саргис по опыту десятков воркшопов, бизнес обожает изобретать собственные форматы штрихкодов.
Самый частый пример из ритейла и пищевки — весовой EAN-13: внешне это обычный 13-символьный баркод, но его нужно налету распилить на две части: первые цифры кодируют сам товар, по которому нужно сделать поиск в справочнике, а последние 5 или 6 цифр перед контрольной суммой содержат вес конкретной упаковки. Другой пример с производства — внутренние этикетки на коробах без спецсимволов-разделителей, где в одной строке склеены артикул, номер партии и вес: B123456W000250 или P970001S211000101.
Вместо того чтобы писать кастомный парсер на регулярках под каждого клиента, в платформе используются Шаблоны штрихкодов (Barcode Data Templates), состоящие из констант и именованных переменных заданной длины:
P{ProductCode:6}S{SerialNumber:9}
или для сборного микс-короба:
MXD{BoxID:5}Q{Quantity:3}ITM{ItemCode:5}
Как только луч сканера считывает такой штрихкод, ядро платформы автоматически сопоставляет его с зарегистрированными шаблонами, понимает, какой именно объект отсканирован (товар, упаковка, адресная ячейка, документ или определенный тип контейнера), и само раскладывает извлеченные переменные {ProductCode}, {Quantity} или {Weight} в поля операции. А стандартные коды GS1-128 вроде (01)012345678905(10)ABC123(17)231231(30)025 разбираются платформой автоматически вообще без настройки шаблонов.
Практика: как устроена разработка внутри платформы (по следам живых воркшопов)
Посмотрим теперь, с чем сталкивается программист, когда открывает среду разработки платформы (Панель управления Mobile SMARTS), и почему подход с визуальными действиями позволяет собирать рабочие решения в разы быстрее классического кодинга.
Двухуровневая архитектура разработки
Платформа разделяет разработку на два независимых слоя, чтобы простые бизнес-задачи решались за минуты, но при этом у системных программистов не было потолка возможностей:
Слой разработки | Инструментарий и стек | Какие задачи решает |
|---|---|---|
Прикладной уровень (разработка и кастомизация мобильных приложений) | Визуальный редактор действий («стрелочки»), встроенный скриптовый язык с упрощенным C#-подобным синтаксисом, Cleverence Framework, СУБД HYDB | Сборка экранов ТСД, логика переходов, валидация сканов, верстка интерфейса, шаблоны ШК, работа с таблицами и документами |
Системный уровень (ядро, тяжелые интеграции и расширения) | C# (.NET Core 6) для сервера и клиентов, JavaScript (React Web) для веб-приложений, SQLite / PostgreSQL, XML, бинарные индексы | Написание собственных внешних коннекторов ( |
Саргис формулирует суть прикладного уровня просто: «Это разработка мобильных приложений с помощью визуальных действий и одновременный инструмент интеграции с учетными системами».
Для разработчиков 1С интерфейс Панели управления оказывается интуитивно знакомым — структура дерева конфигурации создавалась с оглядкой на конфигуратор 1С, но без его избыточной перегруженности. Главное отличие кроется в самом процессе создания форм и алгоритмов: даже в 1С разработчику приходится кодом или ручной привязкой задавать элементы форм, их размеры и обработчики кнопок. В платформе же операция собирается как блок-схема из готовых визуальных действий, соединенных переходами, а внутри каждого действия при необходимости дописывается обычная скриптовая логика — на встроенном языке с сильно упрощенным, лаконичным C#-подобным синтаксисом (без лишних сложных конструкций, которые на ТСД просто не нужны). Прямо в Панели управления по сочетанию клавиш работает встроенный IntelliSense, подсказывающий все доступные свойства и методы внутренних объектов.
Базовый воркшоп-тест: рабочий обмен с учеткой за 3 действия
Чтобы участники воркшопа сразу почувствовали разницу в скорости разработки, первое упражнение делается буквально за пять минут вживую:
В Панели управления создается новый Тип документа.
В алгоритм документа перетаскиваются всего три визуальных действия:
Сканирование товара→→Ввод количества→→Запись в документ.В учетной системе (например, в 1С) в пару кликов клонируется типовой бизнес-процесс и привязывается к только что созданному типу документа.
Никакой возни с сокетами, сериализацией JSON и версткой списков: участник сканирует штрихкод, вводит число — и готовый документ с товаром и количеством уже создан в учетной системе.
А дальше на этой базе разбираются реальные кастомные задачи, ради которых разработчики и приходят на воркшоп.
Кейс 1. Привязка фотографий на ТСД за 2 действия
На одном из первых воркшопов Саргис показал доработку, которая вызвала такой живой отклик у зала, что её включили в обязательную программу всех следующих городов: обязательное фотографирование товара при сборе штрихкодов. Оказывается, многие интеграторы и разработчики даже не подозревали, насколько просто платформа работает с медиафайлами. В существующий алгоритм сканирования добавляются буквально два действия: запрос снимка с камеры на каждый скан и сохранение фотографии. При этом разработчику не нужно думать, как пропихнуть тяжелые JPEG-файлы через слабый складской интернет: HYDB сама отделяет бинарный блоб от легкой структуры документа, передает его на сервер в фоновом режиме по частям и позволяет гибко настроить, куда именно эта фотография должна улететь и где храниться на стороне учетной системы.
Кейс 2. Живая верстка в отладчике и полная стилизация APK через файлы базы
Второй момент, который неизменно удивляет программистов на воркшопах, — то, как в платформе устроено управление внешним видом приложения:
Мгновенная разметка внутри окон: на воркшопе в Новосибирске участник попросил показать, как поменять оформление кнопок и шрифтов в документе. Вы запускаете отладку в десктопном эмуляторе
WinClient, открываете свойство кнопки, пишете словамиRed— и кнопка тут же становится красной. Хотите поменять черный текст внутри строки на белый? Оборачиваете текст в простой HTML-подобный тег<white>Текст</white>, и он мгновенно перекрашивается на экране без какого-либо лишнего кода.Переопределение главного бургер-меню и цветовых тем без пересборки APK: многие считают, что раз стандартные продукты имеют фиксированные цвета (например, «Склад 15» — оранжевый, «Магазин 15» — красный), а шапка и боковое бургер-меню принадлежат самому Android-клиенту, то изменить их без пересборки APK нельзя. На самом деле в платформе это решено гораздо элегантнее: и палитра цветов всех кнопок, и структура главного бургер-меню могут задаваться внешними файлами стилей и конфигурации, которые лежат на сервере внутри конкретной базы. Когда ТСД подключается к этой базе, эти файлы прилетают на устройство, и мобильный клиент отрисовывает бургер-меню уже не по дефолтному шаблону, зашитому в APK, а по файлу вашей базы. Вы можете самостоятельно, без обращения к вендору, перекрасить интерфейс в корпоративные цвета заказчика, добавить в бургер-меню собственные пункты со своими иконками и повесить на нажатие прямой запуск нужного типа документа.
Кейс 3. Универсальность конструктора: регистрация гостей и печать бейджей за 3 часа
Наконец, самый наглядный ответ на вопрос «разве это не просто узкая программа для складского сканера?» участники видели прямо на входе в зал. Регистрация самих гостей воркшопа, их запись в базу и мгновенная печать именных бейджей на принтере этикеток работали на мобильном приложении, собранном на этой же платформе. Как признается Саргис, всю эту конфигурацию регистратора он написал с нуля «на выходных за три часа под банку пива». Потому что визуальные действия позволяют собирать на Android практически любые прикладные сценарии ввода, обработки и печати данных.
Архитектурный нюанс отладки: почему новички путаются в Hot Reload (WinClient vs Сервер)
Если вы впервые сядете за Панель управления после классических IDE вроде Android Studio или Visual Studio, есть один архитектурный момент, который гарантированно вызовет у вас вопросы. На воркшопах вокруг него регулярно возникают дискуссии.
В привычной мобильной разработке схема линейная: вы запустили эмулятор, изменили код в IDE, нажали Hot Reload — и IDE напрямую подменила файлы внутри работающего эмулятора. В Панели управления Mobile SMARTS вы тоже можете подключить к отладчику живой ТСД или запустить встроенный десктопный эмулятор терминала (WinClient), менять визуальные действия или серверную логику и сразу видеть результат. Но как только вы добавляете новый справочник или меняете структуру таблиц для типа документа, вы замечаете, что в открытом эмуляторе эти данные не появляются до тех пор, пока вы явно не выполните операцию «Обмен».
Почему так происходит? Потому что в Панели управления вы редактируете не файлы внутри мобильного устройства, а конфигурацию самой серверной базы данных платформы. В одном и том же окне редактора вы пишете и серверный код, и клиентский код. Все ваши правки сохраняются в виде XML-файлов конфигурации на сервере. Поэтому, когда вы отлаживаете серверные операции, изменения подхватываются мгновенно — они уже на сервере. А вот клиентское устройство (и эмулятор WinClient, который честно эмулирует работу отдельного терминала) должно получить обновленную структуру и справочники с сервера через штатный механизм синхронизации.
Из этой же архитектуры следует важное практическое правило: хотя вся конфигурация базы физически представляет собой набор текстовых XML-файлов, править эти XML-файлы напрямую в стороннем текстовом редакторе или Visual Studio крайне опасно. Если вы допустите малейшую опечатку или забудете закрыть тег, база при запуске не упадет с фатальной ошибкой, но парсер просто отбросит невалидный узел — и написанные вами операции бесследно исчезнут из приложения. Панель управления тем и ценна, что позволяет безопасно вносить правки и одновременно вести отладку сразу в трех контурах: на сервере, на удаленно подключенном физическом ТСД и в локальном WinClient. (маленькое уточнение от автора -с использованием ИИ это уже кажется лишним и грамотные специалисты научились тупо править файлы).
«А у нас сервера на Linux!»: как устроена работа в Linux-окружении
Отдельная большая тема, которая звучит почти на каждой встрече с корпоративными разработчиками, — работа под Linux. Поскольку демонстрация на воркшопах обычно идет на ноутбуке с Windows, из зала обязательно спрашивают: «У нас в компании все сервера переведены на Linux (Ubuntu, Debian, Astra Linux). Как нам разворачивать платформу и как её конфигурировать, если ваша Панель управления работает только под Windows?»
Здесь нужно четко разделить серверную среду исполнения (Apps Server) и инструмент разработки (Панель управления):
Сервер платформы нативно работает на Linux. Серверное ядро написано на
.NET Coreи штатно разворачивается на Linux-серверах (включая отечественные дистрибутивы вроде Astra Linux). Для установки не нужна графическая оболочка: достаточно выполнить в терминале буквально три команды — скачать архив с сайта, распаковать его и запустить консольный установщик.Конфигурирование работает удаленно по клиент-серверной схеме. Пытаться запустить десктопную Панель управления или
WinClientнапрямую внутри графической оболочки Ubuntu не нужно — они созданы под Windows-среду. Вместо этого разработчики работают точно так же, как с серверной базой 1С или классической СУБД:На Linux-сервере в контейнере или службе разворачивается база платформы и формируется строка подключения.
Разработчик копирует эту строку подключения на свою рабочую машину с Windows, вставляет её в Панель управления и подключается к серверной базе по сети.
Вся разработка, настройка таблиц и отладка ведутся удаленно с рабочего места инженера, в то время как сама база и серверные операции крутятся на Linux-сервере.
А для того чтобы сделать запуск и проверку клиентских форм полностью независимыми от операционной системы, команда платформы сейчас ведет разработку браузерного Web-клиента, который позволит открывать интерфейс терминала прямо в браузере (и станет кроссплатформенной заменой WinClient).
Интеграция с учетными системами: готовые коннекторы, свои велосипеды и «путь здоровой лени»
Переходим к главному вопросу для авторов самописных учетных систем и разработчиков 1С: как именно платформа стыкуется с внешним бэкендом и где проходит граница ответственности между кодом платформы и кодом ERP?
Во-первых, для большинства популярных систем на рынке уже существуют готовые тиражируемые коннекторы: от десятков типовых, отраслевых и облачных конфигураций 1С и МойСклад до iiko, SAP S/4HANA, Microsoft Dynamics (AX 2012 / D365) и Odoo (v13–v17). Во-вторых, сама архитектура интеграции построена так, чтобы подключение любой нестандартной или полностью самописной ERP сводилось к реализации простого, четко описанного контракта.
Архитектура двустороннего обмена и единый Inventory API
В распределенной системе с мобильными терминалами роли «клиента» и «сервера» определяются тем, кто инициирует соединение. Главная аксиома надежности здесь звучит так: сервер никогда не инициирует подключение к мобильному терминалу. ТСД может находиться в спящем режиме, ехать в лифте или лежать вне зоны покрытия Wi-Fi — поэтому сервер платформы (Apps Server) лишь подготавливает данные и ждет, пока мобильный клиент сам выйдет на связь и заберет их.
А вот взаимодействие между сервером платформы и вашей ERP является полноценным двусторонним (2-Way Integration) и может работать по двум моделям:
Модель 1 (ERP как сервер данных — рекомендуемый путь): ваша учетная система выставляет наружу стандартный интерфейс Inventory API (набор типовых REST/JSON эндпоинтов для отдачи справочников/документов и приема результатов). Сервер платформы сам обращается к этому API как за данными по расписанию, так и при синхронных онлайн-запросах с ТСД.
Модель 2 (ERP как активный инициатор): ваша учетная система сама выступает клиентом, вызывая API сервера платформы, чтобы принудительно выгрузить новое задание на сборку или обновить справочник, а затем забирает готовый результат (например, когда ТСД завершает документ и платформа шлет в учетку сигнал о готовности).
Ключевое инженерное преимущество этого подхода в том, что для Real-Time (онлайн) и Batched (пакетного) обмена используется одна и та же архитектура и один и тот же код коннектора Inventory API. Разработчику не нужно писать две разные интеграции для онлайн-проверок и для ночной выгрузки справочников.
При этом сам обмен данными опирается на документно-ориентированную модель транзакций (Document-Based Transaction Model): вместо того чтобы нагружать ERP сотнями мелких запросов на каждое действие кладовщика, платформа агрегирует все собранные сканы, серии и тару в структурированный документ и передает его в учетную систему одним пакетом.
Таблицы «Бизнес-процессов»: декларативный оркестратор обмена
Чтобы не хардкодить логику преобразования документов внутри интеграционного модуля, в платформе используется механизм Бизнес-процессов (Business Processes).
По сути, таблица бизнес-процессов — это конфигурационный словарь, который связывает три сущности:
Исходный документ ERP (
erpSourceDocumentType+erpSourceConfigSettings): какой документ берем из учетной системы (например,PurchaseOrder), каким алгоритмом конвертируем и с какими JSON-параметрами фильтрации ({ "scanLot": true, "allowUnknown": false }).Документ мобильного приложения (
mobileAppDocumentType+mobileExecutionSettings): в какой тип документа на ТСД он трансформируется (Receiving Document) и какие правила действуют на устройстве ({ "scanSerialNum": true }).Результирующий документ ERP (
erpResultDocumentType+erpResultConfigSettings): какой документ создается или обновляется в ERP по итогам сканирования и с какими настройками алгоритма ({ "highlightDiscrepancies": true }).
Если для выбранного документа в таблице существует только один подходящий бизнес-процесс, терминал подхватывает и запускает его автоматически, просто выводя в шапке подсказку для пользователя. Если же к одному типу документа привязано несколько процессов (например, обычная приемка и приемка с отбраковкой), ТСД автоматически выведет всплывающее меню выбора.
Как один C#-коннектор закрывает 4 разных процесса за счет JSON-конфигурации В архитектурном руководстве платформы приведен отличный пример того, как эта схема экономит время бэкенд-разработчика. Допустим, в вашей облачной учетной системе (будь то кастомная 1С в облаке, веб-система уровня iiko или МойСклад, подключенная через C#-коннектор
InventoryAPI) есть один базовый документ корректировки запасов (Stock Quantity Adjustment), который принимает на вход артикул и разницу количества (QTY Difference). На складе же кладовщики выполняют четыре разные операции:
Выборочный пересчет (
Partial Stock Count): инициируется прямо на ТСД без документа из ERP, считает фактический остаток в ячейке.Полная инвентаризация (
Full Stock Count): идет по выгруженному слепку остатков из ERP.Списание брака (
Write Off): фиксирует только количество разбитого товара.Производство по спецификации (
BOM Execution): списывает сырье и приходует готовую продукцию.Разработчику коннектора не нужно писать четыре разных обработчика. Он пишет один универсальный алгоритм на C#, который смотрит в JSON-поле
erpResultConfigSettingsконкретного бизнес-процесса:
Если в JSON передан параметр
"Adjustment Type": "New Stock Value"(для инвентаризаций), коннектор сам запрашивает из ERP текущий учетный остаток товара, вычитает его из присланного с ТСД факта (QTY Difference = New - Current) и записывает дельту.Если в JSON стоит
"Adjustment Type": "Direct Adjustment"(для списания брака или BOM), коннектор использует количество с ТСД напрямую как готовую дельту и автоматически подставляет нужный комментарий (Memo) и правило расчета себестоимости. Чтобы добавить пятый вариант складской операции, программисту вообще не нужно трогать C#-код — достаточно скопировать строку в таблице бизнес-процессов и поменять JSON-параметры.
Два пути кастомизации: внутри платформы или на стороне своей ERP
Наблюдая за тем, как реальные программисты внедряют и дорабатывают проекты после воркшопов, Саргис выделил два характерных сценария работы.
Путь 1 (Логика внутри платформы): если вам нужно отправить внешний REST-запрос к стороннему сервису или обработать данные прямо на сервере Mobile SMARTS, в платформе для этого есть готовые системные объекты и подробные примеры в базе знаний, а для сложной логики — возможность подключить собственные расширения на C#.
Путь 2 («Путь здоровой лени» на языке своей учетной системы): большинство разработчиков 1С и авторов собственных ERP рассуждают прагматично: зачем тратить время на изучение синтаксиса REST-запросов внутри новой платформы, если свою учетную систему они знают как свои пять пальцев? Поэтому они разделяют задачи:
На стороне платформы делают то, что невозможно сделать в ERP: визуальную верстку экранов под требования заказчика, настройку шаблонов для разбора нестандартных и весовых штрихкодов, управление камерой/сканером и добавление пользовательских полей в документ ТСД.
На стороне своей учетной системы (через вызов метода внешней системы и словарь бизнес-процессов) принимают собранные с ТСД данные и уже в привычной среде — в обработке 1С, на Python, C# или ABAP — пишут все внешние HTTP-вызовы, специфические проверки или логику разбиения одного большого заказа на десяток мелких заданий для терминалов.
И даже тогда, когда клиенты устраивают в своей учетной базе полный хаос (например, заводят штрихкоды с нарушением всех мыслимых правил, из-за чего падает стандартная коробочная логика), открытая архитектура платформы позволяет решить проблему малой кровью. Саргис вспоминает, как в Ростове, Краснодаре и Ставрополе интеграторы специально приезжали на воркшоп из соседних городов ради одного вопроса: «Клиент наворотил такое в базе, что коробка не взлетает. Нам что, переписывать всю операцию с нуля?». Вместо тотального переписывания мы просто открывали Панель управления, находили нужный шаг в визуальном алгоритме и точечно вставляли туда одно короткое условие-проверку конкретно под аномалию этого клиента. Пять минут работы, нулевая просадка по скорости — и проблема закрыта.
Итог: инженерная матрица выбора «Самописка vs Модуль ERP vs Платформа»
Чтобы свести всё воедино, вот честная сравнительная таблица, по которой можно оценивать трудозатраты перед стартом проекта мобильной автоматизации:
Архитектурный критерий | Кастомная разработка с нуля (Kotlin / Flutter / Мобильная 1С) | Штатные мобильные модули внутри ERP | Специализированная платформа для ТСД |
|---|---|---|---|
Стартовая скорость (Time-to-Market) | Прототип с ИИ делается быстро, но доводка под реальные ТСД, сеть и периферию съедает месяцы | Быстро только в том случае, если бизнес-процесс на 100% совпадает со стандартной логикой ERP | Простой процесс с выгрузкой в ERP собирается за 3 действия; есть готовые коробочные конфигурации |
Работа на слабом железе и в плохом Wi-Fi | Нужно с нуля писать кэширование, дельта-синхронизацию, идемпотентность по | Зачастую требуют постоянного онлайна (тонкий клиент / RDP / тяжелый веб) и встают при обрыве связи | Гибридная БД ( |
Аппаратный слой, сложные ШК и маркировка | Интеграция каждого SDK сканера, принтера и поддержка изменений «Честного ЗНАКа» ложатся на ваши плечи | Поддерживают только базовые сценарии; кастомные весовые ШК и тара требуют сложной переделки | Поддержка сотен моделей ТСД, принтеров и RFID из коробки; декларативные шаблоны ШК и готовый объект маркировки |
Гибкость интеграции с учетной системой | Полный контроль, но весь транспортный уровень и батчинг документов вы пишете сами | Жесткая привязка к одной ERP; кастомизация мобильных экранов крайне ограничена | Готовые коннекторы + открытый |
Сопровождение и Bus Factor | Критическая зависимость от автора кода; дорогой поиск замены при увольнении | Требуются дорогие профильные разработчики конкретной ERP | Наглядный визуальный граф действий + простой C#-подобный скриптовый синтаксис со встроенными подсказками |
Когда в финале интервью мы спросили Саргиса, что бы он посоветовал разработчикам, которые смотрят на платформу со стороны и сомневаются, стоит ли тратить время на знакомство с ней, он ответил очень точно:
«Не пугайтесь, если в первый момент вы увидите непривычные визуальные действия со стрелочками и незнакомые названия внутренних объектов. Попробуйте залезть чуть глубже под капот, поэкспериментируйте с версткой, стилями, шаблонами штрихкодов и гибридными справочниками. Вы быстро увидите, что это не просто закрытая "программа для сканирования на складе", а универсальный визуальный конструктор, который берет на себя всю грязную низкоуровневую рутину и оставляет вам чистое инженерное творчество».
А как вы решаете задачу подключения ТСД к своим учетным системам? Пилили свой клиент с нуля или используете готовую платформу? Делитесь своим опытом и набитыми шишками в комментариях!
Комментарии 0